feat(dynamodb): add cross-account global table replication support#36895
feat(dynamodb): add cross-account global table replication support#36895mergify[bot] merged 14 commits intoaws:mainfrom
Conversation
|
|
||||||||||||||
|
|
||||||||||||||
|
|
||
| // Validate replicaSourceTable if provided | ||
| if (props.replicaSourceTable) { | ||
| const sourceStack = Stack.of(props.replicaSourceTable); | ||
| const sourceRegion = sourceStack.splitArn(props.replicaSourceTable.tableArn, ArnFormat.SLASH_RESOURCE_NAME).region; | ||
| if (sourceRegion === this.region) { | ||
| throw new ValidationError( | ||
| `The region in \`replicaSourceArn\` (${sourceRegion}) cannot be the same as the stack region (${this.region}).`, | ||
| this, | ||
| ); | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Again, you don't set the replica properties here. Only set them on the replica class.
| import { IKey } from '../../aws-kms'; | ||
| import { Grant } from '../../aws-iam'; | ||
| import type { IKey } from '../../aws-kms'; | ||
| >>>>>>> internal/main |
There was a problem hiding this comment.
This should be removed.
| >>>>>>> internal/main |
Pull request has been modified.
Abogical
left a comment
There was a problem hiding this comment.
Integration test snapshots would need to be updated: https://github.com/aws/aws-cdk/actions/runs/21766853798/job/62804783432?pr=36895#step:9:5905
Pull request has been modified.
| } | ||
|
|
||
| this.policyResource.addToResourcePolicy(new iam.PolicyStatement({ | ||
| sid: 'AllowMultiAccountReplicaAssociation', |
There was a problem hiding this comment.
There may be a conflict in the SID if the table has multiple cross-account replicas. Multiple policies will be generated with the same SID's, leading to a deployment conflict. Can the SID include the destination account and table name to make sure it is deduplicated and unique?
| sid: 'AllowMultiAccountReplicaAssociation', | |
| sid: `AllowMultiAccountReplicaAssociation-${arnComponents.account}`, |
| })); | ||
|
|
||
| this.policyResource.addToResourcePolicy(new iam.PolicyStatement({ | ||
| sid: 'AllowReplicationServiceReadWrite', |
Pull request has been modified.
| })); | ||
|
|
||
| this.policyResource.addToResourcePolicy(new iam.PolicyStatement({ | ||
| sid: 'AllowReplicationServiceReadWrite', |
Pull request has been modified.
There was a problem hiding this comment.
There is a unit test error, see: https://github.com/aws/aws-cdk/actions/runs/22067324790/job/63762511491?pr=36895#step:9:3500
aws-cdk-lib: FAI
aws-cdk-lib: L aws-
aws-cdk-lib: dynamodb/tes
aws-cdk-lib: t/table-v
aws-cdk-lib: 2.test.t
aws-cdk-lib: s (22.319
aws-cdk-lib: s)
aws-cdk-lib:
aws-cdk-lib: ● grantMulti
aws-cdk-lib: AccountRepl
aws-cdk-lib: icationTo
aws-cdk-lib: adds req
aws-cdk-lib: uired resour
aws-cdk-lib: ce policy
aws-cdk-lib: statement
aws-cdk-lib: s
aws-cdk-lib: E
aws-cdk-lib: xpected valu
aws-cdk-lib: e undefi
aws-cdk-lib: ned
aws-cdk-lib: R
aws-cdk-lib: eceived:
aws-cdk-lib:
aws-cdk-lib: undefine
aws-cdk-lib: d
aws-cdk-lib: Me
aws-cdk-lib: ssage:
aws-cdk-lib:
aws-cdk-lib: Template ha
aws-cdk-lib: s 1 resou
aws-cdk-lib: rces with
aws-cdk-lib: type AWS
aws-cdk-lib: ::Dynamo
aws-cdk-lib: DB::GlobalTa
aws-cdk-lib: ble, but n
aws-cdk-lib: one matc
aws-cdk-lib: h as ex
aws-cdk-lib: pec
aws-cdk-lib: ted.
aws-cdk-lib:
aws-cdk-lib: The 1 close
aws-cdk-lib: st match
aws-cdk-lib: es:
aws-cdk-lib: T
aws-cdk-lib: ableCD117FA1
aws-cdk-lib: :: {
aws-cdk-lib:
aws-cdk-lib: "DeletionPolicy
aws-cdk-lib: ": "Retain",
aws-cdk-lib: "Properties": {
aws-cdk-lib: "AttributeDefinitions": [ { ... } ],
aws-cdk-lib: "BillingMode": "PAY_PER_REQUEST",
aws-cdk-lib: "KeySchema": [ { ... } ],
aws-cdk-lib: "Replicas": [
aws-cdk-lib: {
aws-cdk-lib: "Region": "us-east-2",
aws-cdk-lib: "ResourcePolicy": {
aws-cdk-lib: "Policy
aws-cdk-lib: D
aws-cdk-lib: ocument": {
aws-cdk-lib: "Statement": [
aws-cdk-lib: {
aws-cdk-lib: "Action": "dynamodb:AssociateTableReplica",
aws-cdk-lib: "Effect": "Allow",
aws-cdk-lib: "Principal": { "AWS": { "Fn::Join": [ ... ] } },
aws-cdk-lib: "Resource": "*",
aws-cdk-lib: !! Expected AllowMultiAccountReplicaAssociation but received AllowMultiAccountReplicaAssociation-222222222222
aws-cdk-lib: "Sid": "AllowMultiAccountReplicaAssociation-222222222222"
aws-cdk-lib: },
aws-cdk-lib: {
aws-cdk-lib: "Action": [ ... ],
aws-cdk-lib: "Condition": { "StringEquals": { "aws:SourceAccount": [ "111111111111", "222222222222" ] } },
aws-cdk-lib: "Effect": "Allow",
aws-cdk-lib: "Principal": { "Service": "replication.dynamodb.amazonaws.com" },
aws-cdk-lib: "Resource": "*",
aws-cdk-lib: !! Expected AllowReplicationServiceReadWrite but received AllowReplicationServiceReadWrite-222222222222
aws-cdk-lib: "Sid": "AllowReplicationServiceReadWrite-2222222
aws-cdk-lib: 22222"
aws-cdk-lib: }
aws-cdk-lib: ],
aws-cdk-lib: "Version": "2012-10-17"
aws-cdk-lib: }
aws-cdk-lib: }
aws-cdk-lib: }
aws-cdk-lib: ]
aws-cdk-lib: },
aws-cdk-lib: "Type": "AWS::DynamoDB::GlobalTable",
aws-cdk-lib: "UpdateReplacePolicy": "Retain"
aws-cdk-lib: }
aws-cdk-lib: Difference:
aws-cdk-lib: Compared values have no visual difference.
aws-cdk-lib: 106 | const matchError = hasResourceProperties(this.template, type, props);
aws-cdk-lib: 107 | if (matchError) {
aws-cdk-lib: > 108 | throw new AssertionError(matchError);
aws-cdk-lib: | ^
aws-cdk-lib: 109 | }
aws-cdk-lib: 110 | }
aws-cdk-lib: 111 |
aws-cdk-lib: at Template.hasResourceProperties (assertions/lib/template.ts:108:13)
aws-cdk-lib: at Object.<anonymous> (aws-dynamodb/test/table-v2.test.ts:3739:29)
aws-cdk-lib: ● TableV2MultiAccountReplica creates replica with permissions
aws-cdk-lib: Expected value undefined
aws-cdk-lib: Received:
aws-cdk-lib: undefined
aws-cdk-lib: Message:
aws-cdk-lib: Template has 1 resources with type AWS::DynamoDB::GlobalTable, but none match as expected.
aws-cdk-lib: The 1 closest matches:
aws-cdk-lib: SourceTable70380C26 :: {
aws-cdk-lib: "DeletionPolicy": "Retain
aws-cdk-lib: ",
aws-cdk-lib: "Properties": {
aws-cdk-lib: "AttributeDefinitions": [ { ... } ],
aws-cdk-lib: "BillingMode": "PAY_PER_REQUEST",
aws-cdk-lib: "KeySchema": [ { ... } ],
aws-cdk-lib: "Replicas": [
aws-cdk-lib: {
aws-cdk-lib: "Region": "us-east-2",
aws-cdk-lib: "ResourcePolicy": {
aws-cdk-lib: "PolicyDocument": {
aws-cdk-lib: "Statement": [
aws-cdk-lib: !! Could not match arrayWith pattern 0. This is the closest match
aws-cdk-lib: {
aws-cdk-lib: "Action": "dynamodb:AssociateTableReplica",
aws-cdk-lib: "Effect": "Allow",
aws-cdk-lib: "Principal": { "AWS": { "Fn::Join": [ ... ] } },
aws-cdk-lib: "Resource": "*",
aws-cdk-lib: !! Expected type string but received object
aws-cdk-lib: "Sid": {
aws-cdk-lib: "Fn::Join": [ ... ]
aws-cdk-lib: }
aws-cdk-lib: },
aws-cdk-lib: { ... }
aws-cdk-lib: ],
aws-cdk-lib: "Version": "2012-10-17"
aws-cdk-lib: }
aws-cdk-lib: }
aws-cdk-lib: }
aws-cdk-lib: ],
aws-cdk-lib: "TableName": "sourcestackstacksourcetable4d2d74602f5cc7577a18"
aws-cdk-lib: },
aws-cdk-lib: "Type": "AWS::DynamoDB::GlobalTable",
aws-cdk-lib: "UpdateReplacePolicy": "Retain"
aws-cdk-lib: }
aws-cdk-lib: Difference:
aws-cdk-lib: Compared values have no visual difference.
aws-cdk-lib: 106 | const matchError = hasResourceProperties(this.template, type, props);
aws-cdk-lib: 107 | if (matchError) {
aws-cdk-lib: > 108 | throw new AssertionError(matchError);
aws-cdk-lib: | ^
aws-cdk-lib: 109 | }
aws-cdk-lib: 110 | }
aws-cdk-lib: 111 |
aws-cdk-lib: at Template.hasResourceProperties (assertions/lib/template.ts:108:13)
aws-cdk-lib: at Object.<anonymous> (aws-dynamodb/test/table-v2.test.ts:3901:35)
aws-cdk-lib: Test Suites: 1 failed, 821 passed, 822 total
aws-cdk-lib: Tests: 2 failed, 3 skipped, 16921 passed, 16926 total
aws-cdk-lib: Snapshots: 13 passed, 13 total
aws-cdk-lib: Time: 252.958 s
aws-cdk-lib: Ran all test suites.
aws-cdk-lib:
aws-cdk-lib: error Command failed with exit code 1.
Pull request has been modified.
|
@Mergifyio update |
❌ Mergify doesn't have permission to updateDetailsFor security reasons, Mergify can't update this pull request. Try updating locally. |
Pull request has been modified.
|
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
Merge Queue StatusRule:
This pull request spent 29 minutes 53 seconds in the queue, including 29 minutes 43 seconds running CI. Required conditions to merge
|
|
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
|
Comments on closed issues and PRs are hard for our team to see. |
Reason for this change
DynamoDB global tables currently only support same-account replication across regions. Customers need the ability to replicate tables across AWS accounts for multi-tenant architectures, organizational boundaries, and disaster recovery scenarios.
Description of changes
Added support for cross-account DynamoDB global table replication through a new TableV2MultiAccountReplica construct and automatic permission management:
Core Changes:
Permission Management:
Design Decisions:
Describe any new or updated permissions being added
DynamoDB Table Resource Policies:
KMS Key Permissions (when encryption enabled):
Description of how you validated changes
Unit Tests:
Integration Tests:
Checklist