diff --git a/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts b/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts index a309c994d33ad..795651296873e 100644 --- a/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts +++ b/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts @@ -492,6 +492,8 @@ export class TableV2 extends TableBaseV2 { props.globalSecondaryIndexes?.forEach(gsi => this.addGlobalSecondaryIndex(gsi)); props.localSecondaryIndexes?.forEach(lsi => this.addLocalSecondaryIndex(lsi)); + this.resourcePolicy = props.resourcePolicy; + const resource = new CfnGlobalTable(this, 'Resource', { tableName: this.physicalName, keySchema: this.keySchema, @@ -615,7 +617,6 @@ export class TableV2 extends TableBaseV2 { private configureReplicaTable(props: ReplicaTableProps): CfnGlobalTable.ReplicaSpecificationProperty { const pointInTimeRecovery = props.pointInTimeRecovery ?? this.tableOptions.pointInTimeRecovery; const contributorInsights = props.contributorInsights ?? this.tableOptions.contributorInsights; - const resourcePolicy = props.resourcePolicy ?? this.tableOptions.resourcePolicy; return { region: props.region, @@ -636,8 +637,8 @@ export class TableV2 extends TableBaseV2 { ? props.readCapacity._renderReadCapacity() : this.readProvisioning, tags: props.tags, - resourcePolicy: resourcePolicy - ? { policyDocument: resourcePolicy } + resourcePolicy: this.resourcePolicy + ? { policyDocument: this.resourcePolicy } : undefined, }; } diff --git a/packages/aws-cdk-lib/aws-dynamodb/test/table-v2.test.ts b/packages/aws-cdk-lib/aws-dynamodb/test/table-v2.test.ts index 81e9205211a0b..4e4e4fe3012e8 100644 --- a/packages/aws-cdk-lib/aws-dynamodb/test/table-v2.test.ts +++ b/packages/aws-cdk-lib/aws-dynamodb/test/table-v2.test.ts @@ -2807,49 +2807,155 @@ describe('imports', () => { }); }); -test('Resource policy test', () => { - // GIVEN - const stack = new Stack(undefined, 'Stack'); - - const doc = new PolicyDocument({ - statements: [ - new PolicyStatement({ - actions: ['dynamodb:GetItem'], - principals: [new ArnPrincipal('arn:aws:iam::111122223333:user/foobar')], - resources: ['*'], - }), - ], - }); - - // WHEN - const table = new TableV2(stack, 'Table', { - partitionKey: { name: 'metric', type: AttributeType.STRING }, - resourcePolicy: doc, - }); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::DynamoDB::GlobalTable', { - Replicas: [ - { - Region: { - Ref: 'AWS::Region', - }, - ResourcePolicy: { - PolicyDocument: { - Statement: [ - { - Action: 'dynamodb:GetItem', - Effect: 'Allow', - Principal: { - AWS: 'arn:aws:iam::111122223333:user/foobar', +describe('resource policy', () => { + test('resource policy property provided', () => { + // GIVEN + const stack = new Stack(undefined, 'Stack'); + + const doc = new PolicyDocument({ + statements: [ + new PolicyStatement({ + actions: ['dynamodb:GetItem'], + principals: [new ArnPrincipal('arn:aws:iam::111122223333:user/foobar')], + resources: ['*'], + }), + ], + }); + + // WHEN + new TableV2(stack, 'Table', { + partitionKey: { name: 'metric', type: AttributeType.STRING }, + resourcePolicy: doc, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::DynamoDB::GlobalTable', { + Replicas: [ + { + Region: { + Ref: 'AWS::Region', + }, + ResourcePolicy: { + PolicyDocument: { + Statement: [ + { + Action: 'dynamodb:GetItem', + Effect: 'Allow', + Principal: { + AWS: 'arn:aws:iam::111122223333:user/foobar', + }, + Resource: '*', }, - Resource: '*', - }, - ], - Version: '2012-10-17', + ], + Version: '2012-10-17', + }, }, }, - }, - ], + ], + }); }); -}); \ No newline at end of file + + test('resource policy with addToResourcePolicy', () => { + // GIVEN + const stack = new Stack(undefined, 'Stack'); + + const statement = new PolicyStatement({ + actions: ['dynamodb:GetItem'], + principals: [new ArnPrincipal('arn:aws:iam::111122223333:user/foobar')], + resources: ['*'], + }); + + // WHEN + const table = new TableV2(stack, 'Table', { + partitionKey: { name: 'metric', type: AttributeType.STRING }, + }); + + table.addToResourcePolicy(statement); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::DynamoDB::GlobalTable', { + Replicas: [ + { + Region: { + Ref: 'AWS::Region', + }, + ResourcePolicy: { + PolicyDocument: { + Statement: [ + { + Action: 'dynamodb:GetItem', + Effect: 'Allow', + Principal: { + AWS: 'arn:aws:iam::111122223333:user/foobar', + }, + Resource: '*', + }, + ], + Version: '2012-10-17', + }, + }, + }, + ], + }); + }); + + test('resource policy property provided and with addToResourcePolicy', () => { + // GIVEN + const stack = new Stack(undefined, 'Stack'); + + const statement1 = new PolicyStatement({ + actions: ['dynamodb:GetItem'], + principals: [new ArnPrincipal('arn:aws:iam::111122223333:user/user1')], + resources: ['*'], + }); + + const statement2 = new PolicyStatement({ + actions: ['dynamodb:GetItem'], + principals: [new ArnPrincipal('arn:aws:iam::111122223333:user/user2')], + resources: ['*'], + }); + + // WHEN + const table = new TableV2(stack, 'Table', { + partitionKey: { name: 'metric', type: AttributeType.STRING }, + resourcePolicy: new PolicyDocument({ statements: [statement1] }), + }); + + table.addToResourcePolicy(statement2); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::DynamoDB::GlobalTable', { + Replicas: [ + { + Region: { + Ref: 'AWS::Region', + }, + ResourcePolicy: { + PolicyDocument: { + Statement: [ + { + Action: 'dynamodb:GetItem', + Effect: 'Allow', + Principal: { + AWS: 'arn:aws:iam::111122223333:user/user1', + }, + Resource: '*', + }, + { + Action: 'dynamodb:GetItem', + Effect: 'Allow', + Principal: { + AWS: 'arn:aws:iam::111122223333:user/user2', + }, + Resource: '*', + }, + ], + Version: '2012-10-17', + }, + }, + }, + ], + }); + }); +}); +