Skip to content

Instantly share code, notes, and snippets.

@AdonousTech
Created January 26, 2021 22:54
Show Gist options
  • Save AdonousTech/50bff8a46acb1478067db2af90a474c8 to your computer and use it in GitHub Desktop.
Save AdonousTech/50bff8a46acb1478067db2af90a474c8 to your computer and use it in GitHub Desktop.
A Cloud Coach - Tutorial - Serverless Stripe Store - 008 - SPA Infra CloudFormation Template
{
"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