From b4e264c024bc58053412be1343bed6458628f7cb Mon Sep 17 00:00:00 2001 From: Niranjan Jayakar Date: Mon, 1 Jun 2020 12:52:48 +0100 Subject: [PATCH 1/2] fix(lambda): `SingletonFunction.grantInvoke()` API fails with error 'No child with id' (#8296) Updates to the Grant API[1] introduced the need to return the statement that was added as a result of the grant operation. A corresponding change[2] was applied to lambda module's `FunctionBase` class with the intention to apply this across all constructs that are variants of `Function`. However, the `SingletonFunction` construct behaves differently in how it modifies the construct tree. Specifically, it contains no child node but instead manipulates a node that is a direct child of the `Stack` node. For this reason, `this.node.findChild()` API does not return the expected underlying node. The fix here is to allow such special inheritors of `FunctionBase` to override where the child node is to be found, via an internal method called `_functionNode()`. fixes #8240 [1]: https://github.com/aws/aws-cdk/commit/1819a6b5920bb22a60d09de870ea625455b90395 [2]: https://github.com/aws/aws-cdk/commit/1819a6b5920bb22a60d09de870ea625455b90395#diff-73cb0d8933b87960893373bd263924e2 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-lambda/lib/function-base.ts | 11 +++++++- .../aws-lambda/lib/singleton-lambda.ts | 8 ++++++ .../aws-lambda/test/test.singleton-lambda.ts | 28 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index 65a6fe6c05c26..b9a2e6b4ef166 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -284,7 +284,7 @@ export abstract class FunctionBase extends Resource implements IFunction { action: 'lambda:InvokeFunction', }); - return { statementAdded: true, policyDependable: this.node.findChild(identifier) } as iam.AddToResourcePolicyResult; + return { statementAdded: true, policyDependable: this._functionNode().findChild(identifier) } as iam.AddToResourcePolicyResult; }, node: this.node, }, @@ -318,6 +318,15 @@ export abstract class FunctionBase extends Resource implements IFunction { }); } + /** + * Returns the construct tree node that corresponds to the lambda function. + * For use internally for constructs, when the tree is set up in non-standard ways. Ex: SingletonFunction. + * @internal + */ + protected _functionNode(): ConstructNode { + return this.node; + } + private parsePermissionPrincipal(principal?: iam.IPrincipal) { if (!principal) { return undefined; diff --git a/packages/@aws-cdk/aws-lambda/lib/singleton-lambda.ts b/packages/@aws-cdk/aws-lambda/lib/singleton-lambda.ts index d9bf1f97372a0..f8515dc84e841 100644 --- a/packages/@aws-cdk/aws-lambda/lib/singleton-lambda.ts +++ b/packages/@aws-cdk/aws-lambda/lib/singleton-lambda.ts @@ -81,6 +81,14 @@ export class SingletonFunction extends FunctionBase { down.node.addDependency(this.lambdaFunction); } + /** + * Returns the construct tree node that corresponds to the lambda function. + * @internal + */ + protected _functionNode(): cdk.ConstructNode { + return this.lambdaFunction.node; + } + private ensureLambda(props: SingletonFunctionProps): IFunction { const constructName = (props.lambdaPurpose || 'SingletonLambda') + slugify(props.uuid); const existing = cdk.Stack.of(this).node.tryFindChild(constructName); diff --git a/packages/@aws-cdk/aws-lambda/test/test.singleton-lambda.ts b/packages/@aws-cdk/aws-lambda/test/test.singleton-lambda.ts index 5f815d8f5e237..05512ec54b2f0 100644 --- a/packages/@aws-cdk/aws-lambda/test/test.singleton-lambda.ts +++ b/packages/@aws-cdk/aws-lambda/test/test.singleton-lambda.ts @@ -113,4 +113,32 @@ export = { test.done(); }, + + 'grantInvoke works correctly'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const singleton = new lambda.SingletonFunction(stack, 'Singleton', { + uuid: '84c0de93-353f-4217-9b0b-45b6c993251a', + code: new lambda.InlineCode('def hello(): pass'), + runtime: lambda.Runtime.PYTHON_2_7, + handler: 'index.hello', + }); + + // WHEN + const invokeResult = singleton.grantInvoke(new iam.ServicePrincipal('events.amazonaws.com')); + const statement = stack.resolve(invokeResult.resourceStatement); + + // THEN + expect(stack).to(haveResource('AWS::Lambda::Permission', { + Action: 'lambda:InvokeFunction', + Principal: 'events.amazonaws.com', + })); + test.deepEqual(statement.action, [ 'lambda:InvokeFunction' ]); + test.deepEqual(statement.principal, { Service: [ 'events.amazonaws.com' ] }); + test.deepEqual(statement.effect, 'Allow'); + test.deepEqual(statement.resource, [{ + 'Fn::GetAtt': [ 'SingletonLambda84c0de93353f42179b0b45b6c993251a840BCC38', 'Arn' ], + }]); + test.done(); + }, }; From 6a6324dd9bee8013dbdd2b770636359196b81023 Mon Sep 17 00:00:00 2001 From: Niranjan Jayakar Date: Mon, 1 Jun 2020 14:15:00 +0100 Subject: [PATCH 2/2] chore(release): 1.42.1 --- CHANGELOG.md | 7 +++++++ lerna.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d060fb6f61a28..9e4e7fd080d53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [1.42.1](https://github.com/aws/aws-cdk/compare/v1.42.0...v1.42.1) (2020-06-01) + + +### Bug Fixes + +* **lambda:** `SingletonFunction.grantInvoke()` API fails with error 'No child with id' ([#8296](https://github.com/aws/aws-cdk/issues/8296)) ([b4e264c](https://github.com/aws/aws-cdk/commit/b4e264c024bc58053412be1343bed6458628f7cb)), closes [#8240](https://github.com/aws/aws-cdk/issues/8240) + ## [1.42.0](https://github.com/aws/aws-cdk/compare/v1.41.0...v1.42.0) (2020-05-27) diff --git a/lerna.json b/lerna.json index b533a6ac4d33c..ed6fe98880477 100644 --- a/lerna.json +++ b/lerna.json @@ -10,5 +10,5 @@ "tools/*" ], "rejectCycles": "true", - "version": "1.42.0" + "version": "1.42.1" }