From 8a6173d67a06baf3e536c2b6e5b38dcd390fa215 Mon Sep 17 00:00:00 2001 From: Adam Ruka Date: Wed, 27 May 2020 12:00:08 -0700 Subject: [PATCH] feat(dynamodb): allow providing indexes when importing a Table For imported Tables, the grant() methods skipped adding permissions for indexes, as there was no way of providing the indexes on import. This change adds globalIndexes and localIndexes properties to the TableAttributes interface, so you can now provide indexes when calling Table.fromTableAttributes(). Fixes #6392 --- packages/@aws-cdk/aws-dynamodb/lib/table.ts | 34 ++++++++--- .../aws-dynamodb/test/dynamodb.test.ts | 57 +++++++++++++++++++ 2 files changed, 84 insertions(+), 7 deletions(-) diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index f63ff13a25cf4..1c1802f039153 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -412,7 +412,7 @@ export interface ITable extends IResource { export interface TableAttributes { /** * The ARN of the dynamodb table. - * One of this, or {@link tabeName}, is required. + * One of this, or {@link tableName}, is required. * * @default - no table arn */ @@ -420,7 +420,7 @@ export interface TableAttributes { /** * The table name of the dynamodb table. - * One of this, or {@link tabeArn}, is required. + * One of this, or {@link tableArn}, is required. * * @default - no table name */ @@ -439,6 +439,28 @@ export interface TableAttributes { * @default - no key */ readonly encryptionKey?: kms.IKey; + + /** + * The name of the global indexes set for this Table. + * Note that you need to set either this property, + * or {@link localIndexes}, + * if you want methods like grantReadData() + * to grant permissions for indexes as well as the table itself. + * + * @default - no global indexes + */ + readonly globalIndexes?: string[]; + + /** + * The name of the local indexes set for this Table. + * Note that you need to set either this property, + * or {@link globalIndexes}, + * if you want methods like grantReadData() + * to grant permissions for indexes as well as the table itself. + * + * @default - no local indexes + */ + readonly localIndexes?: string[]; } abstract class TableBase extends Resource implements ITable { @@ -682,7 +704,7 @@ abstract class TableBase extends Resource implements ITable { private combinedGrant( grantee: iam.IGrantable, opts: {keyActions?: string[], tableActions?: string[], streamActions?: string[]}, - ) { + ): iam.Grant { if (opts.tableActions) { const resources = [this.tableArn, Lazy.stringValue({ produce: () => this.hasIndex ? `${this.tableArn}/index/*` : Aws.NO_VALUE }), @@ -773,6 +795,8 @@ export class Table extends TableBase { public readonly tableArn: string; public readonly tableStreamArn?: string; public readonly encryptionKey?: kms.IKey; + protected readonly hasIndex = (attrs.globalIndexes ?? []).length > 0 || + (attrs.localIndexes ?? []).length > 0; constructor(_tableArn: string, tableName: string, tableStreamArn?: string) { super(scope, id); @@ -781,10 +805,6 @@ export class Table extends TableBase { this.tableStreamArn = tableStreamArn; this.encryptionKey = attrs.encryptionKey; } - - protected get hasIndex(): boolean { - return false; - } } let name: string; diff --git a/packages/@aws-cdk/aws-dynamodb/test/dynamodb.test.ts b/packages/@aws-cdk/aws-dynamodb/test/dynamodb.test.ts index 068cfaf5b0edb..c0c0fe9633ac0 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/dynamodb.test.ts +++ b/packages/@aws-cdk/aws-dynamodb/test/dynamodb.test.ts @@ -2182,6 +2182,63 @@ describe('import', () => { Roles: [stack.resolve(role.roleName)], }); }); + + test('creates the correct index grant if indexes have been provided when importing', () => { + const stack = new Stack(); + + const table = Table.fromTableAttributes(stack, 'ImportedTable', { + tableName: 'MyTableName', + globalIndexes: ['global'], + localIndexes: ['local'], + }); + + const role = new iam.Role(stack, 'Role', { + assumedBy: new iam.AnyPrincipal(), + }); + + table.grantReadData(role); + + expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ + 'dynamodb:BatchGetItem', + 'dynamodb:GetRecords', + 'dynamodb:GetShardIterator', + 'dynamodb:Query', + 'dynamodb:GetItem', + 'dynamodb:Scan', + ], + Resource: [ + { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':dynamodb:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':table/MyTableName', + ]], + }, + { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':dynamodb:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':table/MyTableName/index/*', + ]], + }, + ], + }, + ], + }, + }); + }); }); });