AWSTemplateFormatVersion: 2010-09-09 Description: >- AWS Resources to deliver a static website via S3, CloudFront & Lambda@Edge (with EdgeServices) Parameters: FQDN: Type: String Description: FQDN of website. Default: ptylr.com AcmCertificateArn: Type: String Description: ARN of the certificate to use for the CloudFront distribution. RolePermissionBoundaryArn: Type: String Description: ARN of the permission boundary for IAM Role creation. Default: '' Conditions: HasRolePermissionBoundaryArn: !Not [ !Equals [!Ref RolePermissionBoundaryArn, ''] ] Resources: CloudFrontDistribution: Type: 'AWS::CloudFront::Distribution' Properties: DistributionConfig: Aliases: - !Ref FQDN DefaultCacheBehavior: Compress: true ForwardedValues: QueryString: true Headers: - Authorization TargetOriginId: !Sub '${S3Bucket}.s3.amazonaws.com' ViewerProtocolPolicy: redirect-to-https MinTTL: 0 AllowedMethods: - HEAD - GET CachedMethods: - HEAD - GET LambdaFunctionAssociations: - EventType: origin-request LambdaFunctionARN: !Ref OriginRequestLambdaFunctionVersion - EventType: origin-response LambdaFunctionARN: !Ref OriginResponseLambdaFunctionVersion Enabled: true HttpVersion: http2 Origins: - DomainName: !Sub '${S3Bucket}.s3.amazonaws.com' Id: !Sub '${S3Bucket}.s3.amazonaws.com' S3OriginConfig: OriginAccessIdentity: !Sub 'origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}' PriceClass: PriceClass_All ViewerCertificate: AcmCertificateArn: !Ref AcmCertificateArn MinimumProtocolVersion: TLSv1.1_2016 SslSupportMethod: sni-only Tags: - Key: Domain Value: !Ref FQDN CloudFrontOriginAccessIdentity: Type: 'AWS::CloudFront::CloudFrontOriginAccessIdentity' Properties: CloudFrontOriginAccessIdentityConfig: Comment: !Sub 'CloudFront Origin Access Identity for ${FQDN}' S3Bucket: Type: 'AWS::S3::Bucket' Properties: AccessControl: Private BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 Tags: - Key: Domain Value: !Ref FQDN S3BucketPolicy: Type: 'AWS::S3::BucketPolicy' Properties: Bucket: !Ref S3Bucket PolicyDocument: Statement: - Action: - 's3:GetObject' Effect: Allow Resource: !Sub 'arn:aws:s3:::${S3Bucket}/*' Principal: CanonicalUser: !GetAtt - CloudFrontOriginAccessIdentity - S3CanonicalUserId - Action: - 's3:GetObject' Effect: Allow Resource: !Sub 'arn:aws:s3:::${S3Bucket}/*' Principal: '*' Condition: StringLike: 'aws:Referer': - !Sub '${AWS::Region}.${OriginRequestLambdaFunction}' - !Sub '${AWS::Region}.${OriginResponseLambdaFunction}' OriginRequestLambdaFunction: Type: 'AWS::Lambda::Function' Properties: Description: >- EdgeServices - A Pair of Lambda@Edge Functions for Executing Common Operations on Request (see https://github.com/ptylr/Lambda-at-Edge/tree/master/EdgeServices) Code: S3Bucket: lambda-ptylr-com S3Key: EdgeServices_OriginRequest.zip S3ObjectVersion: WUceMAAQDakBdZl5rhHY82MaozSA2pld Handler: handler.handler MemorySize: 128 Role: !Sub '${LambdaFunctionExecutionRole.Arn}' Runtime: nodejs12.x Tags: - Key: Domain Value: !Ref FQDN OriginRequestLambdaFunctionVersion: Type: 'AWS::Lambda::Version' Properties: FunctionName: !Ref OriginRequestLambdaFunction Description: !Sub 'EdgeServices-OriginRequest for ${FQDN}' OriginResponseLambdaFunction: Type: 'AWS::Lambda::Function' Properties: Description: >- EdgeServices - A Pair of Lambda@Edge Functions for Executing Common Operations on Request (see https://github.com/ptylr/Lambda-at-Edge/tree/master/EdgeServices) Code: S3Bucket: lambda-ptylr-com S3Key: EdgeServices_OriginResponse.zip S3ObjectVersion: fmArTnlFsUZyZYhZl6Sok4H7JK6aw42h Handler: handler.handler MemorySize: 128 Role: !Sub '${LambdaFunctionExecutionRole.Arn}' Runtime: nodejs12.x Tags: - Key: Domain Value: !Ref FQDN OriginResponseLambdaFunctionVersion: Type: 'AWS::Lambda::Version' Properties: FunctionName: !Ref OriginResponseLambdaFunction Description: !Sub 'EdgeServices-OriginResponse for ${FQDN}' LambdaFunctionExecutionRole: Type: 'AWS::IAM::Role' Properties: PermissionsBoundary: Fn::If: - HasRolePermissionBoundaryArn - Ref: RolePermissionBoundaryArn - Ref: AWS::NoValue AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - edgelambda.amazonaws.com - lambda.amazonaws.com Action: - 'sts:AssumeRole' ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' LambdaFunctionExecutionPolicies: Type: AWS::IAM::Policy Properties: PolicyName: IAMP-LambdaFunctionExecutionPolicy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - 's3:ListAllMyBuckets' - 's3:GetBucketLocation' Resource: '*' - Effect: Allow Action: - 's3:GetObject' - 's3:ListBucket' Resource: - !Sub 'arn:aws:s3:::${S3Bucket}' - !Sub 'arn:aws:s3:::${S3Bucket}/*' Roles: - !Ref LambdaFunctionExecutionRole