Created
January 26, 2021 22:54
-
-
Save AdonousTech/50bff8a46acb1478067db2af90a474c8 to your computer and use it in GitHub Desktop.
A Cloud Coach - Tutorial - Serverless Stripe Store - 008 - SPA Infra CloudFormation Template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"AWSTemplateFormatVersion": "2010-09-09", | |
"Description": "SPA Infrastructure Template", | |
"Parameters": { | |
"CodeBuildProjectNameParameter": { | |
"Type": "String", | |
"Description": "A name for the CodeBuild project. The name must be unique across all of the projects in your AWS account." | |
}, | |
"CodeBuildImageParameter": { | |
"Type": "String", | |
"Description": "Code Build image to use" | |
}, | |
"DeploymentFunctionS3Key": { | |
"Type": "String", | |
"Description": "S3 key for CB/CP deployment lambda function." | |
}, | |
"DeploymentFunctionFileLocation": { | |
"Type": "String", | |
"Description": "Source code location for deployment lambda function." | |
}, | |
"DeploymentCacheFunctionFileLocation": { | |
"Type": "String", | |
"Description": "Source code location for deployment cache invalidation lambda function." | |
}, | |
"PipelineName": { | |
"Type": "String", | |
"Description": "Unique name for the CodePipeline" | |
}, | |
"UserPoolClientName": { | |
"Type": "String", | |
"Description": "Unique name for user pool client application" | |
}, | |
"IdentityPoolName": { | |
"Type": "String", | |
"Description": "Name of the identity pool" | |
}, | |
"DBTableName": { | |
"Type": "String", | |
"Description": "Name of the DB table" | |
}, | |
"DBHashKey": { | |
"Type": "String", | |
"Description": "Primary/partition/hash key for the table" | |
}, | |
"ExistingHostedZone": { | |
"Type": "String", | |
"Description": "Id of the existing hosted zone." | |
}, | |
"CloudfrontCName": { | |
"Type": "String", | |
"Description": "CNAME for Cloudfront distribution" | |
}, | |
"SSLCertArn": { | |
"Type": "String", | |
"Description": "ARN for the ACM SSL Cert" | |
}, | |
"NoReplyEmail": { | |
"Type": "String", | |
"Description": "Canonical No Reply email address." | |
}, | |
"NoReplyEmailArn": { | |
"Type": "String", | |
"Description": "ARN of the canonical No Reply email address." | |
}, | |
"NoReplyFromEmail": { | |
"Type": "String", | |
"Description": "From email display for No Reply email address." | |
} | |
}, | |
"Resources": { | |
"BucketCodeBuildSource": { | |
"Type": "AWS::S3::Bucket", | |
"Properties": { | |
"PublicAccessBlockConfiguration": { | |
"BlockPublicAcls": true, | |
"BlockPublicPolicy": true, | |
"RestrictPublicBuckets": true, | |
"IgnorePublicAcls": true | |
}, | |
"BucketEncryption" : { | |
"ServerSideEncryptionConfiguration": [ | |
{ | |
"ServerSideEncryptionByDefault": { | |
"SSEAlgorithm": "AES256" | |
} | |
} | |
] | |
}, | |
"VersioningConfiguration": { | |
"Status": "Enabled" | |
} | |
} | |
}, | |
"BucketCodeBuildOutput": { | |
"Type": "AWS::S3::Bucket", | |
"Properties": { | |
"PublicAccessBlockConfiguration": { | |
"BlockPublicAcls": true, | |
"BlockPublicPolicy": true, | |
"RestrictPublicBuckets": true, | |
"IgnorePublicAcls": true | |
}, | |
"BucketEncryption" : { | |
"ServerSideEncryptionConfiguration": [ | |
{ | |
"ServerSideEncryptionByDefault": { | |
"SSEAlgorithm": "AES256" | |
} | |
} | |
] | |
} | |
} | |
}, | |
"BucketCodePipeline": { | |
"Type": "AWS::S3::Bucket", | |
"Properties": { | |
"PublicAccessBlockConfiguration": { | |
"BlockPublicAcls": true, | |
"BlockPublicPolicy": true, | |
"RestrictPublicBuckets": true, | |
"IgnorePublicAcls": true | |
}, | |
"BucketEncryption" : { | |
"ServerSideEncryptionConfiguration": [ | |
{ | |
"ServerSideEncryptionByDefault": { | |
"SSEAlgorithm": "AES256" | |
} | |
} | |
] | |
} | |
} | |
}, | |
"BucketCodePipelineFunctions": { | |
"Type": "AWS::S3::Bucket", | |
"Properties": { | |
"PublicAccessBlockConfiguration": { | |
"BlockPublicAcls": true, | |
"BlockPublicPolicy": true, | |
"RestrictPublicBuckets": true, | |
"IgnorePublicAcls": true | |
}, | |
"BucketEncryption" : { | |
"ServerSideEncryptionConfiguration": [ | |
{ | |
"ServerSideEncryptionByDefault": { | |
"SSEAlgorithm": "AES256" | |
} | |
} | |
] | |
} | |
} | |
}, | |
"StaticWebsiteBucket" : { | |
"Type" : "AWS::S3::Bucket", | |
"Properties": { | |
"WebsiteConfiguration": { | |
"IndexDocument": "index.html", | |
"ErrorDocument": "error.html" | |
}, | |
"PublicAccessBlockConfiguration": { | |
"BlockPublicAcls": true, | |
"BlockPublicPolicy": true, | |
"RestrictPublicBuckets": true, | |
"IgnorePublicAcls": true | |
}, | |
"BucketEncryption" : { | |
"ServerSideEncryptionConfiguration": [ | |
{ | |
"ServerSideEncryptionByDefault": { | |
"SSEAlgorithm": "AES256" | |
} | |
} | |
] | |
}, | |
"CorsConfiguration": { | |
"CorsRules": [ | |
{ | |
"AllowedHeaders": ["*"], | |
"AllowedMethods": [ | |
"GET", | |
"HEAD" | |
], | |
"AllowedOrigins": ["*"] | |
} | |
] | |
} | |
} | |
}, | |
"OriginAccessIdentity": { | |
"Type": "AWS::CloudFront::CloudFrontOriginAccessIdentity", | |
"Properties": { | |
"CloudFrontOriginAccessIdentityConfig": { | |
"Comment": "OAI" | |
} | |
} | |
}, | |
"StaticWebSiteBucketPolicy": { | |
"Type": "AWS::S3::BucketPolicy", | |
"DependsOn": ["StaticWebsiteBucket", "OriginAccessIdentity", "CodePipelineLambdaExecutionRole"], | |
"Properties": { | |
"Bucket": {"Ref": "StaticWebsiteBucket"}, | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Sid": "Grant a CloudFront Origin Identity access to support private content", | |
"Effect": "Allow", | |
"Principal": { | |
"CanonicalUser": { | |
"Fn::GetAtt": ["OriginAccessIdentity", "S3CanonicalUserId"] | |
} | |
}, | |
"Action": "s3:GetObject", | |
"Resource": {"Fn::Join" : [ "", [ {"Fn::GetAtt" : [ "StaticWebsiteBucket", "Arn" ]}, "/*" ] ] } | |
}, | |
{ | |
"Sid": "Grant a CloudFront Origin Identity access to support private content", | |
"Effect": "Allow", | |
"Principal": { | |
"CanonicalUser": { | |
"Fn::GetAtt": ["OriginAccessIdentity", "S3CanonicalUserId"] | |
} | |
}, | |
"Action": "s3:ListBucket", | |
"Resource": {"Fn::GetAtt" : [ "StaticWebsiteBucket", "Arn" ]} | |
}, | |
{ | |
"Sid": "Allow CodePipeline Lambda execution role access to objects", | |
"Effect": "Allow", | |
"Principal": { | |
"AWS": {"Fn::GetAtt" : [ "CodePipelineLambdaExecutionRole", "Arn" ]} | |
}, | |
"Action": "s3:*", | |
"Resource": {"Fn::Join" : [ "", [ {"Fn::GetAtt" : [ "StaticWebsiteBucket", "Arn" ]}, "/*" ] ] } | |
} | |
] | |
} | |
} | |
}, | |
"CodeBuildOutputBucketPolicy": { | |
"Type": "AWS::S3::BucketPolicy", | |
"DependsOn": ["BucketCodeBuildOutput", "CodeBuildRole", "CodePipelineLambdaExecutionRole"], | |
"Properties": { | |
"Bucket": {"Ref" : "BucketCodeBuildOutput"}, | |
"PolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Sid": "Enables CodeBuild role access to source output bucket", | |
"Effect": "Allow", | |
"Principal": { | |
"AWS": {"Fn::GetAtt" : [ "CodeBuildRole", "Arn" ]} | |
}, | |
"Action": "s3:*", | |
"Resource": {"Fn::Join" : [ "", [ {"Fn::GetAtt" : [ "BucketCodeBuildOutput", "Arn" ]}, "/*" ] ] } | |
}, | |
{ | |
"Sid": "Enables Lambda execution role access to source output bucket", | |
"Effect": "Allow", | |
"Principal": { | |
"AWS": {"Fn::GetAtt" : [ "CodePipelineLambdaExecutionRole", "Arn" ]} | |
}, | |
"Action": "s3:GetObject", | |
"Resource": {"Fn::Join" : [ "", [ {"Fn::GetAtt" : [ "BucketCodeBuildOutput", "Arn" ]}, "/*" ] ] } | |
}, | |
{ | |
"Sid": "Enables Lambda execution role access to list bucket objects.", | |
"Effect": "Allow", | |
"Principal": { | |
"AWS": {"Fn::GetAtt" : [ "CodePipelineLambdaExecutionRole", "Arn" ]} | |
}, | |
"Action": "s3:ListBucket", | |
"Resource": {"Fn::GetAtt" : [ "BucketCodeBuildOutput", "Arn" ]} | |
} | |
] | |
} | |
} | |
}, | |
"CodePipelineBucketPolicy": { | |
"Type": "AWS::S3::BucketPolicy", | |
"DependsOn": ["BucketCodePipeline"], | |
"Properties": { | |
"Bucket": {"Ref" : "BucketCodePipeline"}, | |
"PolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Sid": "DenyUnEncryptedObjectUploads", | |
"Effect": "Deny", | |
"Principal": "*", | |
"Action": "s3:PutObject", | |
"Resource": {"Fn::Join" : [ "", [ {"Fn::GetAtt" : [ "BucketCodePipeline", "Arn" ]}, "/*" ] ] }, | |
"Condition": { | |
"StringNotEquals": { | |
"s3:x-amz-server-side-encryption": "aws:kms" | |
} | |
} | |
}, | |
{ | |
"Sid": "DenyInsecureConnections", | |
"Effect": "Deny", | |
"Principal": "*", | |
"Action": "s3:*", | |
"Resource": {"Fn::Join" : [ "", [ {"Fn::GetAtt" : [ "BucketCodePipeline", "Arn" ]}, "/*" ] ] }, | |
"Condition": { | |
"Bool": { | |
"aws:SecureTransport": "false" | |
} | |
} | |
} | |
] | |
} | |
} | |
}, | |
"CloudFrontDistribution": { | |
"Type": "AWS::CloudFront::Distribution", | |
"DependsOn": [ | |
"StaticWebSiteBucketPolicy", | |
"OriginAccessIdentity" | |
], | |
"Properties": { | |
"DistributionConfig": { | |
"Aliases": [{"Ref": "CloudfrontCName"}], | |
"DefaultCacheBehavior": { | |
"AllowedMethods": [ | |
"GET", | |
"HEAD", | |
"OPTIONS" | |
], | |
"Compress": "true", | |
"ForwardedValues": { | |
"Headers": [ | |
"Origin" | |
], | |
"Cookies": { | |
"Forward": "none" | |
}, | |
"QueryString": "false" | |
}, | |
"TargetOriginId": "s3_origin", | |
"ViewerProtocolPolicy": "redirect-to-https" | |
}, | |
"DefaultRootObject": "index.html", | |
"Enabled": "true", | |
"HttpVersion": "http2", | |
"ViewerCertificate": { | |
"AcmCertificateArn": {"Ref": "SSLCertArn"}, | |
"MinimumProtocolVersion": "TLSv1.2_2018", | |
"SslSupportMethod": "sni-only" | |
}, | |
"CustomErrorResponses": [ | |
{ | |
"ErrorCachingMinTTL": 0, | |
"ErrorCode": 500 | |
}, | |
{ | |
"ErrorCachingMinTTL": 300, | |
"ErrorCode": 403, | |
"ResponseCode": 200, | |
"ResponsePagePath": "/index.html" | |
}, | |
{ | |
"ErrorCachingMinTTL": 300, | |
"ErrorCode": 404, | |
"ResponseCode": 200, | |
"ResponsePagePath": "/index.html" | |
} | |
], | |
"Origins": [ | |
{ | |
"DomainName": { | |
"Fn::GetAtt": [ | |
"StaticWebsiteBucket", | |
"DomainName" | |
] | |
}, | |
"Id": "s3_origin", | |
"S3OriginConfig": { | |
"OriginAccessIdentity": {"Fn::Sub": "origin-access-identity/cloudfront/${OriginAccessIdentity}"} | |
} | |
} | |
], | |
"PriceClass": "PriceClass_All" | |
} | |
} | |
}, | |
"CodeBuildRole": { | |
"Type": "AWS::IAM::Role", | |
"DependsOn": [ | |
"BucketCodeBuildSource", | |
"BucketCodePipeline", | |
"BucketCodeBuildOutput", | |
"StaticWebsiteBucket" | |
], | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "codebuild.amazonaws.com" | |
}, | |
"Action": "sts:AssumeRole" | |
} | |
] | |
}, | |
"Policies": [ | |
{ | |
"PolicyName": "CodeBuildRootPolicy", | |
"PolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Resource": [ | |
{"Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*"} | |
], | |
"Action": [ | |
"logs:CreateLogGroup", | |
"logs:CreateLogStream", | |
"logs:PutLogEvents" | |
] | |
}, | |
{ | |
"Effect": "Allow", | |
"Resource": [ | |
{"Fn::Join" : [ "", [ {"Fn::GetAtt" : [ "BucketCodeBuildSource", "Arn" ]}, "/build-source.zip" ] ] } | |
], | |
"Action": [ | |
"s3:GetObject", | |
"s3:GetObjectVersion" | |
] | |
}, | |
{ | |
"Effect": "Allow", | |
"Resource": [ | |
{"Fn::GetAtt" : [ "BucketCodePipeline", "Arn" ]}, | |
{"Fn::Join" : [ "", [ {"Fn::GetAtt" : [ "BucketCodePipeline", "Arn" ]}, "/*" ] ] } | |
], | |
"Action": "s3:*" | |
}, | |
{ | |
"Effect": "Allow", | |
"Resource": [ | |
{"Fn::GetAtt" : [ "BucketCodeBuildOutput", "Arn" ]}, | |
{"Fn::Join" : [ "", [ {"Fn::GetAtt" : [ "BucketCodeBuildOutput", "Arn" ]}, "/*" ] ] } | |
], | |
"Action": "s3:*" | |
}, | |
{ | |
"Effect": "Allow", | |
"Resource": [ | |
{"Fn::GetAtt" : [ "StaticWebsiteBucket", "Arn" ]} | |
], | |
"Action": "s3:*" | |
} | |
] | |
} | |
} | |
] | |
} | |
}, | |
"CodeBuildProject": { | |
"Type": "AWS::CodeBuild::Project", | |
"DependsOn": ["CodeBuildRole", "BucketCodeBuildSource", "BucketCodeBuildOutput"], | |
"Properties": { | |
"Name": {"Ref" : "CodeBuildProjectNameParameter"}, | |
"Description": "Builds static SPA as part of CodePipeline", | |
"Source": { | |
"Type": "S3", | |
"Location": {"Fn::Join" : [ "", [ {"Ref" : "BucketCodeBuildSource"}, "/build-source.zip" ] ] } | |
}, | |
"Artifacts": { | |
"Type": "S3", | |
"Location": {"Ref" : "BucketCodeBuildOutput"}, | |
"Name": "build-output", | |
"Packaging": "ZIP" | |
}, | |
"Environment": { | |
"ComputeType": "BUILD_GENERAL1_MEDIUM", | |
"Image": {"Ref": "CodeBuildImageParameter"}, | |
"Type": "LINUX_CONTAINER", | |
"EnvironmentVariables": [ | |
{"Name": "NODE_OPTIONS", "Value": "--max-old-space-size=6144"} | |
] | |
}, | |
"ServiceRole": {"Fn::GetAtt" : [ "CodeBuildRole", "Arn" ]}, | |
"TimeoutInMinutes": 60 | |
} | |
}, | |
"CodePipelineRole": { | |
"Type": "AWS::IAM::Role", | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Sid": "", | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "codepipeline.amazonaws.com" | |
}, | |
"Action": "sts:AssumeRole" | |
} | |
] | |
}, | |
"Policies": [ | |
{ | |
"PolicyName": "StaticSiteCodePipelineRootPolicy", | |
"PolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Action": [ | |
"s3:GetObject", | |
"s3:GetObjectVersion", | |
"s3:GetBucketVersioning" | |
], | |
"Resource": "*", | |
"Effect":"Allow" | |
}, | |
{ | |
"Action": [ | |
"s3:PutObject" | |
], | |
"Resource": [ | |
"arn:aws:s3:::codepipeline*", | |
"arn:aws:s3:::elasticbeanstalk*" | |
], | |
"Effect": "Allow" | |
}, | |
{ | |
"Action": [ | |
"codecommit:CancelUploadArchive", | |
"codecommit:GetBranch", | |
"codecommit:GetCommit", | |
"codecommit:GetUploadArchiveStatus", | |
"codecommit:UploadArchive" | |
], | |
"Resource": "*", | |
"Effect": "Allow" | |
}, | |
{ | |
"Action": [ | |
"codedeploy:CreateDeployment", | |
"codedeploy:GetApplicationRevision", | |
"codedeploy:GetDeployment", | |
"codedeploy:GetDeploymentConfig", | |
"codedeploy:RegisterApplicationRevision" | |
], | |
"Resource": "*", | |
"Effect": "Allow" | |
}, | |
{ | |
"Action": [ | |
"elasticbeanstalk:*", | |
"ec2:*", | |
"elasticloadbalancing:*", | |
"autoscaling:*", | |
"cloudwatch:*", | |
"s3:*", | |
"sns:*", | |
"cloudformation:*", | |
"rds:*", | |
"sqs:*", | |
"ecs:*", | |
"iam:PassRole" | |
], | |
"Resource": "*", | |
"Effect": "Allow" | |
}, | |
{ | |
"Action": [ | |
"lambda:InvokeFunction", | |
"lambda:ListFunctions" | |
], | |
"Resource": "*", | |
"Effect": "Allow" | |
}, | |
{ | |
"Action": [ | |
"opsworks:CreateDeployment", | |
"opsworks:DescribeApps", | |
"opsworks:DescribeCommands", | |
"opsworks:DescribeDeployments", | |
"opsworks:DescribeInstances", | |
"opsworks:DescribeStacks", | |
"opsworks:UpdateApp", | |
"opsworks:UpdateStack" | |
], | |
"Resource": "*", | |
"Effect": "Allow" | |
}, | |
{ | |
"Action": [ | |
"cloudformation:CreateStack", | |
"cloudformation:DeleteStack", | |
"cloudformation:DescribeStacks", | |
"cloudformation:UpdateStack", | |
"cloudformation:CreateChangeSet", | |
"cloudformation:DeleteChangeSet", | |
"cloudformation:DescribeChangeSet", | |
"cloudformation:ExecuteChangeSet", | |
"cloudformation:SetStackPolicy", | |
"cloudformation:ValidateTemplate", | |
"iam:PassRole" | |
], | |
"Resource": "*", | |
"Effect": "Allow" | |
}, | |
{ | |
"Action": [ | |
"codebuild:BatchGetBuilds", | |
"codebuild:StartBuild" | |
], | |
"Resource": "*", | |
"Effect": "Allow" | |
} | |
] | |
} | |
} | |
] | |
} | |
}, | |
"CodePipelineLambdaExecutionRole": { | |
"Type": "AWS::IAM::Role", | |
"DependsOn": ["BucketCodeBuildOutput", "StaticWebsiteBucket"], | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": { | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "lambda.amazonaws.com" | |
}, | |
"Action": "sts:AssumeRole" | |
} | |
}, | |
"Path": "/", | |
"Policies": [{ | |
"PolicyName": "root", | |
"PolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"logs:*" | |
], | |
"Resource": "arn:aws:logs:*:*:*" | |
}, | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"codepipeline:PutJobSuccessResult", | |
"codepipeline:PutJobFailureResult" | |
], | |
"Resource": "*" | |
}, | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"s3:*" | |
], | |
"Resource": [ | |
{"Fn::Join" : [ "", [ {"Fn::GetAtt" : [ "BucketCodeBuildOutput", "Arn" ]}, "/*" ] ] }, | |
{"Fn::Join" : [ "", [ {"Fn::GetAtt" : [ "StaticWebsiteBucket", "Arn" ]}, "/*" ] ] } | |
] | |
}, | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"cloudfront:CreateInvalidation", | |
"cloudfront:ListInvalidations" | |
], | |
"Resource": [ | |
"*" | |
] | |
} | |
] | |
} | |
}] | |
} | |
}, | |
"CodebuildDeployLambdaFunction": { | |
"Type": "AWS::Lambda::Function", | |
"DependsOn": ["BucketCodeBuildOutput","StaticWebsiteBucket"], | |
"Properties": { | |
"Code": { | |
"ZipFile": {"Ref": "DeploymentFunctionFileLocation"} | |
}, | |
"Handler": "index.handler", | |
"MemorySize": 128, | |
"Role": {"Fn::GetAtt" : [ "CodePipelineLambdaExecutionRole", "Arn" ]}, | |
"Runtime": "nodejs12.x", | |
"Timeout": 30, | |
"Environment": { | |
"Variables": { | |
"SourceBucket": {"Ref": "BucketCodeBuildOutput"}, | |
"DestBucket": {"Ref": "StaticWebsiteBucket"} | |
} | |
} | |
} | |
}, | |
"CodebuildInvalidateCacheLambdaFunction": { | |
"Type": "AWS::Lambda::Function", | |
"DependsOn": ["CodePipelineLambdaExecutionRole", "CloudFrontDistribution"], | |
"Properties": { | |
"Code": { | |
"ZipFile": {"Ref": "DeploymentCacheFunctionFileLocation"} | |
}, | |
"Handler": "index.handler", | |
"MemorySize": 128, | |
"Role": {"Fn::GetAtt" : [ "CodePipelineLambdaExecutionRole", "Arn" ]}, | |
"Runtime": "nodejs12.x", | |
"Timeout": 30, | |
"Environment": { | |
"Variables": { | |
"CloudfrontDistId": {"Ref": "CloudFrontDistribution"} | |
} | |
} | |
} | |
}, | |
"CodePipeline": { | |
"Type": "AWS::CodePipeline::Pipeline", | |
"DependsOn": ["BucketCodePipeline", | |
"CodePipelineRole", | |
"BucketCodeBuildSource", | |
"CodeBuildProject", | |
"CodebuildDeployLambdaFunction", | |
"CodebuildInvalidateCacheLambdaFunction" | |
], | |
"Properties": | |
{ | |
"ArtifactStore": { | |
"Type": "S3", | |
"Location": {"Ref" : "BucketCodePipeline"} | |
}, | |
"Name": {"Ref": "PipelineName"}, | |
"RestartExecutionOnUpdate": true, | |
"RoleArn": {"Fn::GetAtt" : [ "CodePipelineRole", "Arn" ]}, | |
"Stages": [ | |
{ | |
"Name": "Source", | |
"Actions": [ | |
{ | |
"Name": "Source", | |
"ActionTypeId": { | |
"Category": "Source", | |
"Owner": "AWS", | |
"Provider": "S3", | |
"Version": "1" | |
}, | |
"OutputArtifacts": [ | |
{ | |
"Name": "StaticAppPayload" | |
} | |
], | |
"Configuration": { | |
"S3Bucket": {"Ref": "BucketCodeBuildSource"}, | |
"S3ObjectKey": "build-source.zip" | |
} | |
} | |
] | |
}, | |
{ | |
"Name": "Build", | |
"Actions": [ | |
{ | |
"InputArtifacts": [ | |
{ | |
"Name": "StaticAppPayload" | |
} | |
], | |
"Name": "CodeBuild", | |
"ActionTypeId": { | |
"Category": "Build", | |
"Owner": "AWS", | |
"Provider": "CodeBuild", | |
"Version": "1" | |
}, | |
"OutputArtifacts": [ | |
{ | |
"Name": "StaticAppBuild" | |
} | |
], | |
"Configuration": { | |
"ProjectName": {"Ref" : "CodeBuildProject"} | |
} | |
} | |
] | |
}, | |
{ | |
"Name": "DeployStaticAssets", | |
"Actions": [ | |
{ | |
"InputArtifacts": [], | |
"Name": "StaticAssetDeploy", | |
"ActionTypeId": { | |
"Category": "Invoke", | |
"Owner": "AWS", | |
"Provider": "Lambda", | |
"Version": "1" | |
}, | |
"OutputArtifacts": [], | |
"Configuration": { | |
"FunctionName": {"Ref" : "CodebuildDeployLambdaFunction"} | |
} | |
} | |
] | |
}, | |
{ | |
"Name": "InvalidateCache", | |
"Actions": [ | |
{ | |
"InputArtifacts": [], | |
"Name": "CacheInvalidation", | |
"ActionTypeId": { | |
"Category": "Invoke", | |
"Owner": "AWS", | |
"Provider": "Lambda", | |
"Version": "1" | |
}, | |
"OutputArtifacts": [], | |
"Configuration": { | |
"FunctionName": {"Ref" : "CodebuildInvalidateCacheLambdaFunction"} | |
} | |
} | |
] | |
} | |
] | |
} | |
}, | |
"UserPool": { | |
"Type": "AWS::Cognito::UserPool", | |
"Properties": { | |
"UserPoolName": {"Ref": "UserPoolClientName"}, | |
"AutoVerifiedAttributes": ["email"], | |
"EmailConfiguration": { | |
"EmailSendingAccount": "DEVELOPER", | |
"From": {"Ref": "NoReplyEmail"}, | |
"ReplyToEmailAddress": {"Ref": "NoReplyFromEmail"}, | |
"SourceArn": {"Ref": "NoReplyEmailArn"} | |
}, | |
"Policies": { | |
"PasswordPolicy": { | |
"MinimumLength" : 8, | |
"RequireLowercase" : true, | |
"RequireNumbers" : true, | |
"RequireSymbols" : true, | |
"RequireUppercase" : true | |
} | |
}, | |
"Schema": [ | |
{ | |
"AttributeDataType" : "String", | |
"DeveloperOnlyAttribute" : false, | |
"Mutable" : true, | |
"Name" : "email", | |
"Required" : true | |
} | |
] | |
} | |
}, | |
"UserPoolClient": { | |
"Type": "AWS::Cognito::UserPoolClient", | |
"DependsOn": ["UserPool"], | |
"Properties": { | |
"ClientName": {"Ref": "UserPoolClientName"}, | |
"UserPoolId": {"Ref": "UserPool"}, | |
"ExplicitAuthFlows": ["ADMIN_NO_SRP_AUTH","USER_PASSWORD_AUTH"] | |
} | |
}, | |
"IdentityPool": { | |
"Type": "AWS::Cognito::IdentityPool", | |
"DependsOn": ["UserPool","UserPoolClient"], | |
"Properties": { | |
"IdentityPoolName": {"Ref": "IdentityPoolName"}, | |
"AllowUnauthenticatedIdentities": true, | |
"CognitoIdentityProviders": [ | |
{ | |
"ClientId": {"Ref": "UserPoolClient"}, | |
"ProviderName": {"Fn::Join" : | |
[ "", [ {"Fn::Sub": "cognito-idp.${AWS::Region}.amazonaws.com/"}, | |
{"Ref": "UserPool"} | |
] | |
] } | |
} | |
] | |
} | |
}, | |
"IdentityPoolAuthenticatedRole": { | |
"Type": "AWS::IAM::Role", | |
"DependsOn": ["IdentityPool", "DBTable"], | |
"Properties": { | |
"Path": "/", | |
"AssumeRolePolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Principal": { | |
"Federated": "cognito-identity.amazonaws.com" | |
}, | |
"Action": "sts:AssumeRoleWithWebIdentity", | |
"Condition": { | |
"StringEquals": { | |
"cognito-identity.amazonaws.com:aud": {"Ref": "IdentityPool"} | |
}, | |
"ForAnyValue:StringLike": { | |
"cognito-identity.amazonaws.com:amr": "authenticated" | |
} | |
} | |
} | |
] | |
}, | |
"Policies": [{ | |
"PolicyName": "root", | |
"PolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"lambda:InvokeFunction" | |
], | |
"Resource": [ | |
"*" | |
] | |
}, | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"mobileanalytics:PutEvents", | |
"cognito-sync:*", | |
"cognito-identity:*" | |
], | |
"Resource": [ | |
"*" | |
] | |
}, | |
{ | |
"Action": [ | |
"dynamodb:*" | |
], | |
"Effect": "Allow", | |
"Resource": {"Fn::Join" : [ "", [{"Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/"}, {"Ref" : "DBTable"}] ] } | |
} | |
] | |
} | |
}] | |
} | |
}, | |
"IdentityPoolUnAuthenticatedRole": { | |
"Type": "AWS::IAM::Role", | |
"DependsOn": ["IdentityPool"], | |
"Properties": { | |
"Path": "/", | |
"AssumeRolePolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Principal": { | |
"Federated": "cognito-identity.amazonaws.com" | |
}, | |
"Action": "sts:AssumeRoleWithWebIdentity", | |
"Condition": { | |
"StringEquals": { | |
"cognito-identity.amazonaws.com:aud": {"Ref": "IdentityPool"} | |
}, | |
"ForAnyValue:StringLike": { | |
"cognito-identity.amazonaws.com:amr": "unauthenticated" | |
} | |
} | |
} | |
] | |
}, | |
"Policies": [{ | |
"PolicyName": "root", | |
"PolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"mobileanalytics:PutEvents", | |
"cognito-sync:*" | |
], | |
"Resource": [ | |
"*" | |
] | |
} | |
] | |
} | |
}] | |
} | |
}, | |
"IdentityPoolRoleAttachment": { | |
"Type": "AWS::Cognito::IdentityPoolRoleAttachment", | |
"DependsOn": ["IdentityPool", "IdentityPoolAuthenticatedRole", "IdentityPoolUnAuthenticatedRole"], | |
"Properties": { | |
"IdentityPoolId": {"Ref": "IdentityPool"}, | |
"Roles": | |
{ | |
"authenticated": {"Fn::GetAtt" : [ "IdentityPoolAuthenticatedRole", "Arn" ]}, | |
"unauthenticated": {"Fn::GetAtt" : [ "IdentityPoolUnAuthenticatedRole", "Arn" ]} | |
} | |
} | |
}, | |
"DBTable": { | |
"Type": "AWS::DynamoDB::Table", | |
"Properties": { | |
"TableName": {"Ref": "DBTableName"}, | |
"BillingMode": "PAY_PER_REQUEST", | |
"SSESpecification": { | |
"SSEEnabled": true | |
}, | |
"KeySchema": [ | |
{ | |
"AttributeName": {"Ref": "DBHashKey"}, | |
"KeyType": "HASH" | |
} | |
], | |
"AttributeDefinitions": [ | |
{ | |
"AttributeName": {"Ref": "DBHashKey"}, | |
"AttributeType": "S" | |
} | |
] | |
} | |
}, | |
"R53RecordSet": { | |
"Type": "AWS::Route53::RecordSet", | |
"DependsOn": ["CloudFrontDistribution"], | |
"Properties": { | |
"HostedZoneId": {"Ref": "ExistingHostedZone"}, | |
"Name": {"Ref": "CloudfrontCName"}, | |
"Type": "CNAME", | |
"TTL": "300", | |
"ResourceRecords": [ | |
{"Fn::GetAtt": ["CloudFrontDistribution", "DomainName"]} | |
] | |
} | |
} | |
}, | |
"Outputs": { | |
"OAI": { | |
"Description": "OAI for use with Cloudfront", | |
"Value": {"Ref": "OriginAccessIdentity"} | |
}, | |
"CodePipelineArtifactBucketLocation": { | |
"Description": "Location of the Code Pipeline artifact S3 bucket.", | |
"Value": {"Fn::Join" : [ "", ["s3://", {"Ref" : "BucketCodePipeline"}] ] } | |
}, | |
"CodePipelineArtifactBucketName": { | |
"Description": "Name of the Code Pipeline artifact S3 bucket.", | |
"Value": {"Ref" : "BucketCodePipeline"} | |
}, | |
"CodeBuildSourceBucket": { | |
"Description": "Codebuild source bucket name", | |
"Value": {"Ref": "BucketCodeBuildSource"} | |
}, | |
"CodeBuildSourceBucketArn": { | |
"Description": "Codebuild source bucket Arn", | |
"Value": {"Fn::GetAtt" : [ "BucketCodeBuildSource", "Arn" ]} | |
}, | |
"CodeBuildOutputBucket": { | |
"Description": "Codebuild output bucket name", | |
"Value": {"Ref": "BucketCodeBuildOutput"} | |
}, | |
"CodePipelineFunctionsBucketArn": { | |
"Description": "Codepipeline functions bucket Arn", | |
"Value": {"Fn::GetAtt" : [ "BucketCodePipelineFunctions", "Arn" ]} | |
}, | |
"CodePipelineFunctionsBucketName": { | |
"Description": "Codepipeline functions bucket name", | |
"Value": {"Ref": "BucketCodePipelineFunctions"} | |
}, | |
"CodeBuildOutputBucketArn": { | |
"Description": "Codebuild output bucket Arn", | |
"Value": {"Fn::GetAtt" : [ "BucketCodeBuildOutput", "Arn" ]} | |
}, | |
"CloudFrontDistributionId": { | |
"Description": "Cloudfront distribution ID", | |
"Value": {"Ref": "CloudFrontDistribution"} | |
}, | |
"CloudFrontDistributionDomain": { | |
"Description": "Cloudfront distribution domain", | |
"Value": {"Fn::GetAtt": ["CloudFrontDistribution", "DomainName"]} | |
}, | |
"CodeBuildProjectArn": { | |
"Description": "CodeBuild Project Arn", | |
"Value": {"Fn::GetAtt": ["CodeBuildProject", "Arn"]} | |
}, | |
"LambdaPipelineFunctionExecutionRole": { | |
"Description": "Execution role for Lambda pipeline functions.", | |
"Value": {"Fn::GetAtt" : [ "CodePipelineLambdaExecutionRole", "Arn" ]} | |
}, | |
"CodePipelineName": { | |
"Description": "Code deployment pipeline name.", | |
"Value": {"Ref" : "CodePipeline"} | |
}, | |
"UserPoolId": { | |
"Description": "The ID of the Cognito User Pool.", | |
"Value": {"Ref" : "UserPool"} | |
}, | |
"UserPoolWebClientId": { | |
"Description": "The ID of the Cognito User Pool Web Client", | |
"Value": {"Ref": "UserPoolClient"} | |
}, | |
"IdentityPoolId": { | |
"Description": "The ID of the Federated Identity Pool", | |
"Value": {"Ref": "IdentityPool"} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment