Skip to content

Commit

Permalink
fix(dynamodb): grantXxx() does not grant in replication regions
Browse files Browse the repository at this point in the history
Add all replication regions when granting permissions.

Closes #7362
  • Loading branch information
jogold committed Apr 23, 2020
1 parent 8c687f5 commit 98429e0
Show file tree
Hide file tree
Showing 2 changed files with 409 additions and 12 deletions.
36 changes: 24 additions & 12 deletions packages/@aws-cdk/aws-dynamodb/lib/table.ts
Expand Up @@ -348,6 +348,8 @@ abstract class TableBase extends Resource implements ITable {
*/
public abstract readonly tableStreamArn?: string;

protected readonly regionalArns = new Array<string>();

/**
* Adds an IAM policy statement associated with this table to an IAM
* principal's policy.
Expand All @@ -361,6 +363,10 @@ abstract class TableBase extends Resource implements ITable {
resourceArns: [
this.tableArn,
Lazy.stringValue({ produce: () => this.hasIndex ? `${this.tableArn}/index/*` : Aws.NO_VALUE }),
...this.regionalArns,
...this.regionalArns.map(arn => Lazy.stringValue({
produce: () => this.hasIndex ? `${arn}/index/*` : Aws.NO_VALUE,
})),
],
scope: this,
});
Expand Down Expand Up @@ -403,11 +409,13 @@ abstract class TableBase extends Resource implements ITable {
if (!this.tableStreamArn) {
throw new Error(`DynamoDB Streams must be enabled on the table ${this.node.path}`);
}

return iam.Grant.addToPrincipal({
grantee,
actions: ['dynamodb:ListStreams'],
resourceArns: [
Lazy.stringValue({ produce: () => `${this.tableArn}/stream/*` }),
...this.regionalArns.map(arn => Lazy.stringValue({ produce: () => `${arn}/stream/*` })),
],
});
}
Expand Down Expand Up @@ -1023,17 +1031,6 @@ export class Table extends TableBase {
this.grant(provider.onEventHandler, 'dynamodb:*');
this.grant(provider.isCompleteHandler, 'dynamodb:DescribeTable');

// Permissions in the destination regions
provider.onEventHandler.addToRolePolicy(new iam.PolicyStatement({
actions: ['dynamodb:*'],
resources: regions.map(region => stack.formatArn({
region,
service: 'dynamodb',
resource: 'table',
resourceName: this.tableName,
})),
}));

let previousRegion;
for (const region of new Set(regions)) { // Remove duplicates
// Use multiple custom resources because multiple create/delete
Expand All @@ -1058,14 +1055,29 @@ export class Table extends TableBase {
cfnCustomResource.cfnOptions.condition = createReplica;
}

// Save regional arns for grantXxx() methods
this.regionalArns.push(stack.formatArn({
region,
service: 'dynamodb',
resource: 'table',
resourceName: this.tableName,
}));

// We need to create/delete regions sequentially because we cannot
// have multiple table updates at the same time. The `isCompleteHandler`
// of the provider waits until the replica is an ACTIVE state.
// of the provider waits until the replica is in an ACTIVE state.
if (previousRegion) {
currentRegion.node.addDependency(previousRegion);
}
previousRegion = currentRegion;
}

// Permissions in the destination regions (outside of the loop to
// minimize statements in the policy)
provider.onEventHandler.addToRolePolicy(new iam.PolicyStatement({
actions: ['dynamodb:*'],
resources: this.regionalArns,
}));
}

/**
Expand Down

0 comments on commit 98429e0

Please sign in to comment.