Skip to content

Commit

Permalink
fix(dynamodb): prevent "StreamARN not found for resource" errors (aws…
Browse files Browse the repository at this point in the history
…#3935)

* do not allowing adding table as stream source if streams were not enabled at create time

* make StreamArn undefinable and move error check to DynamoDB table

* add check back

* test fix

* another test fix :)

* allow this breaking change

* breaking change fix
  • Loading branch information
parisholley authored and mergify[bot] committed Sep 8, 2019
1 parent 5da6b36 commit 617ef82
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 2 deletions.
1 change: 1 addition & 0 deletions allowed-breaking-changes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ removed:@aws-cdk/aws-apigateway.MockIntegration.props
incompatible-argument:@aws-cdk/aws-lambda.Function.<initializer>
incompatible-argument:@aws-cdk/aws-lambda.SingletonFunction.<initializer>
incompatible-argument:@aws-cdk/aws-lambda.Function.addEnvironment
changed-type:@aws-cdk/aws-dynamodb.Table.tableStreamArn
8 changes: 6 additions & 2 deletions packages/@aws-cdk/aws-dynamodb/lib/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ export class Table extends Resource {
/**
* @attribute
*/
public readonly tableStreamArn: string;
public readonly tableStreamArn: string | undefined;

private readonly table: CfnTable;

Expand Down Expand Up @@ -266,7 +266,7 @@ export class Table extends Resource {
});
this.tableName = this.getResourceNameAttribute(this.table.ref);

this.tableStreamArn = this.table.attrStreamArn;
this.tableStreamArn = props.stream ? this.table.attrStreamArn : undefined;

this.scalingRole = this.makeScalingRole();

Expand Down Expand Up @@ -452,6 +452,10 @@ export class Table extends Resource {
* @param actions The set of actions to allow (i.e. "dynamodb:DescribeStream", "dynamodb:GetRecords", ...)
*/
public grantStream(grantee: iam.IGrantable, ...actions: string[]) {
if (!this.tableStreamArn) {
throw new Error(`DynamoDB Streams must be enabled on the table ${this.node.path}`);
}

return iam.Grant.addToPrincipal({
grantee,
actions,
Expand Down
17 changes: 17 additions & 0 deletions packages/@aws-cdk/aws-dynamodb/test/test.dynamodb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1184,6 +1184,23 @@ export = {
test.done();
},

'"grantStreamRead" should fail if streaming is not enabled on table"'(test: Test) {
// GIVEN
const stack = new Stack();
const table = new Table(stack, 'my-table', {
partitionKey: {
name: 'id',
type: AttributeType.STRING
}
});
const user = new iam.User(stack, 'user');

// WHEN
test.throws(() => table.grantStreamRead(user), /DynamoDB Streams must be enabled on the table my-table/);

test.done();
},

'"grantStreamRead" allows principal to read and describe the table stream"'(test: Test) {
// GIVEN
const stack = new Stack();
Expand Down
4 changes: 4 additions & 0 deletions packages/@aws-cdk/aws-lambda-event-sources/lib/dynamodb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export class DynamoEventSource implements lambda.IEventSource {
}

public bind(target: lambda.IFunction) {
if (!this.table.tableStreamArn) {
throw new Error(`DynamoDB Streams must be enabled on the table ${this.table.node.path}`);
}

target.addEventSourceMapping(`DynamoDBEventSource:${this.table.node.uniqueId}`, {
batchSize: this.props.batchSize || 100,
eventSourceArn: this.table.tableStreamArn,
Expand Down
20 changes: 20 additions & 0 deletions packages/@aws-cdk/aws-lambda-event-sources/test/test.dynamo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,26 @@ export = {
test.done();
},

'fails if streaming not enabled on table'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
const fn = new TestFunction(stack, 'Fn');
const table = new dynamodb.Table(stack, 'T', {
partitionKey: {
name: 'id',
type: dynamodb.AttributeType.STRING
}
});

// WHEN
test.throws(() => fn.addEventSource(new sources.DynamoEventSource(table, {
batchSize: 50,
startingPosition: lambda.StartingPosition.LATEST
})), /DynamoDB Streams must be enabled on the table T/);

test.done();
},

'fails if batch size < 1'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
Expand Down

0 comments on commit 617ef82

Please sign in to comment.