diff --git a/packages/@aws-cdk/aws-cloudfront/lib/private/cache-behavior.ts b/packages/@aws-cdk/aws-cloudfront/lib/private/cache-behavior.ts index 18b4d75aac2c7..09082c1dd4f8b 100644 --- a/packages/@aws-cdk/aws-cloudfront/lib/private/cache-behavior.ts +++ b/packages/@aws-cdk/aws-cloudfront/lib/private/cache-behavior.ts @@ -1,5 +1,6 @@ +import * as iam from '@aws-cdk/aws-iam'; import { CfnDistribution } from '../cloudfront.generated'; -import { AddBehaviorOptions, ViewerProtocolPolicy } from '../distribution'; +import { AddBehaviorOptions, EdgeLambda, ViewerProtocolPolicy } from '../distribution'; /** * Properties for specifying custom behaviors for origins. @@ -24,6 +25,8 @@ export class CacheBehavior { constructor(originId: string, private readonly props: CacheBehaviorProps) { this.originId = originId; + + this.grantEdgeLambdaFunctionExecutionRole(props.edgeLambdas); } /** @@ -55,4 +58,17 @@ export class CacheBehavior { : undefined, }; } + + private grantEdgeLambdaFunctionExecutionRole(edgeLambdas?: EdgeLambda[]) { + if (!edgeLambdas || edgeLambdas.length === 0) { return; } + edgeLambdas.forEach((edgeLambda) => { + const role = edgeLambda.functionVersion.role; + if (role && role instanceof iam.Role && role.assumeRolePolicy) { + role.assumeRolePolicy.addStatements(new iam.PolicyStatement({ + actions: ['sts:AssumeRole'], + principals: [new iam.ServicePrincipal('edgelambda.amazonaws.com')], + })); + } + }); + } } diff --git a/packages/@aws-cdk/aws-cloudfront/test/distribution.test.ts b/packages/@aws-cdk/aws-cloudfront/test/distribution.test.ts index 0a8b5933e7f59..b4368de309232 100644 --- a/packages/@aws-cdk/aws-cloudfront/test/distribution.test.ts +++ b/packages/@aws-cdk/aws-cloudfront/test/distribution.test.ts @@ -489,6 +489,42 @@ describe('with Lambda@Edge functions', () => { }); }); + test('edgelambda.amazonaws.com is added to the trust policy of lambda', () => { + new Distribution(stack, 'MyDist', { + defaultBehavior: { + origin, + edgeLambdas: [ + { + functionVersion: lambdaFunction.currentVersion, + eventType: LambdaEdgeEventType.ORIGIN_REQUEST, + }, + ], + }, + }); + + expect(stack).toHaveResource('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'lambda.amazonaws.com', + }, + }, + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'edgelambda.amazonaws.com', + }, + }, + ], + Version: '2012-10-17', + }, + }); + }); + test('can add an edge lambdas to additional behaviors', () => { new Distribution(stack, 'MyDist', { defaultBehavior: { origin }, diff --git a/packages/@aws-cdk/aws-cloudfront/test/integ.distribution-lambda.expected.json b/packages/@aws-cdk/aws-cloudfront/test/integ.distribution-lambda.expected.json new file mode 100644 index 0000000000000..ef6030afded59 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudfront/test/integ.distribution-lambda.expected.json @@ -0,0 +1,103 @@ +{ + "Resources": { + "LambdaServiceRoleA8ED4D3B": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + }, + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "edgelambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "LambdaD247545B": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LambdaServiceRoleA8ED4D3B", + "Arn" + ] + }, + "Runtime": "nodejs10.x" + }, + "DependsOn": [ + "LambdaServiceRoleA8ED4D3B" + ] + }, + "LambdaCurrentVersionDF706F6A97fb843e9bd06fcd2bb15eeace80e13e": { + "Type": "AWS::Lambda::Version", + "Properties": { + "FunctionName": { + "Ref": "LambdaD247545B" + } + } + }, + "DistB3B78991": { + "Type": "AWS::CloudFront::Distribution", + "Properties": { + "DistributionConfig": { + "DefaultCacheBehavior": { + "ForwardedValues": { + "QueryString": false + }, + "LambdaFunctionAssociations": [ + { + "EventType": "origin-request", + "LambdaFunctionARN": { + "Ref": "LambdaCurrentVersionDF706F6A97fb843e9bd06fcd2bb15eeace80e13e" + } + } + ], + "TargetOriginId": "integdistributionlambdaDistOrigin133A13098", + "ViewerProtocolPolicy": "allow-all" + }, + "Enabled": true, + "HttpVersion": "http2", + "IPV6Enabled": true, + "Origins": [ + { + "CustomOriginConfig": { + "OriginProtocolPolicy": "https-only" + }, + "DomainName": "www.example.com", + "Id": "integdistributionlambdaDistOrigin133A13098" + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudfront/test/integ.distribution-lambda.ts b/packages/@aws-cdk/aws-cloudfront/test/integ.distribution-lambda.ts new file mode 100644 index 0000000000000..52bc6c1a320c5 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudfront/test/integ.distribution-lambda.ts @@ -0,0 +1,25 @@ +import * as lambda from '@aws-cdk/aws-lambda'; +import * as cdk from '@aws-cdk/core'; +import * as cloudfront from '../lib'; +import { TestOrigin } from './test-origin'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'integ-distribution-lambda', { env: { region: 'us-east-1' } }); + +const lambdaFunction = new lambda.Function(stack, 'Lambda', { + code: lambda.Code.fromInline('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, +}); + +new cloudfront.Distribution(stack, 'Dist', { + defaultBehavior: { + origin: new TestOrigin('www.example.com'), + edgeLambdas: [{ + functionVersion: lambdaFunction.currentVersion, + eventType: cloudfront.LambdaEdgeEventType.ORIGIN_REQUEST, + }], + }, +}); + +app.synth();