From a116edb01936f18c980dda6e3e69c1654c624b91 Mon Sep 17 00:00:00 2001 From: Niranjan Jayakar Date: Mon, 2 Sep 2019 15:58:55 +0100 Subject: [PATCH] fix(apigateway): cross-stack lambda integration fails token resolution and/or creates cyclic references 1. Token resolution of Deployment construct must not resolve the entire stack, specifically during the prepare phase. stack.resolve() works only after the CDK app has been fully prepared. During the 'prepare' phase, token resolution should instead resolve the token partially and within the local context. 2. Scope the lambda.CfnPermission construct closer to the consumer of the permission rather than being closer to the lambda function. For instance, when a lambda function is being consumed by an APIGateway RestApi Method as a cross-stack reference, placing the lambda.CfnPermission construct closer to the RestApi Method reduces the possibility of cyclic dependencies. fixes #3705, #3000 --- .../@aws-cdk/aws-apigateway/lib/deployment.ts | 13 +- .../aws-apigateway/lib/integrations/lambda.ts | 4 +- .../test/integ.restapi.books.expected.json | 24 +- .../test/integ.restapi.expected.json | 16 +- .../integ.restapi.multistack.expected.json | 241 ++++++ .../test/integ.restapi.multistack.ts | 48 ++ .../test/integ.restapi.multiuse.expected.json | 16 +- .../@aws-cdk/aws-lambda/lib/function-base.ts | 13 +- .../@aws-cdk/aws-lambda/lib/permission.ts | 11 + ...nteg.api-gateway-domain-name.expected.json | 12 +- packages/@aws-cdk/core/lib/token.ts | 11 +- packages/decdk/package.json | 2 +- .../test/__snapshots__/synth.test.js.snap | 728 +++++++++--------- 13 files changed, 731 insertions(+), 408 deletions(-) create mode 100644 packages/@aws-cdk/aws-apigateway/test/integ.restapi.multistack.expected.json create mode 100644 packages/@aws-cdk/aws-apigateway/test/integ.restapi.multistack.ts diff --git a/packages/@aws-cdk/aws-apigateway/lib/deployment.ts b/packages/@aws-cdk/aws-apigateway/lib/deployment.ts index 6de9f7d71cfec..9a827f6038fc0 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/deployment.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/deployment.ts @@ -1,4 +1,4 @@ -import { Construct, Lazy, RemovalPolicy, Resource, Stack } from '@aws-cdk/core'; +import { Construct, DefaultTokenResolver, Lazy, RemovalPolicy, Resource, Stack, StringConcat, Tokenization } from '@aws-cdk/core'; import crypto = require('crypto'); import { CfnDeployment, CfnDeploymentProps } from './apigateway.generated'; import { IRestApi } from './restapi'; @@ -121,19 +121,22 @@ class LatestDeploymentResource extends CfnDeployment { * add via `addToLogicalId`. */ protected prepare() { - const stack = Stack.of(this); - // if hash components were added to the deployment, we use them to calculate // a logical ID for the deployment resource. if (this.hashComponents.length > 0) { const md5 = crypto.createHash('md5'); this.hashComponents - .map(c => stack.resolve(c)) + .map(c => { + return Tokenization.resolve(c, { + scope: this, + resolver: new DefaultTokenResolver(new StringConcat()), + preparing: true, + }); + }) .forEach(c => md5.update(JSON.stringify(c))); this.overrideLogicalId(this.originalLogicalId + md5.digest("hex")); } - super.prepare(); } } diff --git a/packages/@aws-cdk/aws-apigateway/lib/integrations/lambda.ts b/packages/@aws-cdk/aws-apigateway/lib/integrations/lambda.ts index 1aab6b38bedac..4e4cc618f7b43 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/integrations/lambda.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/integrations/lambda.ts @@ -59,6 +59,7 @@ export class LambdaIntegration extends AwsIntegration { this.handler.addPermission(`ApiPermission.${desc}`, { principal, + scope: method, sourceArn: method.methodArn, }); @@ -66,7 +67,8 @@ export class LambdaIntegration extends AwsIntegration { if (this.enableTest) { this.handler.addPermission(`ApiPermission.Test.${desc}`, { principal, - sourceArn: method.testMethodArn + scope: method, + sourceArn: method.testMethodArn, }); } } diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.books.expected.json b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.books.expected.json index 30a9f8c4a180c..ea0156dfca4fa 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.books.expected.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.books.expected.json @@ -50,7 +50,7 @@ "BooksHandlerServiceRole5B6A8847" ] }, - "BooksHandlerApiPermissionrestapibooksexamplebooksapi4538F335GETbooks727D645E": { + "booksapibooksGETApiPermissionrestapibooksexamplebooksapi4538F335GETbooks391776D8": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -91,7 +91,7 @@ } } }, - "BooksHandlerApiPermissionTestrestapibooksexamplebooksapi4538F335GETbooksCC375808": { + "booksapibooksGETApiPermissionTestrestapibooksexamplebooksapi4538F335GETbooks01FB3D1B": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -128,7 +128,7 @@ } } }, - "BooksHandlerApiPermissionrestapibooksexamplebooksapi4538F335POSTbooksFDED8A87": { + "booksapibooksPOSTApiPermissionrestapibooksexamplebooksapi4538F335POSTbooksDFEC643F": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -169,7 +169,7 @@ } } }, - "BooksHandlerApiPermissionTestrestapibooksexamplebooksapi4538F335POSTbooks4667899F": { + "booksapibooksPOSTApiPermissionTestrestapibooksexamplebooksapi4538F335POSTbooks1C6D24C8": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -256,7 +256,7 @@ "BookHandlerServiceRole894768AD" ] }, - "BookHandlerApiPermissionrestapibooksexamplebooksapi4538F335GETbooksbookidA10D3CE2": { + "booksapibooksbookidGETApiPermissionrestapibooksexamplebooksapi4538F335GETbooksbookidBB91DFBD": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -297,7 +297,7 @@ } } }, - "BookHandlerApiPermissionTestrestapibooksexamplebooksapi4538F335GETbooksbookidAB5191B6": { + "booksapibooksbookidGETApiPermissionTestrestapibooksexamplebooksapi4538F335GETbooksbookidA0230B08": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -334,7 +334,7 @@ } } }, - "BookHandlerApiPermissionrestapibooksexamplebooksapi4538F335DELETEbooksbookidB3A85313": { + "booksapibooksbookidDELETEApiPermissionrestapibooksexamplebooksapi4538F335DELETEbooksbookid76C1C947": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -375,7 +375,7 @@ } } }, - "BookHandlerApiPermissionTestrestapibooksexamplebooksapi4538F335DELETEbooksbookid9308C830": { + "booksapibooksbookidDELETEApiPermissionTestrestapibooksexamplebooksapi4538F335DELETEbooksbookid09D6CB8A": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -462,7 +462,7 @@ "HelloServiceRole1E55EA16" ] }, - "HelloApiPermissionrestapibooksexamplebooksapi4538F335ANYE385693C": { + "booksapiANYApiPermissionrestapibooksexamplebooksapi4538F335ANY73B3CDDC": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -503,7 +503,7 @@ } } }, - "HelloApiPermissionTestrestapibooksexamplebooksapi4538F335ANY46B0DA7B": { + "booksapiANYApiPermissionTestrestapibooksexamplebooksapi4538F335ANYB0D7D8AC": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -546,7 +546,7 @@ "Name": "books-api" } }, - "booksapiDeployment308B08F1c828b08824c062376eba921738884f85": { + "booksapiDeployment308B08F1038c4647da4cb72c7574b891fb62b77f": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { @@ -571,7 +571,7 @@ "Ref": "booksapiE1885304" }, "DeploymentId": { - "Ref": "booksapiDeployment308B08F1c828b08824c062376eba921738884f85" + "Ref": "booksapiDeployment308B08F1038c4647da4cb72c7574b891fb62b77f" }, "StageName": "prod" } diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.expected.json b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.expected.json index d8781b60a8f8c..8f78dec8c5d43 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.expected.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.expected.json @@ -6,7 +6,7 @@ "Name": "my-api" } }, - "myapiDeployment92F2CB4919460d935da8177bcfbc418506e514ff": { + "myapiDeployment92F2CB49a38a6824a90d7d4e6cc3a7f11357e163": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { @@ -38,7 +38,7 @@ "CacheClusterEnabled": true, "CacheClusterSize": "0.5", "DeploymentId": { - "Ref": "myapiDeployment92F2CB4919460d935da8177bcfbc418506e514ff" + "Ref": "myapiDeployment92F2CB49a38a6824a90d7d4e6cc3a7f11357e163" }, "Description": "beta stage", "MethodSettings": [ @@ -430,7 +430,7 @@ "MyHandlerServiceRoleFFA06653" ] }, - "MyHandlerApiPermissiontestapigatewayrestapimyapi1AE401C4GETv1toys00F704BC": { + "myapiv1toysGETApiPermissiontestapigatewayrestapimyapi1AE401C4GETv1toysA829D1CC": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -471,7 +471,7 @@ } } }, - "MyHandlerApiPermissionTesttestapigatewayrestapimyapi1AE401C4GETv1toysDBCC8082": { + "myapiv1toysGETApiPermissionTesttestapigatewayrestapimyapi1AE401C4GETv1toys9E0BAE9F": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -508,7 +508,7 @@ } } }, - "MyHandlerApiPermissiontestapigatewayrestapimyapi1AE401C4GETv1books96EB3DB8": { + "myapiv1booksGETApiPermissiontestapigatewayrestapimyapi1AE401C4GETv1books484ACD3F": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -549,7 +549,7 @@ } } }, - "MyHandlerApiPermissionTesttestapigatewayrestapimyapi1AE401C4GETv1books906B3BB6": { + "myapiv1booksGETApiPermissionTesttestapigatewayrestapimyapi1AE401C4GETv1booksE255E31A": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -586,7 +586,7 @@ } } }, - "MyHandlerApiPermissiontestapigatewayrestapimyapi1AE401C4POSTv1booksA48C273B": { + "myapiv1booksPOSTApiPermissiontestapigatewayrestapimyapi1AE401C4POSTv1books2B1BC62B": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -627,7 +627,7 @@ } } }, - "MyHandlerApiPermissionTesttestapigatewayrestapimyapi1AE401C4POSTv1booksA566985D": { + "myapiv1booksPOSTApiPermissionTesttestapigatewayrestapimyapi1AE401C4POSTv1books816A6B37": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.multistack.expected.json b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.multistack.expected.json new file mode 100644 index 0000000000000..a88c397812638 --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.multistack.expected.json @@ -0,0 +1,241 @@ +[ + { + "Outputs": { + "ExportsOutputFnGetAttfirstLambda395F9ADEArn1A9B3BC3": { + "Export": { "Name": "FirstStack:ExportsOutputFnGetAttfirstLambda395F9ADEArn1A9B3BC3" }, + "Value": { + "Fn::GetAtt": [ "firstLambda395F9ADE", "Arn" ] + } + } + }, + "Resources": { + "firstLambda395F9ADE": { + "DependsOn": [ "firstLambdaServiceRoleB6408C31" ], + "Properties": { + "Code": { + "ZipFile": "exports.handler = async function(event) {\n return {\n 'headers': { 'Content-Type': 'text/plain' },\n 'statusCode': 200\n }\n }" + }, + "FunctionName": "FirstLambda", + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "firstLambdaServiceRoleB6408C31", + "Arn" + ] + }, + "Runtime": "nodejs8.10" + }, + "Type": "AWS::Lambda::Function" + }, + "firstLambdaServiceRoleB6408C31": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { "Service": "lambda.amazonaws.com" } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { "Ref": "AWS::Partition" }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +}, + { + "Resources": { + "BooksApi60AC975F": { + "Type":"AWS::ApiGateway::RestApi", + "Properties": { "Name":"SecondRestAPI" } + }, + "BooksApiDeployment86CA39AF794fe41ee968b295eca9a15ee72a4a7c": { + "Type":"AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { "Ref": "BooksApi60AC975F" }, + "Description": "Automatically created by the RestApi construct" }, + "DependsOn": [ + "BooksApiANY0C4EABE3", + "BooksApibooksGET6066BF7E", + "BooksApibooks1F745538" + ] + }, + "BooksApiDeploymentStageprod0693B760": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "RestApiId": { "Ref": "BooksApi60AC975F" }, + "DeploymentId": { "Ref": "BooksApiDeployment86CA39AF794fe41ee968b295eca9a15ee72a4a7c" }, + "StageName": "prod" + } + }, + "BooksApiCloudWatchRoleB120ADBA": { + "Type":"AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument":{ + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": {"Service":"apigateway.amazonaws.com"} + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { "Ref": "AWS::Partition" }, + ":iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs" + ] + ] + } + ] + } + }, + "BooksApiAccount9C44AF8E": { + "Type": "AWS::ApiGateway::Account", + "Properties": { + "CloudWatchRoleArn": { + "Fn::GetAtt": [ "BooksApiCloudWatchRoleB120ADBA", "Arn" ] + } + }, + "DependsOn":[ "BooksApi60AC975F" ] + }, + "BooksApiANY0C4EABE3": { + "Type": "AWS::ApiGateway::Method", + "Properties": { + "HttpMethod": "ANY", + "ResourceId": { + "Fn::GetAtt": [ "BooksApi60AC975F","RootResourceId" ] + }, + "RestApiId": { "Ref":"BooksApi60AC975F" }, + "AuthorizationType": "NONE", + "Integration": { "Type": "MOCK" } + } + }, + "BooksApibooks1F745538": { + "Type": "AWS::ApiGateway::Resource", + "Properties": { + "ParentId": { + "Fn::GetAtt":[ "BooksApi60AC975F", "RootResourceId" ] + }, + "PathPart": "books", + "RestApiId": { "Ref": "BooksApi60AC975F" } + } + }, + "BooksApibooksGET6066BF7E": { + "Type": "AWS::ApiGateway::Method", + "Properties": { + "HttpMethod": "GET", + "ResourceId": { "Ref": "BooksApibooks1F745538" }, + "RestApiId": { "Ref": "BooksApi60AC975F" }, + "AuthorizationType": "NONE", + "Integration": { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": { + "Fn::Join": [ + "", + [ + "arn:", + { "Ref":"AWS::Partition" }, + ":apigateway:", + { "Ref": "AWS::Region" }, + ":lambda:path/2015-03-31/functions/", + { "Fn::ImportValue": "FirstStack:ExportsOutputFnGetAttfirstLambda395F9ADEArn1A9B3BC3" }, + "/invocations" + ] + ] + } + } + } + }, + "BooksApibooksGETApiPermissionSecondStackBooksApi2660DEC5GETbooksE54B6E9B": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { "Fn::ImportValue": "FirstStack:ExportsOutputFnGetAttfirstLambda395F9ADEArn1A9B3BC3" }, + "Principal":"apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { "Ref": "AWS::Partition" }, + ":execute-api:", + { "Ref": "AWS::Region" }, + ":", + { "Ref": "AWS::AccountId" }, + ":", + { "Ref": "BooksApi60AC975F" }, + "/", + { "Ref": "BooksApiDeploymentStageprod0693B760" }, + "/GET/books" + ] + ] + } + } + }, + "BooksApibooksGETApiPermissionTestSecondStackBooksApi2660DEC5GETbooks0B7ED39D": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { "Fn::ImportValue": "FirstStack:ExportsOutputFnGetAttfirstLambda395F9ADEArn1A9B3BC3" }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { "Ref": "AWS::Partition" }, + ":execute-api:", + { "Ref": "AWS::Region" }, + ":", + { "Ref": "AWS::AccountId" }, + ":", + { "Ref": "BooksApi60AC975F" }, + "/test-invoke-stage/GET/books" + ] + ] + } + } + } + }, + "Outputs": { + "BooksApiEndpointF2AA70A2": { + "Value": { + "Fn::Join": [ + "", + [ + "https://", + { "Ref": "BooksApi60AC975F" }, + ".execute-api.", + { "Ref": "AWS::Region" }, + ".", + { "Ref": "AWS::URLSuffix" }, + "/", + { "Ref": "BooksApiDeploymentStageprod0693B760" }, + "/" + ] + ] + } + } + } + } +] \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.multistack.ts b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.multistack.ts new file mode 100644 index 0000000000000..27b46f4c21604 --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.multistack.ts @@ -0,0 +1,48 @@ +/// !cdk-integ * + +import lambda = require('@aws-cdk/aws-lambda'); +import cdk = require('@aws-cdk/core'); +import apig = require('../lib'); + +class FirstStack extends cdk.Stack { + public readonly firstLambda: lambda.Function; + + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + this.firstLambda = new lambda.Function(this, 'firstLambda', { + functionName: 'FirstLambda', + code: lambda.Code.fromInline(`exports.handler = async function(event) { + return { + 'headers': { 'Content-Type': 'text/plain' }, + 'statusCode': 200 + } + }`), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_8_10, + }); + } +} + +interface SecondStackProps extends cdk.StackProps { + readonly lambda: lambda.Function; +} + +class SecondStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props: SecondStackProps) { + super(scope, id, props); + + const api = new apig.RestApi(this, 'BooksApi', { + restApiName: 'SecondRestAPI' + }); + api.root.addMethod('ANY'); + const booksApi = api.root.addResource('books'); + const lambdaIntegration = new apig.LambdaIntegration(props.lambda); + booksApi.addMethod('GET', lambdaIntegration); + } +} + +const app = new cdk.App(); +const first = new FirstStack(app, 'FirstStack'); +new SecondStack(app, 'SecondStack', { lambda: first.firstLambda }); +app.synth(); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.multiuse.expected.json b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.multiuse.expected.json index 74179f434ccde..2a9857028ed40 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.multiuse.expected.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.multiuse.expected.json @@ -50,7 +50,7 @@ "HelloServiceRole1E55EA16" ] }, - "HelloApiPermissionrestapimultiuseexamplehelloapi9FD0148DGEThello305E0522": { + "helloapihelloGETApiPermissionrestapimultiuseexamplehelloapi9FD0148DGEThello2FD34BC2": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -91,7 +91,7 @@ } } }, - "HelloApiPermissionTestrestapimultiuseexamplehelloapi9FD0148DGEThello8476E396": { + "helloapihelloGETApiPermissionTestrestapimultiuseexamplehelloapi9FD0148DGEThelloA58B2FAE": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -128,7 +128,7 @@ } } }, - "HelloApiPermissionrestapimultiuseexamplesecondapi5CB05B89GEThello268B558F": { + "secondapihelloGETApiPermissionrestapimultiuseexamplesecondapi5CB05B89GEThello2D6C1879": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -169,7 +169,7 @@ } } }, - "HelloApiPermissionTestrestapimultiuseexamplesecondapi5CB05B89GEThelloFF28C5F8": { + "secondapihelloGETApiPermissionTestrestapimultiuseexamplesecondapi5CB05B89GEThelloB0B3B749": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -212,7 +212,7 @@ "Name": "hello-api" } }, - "helloapiDeploymentFA89AEEC086c88c5044fbc117bd88fffcee53ab2": { + "helloapiDeploymentFA89AEEC331621072ce7985d6b7954c9edc6b823": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { @@ -232,7 +232,7 @@ "Ref": "helloapi4446A35B" }, "DeploymentId": { - "Ref": "helloapiDeploymentFA89AEEC086c88c5044fbc117bd88fffcee53ab2" + "Ref": "helloapiDeploymentFA89AEEC331621072ce7985d6b7954c9edc6b823" }, "StageName": "prod" } @@ -343,7 +343,7 @@ "Name": "second-api" } }, - "secondapiDeployment20F2C7001932445454ace403a6bfe89c1430ff70": { + "secondapiDeployment20F2C700049800d8702d4c66b5ee8e4a9eed7b35": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { @@ -363,7 +363,7 @@ "Ref": "secondapi730EF3C7" }, "DeploymentId": { - "Ref": "secondapiDeployment20F2C7001932445454ace403a6bfe89c1430ff70" + "Ref": "secondapiDeployment20F2C700049800d8702d4c66b5ee8e4a9eed7b35" }, "StageName": "prod" } diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index 984e9588efdc6..9d3f60f84603f 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -56,9 +56,14 @@ export interface IFunction extends IResource, ec2.IConnectable, iam.IGrantable { /** * Adds a permission to the Lambda resource policy. * @param id The id ƒor the permission construct + * @param permission The permission to grant to this Lambda function. @see Permission for details. + * @param scope An optional scope to which this permission should be attached. */ addPermission(id: string, permission: Permission): void; + /** + * Adds a statement to the IAM role assumed by the instance. + */ addToRolePolicy(statement: iam.PolicyStatement): void; /** @@ -178,6 +183,8 @@ export abstract class FunctionBase extends Resource implements IFunction { /** * Adds a permission to the Lambda resource policy. * @param id The id ƒor the permission construct + * @param permission The permission to grant to this Lambda function. @see Permission for details. + * @param scope An optional scope to which this permission should be attached. By default, this will be the function handler. */ public addPermission(id: string, permission: Permission) { if (!this.canCreatePermissions) { @@ -187,8 +194,9 @@ export abstract class FunctionBase extends Resource implements IFunction { const principal = this.parsePermissionPrincipal(permission.principal); const action = permission.action || 'lambda:InvokeFunction'; + const scope = permission.scope || this; - new CfnPermission(this, id, { + new CfnPermission(scope, id, { action, principal, functionName: this.functionArn, @@ -198,6 +206,9 @@ export abstract class FunctionBase extends Resource implements IFunction { }); } + /** + * Adds a statement to the IAM role assumed by the instance. + */ public addToRolePolicy(statement: iam.PolicyStatement) { if (!this.role) { return; diff --git a/packages/@aws-cdk/aws-lambda/lib/permission.ts b/packages/@aws-cdk/aws-lambda/lib/permission.ts index e2a3fcbee57d3..f06a6a7c58a9c 100644 --- a/packages/@aws-cdk/aws-lambda/lib/permission.ts +++ b/packages/@aws-cdk/aws-lambda/lib/permission.ts @@ -1,4 +1,5 @@ import iam = require('@aws-cdk/aws-iam'); +import { Construct } from '@aws-cdk/core'; /** * Represents a permission statement that can be added to a Lambda's resource policy @@ -36,6 +37,16 @@ export interface Permission { */ readonly principal: iam.IPrincipal; + /** + * The scope to which the permission constructs be attached. The default is + * the Lambda function construct itself, but this would need to be different + * in cases such as cross-stack references where the Permissions would need + * to sit closer to the consumer of this permission (i.e., the caller). + * + * @default The instance of lambda.IFunction + */ + readonly scope?: Construct; + /** * The AWS account ID (without hyphens) of the source owner. For example, if * you specify an S3 bucket in the SourceArn property, this value is the diff --git a/packages/@aws-cdk/aws-route53-targets/test/integ.api-gateway-domain-name.expected.json b/packages/@aws-cdk/aws-route53-targets/test/integ.api-gateway-domain-name.expected.json index c0b7ef3d6df98..305fe4aefc6e6 100644 --- a/packages/@aws-cdk/aws-route53-targets/test/integ.api-gateway-domain-name.expected.json +++ b/packages/@aws-cdk/aws-route53-targets/test/integ.api-gateway-domain-name.expected.json @@ -50,7 +50,7 @@ "HandlerServiceRoleFCDC14AE" ] }, - "HandlerApiPermissionawscdkapigwaliasintegapiF4DF08ACANY133739C8": { + "apiANYApiPermissionawscdkapigwaliasintegapiF4DF08ACANYBCED9DDA": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -91,7 +91,7 @@ } } }, - "HandlerApiPermissionTestawscdkapigwaliasintegapiF4DF08ACANY872335B7": { + "apiANYApiPermissionTestawscdkapigwaliasintegapiF4DF08ACANYC10548C8": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -128,7 +128,7 @@ } } }, - "HandlerApiPermissionawscdkapigwaliasintegapiF4DF08ACANYproxyD4D13682": { + "apiproxyANYApiPermissionawscdkapigwaliasintegapiF4DF08ACANYproxy80933581": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -169,7 +169,7 @@ } } }, - "HandlerApiPermissionTestawscdkapigwaliasintegapiF4DF08ACANYproxyFF16208A": { + "apiproxyANYApiPermissionTestawscdkapigwaliasintegapiF4DF08ACANYproxyCF8E3D8C": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -212,7 +212,7 @@ "Name": "api" } }, - "apiDeployment149F12949ab8cbc5717926c7a1a01815778330c4": { + "apiDeployment149F1294105e69daf383d35e4d5131c97d37f9f8": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { @@ -233,7 +233,7 @@ "Ref": "apiC8550315" }, "DeploymentId": { - "Ref": "apiDeployment149F12949ab8cbc5717926c7a1a01815778330c4" + "Ref": "apiDeployment149F1294105e69daf383d35e4d5131c97d37f9f8" }, "StageName": "prod" } diff --git a/packages/@aws-cdk/core/lib/token.ts b/packages/@aws-cdk/core/lib/token.ts index c57ace245b273..de52b29b8c98f 100644 --- a/packages/@aws-cdk/core/lib/token.ts +++ b/packages/@aws-cdk/core/lib/token.ts @@ -112,8 +112,9 @@ export class Tokenization { */ public static resolve(obj: any, options: ResolveOptions): any { return resolve(obj, { - ...options, - preparing: false + scope: options.scope, + resolver: options.resolver, + preparing: (options.preparing !== undefined ? options.preparing : false) }); } @@ -150,6 +151,12 @@ export interface ResolveOptions { * The resolver to apply to any resolvable tokens found */ readonly resolver: ITokenResolver; + + /** + * Whether the resolution is being executed during the prepare phase or not. + * @default false + */ + readonly preparing?: boolean; } /** diff --git a/packages/decdk/package.json b/packages/decdk/package.json index ea3bfc619b568..ef49b447eebf2 100644 --- a/packages/decdk/package.json +++ b/packages/decdk/package.json @@ -170,4 +170,4 @@ "engines": { "node": ">= 8.10.0" } -} +} \ No newline at end of file diff --git a/packages/decdk/test/__snapshots__/synth.test.js.snap b/packages/decdk/test/__snapshots__/synth.test.js.snap index 3f3370f18a219..53668cca3364e 100644 --- a/packages/decdk/test/__snapshots__/synth.test.js.snap +++ b/packages/decdk/test/__snapshots__/synth.test.js.snap @@ -88,61 +88,7 @@ Object { }, "Type": "AWS::ApiGateway::Method", }, - "HelloLambda3D9C82D6": Object { - "DependsOn": Array [ - "HelloLambdaServiceRoleE071F162", - ], - "Properties": Object { - "Code": Object { - "S3Bucket": Object { - "Ref": "HelloLambdaCodeS3BucketB83F7900", - }, - "S3Key": Object { - "Fn::Join": Array [ - "", - Array [ - Object { - "Fn::Select": Array [ - 0, - Object { - "Fn::Split": Array [ - "||", - Object { - "Ref": "HelloLambdaCodeS3VersionKey2936C385", - }, - ], - }, - ], - }, - Object { - "Fn::Select": Array [ - 1, - Object { - "Fn::Split": Array [ - "||", - Object { - "Ref": "HelloLambdaCodeS3VersionKey2936C385", - }, - ], - }, - ], - }, - ], - ], - }, - }, - "Handler": "index.handler", - "Role": Object { - "Fn::GetAtt": Array [ - "HelloLambdaServiceRoleE071F162", - "Arn", - ], - }, - "Runtime": "python3.6", - }, - "Type": "AWS::Lambda::Function", - }, - "HelloLambdaApiPermissionTestapigwMyApiCBFBC5B0ANYFEA3C9DF": Object { + "GetRootApiPermissionTestapigwMyApiCBFBC5B0GET5B244F0C": Object { "Properties": Object { "Action": "lambda:InvokeFunction", "FunctionName": Object { @@ -172,14 +118,14 @@ Object { Object { "Ref": "MyApi49610EDF", }, - "/test-invoke-stage/*/", + "/test-invoke-stage/GET/", ], ], }, }, "Type": "AWS::Lambda::Permission", }, - "HelloLambdaApiPermissionTestapigwMyApiCBFBC5B0ANYproxy6D2D9150": Object { + "GetRootApiPermissionapigwMyApiCBFBC5B0GETC314E626": Object { "Properties": Object { "Action": "lambda:InvokeFunction", "FunctionName": Object { @@ -209,92 +155,109 @@ Object { Object { "Ref": "MyApi49610EDF", }, - "/test-invoke-stage/*/{proxy+}", + "/", + Object { + "Ref": "MyApiDeploymentStageprodE1054AF0", + }, + "/GET/", ], ], }, }, "Type": "AWS::Lambda::Permission", }, - "HelloLambdaApiPermissionTestapigwMyApiCBFBC5B0GETAA79D33A": Object { + "HelloLambda3D9C82D6": Object { + "DependsOn": Array [ + "HelloLambdaServiceRoleE071F162", + ], "Properties": Object { - "Action": "lambda:InvokeFunction", - "FunctionName": Object { + "Code": Object { + "S3Bucket": Object { + "Ref": "HelloLambdaCodeS3BucketB83F7900", + }, + "S3Key": Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "HelloLambdaCodeS3VersionKey2936C385", + }, + ], + }, + ], + }, + Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "HelloLambdaCodeS3VersionKey2936C385", + }, + ], + }, + ], + }, + ], + ], + }, + }, + "Handler": "index.handler", + "Role": Object { "Fn::GetAtt": Array [ - "HelloLambda3D9C82D6", + "HelloLambdaServiceRoleE071F162", "Arn", ], }, - "Principal": "apigateway.amazonaws.com", - "SourceArn": Object { - "Fn::Join": Array [ - "", - Array [ - "arn:", - Object { - "Ref": "AWS::Partition", - }, - ":execute-api:", - Object { - "Ref": "AWS::Region", - }, - ":", - Object { - "Ref": "AWS::AccountId", - }, - ":", - Object { - "Ref": "MyApi49610EDF", - }, - "/test-invoke-stage/GET/", - ], - ], - }, + "Runtime": "python3.6", }, - "Type": "AWS::Lambda::Permission", + "Type": "AWS::Lambda::Function", }, - "HelloLambdaApiPermissionapigwMyApiCBFBC5B0ANYD4AEE60C": Object { + "HelloLambdaServiceRoleE071F162": Object { "Properties": Object { - "Action": "lambda:InvokeFunction", - "FunctionName": Object { - "Fn::GetAtt": Array [ - "HelloLambda3D9C82D6", - "Arn", - ], - }, - "Principal": "apigateway.amazonaws.com", - "SourceArn": Object { - "Fn::Join": Array [ - "", - Array [ - "arn:", - Object { - "Ref": "AWS::Partition", - }, - ":execute-api:", - Object { - "Ref": "AWS::Region", - }, - ":", - Object { - "Ref": "AWS::AccountId", - }, - ":", - Object { - "Ref": "MyApi49610EDF", - }, - "/", - Object { - "Ref": "MyApiDeploymentStageprodE1054AF0", + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", }, - "/*/", - ], + }, ], + "Version": "2012-10-17", }, + "ManagedPolicyArns": Array [ + Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], }, - "Type": "AWS::Lambda::Permission", + "Type": "AWS::IAM::Role", + }, + "MyApi49610EDF": Object { + "Properties": Object { + "Name": "MyApi", + }, + "Type": "AWS::ApiGateway::RestApi", }, - "HelloLambdaApiPermissionapigwMyApiCBFBC5B0ANYproxy31C1851A": Object { + "MyApiANYApiPermissionTestapigwMyApiCBFBC5B0ANYAD86D377": Object { "Properties": Object { "Action": "lambda:InvokeFunction", "FunctionName": Object { @@ -324,18 +287,14 @@ Object { Object { "Ref": "MyApi49610EDF", }, - "/", - Object { - "Ref": "MyApiDeploymentStageprodE1054AF0", - }, - "/*/{proxy+}", + "/test-invoke-stage/*/", ], ], }, }, "Type": "AWS::Lambda::Permission", }, - "HelloLambdaApiPermissionapigwMyApiCBFBC5B0GET03C31BDB": Object { + "MyApiANYApiPermissionapigwMyApiCBFBC5B0ANY5BBED348": Object { "Properties": Object { "Action": "lambda:InvokeFunction", "FunctionName": Object { @@ -369,50 +328,13 @@ Object { Object { "Ref": "MyApiDeploymentStageprodE1054AF0", }, - "/GET/", + "/*/", ], ], }, }, "Type": "AWS::Lambda::Permission", }, - "HelloLambdaServiceRoleE071F162": Object { - "Properties": Object { - "AssumeRolePolicyDocument": Object { - "Statement": Array [ - Object { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": Object { - "Service": "lambda.amazonaws.com", - }, - }, - ], - "Version": "2012-10-17", - }, - "ManagedPolicyArns": Array [ - Object { - "Fn::Join": Array [ - "", - Array [ - "arn:", - Object { - "Ref": "AWS::Partition", - }, - ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - ], - ], - }, - ], - }, - "Type": "AWS::IAM::Role", - }, - "MyApi49610EDF": Object { - "Properties": Object { - "Name": "MyApi", - }, - "Type": "AWS::ApiGateway::RestApi", - }, "MyApiANYEC3618D9": Object { "Properties": Object { "AuthorizationType": "NONE", @@ -501,7 +423,7 @@ Object { }, "Type": "AWS::IAM::Role", }, - "MyApiDeploymentECB0D05Ed646248a19f9620d956e9fa33de3ed89": Object { + "MyApiDeploymentECB0D05E2f18928c76b78fb3e3f06fb75c7e195c": Object { "DependsOn": Array [ "GetRootA9424890", "MyApiproxyANYFCF46C66", @@ -519,7 +441,7 @@ Object { "MyApiDeploymentStageprodE1054AF0": Object { "Properties": Object { "DeploymentId": Object { - "Ref": "MyApiDeploymentECB0D05Ed646248a19f9620d956e9fa33de3ed89", + "Ref": "MyApiDeploymentECB0D05E2f18928c76b78fb3e3f06fb75c7e195c", }, "RestApiId": Object { "Ref": "MyApi49610EDF", @@ -528,6 +450,84 @@ Object { }, "Type": "AWS::ApiGateway::Stage", }, + "MyApiproxyANYApiPermissionTestapigwMyApiCBFBC5B0ANYproxy6DC68FBB": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "HelloLambda3D9C82D6", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "MyApi49610EDF", + }, + "/test-invoke-stage/*/{proxy+}", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "MyApiproxyANYApiPermissionapigwMyApiCBFBC5B0ANYproxyB3375D73": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "HelloLambda3D9C82D6", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "MyApi49610EDF", + }, + "/", + Object { + "Ref": "MyApiDeploymentStageprodE1054AF0", + }, + "/*/{proxy+}", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, "MyApiproxyANYFCF46C66": Object { "Properties": Object { "AuthorizationType": "NONE", @@ -904,175 +904,44 @@ Object { "Fn::Join": Array [ "", Array [ - "https://", - Object { - "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F12449C5F", - }, - ".execute-api.", - Object { - "Ref": "AWS::Region", - }, - ".", - Object { - "Ref": "AWS::URLSuffix", - }, - "/", - Object { - "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FDeploymentStageprod6A86C016", - }, - "/", - ], - ], - }, - }, - }, - "Parameters": Object { - "HelloWorldFunctionCodeArtifactHashEF4E01C5": Object { - "Description": "Artifact hash for asset \\"lambda-events/HelloWorldFunction/Code\\"", - "Type": "String", - }, - "HelloWorldFunctionCodeS3BucketF87BE172": Object { - "Description": "S3 bucket for asset \\"lambda-events/HelloWorldFunction/Code\\"", - "Type": "String", - }, - "HelloWorldFunctionCodeS3VersionKeyF84D6469": Object { - "Description": "S3 key for asset version \\"lambda-events/HelloWorldFunction/Code\\"", - "Type": "String", - }, - }, - "Resources": Object { - "HelloWorldFunctionAllowInvokelambdaeventsMyTopic988FAB3E43035740": Object { - "Properties": Object { - "Action": "lambda:InvokeFunction", - "FunctionName": Object { - "Fn::GetAtt": Array [ - "HelloWorldFunctionB2AB6E79", - "Arn", - ], - }, - "Principal": "sns.amazonaws.com", - "SourceArn": Object { - "Ref": "MyTopic86869434", - }, - }, - "Type": "AWS::Lambda::Permission", - }, - "HelloWorldFunctionApiPermissionTestlambdaeventslambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F0AAEF724GEThello96B3E361": Object { - "Properties": Object { - "Action": "lambda:InvokeFunction", - "FunctionName": Object { - "Fn::GetAtt": Array [ - "HelloWorldFunctionB2AB6E79", - "Arn", - ], - }, - "Principal": "apigateway.amazonaws.com", - "SourceArn": Object { - "Fn::Join": Array [ - "", - Array [ - "arn:", - Object { - "Ref": "AWS::Partition", - }, - ":execute-api:", - Object { - "Ref": "AWS::Region", - }, - ":", - Object { - "Ref": "AWS::AccountId", - }, - ":", - Object { - "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F12449C5F", - }, - "/test-invoke-stage/GET/hello", - ], - ], - }, - }, - "Type": "AWS::Lambda::Permission", - }, - "HelloWorldFunctionApiPermissionTestlambdaeventslambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F0AAEF724POSThello36178555": Object { - "Properties": Object { - "Action": "lambda:InvokeFunction", - "FunctionName": Object { - "Fn::GetAtt": Array [ - "HelloWorldFunctionB2AB6E79", - "Arn", - ], - }, - "Principal": "apigateway.amazonaws.com", - "SourceArn": Object { - "Fn::Join": Array [ - "", - Array [ - "arn:", - Object { - "Ref": "AWS::Partition", - }, - ":execute-api:", - Object { - "Ref": "AWS::Region", - }, - ":", - Object { - "Ref": "AWS::AccountId", - }, - ":", - Object { - "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F12449C5F", - }, - "/test-invoke-stage/POST/hello", - ], + "https://", + Object { + "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F12449C5F", + }, + ".execute-api.", + Object { + "Ref": "AWS::Region", + }, + ".", + Object { + "Ref": "AWS::URLSuffix", + }, + "/", + Object { + "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FDeploymentStageprod6A86C016", + }, + "/", ], - }, + ], }, - "Type": "AWS::Lambda::Permission", }, - "HelloWorldFunctionApiPermissionlambdaeventslambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F0AAEF724GEThello84577BE4": Object { - "Properties": Object { - "Action": "lambda:InvokeFunction", - "FunctionName": Object { - "Fn::GetAtt": Array [ - "HelloWorldFunctionB2AB6E79", - "Arn", - ], - }, - "Principal": "apigateway.amazonaws.com", - "SourceArn": Object { - "Fn::Join": Array [ - "", - Array [ - "arn:", - Object { - "Ref": "AWS::Partition", - }, - ":execute-api:", - Object { - "Ref": "AWS::Region", - }, - ":", - Object { - "Ref": "AWS::AccountId", - }, - ":", - Object { - "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F12449C5F", - }, - "/", - Object { - "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FDeploymentStageprod6A86C016", - }, - "/GET/hello", - ], - ], - }, - }, - "Type": "AWS::Lambda::Permission", + }, + "Parameters": Object { + "HelloWorldFunctionCodeArtifactHashEF4E01C5": Object { + "Description": "Artifact hash for asset \\"lambda-events/HelloWorldFunction/Code\\"", + "Type": "String", }, - "HelloWorldFunctionApiPermissionlambdaeventslambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F0AAEF724POSThello0B1FC69D": Object { + "HelloWorldFunctionCodeS3BucketF87BE172": Object { + "Description": "S3 bucket for asset \\"lambda-events/HelloWorldFunction/Code\\"", + "Type": "String", + }, + "HelloWorldFunctionCodeS3VersionKeyF84D6469": Object { + "Description": "S3 key for asset version \\"lambda-events/HelloWorldFunction/Code\\"", + "Type": "String", + }, + }, + "Resources": Object { + "HelloWorldFunctionAllowInvokelambdaeventsMyTopic988FAB3E43035740": Object { "Properties": Object { "Action": "lambda:InvokeFunction", "FunctionName": Object { @@ -1081,34 +950,9 @@ Object { "Arn", ], }, - "Principal": "apigateway.amazonaws.com", + "Principal": "sns.amazonaws.com", "SourceArn": Object { - "Fn::Join": Array [ - "", - Array [ - "arn:", - Object { - "Ref": "AWS::Partition", - }, - ":execute-api:", - Object { - "Ref": "AWS::Region", - }, - ":", - Object { - "Ref": "AWS::AccountId", - }, - ":", - Object { - "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F12449C5F", - }, - "/", - Object { - "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FDeploymentStageprod6A86C016", - }, - "/POST/hello", - ], - ], + "Ref": "MyTopic86869434", }, }, "Type": "AWS::Lambda::Permission", @@ -1350,7 +1194,7 @@ Object { }, "Type": "AWS::IAM::Role", }, - "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FDeploymentFF3F4A1Aa119fa0e654d84489ef88606c21a73fb": Object { + "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FDeploymentFF3F4A1A61cb9465f6a55a6eaadc6dd0ea839d94": Object { "DependsOn": Array [ "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FhelloGET04FBC7F6", "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FhelloPOST53F177B1", @@ -1367,7 +1211,7 @@ Object { "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FDeploymentStageprod6A86C016": Object { "Properties": Object { "DeploymentId": Object { - "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FDeploymentFF3F4A1Aa119fa0e654d84489ef88606c21a73fb", + "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FDeploymentFF3F4A1A61cb9465f6a55a6eaadc6dd0ea839d94", }, "RestApiId": Object { "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F12449C5F", @@ -1431,6 +1275,84 @@ Object { }, "Type": "AWS::ApiGateway::Method", }, + "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FhelloGETApiPermissionTestlambdaeventslambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F0AAEF724GEThello5EA12CF5": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "HelloWorldFunctionB2AB6E79", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F12449C5F", + }, + "/test-invoke-stage/GET/hello", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FhelloGETApiPermissionlambdaeventslambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F0AAEF724GEThelloAC4AB5E4": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "HelloWorldFunctionB2AB6E79", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F12449C5F", + }, + "/", + Object { + "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FDeploymentStageprod6A86C016", + }, + "/GET/hello", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FhelloPOST53F177B1": Object { "Properties": Object { "AuthorizationType": "NONE", @@ -1471,6 +1393,84 @@ Object { }, "Type": "AWS::ApiGateway::Method", }, + "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FhelloPOSTApiPermissionTestlambdaeventslambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F0AAEF724POSThello991892DD": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "HelloWorldFunctionB2AB6E79", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F12449C5F", + }, + "/test-invoke-stage/POST/hello", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FhelloPOSTApiPermissionlambdaeventslambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F0AAEF724POSThello3501FACF": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "HelloWorldFunctionB2AB6E79", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4F12449C5F", + }, + "/", + Object { + "Ref": "lambdaeventsHelloWorldFunctionAB27BB65ApiEventSourceA7A86A4FDeploymentStageprod6A86C016", + }, + "/POST/hello", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, }, } `;