From ff82f59d4186bcc006f0c35bac5ef8755a9e1040 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Mon, 29 Apr 2019 15:03:59 +0200 Subject: [PATCH] fix(lambda): allow grantInvoke with principals Fixes 'Cannot use tokens in construct ID' when calling grantInvoke with a service or account principal. Error with a service: Cannot use tokens in construct ID: Invoke{"Service":["${Token[TOKEN.139]}"]} Error with an account: Cannot use tokens in construct ID: Invoke{"AWS":["${Token[TOKEN.813]}"]} --- .../@aws-cdk/aws-lambda/lib/function-base.ts | 2 +- .../@aws-cdk/aws-lambda/test/test.lambda.ts | 56 +++++++++++++++++++ 2 files changed, 57 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 8a1f9e004c9fe..5323614538ee6 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -228,7 +228,7 @@ export abstract class FunctionBase extends Resource implements IFunction { resource: { addToResourcePolicy: (_statement) => { // Couldn't add permissions to the principal, so add them locally. - const identifier = 'Invoke' + JSON.stringify(grantee!.grantPrincipal.policyFragment.principalJson); + const identifier = `Invoke${grantee.grantPrincipal}`; // calls the .toString() of the princpal this.addPermission(identifier, { principal: grantee.grantPrincipal!, action: 'lambda:InvokeFunction', diff --git a/packages/@aws-cdk/aws-lambda/test/test.lambda.ts b/packages/@aws-cdk/aws-lambda/test/test.lambda.ts index d717376462991..dca4bb34d5d09 100644 --- a/packages/@aws-cdk/aws-lambda/test/test.lambda.ts +++ b/packages/@aws-cdk/aws-lambda/test/test.lambda.ts @@ -1020,6 +1020,62 @@ export = { test.done(); }, + 'grantInvoke with a service principal'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const fn = new lambda.Function(stack, 'Function', { + code: lambda.Code.inline('xxx'), + handler: 'index.handler', + runtime: lambda.Runtime.NodeJS810, + }); + const service = new iam.ServicePrincipal('apigateway.amazonaws.com'); + + // WHEN + fn.grantInvoke(service); + + // THEN + expect(stack).to(haveResource('AWS::Lambda::Permission', { + Action: 'lambda:InvokeFunction', + FunctionName: { + 'Fn::GetAtt': [ + 'Function76856677', + 'Arn' + ] + }, + Principal: 'apigateway.amazonaws.com' + })); + + test.done(); + }, + + 'grantInvoke with an account principal'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const fn = new lambda.Function(stack, 'Function', { + code: lambda.Code.inline('xxx'), + handler: 'index.handler', + runtime: lambda.Runtime.NodeJS810, + }); + const account = new iam.AccountPrincipal('123456789012'); + + // WHEN + fn.grantInvoke(account); + + // THEN + expect(stack).to(haveResource('AWS::Lambda::Permission', { + Action: 'lambda:InvokeFunction', + FunctionName: { + 'Fn::GetAtt': [ + 'Function76856677', + 'Arn' + ] + }, + Principal: '123456789012' + })); + + test.done(); + }, + 'Can use metricErrors on a lambda Function'(test: Test) { // GIVEN const stack = new cdk.Stack();