From 6c9f2fd042f1fc955661c5c24796265d4625428a Mon Sep 17 00:00:00 2001 From: brtrvn Date: Fri, 1 Mar 2024 12:31:49 -0800 Subject: [PATCH] Updates for WorkshopStudio compatibility --- Lab2/Part1/product-manager/deploy.sh | 10 +- Lab2/Part2/product-manager/deploy.sh | 10 +- Lab2/Part3/product-manager/deploy.sh | 10 +- Lab3/Part1/product-manager/deploy.sh | 10 +- Lab3/Part4/product-manager/deploy.sh | 10 +- Lab3/Part5/product-manager/deploy.sh | 10 +- resources/auth-service.yml | 23 +- resources/baseline.yml | 52 +++-- resources/ee-team-role.json | 50 ---- resources/order-service.yml | 23 +- resources/product-service.yml | 26 ++- resources/registration-service.yml | 23 +- resources/tenant-service.yml | 23 +- resources/user-service.yml | 23 +- resources/web-client.yml | 39 +++- resources/workshop.yml | 329 +++++++++++++++------------ 16 files changed, 384 insertions(+), 287 deletions(-) delete mode 100644 resources/ee-team-role.json diff --git a/Lab2/Part1/product-manager/deploy.sh b/Lab2/Part1/product-manager/deploy.sh index 0cf71cb..92e9c2f 100755 --- a/Lab2/Part1/product-manager/deploy.sh +++ b/Lab2/Part1/product-manager/deploy.sh @@ -23,7 +23,8 @@ AWS_REGION=$(aws configure list | grep region | awk '{print $2}') CODEBUILD_PROJECT="saas-bootcamp-product-svc" CODE_PIPELINE="saas-bootcamp-product-svc" BOOTCAMP_BUCKET=$(aws ssm get-parameter --name "saas-bootcamp-bucket" | jq -r '.Parameter.Value') -DEPLOY_MONITOR_QUEUE=$(aws ssm get-parameter --name "saas-bootcamp-ci-cd-queue-${AWS_REGION}" | jq -r '.Parameter.Value') +BOOTCAMP_BUCKET_PREFIX=$(aws ssm get-parameter --name "saas-bootcamp-bucket-prefix" | jq -r '.Parameter.Value') +DEPLOY_MONITOR_QUEUE=$(aws ssm get-parameter --name "saas-bootcamp-ci-cd-queue" | jq -r '.Parameter.Value') if [ -z "$BOOTCAMP_BUCKET" ]; then echo "Error: Can't determine SaaS Bootcamp S3 bucket name" @@ -34,7 +35,12 @@ if [ -z "$DEPLOY_MONITOR_QUEUE" ]; then exit 1 fi +if [ "N/A" == "$BOOTCAMP_BUCKET_PREFIX" ]; then + BOOTCAMP_BUCKET_PREFIX="" +fi + echo "SaaS Bootcamp S3 bucket: $BOOTCAMP_BUCKET" +echo "SaaS Bootcamp S3 bucket prefix: $BOOTCAMP_BUCKET_PREFIX" echo "SaaS Bootcamp SQS queue: $DEPLOY_MONITOR_QUEUE" echo @@ -43,7 +49,7 @@ aws sqs purge-queue --queue-url "$DEPLOY_MONITOR_QUEUE" > /dev/null # Upload the updated code to S3 echo "Uploading code to S3" -aws s3 cp server.js s3://${BOOTCAMP_BUCKET}/source/product-manager/ +aws s3 cp server.js s3://${BOOTCAMP_BUCKET}/${BOOTCAMP_BUCKET_PREFIX}source/product-manager/ # Trigger a new build to create a fresh docker image with the updated code BUILD_PROJECT=$(aws codebuild start-build --project-name ${CODEBUILD_PROJECT}) diff --git a/Lab2/Part2/product-manager/deploy.sh b/Lab2/Part2/product-manager/deploy.sh index 0cf71cb..92e9c2f 100755 --- a/Lab2/Part2/product-manager/deploy.sh +++ b/Lab2/Part2/product-manager/deploy.sh @@ -23,7 +23,8 @@ AWS_REGION=$(aws configure list | grep region | awk '{print $2}') CODEBUILD_PROJECT="saas-bootcamp-product-svc" CODE_PIPELINE="saas-bootcamp-product-svc" BOOTCAMP_BUCKET=$(aws ssm get-parameter --name "saas-bootcamp-bucket" | jq -r '.Parameter.Value') -DEPLOY_MONITOR_QUEUE=$(aws ssm get-parameter --name "saas-bootcamp-ci-cd-queue-${AWS_REGION}" | jq -r '.Parameter.Value') +BOOTCAMP_BUCKET_PREFIX=$(aws ssm get-parameter --name "saas-bootcamp-bucket-prefix" | jq -r '.Parameter.Value') +DEPLOY_MONITOR_QUEUE=$(aws ssm get-parameter --name "saas-bootcamp-ci-cd-queue" | jq -r '.Parameter.Value') if [ -z "$BOOTCAMP_BUCKET" ]; then echo "Error: Can't determine SaaS Bootcamp S3 bucket name" @@ -34,7 +35,12 @@ if [ -z "$DEPLOY_MONITOR_QUEUE" ]; then exit 1 fi +if [ "N/A" == "$BOOTCAMP_BUCKET_PREFIX" ]; then + BOOTCAMP_BUCKET_PREFIX="" +fi + echo "SaaS Bootcamp S3 bucket: $BOOTCAMP_BUCKET" +echo "SaaS Bootcamp S3 bucket prefix: $BOOTCAMP_BUCKET_PREFIX" echo "SaaS Bootcamp SQS queue: $DEPLOY_MONITOR_QUEUE" echo @@ -43,7 +49,7 @@ aws sqs purge-queue --queue-url "$DEPLOY_MONITOR_QUEUE" > /dev/null # Upload the updated code to S3 echo "Uploading code to S3" -aws s3 cp server.js s3://${BOOTCAMP_BUCKET}/source/product-manager/ +aws s3 cp server.js s3://${BOOTCAMP_BUCKET}/${BOOTCAMP_BUCKET_PREFIX}source/product-manager/ # Trigger a new build to create a fresh docker image with the updated code BUILD_PROJECT=$(aws codebuild start-build --project-name ${CODEBUILD_PROJECT}) diff --git a/Lab2/Part3/product-manager/deploy.sh b/Lab2/Part3/product-manager/deploy.sh index 0cf71cb..92e9c2f 100755 --- a/Lab2/Part3/product-manager/deploy.sh +++ b/Lab2/Part3/product-manager/deploy.sh @@ -23,7 +23,8 @@ AWS_REGION=$(aws configure list | grep region | awk '{print $2}') CODEBUILD_PROJECT="saas-bootcamp-product-svc" CODE_PIPELINE="saas-bootcamp-product-svc" BOOTCAMP_BUCKET=$(aws ssm get-parameter --name "saas-bootcamp-bucket" | jq -r '.Parameter.Value') -DEPLOY_MONITOR_QUEUE=$(aws ssm get-parameter --name "saas-bootcamp-ci-cd-queue-${AWS_REGION}" | jq -r '.Parameter.Value') +BOOTCAMP_BUCKET_PREFIX=$(aws ssm get-parameter --name "saas-bootcamp-bucket-prefix" | jq -r '.Parameter.Value') +DEPLOY_MONITOR_QUEUE=$(aws ssm get-parameter --name "saas-bootcamp-ci-cd-queue" | jq -r '.Parameter.Value') if [ -z "$BOOTCAMP_BUCKET" ]; then echo "Error: Can't determine SaaS Bootcamp S3 bucket name" @@ -34,7 +35,12 @@ if [ -z "$DEPLOY_MONITOR_QUEUE" ]; then exit 1 fi +if [ "N/A" == "$BOOTCAMP_BUCKET_PREFIX" ]; then + BOOTCAMP_BUCKET_PREFIX="" +fi + echo "SaaS Bootcamp S3 bucket: $BOOTCAMP_BUCKET" +echo "SaaS Bootcamp S3 bucket prefix: $BOOTCAMP_BUCKET_PREFIX" echo "SaaS Bootcamp SQS queue: $DEPLOY_MONITOR_QUEUE" echo @@ -43,7 +49,7 @@ aws sqs purge-queue --queue-url "$DEPLOY_MONITOR_QUEUE" > /dev/null # Upload the updated code to S3 echo "Uploading code to S3" -aws s3 cp server.js s3://${BOOTCAMP_BUCKET}/source/product-manager/ +aws s3 cp server.js s3://${BOOTCAMP_BUCKET}/${BOOTCAMP_BUCKET_PREFIX}source/product-manager/ # Trigger a new build to create a fresh docker image with the updated code BUILD_PROJECT=$(aws codebuild start-build --project-name ${CODEBUILD_PROJECT}) diff --git a/Lab3/Part1/product-manager/deploy.sh b/Lab3/Part1/product-manager/deploy.sh index 0cf71cb..92e9c2f 100755 --- a/Lab3/Part1/product-manager/deploy.sh +++ b/Lab3/Part1/product-manager/deploy.sh @@ -23,7 +23,8 @@ AWS_REGION=$(aws configure list | grep region | awk '{print $2}') CODEBUILD_PROJECT="saas-bootcamp-product-svc" CODE_PIPELINE="saas-bootcamp-product-svc" BOOTCAMP_BUCKET=$(aws ssm get-parameter --name "saas-bootcamp-bucket" | jq -r '.Parameter.Value') -DEPLOY_MONITOR_QUEUE=$(aws ssm get-parameter --name "saas-bootcamp-ci-cd-queue-${AWS_REGION}" | jq -r '.Parameter.Value') +BOOTCAMP_BUCKET_PREFIX=$(aws ssm get-parameter --name "saas-bootcamp-bucket-prefix" | jq -r '.Parameter.Value') +DEPLOY_MONITOR_QUEUE=$(aws ssm get-parameter --name "saas-bootcamp-ci-cd-queue" | jq -r '.Parameter.Value') if [ -z "$BOOTCAMP_BUCKET" ]; then echo "Error: Can't determine SaaS Bootcamp S3 bucket name" @@ -34,7 +35,12 @@ if [ -z "$DEPLOY_MONITOR_QUEUE" ]; then exit 1 fi +if [ "N/A" == "$BOOTCAMP_BUCKET_PREFIX" ]; then + BOOTCAMP_BUCKET_PREFIX="" +fi + echo "SaaS Bootcamp S3 bucket: $BOOTCAMP_BUCKET" +echo "SaaS Bootcamp S3 bucket prefix: $BOOTCAMP_BUCKET_PREFIX" echo "SaaS Bootcamp SQS queue: $DEPLOY_MONITOR_QUEUE" echo @@ -43,7 +49,7 @@ aws sqs purge-queue --queue-url "$DEPLOY_MONITOR_QUEUE" > /dev/null # Upload the updated code to S3 echo "Uploading code to S3" -aws s3 cp server.js s3://${BOOTCAMP_BUCKET}/source/product-manager/ +aws s3 cp server.js s3://${BOOTCAMP_BUCKET}/${BOOTCAMP_BUCKET_PREFIX}source/product-manager/ # Trigger a new build to create a fresh docker image with the updated code BUILD_PROJECT=$(aws codebuild start-build --project-name ${CODEBUILD_PROJECT}) diff --git a/Lab3/Part4/product-manager/deploy.sh b/Lab3/Part4/product-manager/deploy.sh index 0cf71cb..92e9c2f 100755 --- a/Lab3/Part4/product-manager/deploy.sh +++ b/Lab3/Part4/product-manager/deploy.sh @@ -23,7 +23,8 @@ AWS_REGION=$(aws configure list | grep region | awk '{print $2}') CODEBUILD_PROJECT="saas-bootcamp-product-svc" CODE_PIPELINE="saas-bootcamp-product-svc" BOOTCAMP_BUCKET=$(aws ssm get-parameter --name "saas-bootcamp-bucket" | jq -r '.Parameter.Value') -DEPLOY_MONITOR_QUEUE=$(aws ssm get-parameter --name "saas-bootcamp-ci-cd-queue-${AWS_REGION}" | jq -r '.Parameter.Value') +BOOTCAMP_BUCKET_PREFIX=$(aws ssm get-parameter --name "saas-bootcamp-bucket-prefix" | jq -r '.Parameter.Value') +DEPLOY_MONITOR_QUEUE=$(aws ssm get-parameter --name "saas-bootcamp-ci-cd-queue" | jq -r '.Parameter.Value') if [ -z "$BOOTCAMP_BUCKET" ]; then echo "Error: Can't determine SaaS Bootcamp S3 bucket name" @@ -34,7 +35,12 @@ if [ -z "$DEPLOY_MONITOR_QUEUE" ]; then exit 1 fi +if [ "N/A" == "$BOOTCAMP_BUCKET_PREFIX" ]; then + BOOTCAMP_BUCKET_PREFIX="" +fi + echo "SaaS Bootcamp S3 bucket: $BOOTCAMP_BUCKET" +echo "SaaS Bootcamp S3 bucket prefix: $BOOTCAMP_BUCKET_PREFIX" echo "SaaS Bootcamp SQS queue: $DEPLOY_MONITOR_QUEUE" echo @@ -43,7 +49,7 @@ aws sqs purge-queue --queue-url "$DEPLOY_MONITOR_QUEUE" > /dev/null # Upload the updated code to S3 echo "Uploading code to S3" -aws s3 cp server.js s3://${BOOTCAMP_BUCKET}/source/product-manager/ +aws s3 cp server.js s3://${BOOTCAMP_BUCKET}/${BOOTCAMP_BUCKET_PREFIX}source/product-manager/ # Trigger a new build to create a fresh docker image with the updated code BUILD_PROJECT=$(aws codebuild start-build --project-name ${CODEBUILD_PROJECT}) diff --git a/Lab3/Part5/product-manager/deploy.sh b/Lab3/Part5/product-manager/deploy.sh index 0cf71cb..92e9c2f 100755 --- a/Lab3/Part5/product-manager/deploy.sh +++ b/Lab3/Part5/product-manager/deploy.sh @@ -23,7 +23,8 @@ AWS_REGION=$(aws configure list | grep region | awk '{print $2}') CODEBUILD_PROJECT="saas-bootcamp-product-svc" CODE_PIPELINE="saas-bootcamp-product-svc" BOOTCAMP_BUCKET=$(aws ssm get-parameter --name "saas-bootcamp-bucket" | jq -r '.Parameter.Value') -DEPLOY_MONITOR_QUEUE=$(aws ssm get-parameter --name "saas-bootcamp-ci-cd-queue-${AWS_REGION}" | jq -r '.Parameter.Value') +BOOTCAMP_BUCKET_PREFIX=$(aws ssm get-parameter --name "saas-bootcamp-bucket-prefix" | jq -r '.Parameter.Value') +DEPLOY_MONITOR_QUEUE=$(aws ssm get-parameter --name "saas-bootcamp-ci-cd-queue" | jq -r '.Parameter.Value') if [ -z "$BOOTCAMP_BUCKET" ]; then echo "Error: Can't determine SaaS Bootcamp S3 bucket name" @@ -34,7 +35,12 @@ if [ -z "$DEPLOY_MONITOR_QUEUE" ]; then exit 1 fi +if [ "N/A" == "$BOOTCAMP_BUCKET_PREFIX" ]; then + BOOTCAMP_BUCKET_PREFIX="" +fi + echo "SaaS Bootcamp S3 bucket: $BOOTCAMP_BUCKET" +echo "SaaS Bootcamp S3 bucket prefix: $BOOTCAMP_BUCKET_PREFIX" echo "SaaS Bootcamp SQS queue: $DEPLOY_MONITOR_QUEUE" echo @@ -43,7 +49,7 @@ aws sqs purge-queue --queue-url "$DEPLOY_MONITOR_QUEUE" > /dev/null # Upload the updated code to S3 echo "Uploading code to S3" -aws s3 cp server.js s3://${BOOTCAMP_BUCKET}/source/product-manager/ +aws s3 cp server.js s3://${BOOTCAMP_BUCKET}/${BOOTCAMP_BUCKET_PREFIX}source/product-manager/ # Trigger a new build to create a fresh docker image with the updated code BUILD_PROJECT=$(aws codebuild start-build --project-name ${CODEBUILD_PROJECT}) diff --git a/resources/auth-service.yml b/resources/auth-service.yml index 3697dc9..8ff9974 100644 --- a/resources/auth-service.yml +++ b/resources/auth-service.yml @@ -2,9 +2,13 @@ AWSTemplateFormatVersion: 2010-09-09 Description: AWS SaaS Factory Bootcamp Auth Service Parameters: - BootcampBucket: + WorkshopBucket: Description: The S3 bucket with bootcamp resources Type: String + AssetsBucketPrefix: + Description: S3 folder containing workshop assets. Leave blank if you did not put the assets in a subfolder. + Type: String + Default: '' ArtifactBucket: Description: The S3 bucket for CodeBuild to store built artifacts Type: String @@ -74,6 +78,9 @@ Resources: Path: '/' Name: auth-manager Packaging: ZIP + Cache: + Type: S3 + Location: !Sub ${WorkshopBucket}/${AssetsBucketPrefix}codebuild-cache Environment: ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0 @@ -82,8 +89,10 @@ Resources: EnvironmentVariables: - Name: REPOSITORY_URI Value: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECSRepository} - - Name: BOOTCAMP_BUCKET - Value: !Ref BootcampBucket + - Name: SOURCE_BUCKET + Value: !Ref WorkshopBucket + - Name: SOURCE_BUCKET_PREFIX + Value: !Ref AssetsBucketPrefix Source: Type: NO_SOURCE BuildSpec: | @@ -91,8 +100,8 @@ Resources: phases: pre_build: commands: - - aws s3 cp --recursive s3://$BOOTCAMP_BUCKET/source/auth-manager ./auth-manager - - aws s3 cp --recursive s3://$BOOTCAMP_BUCKET/source/shared-modules ./auth-manager/shared-modules + - aws s3 cp --recursive s3://$SOURCE_BUCKET/${SOURCE_BUCKET_PREFIX}source/auth-manager ./auth-manager + - aws s3 cp --recursive s3://$SOURCE_BUCKET/${SOURCE_BUCKET_PREFIX}source/shared-modules ./auth-manager/shared-modules - aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $REPOSITORY_URI build: commands: @@ -184,7 +193,7 @@ Resources: Type: AWS::IAM::Role DependsOn: ECSLogGroup Properties: - RoleName: saas-bootcamp-auth-svc-exec-role + RoleName: !Sub saas-bootcamp-auth-svc-exec-role-${AWS::Region} Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 @@ -228,7 +237,7 @@ Resources: ECSTaskRole: Type: AWS::IAM::Role Properties: - RoleName: saas-bootcamp-auth-svc-task-role + RoleName: !Sub saas-bootcamp-auth-svc-task-role-${AWS::Region} Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 diff --git a/resources/baseline.yml b/resources/baseline.yml index 5065435..dacb6b8 100644 --- a/resources/baseline.yml +++ b/resources/baseline.yml @@ -2,9 +2,13 @@ AWSTemplateFormatVersion: 2010-09-09 Description: AWS SaaS Factory Bootcamp Baseline Parameters: - BootcampBucket: + WorkshopBucket: Description: S3 bucket with workshop resources Type: String + AssetsBucketPrefix: + Description: S3 folder containing workshop assets. Leave blank if you did not put the assets in a subfolder. + Type: String + Default: '' ParticipantAssumedRoleArn: Description: Workshop Studio Participant IAM Role. Leave blank when not using Workshop Studio. Type: String @@ -167,6 +171,7 @@ Resources: AutomaticStopTimeMinutes: 60 SubnetId: !Ref SubnetPublicA InstanceType: t3.medium + ImageId: amazonlinux-2-x86_64 Name: SaaS Bootcamp IDE Repositories: - RepositoryUrl: https://github.com/aws-samples/aws-saas-factory-bootcamp @@ -268,7 +273,7 @@ Resources: - s3:ListBucketVersions - s3:GetBucketVersioning Resource: - - !Sub arn:aws:s3:::${BootcampBucket} + - !Sub arn:aws:s3:::${WorkshopBucket} - Effect: Allow Action: - s3:GetObject @@ -276,7 +281,7 @@ Resources: - s3:DeleteObject - s3:DeleteObjectVersion Resource: - - !Sub arn:aws:s3:::${BootcampBucket}/* + - !Sub arn:aws:s3:::${WorkshopBucket}/* LambdaCodeBuildStartBuildLogs: Type: AWS::Logs::LogGroup Properties: @@ -346,7 +351,7 @@ Resources: - s3:listBucket - s3:GetBucketVersioning Resource: - - !Sub arn:aws:s3:::${BootcampBucket} + - !Sub arn:aws:s3:::${WorkshopBucket} - !Sub arn:aws:s3:::${ArtifactBucket} - !Sub arn:aws:s3:::${WebsiteBucket} - Effect: Allow @@ -357,7 +362,7 @@ Resources: - s3:GetObject - s3:GetObjectVersion Resource: - - !Sub arn:aws:s3:::${BootcampBucket}/* + - !Sub arn:aws:s3:::${WorkshopBucket}/* - !Sub arn:aws:s3:::${ArtifactBucket}/* - !Sub arn:aws:s3:::${WebsiteBucket}/* - Effect: Allow @@ -668,15 +673,16 @@ Resources: ApiGateway: Type: AWS::CloudFormation::Stack Properties: - TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${BootcampBucket}/resources/api-gateway.yml + TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${WorkshopBucket}/${AssetsBucketPrefix}resources/api-gateway.yml Parameters: ECSLoadBalancer: !GetAtt ECSLoadBalancer.DNSName UserService: Type: AWS::CloudFormation::Stack Properties: - TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${BootcampBucket}/resources/user-service.yml + TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${WorkshopBucket}/${AssetsBucketPrefix}resources/user-service.yml Parameters: - BootcampBucket: !Ref BootcampBucket + WorkshopBucket: !Ref WorkshopBucket + AssetsBucketPrefix: !Ref AssetsBucketPrefix ArtifactBucket: !Ref ArtifactBucket CodeBuildRoleArn: !GetAtt CodeBuildRole.Arn CodePipelineRoleArn: !GetAtt CodePipelineRole.Arn @@ -693,9 +699,10 @@ Resources: AuthService: Type: AWS::CloudFormation::Stack Properties: - TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${BootcampBucket}/resources/auth-service.yml + TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${WorkshopBucket}/${AssetsBucketPrefix}resources/auth-service.yml Parameters: - BootcampBucket: !Ref BootcampBucket + WorkshopBucket: !Ref WorkshopBucket + AssetsBucketPrefix: !Ref AssetsBucketPrefix ArtifactBucket: !Ref ArtifactBucket CodeBuildRoleArn: !GetAtt CodeBuildRole.Arn CodePipelineRoleArn: !GetAtt CodePipelineRole.Arn @@ -712,9 +719,10 @@ Resources: TenantService: Type: AWS::CloudFormation::Stack Properties: - TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${BootcampBucket}/resources/tenant-service.yml + TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${WorkshopBucket}/${AssetsBucketPrefix}resources/tenant-service.yml Parameters: - BootcampBucket: !Ref BootcampBucket + WorkshopBucket: !Ref WorkshopBucket + AssetsBucketPrefix: !Ref AssetsBucketPrefix ArtifactBucket: !Ref ArtifactBucket CodeBuildRoleArn: !GetAtt CodeBuildRole.Arn CodePipelineRoleArn: !GetAtt CodePipelineRole.Arn @@ -731,9 +739,10 @@ Resources: RegistrationService: Type: AWS::CloudFormation::Stack Properties: - TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${BootcampBucket}/resources/registration-service.yml + TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${WorkshopBucket}/${AssetsBucketPrefix}resources/registration-service.yml Parameters: - BootcampBucket: !Ref BootcampBucket + WorkshopBucket: !Ref WorkshopBucket + AssetsBucketPrefix: !Ref AssetsBucketPrefix ArtifactBucket: !Ref ArtifactBucket CodeBuildRoleArn: !GetAtt CodeBuildRole.Arn CodePipelineRoleArn: !GetAtt CodePipelineRole.Arn @@ -750,9 +759,10 @@ Resources: OrderService: Type: AWS::CloudFormation::Stack Properties: - TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${BootcampBucket}/resources/order-service.yml + TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${WorkshopBucket}/${AssetsBucketPrefix}resources/order-service.yml Parameters: - BootcampBucket: !Ref BootcampBucket + WorkshopBucket: !Ref WorkshopBucket + AssetsBucketPrefix: !Ref AssetsBucketPrefix ArtifactBucket: !Ref ArtifactBucket CodeBuildRoleArn: !GetAtt CodeBuildRole.Arn CodePipelineRoleArn: !GetAtt CodePipelineRole.Arn @@ -769,9 +779,10 @@ Resources: ProductService: Type: AWS::CloudFormation::Stack Properties: - TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${BootcampBucket}/resources/product-service.yml + TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${WorkshopBucket}/${AssetsBucketPrefix}resources/product-service.yml Parameters: - BootcampBucket: !Ref BootcampBucket + WorkshopBucket: !Ref WorkshopBucket + AssetsBucketPrefix: !Ref AssetsBucketPrefix ArtifactBucket: !Ref ArtifactBucket CodeBuildRoleArn: !GetAtt CodeBuildRole.Arn CodePipelineRoleArn: !GetAtt CodePipelineRole.Arn @@ -788,9 +799,10 @@ Resources: WebClient: Type: AWS::CloudFormation::Stack Properties: - TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${BootcampBucket}/resources/web-client.yml + TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${WorkshopBucket}/${AssetsBucketPrefix}resources/web-client.yml Parameters: - BootcampBucket: !Ref BootcampBucket + WorkshopBucket: !Ref WorkshopBucket + AssetsBucketPrefix: !Ref AssetsBucketPrefix WebsiteBucket: !Ref WebsiteBucket CodeBuildRoleArn: !GetAtt CodeBuildRole.Arn LambdaCodeBuildStartBuildArn: !GetAtt LambdaCodeBuildStartBuild.Arn diff --git a/resources/ee-team-role.json b/resources/ee-team-role.json deleted file mode 100644 index a12d735..0000000 --- a/resources/ee-team-role.json +++ /dev/null @@ -1,50 +0,0 @@ -[ - { - "Sid": "SaaSBootcampTeamRolePolicy", - "Action": [ - "cloud9:DescribeEnvironmentMemberships", - "apigateway:GET", - "waf-regional:ListWebACLs", - "waf-regional:AssociateWebACL", - "wafv2:ListWebACLs", - "wafv2:AssociateWebACL", - "cloudfront:List*", - "cloudfront:Get*", - "application-autoscaling:*", - "dynamodb:*", - "cognito-identity:*", - "cognito-idp:*", - "cognito-sync:*", - "ssm:GetParameter", - "sqs:ReceiveMessage", - "sqs:PurgeQueue", - "sqs:DeleteMessage", - "s3:PutObject", - "codebuild:*", - "ecr:*", - "ecs:*", - "sns:CreateTopic", - "cloudwatch:*", - "logs:*" - ], - "Resource": "*", - "Effect": "Allow" - }, - { - "Sid": "CognitoIdPoolRoles", - "Effect": "Allow", - "Action": [ - "iam:CreateRole", - "iam:PutRolePolicy" - ], - "Resource": "arn:aws:iam::$$teamAccountId:role/Cognito*" - }, - { - "Sid": "DynamoDBRequestConditions", - "Effect": "Allow", - "Action": [ - "iam:CreatePolicyVersion" - ], - "Resource": "arn:aws:iam::$$teamAccountId:policy/TENANT*" - } -] diff --git a/resources/order-service.yml b/resources/order-service.yml index 819d33f..94aa686 100644 --- a/resources/order-service.yml +++ b/resources/order-service.yml @@ -2,9 +2,13 @@ AWSTemplateFormatVersion: 2010-09-09 Description: AWS SaaS Factory Bootcamp Order Service Parameters: - BootcampBucket: + WorkshopBucket: Description: The S3 bucket with bootcamp resources Type: String + AssetsBucketPrefix: + Description: S3 folder containing workshop assets. Leave blank if you did not put the assets in a subfolder. + Type: String + Default: '' ArtifactBucket: Description: The S3 bucket for CodeBuild to store built artifacts Type: String @@ -91,6 +95,9 @@ Resources: Path: '/' Name: order-manager Packaging: ZIP + Cache: + Type: S3 + Location: !Sub ${WorkshopBucket}/${AssetsBucketPrefix}codebuild-cache Environment: ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0 @@ -99,8 +106,10 @@ Resources: EnvironmentVariables: - Name: REPOSITORY_URI Value: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECSRepository} - - Name: BOOTCAMP_BUCKET - Value: !Ref BootcampBucket + - Name: SOURCE_BUCKET + Value: !Ref WorkshopBucket + - Name: SOURCE_BUCKET_PREFIX + Value: !Ref AssetsBucketPrefix Source: Type: NO_SOURCE BuildSpec: | @@ -108,8 +117,8 @@ Resources: phases: pre_build: commands: - - aws s3 cp --recursive s3://$BOOTCAMP_BUCKET/source/order-manager ./order-manager - - aws s3 cp --recursive s3://$BOOTCAMP_BUCKET/source/shared-modules ./order-manager/shared-modules + - aws s3 cp --recursive s3://$SOURCE_BUCKET/${SOURCE_BUCKET_PREFIX}source/order-manager ./order-manager + - aws s3 cp --recursive s3://$SOURCE_BUCKET/${SOURCE_BUCKET_PREFIX}source/shared-modules ./order-manager/shared-modules - aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $REPOSITORY_URI build: commands: @@ -201,7 +210,7 @@ Resources: Type: AWS::IAM::Role DependsOn: ECSLogGroup Properties: - RoleName: saas-bootcamp-order-svc-exec-role + RoleName: !Sub saas-bootcamp-order-svc-exec-role-${AWS::Region} Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 @@ -245,7 +254,7 @@ Resources: ECSTaskRole: Type: AWS::IAM::Role Properties: - RoleName: saas-bootcamp-order-svc-task-role + RoleName: !Sub saas-bootcamp-order-svc-task-role-${AWS::Region} Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 diff --git a/resources/product-service.yml b/resources/product-service.yml index 9c22628..ee6b806 100644 --- a/resources/product-service.yml +++ b/resources/product-service.yml @@ -2,9 +2,13 @@ AWSTemplateFormatVersion: 2010-09-09 Description: AWS SaaS Factory Bootcamp Product Service Parameters: - BootcampBucket: + WorkshopBucket: Description: The S3 bucket with bootcamp resources Type: String + AssetsBucketPrefix: + Description: S3 folder containing workshop assets. Leave blank if you did not put the assets in a subfolder. + Type: String + Default: '' ArtifactBucket: Description: The S3 bucket for CodeBuild to store built artifacts Type: String @@ -74,6 +78,9 @@ Resources: Path: '/' Name: product-manager Packaging: ZIP + Cache: + Type: S3 + Location: !Sub ${WorkshopBucket}/${AssetsBucketPrefix}codebuild-cache Environment: ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0 @@ -82,8 +89,10 @@ Resources: EnvironmentVariables: - Name: REPOSITORY_URI Value: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECSRepository} - - Name: BOOTCAMP_BUCKET - Value: !Ref BootcampBucket + - Name: SOURCE_BUCKET + Value: !Ref WorkshopBucket + - Name: SOURCE_BUCKET_PREFIX + Value: !Ref AssetsBucketPrefix Source: Type: NO_SOURCE BuildSpec: | @@ -91,8 +100,8 @@ Resources: phases: pre_build: commands: - - aws s3 cp --recursive s3://$BOOTCAMP_BUCKET/source/product-manager ./product-manager - - aws s3 cp --recursive s3://$BOOTCAMP_BUCKET/source/shared-modules ./product-manager/shared-modules + - aws s3 cp --recursive s3://$SOURCE_BUCKET/${SOURCE_BUCKET_PREFIX}source/product-manager ./product-manager + - aws s3 cp --recursive s3://$SOURCE_BUCKET/${SOURCE_BUCKET_PREFIX}source/shared-modules ./product-manager/shared-modules - aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $REPOSITORY_URI build: commands: @@ -203,6 +212,7 @@ Resources: Type: AWS::SQS::Queue Properties: QueueName: saas-bootcamp-product-svc + SqsManagedSseEnabled: true CodePipelineMonitorQueuePolicy: Type: AWS::SQS::QueuePolicy Properties: @@ -220,14 +230,14 @@ Resources: CodePipelineMonitorQueueSsmParam: Type: AWS::SSM::Parameter Properties: - Name: !Sub saas-bootcamp-ci-cd-queue-${AWS::Region} + Name: saas-bootcamp-ci-cd-queue Type: String Value: !Ref CodePipelineMonitorQueue ECSTaskExecutionRole: Type: AWS::IAM::Role DependsOn: ECSLogGroup Properties: - RoleName: saas-bootcamp-product-svc-exec-role + RoleName: !Sub saas-bootcamp-product-svc-exec-role-${AWS::Region} Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 @@ -271,7 +281,7 @@ Resources: ECSTaskRole: Type: AWS::IAM::Role Properties: - RoleName: saas-bootcamp-product-svc-task-role + RoleName: !Sub saas-bootcamp-product-svc-task-role-${AWS::Region} Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 diff --git a/resources/registration-service.yml b/resources/registration-service.yml index d40912a..be9f82e 100644 --- a/resources/registration-service.yml +++ b/resources/registration-service.yml @@ -2,9 +2,13 @@ AWSTemplateFormatVersion: 2010-09-09 Description: AWS SaaS Factory Bootcamp Tenant Registration Service Parameters: - BootcampBucket: + WorkshopBucket: Description: The S3 bucket with bootcamp resources Type: String + AssetsBucketPrefix: + Description: S3 folder containing workshop assets. Leave blank if you did not put the assets in a subfolder. + Type: String + Default: '' ArtifactBucket: Description: The S3 bucket for CodeBuild to store built artifacts Type: String @@ -74,6 +78,9 @@ Resources: Path: '/' Name: tenant-registration Packaging: ZIP + Cache: + Type: S3 + Location: !Sub ${WorkshopBucket}/${AssetsBucketPrefix}codebuild-cache Environment: ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0 @@ -82,8 +89,10 @@ Resources: EnvironmentVariables: - Name: REPOSITORY_URI Value: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECSRepository} - - Name: BOOTCAMP_BUCKET - Value: !Ref BootcampBucket + - Name: SOURCE_BUCKET + Value: !Ref WorkshopBucket + - Name: SOURCE_BUCKET_PREFIX + Value: !Ref AssetsBucketPrefix Source: Type: NO_SOURCE BuildSpec: | @@ -91,8 +100,8 @@ Resources: phases: pre_build: commands: - - aws s3 cp --recursive s3://$BOOTCAMP_BUCKET/source/tenant-registration ./tenant-registration - - aws s3 cp --recursive s3://$BOOTCAMP_BUCKET/source/shared-modules ./tenant-registration/shared-modules + - aws s3 cp --recursive s3://$SOURCE_BUCKET/${SOURCE_BUCKET_PREFIX}source/tenant-registration ./tenant-registration + - aws s3 cp --recursive s3://$SOURCE_BUCKET/${SOURCE_BUCKET_PREFIX}source/shared-modules ./tenant-registration/shared-modules - aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $REPOSITORY_URI build: commands: @@ -184,7 +193,7 @@ Resources: Type: AWS::IAM::Role DependsOn: ECSLogGroup Properties: - RoleName: saas-bootcamp-registration-svc-exec-role + RoleName: !Sub saas-bootcamp-registration-svc-exec-role-${AWS::Region} Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 @@ -228,7 +237,7 @@ Resources: ECSTaskRole: Type: AWS::IAM::Role Properties: - RoleName: saas-bootcamp-registration-svc-task-role + RoleName: !Sub saas-bootcamp-registration-svc-task-role-${AWS::Region} Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 diff --git a/resources/tenant-service.yml b/resources/tenant-service.yml index ee2750d..bc79ea7 100644 --- a/resources/tenant-service.yml +++ b/resources/tenant-service.yml @@ -2,9 +2,13 @@ AWSTemplateFormatVersion: 2010-09-09 Description: AWS SaaS Factory Bootcamp Tenant Service Parameters: - BootcampBucket: + WorkshopBucket: Description: The S3 bucket with bootcamp resources Type: String + AssetsBucketPrefix: + Description: S3 folder containing workshop assets. Leave blank if you did not put the assets in a subfolder. + Type: String + Default: '' ArtifactBucket: Description: The S3 bucket for CodeBuild to store built artifacts Type: String @@ -87,6 +91,9 @@ Resources: Path: '/' Name: tenant-manager Packaging: ZIP + Cache: + Type: S3 + Location: !Sub ${WorkshopBucket}/${AssetsBucketPrefix}codebuild-cache Environment: ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0 @@ -95,8 +102,10 @@ Resources: EnvironmentVariables: - Name: REPOSITORY_URI Value: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECSRepository} - - Name: BOOTCAMP_BUCKET - Value: !Ref BootcampBucket + - Name: SOURCE_BUCKET + Value: !Ref WorkshopBucket + - Name: SOURCE_BUCKET_PREFIX + Value: !Ref AssetsBucketPrefix Source: Type: NO_SOURCE BuildSpec: | @@ -104,8 +113,8 @@ Resources: phases: pre_build: commands: - - aws s3 cp --recursive s3://$BOOTCAMP_BUCKET/source/tenant-manager ./tenant-manager - - aws s3 cp --recursive s3://$BOOTCAMP_BUCKET/source/shared-modules ./tenant-manager/shared-modules + - aws s3 cp --recursive s3://$SOURCE_BUCKET/${SOURCE_BUCKET_PREFIX}source/tenant-manager ./tenant-manager + - aws s3 cp --recursive s3://$SOURCE_BUCKET/${SOURCE_BUCKET_PREFIX}source/shared-modules ./tenant-manager/shared-modules - aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $REPOSITORY_URI build: commands: @@ -197,7 +206,7 @@ Resources: Type: AWS::IAM::Role DependsOn: ECSLogGroup Properties: - RoleName: saas-bootcamp-tenant-svc-exec-role + RoleName: !Sub saas-bootcamp-tenant-svc-exec-role-${AWS::Region} Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 @@ -241,7 +250,7 @@ Resources: ECSTaskRole: Type: AWS::IAM::Role Properties: - RoleName: saas-bootcamp-tenant-svc-task-role + RoleName: !Sub saas-bootcamp-tenant-svc-task-role-${AWS::Region} Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 diff --git a/resources/user-service.yml b/resources/user-service.yml index f2b91f6..560522c 100644 --- a/resources/user-service.yml +++ b/resources/user-service.yml @@ -2,9 +2,13 @@ AWSTemplateFormatVersion: 2010-09-09 Description: AWS SaaS Factory Bootcamp User Service Parameters: - BootcampBucket: + WorkshopBucket: Description: The S3 bucket with bootcamp resources Type: String + AssetsBucketPrefix: + Description: S3 folder containing workshop assets. Leave blank if you did not put the assets in a subfolder. + Type: String + Default: '' ArtifactBucket: Description: The S3 bucket for CodeBuild to store built artifacts Type: String @@ -101,6 +105,9 @@ Resources: Path: '/' Name: user-manager Packaging: ZIP + Cache: + Type: S3 + Location: !Sub ${WorkshopBucket}/${AssetsBucketPrefix}codebuild-cache Environment: ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0 @@ -109,8 +116,10 @@ Resources: EnvironmentVariables: - Name: REPOSITORY_URI Value: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECSRepository} - - Name: BOOTCAMP_BUCKET - Value: !Ref BootcampBucket + - Name: SOURCE_BUCKET + Value: !Ref WorkshopBucket + - Name: SOURCE_BUCKET_PREFIX + Value: !Ref AssetsBucketPrefix Source: Type: NO_SOURCE BuildSpec: | @@ -118,8 +127,8 @@ Resources: phases: pre_build: commands: - - aws s3 cp --recursive s3://$BOOTCAMP_BUCKET/source/user-manager ./user-manager - - aws s3 cp --recursive s3://$BOOTCAMP_BUCKET/source/shared-modules ./user-manager/shared-modules + - aws s3 cp --recursive s3://$SOURCE_BUCKET/${SOURCE_BUCKET_PREFIX}source/user-manager ./user-manager + - aws s3 cp --recursive s3://$SOURCE_BUCKET/${SOURCE_BUCKET_PREFIX}source/shared-modules ./user-manager/shared-modules - aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $REPOSITORY_URI build: commands: @@ -210,7 +219,7 @@ Resources: Type: AWS::IAM::Role DependsOn: ECSLogGroup Properties: - RoleName: saas-bootcamp-user-svc-exec-role + RoleName: !Sub saas-bootcamp-user-svc-exec-role-${AWS::Region} Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 @@ -254,7 +263,7 @@ Resources: ECSTaskRole: Type: AWS::IAM::Role Properties: - RoleName: saas-bootcamp-user-svc-task-role + RoleName: !Sub saas-bootcamp-user-svc-task-role-${AWS::Region} Path: '/' AssumeRolePolicyDocument: Version: 2012-10-17 diff --git a/resources/web-client.yml b/resources/web-client.yml index 478d22e..bc8518c 100644 --- a/resources/web-client.yml +++ b/resources/web-client.yml @@ -2,9 +2,13 @@ AWSTemplateFormatVersion: 2010-09-09 Description: AWS SaaS Factory Bootcamp Web Client Parameters: - BootcampBucket: + WorkshopBucket: Description: The S3 bucket with bootcamp resources Type: String + AssetsBucketPrefix: + Description: S3 folder containing workshop assets. Leave blank if you did not put the assets in a subfolder. + Type: String + Default: '' WebsiteBucket: Description: The S3 bucket to host the web client from Type: String @@ -40,6 +44,7 @@ Resources: - ErrorCode: 403 ResponseCode: 200 ResponsePagePath: /index.html + ErrorCachingMinTTL: 300 DefaultCacheBehavior: AllowedMethods: - DELETE @@ -56,12 +61,14 @@ Resources: TargetOriginId: !Sub S3-Website-${WebsiteBucket} ViewerProtocolPolicy: redirect-to-https Compress: true - ForwardedValues: - Headers: - - Origin - - Access-Control-Request-Headers - - Access-Control-Request-Method - QueryString: false + # CachingOptimized managed cache policy + CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 + # CORS-S3Origin managed origin request policy + OriginRequestPolicyId: 88a5eaf4-2fd4-4709-b370-b4c650ea3fcf + # CORS-with-preflight-and-SecurityHeadersPolicy managed response headers policy + ResponseHeadersPolicyId: eaab4381-ed33-4a86-88ca-d9558dc6cd63 + ViewerCertificate: + CloudFrontDefaultCertificate: true WebBucketPolicy: Type: AWS::S3::BucketPolicy Properties: @@ -100,13 +107,18 @@ Resources: TimeoutInMinutes: 10 Artifacts: Type: NO_ARTIFACTS + Cache: + Type: S3 + Location: !Sub ${WorkshopBucket}/${AssetsBucketPrefix}codebuild-cache Environment: ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0 Type: LINUX_CONTAINER EnvironmentVariables: - - Name: BOOTCAMP_BUCKET - Value: !Ref BootcampBucket + - Name: SOURCE_BUCKET + Value: !Ref WorkshopBucket + - Name: SOURCE_BUCKET_PREFIX + Value: !Ref AssetsBucketPrefix - Name: WEBSITE_BUCKET Value: !Ref WebsiteBucket - Name: SERVICE_URL @@ -119,7 +131,7 @@ Resources: pre_build: commands: - n 16 - - aws s3 cp --recursive s3://$BOOTCAMP_BUCKET/source/web-client ./web-client + - aws s3 cp --recursive s3://$SOURCE_BUCKET/${SOURCE_BUCKET_PREFIX}source/web-client ./web-client - sed -i -e "s#DOMAIN_URL#$SERVICE_URL#g" ./web-client/app/scripts/constants.js build: commands: @@ -128,10 +140,15 @@ Resources: - npm install grunt-cli - ./node_modules/bower/bin/bower install --allow-root - ./node_modules/grunt-cli/bin/grunt build + - ls -la dist - cd ../ post_build: commands: - - aws s3 sync --delete --cache-control no-store ./web-client/dist/ s3://$WEBSITE_BUCKET/ + - aws s3 sync ./web-client/dist/ s3://$WEBSITE_BUCKET/ --delete --cache-control no-store --exclude "*" --include "index.html" --include "scripts/*" + - aws s3 sync ./web-client/dist/ s3://$WEBSITE_BUCKET/ --delete --include "*" --exclude "index.html" --exclude "scripts/*" + cache: + paths: + - $CODEBUILD_SRC_DIR/web-client/node_modules/**/* InvokeLambdaCodeBuildStartBuild: Type: Custom::CustomResource DependsOn: diff --git a/resources/workshop.yml b/resources/workshop.yml index 3af4448..5f66568 100644 --- a/resources/workshop.yml +++ b/resources/workshop.yml @@ -2,44 +2,62 @@ AWSTemplateFormatVersion: 2010-09-09 Description: AWS SaaS Factory Bootcamp Master Stack Parameters: - AssetsPath: - Description: S3 bucket path containing workshop resources. + AssetsBucket: + Description: S3 bucket containing workshop assets. Type: String + Default: aws-bootcamp-us-east-1 + AssetsBucketPrefix: + Description: S3 folder containing workshop assets. Leave blank if you did not put the assets in a subfolder. + Type: String + Default: '' ParticipantAssumedRoleArn: Description: Workshop Studio Participant IAM Role. Leave blank when not using Workshop Studio. Type: String Default: '' +Conditions: + HasAssetBucketPrefix: !Not [!Equals ['', !Ref AssetsBucketPrefix]] Resources: - BootcampBucket: + WorkshopBucket: Type: AWS::S3::Bucket - BootcampBucketSsmParam: + Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + WorkshopBucketSsmParam: Type: AWS::SSM::Parameter Properties: - Name: !Sub saas-bootcamp-bucket-${AWS::Region} + Name: saas-bootcamp-bucket Type: String - Value: !Ref BootcampBucket + Value: !Ref WorkshopBucket + WorkshopBucketPrefixSsmParam: + Type: AWS::SSM::Parameter + Properties: + Name: saas-bootcamp-bucket-prefix + Type: String + Value: !If [HasAssetBucketPrefix, !Ref AssetsBucketPrefix, 'N/A'] WebsiteBucket: Type: AWS::S3::Bucket Properties: - WebsiteConfiguration: - IndexDocument: index.html - Tags: - - Key: Name - Value: !Sub saas-bootcamp-website-bucket-${AWS::Region} + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 ArtifactBucket: Type: AWS::S3::Bucket Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 VersioningConfiguration: Status: Enabled NotificationConfiguration: EventBridgeConfiguration: EventBridgeEnabled: true - Tags: - - Key: Name - Value: !Sub saas-bootcamp-artifact-bucket-${AWS::Region} S3ObjectsExecutionRole: Type: AWS::IAM::Role - DependsOn: BootcampBucket + DependsOn: WorkshopBucket Properties: RoleName: !Sub saas-bootcamp-s3-copy-role-${AWS::Region} Path: '/' @@ -71,14 +89,14 @@ Resources: Action: - s3:GetObject Resource: - - !Sub arn:aws:s3:::${AssetsPath}* + - !Sub arn:${AWS::Partition}:s3:::${AssetsBucket}/${AssetsBucketPrefix}* - Effect: Allow Action: - s3:ListBucket - s3:ListBucketVersions - s3:GetBucketVersioning Resource: - - !Sub arn:aws:s3:::${BootcampBucket} + - !Sub arn:aws:s3:::${WorkshopBucket} - !Sub arn:aws:s3:::${ArtifactBucket} - !Sub arn:aws:s3:::${WebsiteBucket} - Effect: Allow @@ -87,7 +105,7 @@ Resources: - s3:DeleteObject - s3:DeleteObjectVersion Resource: - - !Sub arn:aws:s3:::${BootcampBucket}/* + - !Sub arn:aws:s3:::${WorkshopBucket}/* - !Sub arn:aws:s3:::${ArtifactBucket}/* - !Sub arn:aws:s3:::${WebsiteBucket}/* CopyS3ObjectsLogs: @@ -114,145 +132,153 @@ Resources: from botocore.exceptions import ClientError def lambda_handler(event, context): - print(json.dumps(event, default=str)) - source_bucket_slash = event['ResourceProperties']['Source'] - if source_bucket_slash.endswith ('/'): - source_bucket = source_bucket_slash[:-1] - else: - source_bucket = source_bucket_slash - destination_bucket = event['ResourceProperties']['Destination'] - destination_region = event['ResourceProperties']['DestinationRegion'] - objects_to_copy = event['ResourceProperties']['Objects'] - + print(json.dumps(event, default=str)) + source_bucket_slash = event['ResourceProperties']['Source'] + if source_bucket_slash.endswith ('/'): + source_bucket = source_bucket_slash[:-1] + else: + source_bucket = source_bucket_slash + source_prefix = event['ResourceProperties']['SourcePrefix'] + destination_bucket = event['ResourceProperties']['Destination'] + destination_region = event['ResourceProperties']['DestinationRegion'] + objects_to_copy = event['ResourceProperties']['Objects'] + + if event['RequestType'] in ['Create', 'Update']: + if not objects_to_copy: + # If we weren't given a specific list of objects to copy, + # just copy everything to the destination bucket + s3 = boto3.client('s3') + source_objects = s3.list_objects_v2(Bucket=source_bucket, Prefix=source_prefix) + objects_to_copy = list(map(lambda obj : obj['Key'], source_objects.get('Contents', []))) + print("Creating S3 client in destination region %s" % destination_region) s3 = boto3.client('s3', region_name=destination_region) - - if event['RequestType'] in ['Create', 'Update']: - for key in objects_to_copy: - print("Copying %s/%s -> %s/%s" % (source_bucket, key, destination_bucket, key)) - try: - s3.copy_object(CopySource={'Bucket':source_bucket, 'Key':key}, Bucket=destination_bucket, Key=key) - except ClientError as s3_error: - cfnresponse.send(event, context, cfnresponse.FAILED, {"Reason": str(s3_error)}) - raise - cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) - elif event['RequestType'] == 'Delete': - cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) - else: - cfnresponse.send(event, context, cfnresponse.FAILED, {"Reason": "Unknown RequestType %s" % event['RequestType']}) + for key in objects_to_copy: + print("Copying %s/%s -> %s/%s" % (source_bucket, key, destination_bucket, key)) + try: + s3.copy_object(CopySource={'Bucket':source_bucket, 'Key':key}, Bucket=destination_bucket, Key=key) + except ClientError as s3_error: + cfnresponse.send(event, context, cfnresponse.FAILED, {"Reason": str(s3_error)}) + raise + cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) + elif event['RequestType'] == 'Delete': + cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) + else: + cfnresponse.send(event, context, cfnresponse.FAILED, {"Reason": "Unknown RequestType %s" % event['RequestType']}) InvokeLambdaCopyS3Objects: Type: Custom::CustomResource DependsOn: - CopyS3ObjectsLogs Properties: ServiceToken: !GetAtt CopyS3Objects.Arn - Source: !Ref AssetsPath - Destination: !Ref BootcampBucket + Source: !Ref AssetsBucket + SourcePrefix: !Ref AssetsBucketPrefix + Destination: !Ref WorkshopBucket DestinationRegion: !Ref AWS::Region Objects: - - resources/baseline.yml - - resources/api-gateway.yml - - resources/auth-service.yml - - resources/tenant-service.yml - - resources/user-service.yml - - resources/registration-service.yml - - resources/order-service.yml - - resources/product-service.yml - - resources/web-client.yml - - source/shared-modules/config-helper/config.js - - source/shared-modules/config-helper/package.json - - source/shared-modules/config-helper/config/default.json - - source/shared-modules/config-helper/config/development.json - - source/shared-modules/config-helper/config/production.json - - source/shared-modules/token-manager/token-manager.js - - source/shared-modules/token-manager/package.json - - source/shared-modules/dynamodb-helper/dynamodb-helper.js - - source/shared-modules/dynamodb-helper/package.json - - source/auth-manager/Dockerfile - - source/auth-manager/server.js - - source/auth-manager/package.json - - source/tenant-manager/Dockerfile - - source/tenant-manager/server.js - - source/tenant-manager/package.json - - source/user-manager/cognito-user.js - - source/user-manager/Dockerfile - - source/user-manager/server.js - - source/user-manager/package.json - - source/tenant-registration/Dockerfile - - source/tenant-registration/server.js - - source/tenant-registration/package.json - - source/order-manager/Dockerfile - - source/order-manager/server.js - - source/order-manager/package.json - - source/product-manager/Dockerfile - - source/product-manager/server.js - - source/product-manager/package.json - - source/web-client/Gruntfile.js - - source/web-client/app/404.html - - source/web-client/app/config.json - - source/web-client/app/favicon.ico - - source/web-client/app/images/Auctioneer2-300px.png - - source/web-client/app/images/chart.png - - source/web-client/app/images/favicon.ico - - source/web-client/app/images/green-circle.png - - source/web-client/app/images/matt-icons_package-300px.png - - source/web-client/app/images/matt-icons_package-800px.png - - source/web-client/app/images/monitor.png - - source/web-client/app/images/red-circle.png - - source/web-client/app/images/yeoman.png - - source/web-client/app/index.html - - source/web-client/app/robots.txt - - source/web-client/app/scripts/app.js - - source/web-client/app/scripts/constants.js - - source/web-client/app/scripts/controllers/confirm.js - - source/web-client/app/scripts/controllers/login.js - - source/web-client/app/scripts/controllers/main.js - - source/web-client/app/scripts/controllers/order-add.js - - source/web-client/app/scripts/controllers/order-delete.js - - source/web-client/app/scripts/controllers/order-edit.js - - source/web-client/app/scripts/controllers/orders.js - - source/web-client/app/scripts/controllers/product-add.js - - source/web-client/app/scripts/controllers/product-delete.js - - source/web-client/app/scripts/controllers/product-edit.js - - source/web-client/app/scripts/controllers/product-view.js - - source/web-client/app/scripts/controllers/products.js - - source/web-client/app/scripts/controllers/register.js - - source/web-client/app/scripts/controllers/tenant-delete.js - - source/web-client/app/scripts/controllers/tenant-edit.js - - source/web-client/app/scripts/controllers/tenants.js - - source/web-client/app/scripts/controllers/user-add.js - - source/web-client/app/scripts/controllers/user-delete.js - - source/web-client/app/scripts/controllers/user-edit.js - - source/web-client/app/scripts/controllers/user-enable.js - - source/web-client/app/scripts/controllers/users.js - - source/web-client/app/styles/main.css - - source/web-client/app/styles/main.scss - - source/web-client/app/views/confirm.html - - source/web-client/app/views/login.html - - source/web-client/app/views/main.html - - source/web-client/app/views/order-add.html - - source/web-client/app/views/order-delete.html - - source/web-client/app/views/order-edit.html - - source/web-client/app/views/order-nav.html - - source/web-client/app/views/orders.html - - source/web-client/app/views/product-add.html - - source/web-client/app/views/product-delete.html - - source/web-client/app/views/product-edit.html - - source/web-client/app/views/product-nav.html - - source/web-client/app/views/product-view.html - - source/web-client/app/views/products.html - - source/web-client/app/views/register.html - - source/web-client/app/views/tenant-delete.html - - source/web-client/app/views/tenant-edit.html - - source/web-client/app/views/tenants.html - - source/web-client/app/views/user-add.html - - source/web-client/app/views/user-delete.html - - source/web-client/app/views/user-edit.html - - source/web-client/app/views/user-enable.html - - source/web-client/app/views/user-nav.html - - source/web-client/app/views/users.html - - source/web-client/bower.json - - source/web-client/package.json + - !Sub ${AssetsBucketPrefix}resources/baseline.yml + - !Sub ${AssetsBucketPrefix}resources/api-gateway.yml + - !Sub ${AssetsBucketPrefix}resources/auth-service.yml + - !Sub ${AssetsBucketPrefix}resources/tenant-service.yml + - !Sub ${AssetsBucketPrefix}resources/user-service.yml + - !Sub ${AssetsBucketPrefix}resources/registration-service.yml + - !Sub ${AssetsBucketPrefix}resources/order-service.yml + - !Sub ${AssetsBucketPrefix}resources/product-service.yml + - !Sub ${AssetsBucketPrefix}resources/web-client.yml + - !Sub ${AssetsBucketPrefix}source/shared-modules/config-helper/config.js + - !Sub ${AssetsBucketPrefix}source/shared-modules/config-helper/package.json + - !Sub ${AssetsBucketPrefix}source/shared-modules/config-helper/config/default.json + - !Sub ${AssetsBucketPrefix}source/shared-modules/config-helper/config/development.json + - !Sub ${AssetsBucketPrefix}source/shared-modules/config-helper/config/production.json + - !Sub ${AssetsBucketPrefix}source/shared-modules/token-manager/token-manager.js + - !Sub ${AssetsBucketPrefix}source/shared-modules/token-manager/package.json + - !Sub ${AssetsBucketPrefix}source/shared-modules/dynamodb-helper/dynamodb-helper.js + - !Sub ${AssetsBucketPrefix}source/shared-modules/dynamodb-helper/package.json + - !Sub ${AssetsBucketPrefix}source/auth-manager/Dockerfile + - !Sub ${AssetsBucketPrefix}source/auth-manager/server.js + - !Sub ${AssetsBucketPrefix}source/auth-manager/package.json + - !Sub ${AssetsBucketPrefix}source/tenant-manager/Dockerfile + - !Sub ${AssetsBucketPrefix}source/tenant-manager/server.js + - !Sub ${AssetsBucketPrefix}source/tenant-manager/package.json + - !Sub ${AssetsBucketPrefix}source/user-manager/cognito-user.js + - !Sub ${AssetsBucketPrefix}source/user-manager/Dockerfile + - !Sub ${AssetsBucketPrefix}source/user-manager/server.js + - !Sub ${AssetsBucketPrefix}source/user-manager/package.json + - !Sub ${AssetsBucketPrefix}source/tenant-registration/Dockerfile + - !Sub ${AssetsBucketPrefix}source/tenant-registration/server.js + - !Sub ${AssetsBucketPrefix}source/tenant-registration/package.json + - !Sub ${AssetsBucketPrefix}source/order-manager/Dockerfile + - !Sub ${AssetsBucketPrefix}source/order-manager/server.js + - !Sub ${AssetsBucketPrefix}source/order-manager/package.json + - !Sub ${AssetsBucketPrefix}source/product-manager/Dockerfile + - !Sub ${AssetsBucketPrefix}source/product-manager/server.js + - !Sub ${AssetsBucketPrefix}source/product-manager/package.json + - !Sub ${AssetsBucketPrefix}source/web-client/Gruntfile.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/404.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/config.json + - !Sub ${AssetsBucketPrefix}source/web-client/app/favicon.ico + - !Sub ${AssetsBucketPrefix}source/web-client/app/images/Auctioneer2-300px.png + - !Sub ${AssetsBucketPrefix}source/web-client/app/images/chart.png + - !Sub ${AssetsBucketPrefix}source/web-client/app/images/favicon.ico + - !Sub ${AssetsBucketPrefix}source/web-client/app/images/green-circle.png + - !Sub ${AssetsBucketPrefix}source/web-client/app/images/matt-icons_package-300px.png + - !Sub ${AssetsBucketPrefix}source/web-client/app/images/matt-icons_package-800px.png + - !Sub ${AssetsBucketPrefix}source/web-client/app/images/monitor.png + - !Sub ${AssetsBucketPrefix}source/web-client/app/images/red-circle.png + - !Sub ${AssetsBucketPrefix}source/web-client/app/images/yeoman.png + - !Sub ${AssetsBucketPrefix}source/web-client/app/index.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/robots.txt + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/app.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/constants.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/confirm.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/login.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/main.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/order-add.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/order-delete.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/order-edit.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/orders.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/product-add.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/product-delete.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/product-edit.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/product-view.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/products.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/register.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/tenant-delete.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/tenant-edit.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/tenants.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/user-add.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/user-delete.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/user-edit.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/user-enable.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/scripts/controllers/users.js + - !Sub ${AssetsBucketPrefix}source/web-client/app/styles/main.css + - !Sub ${AssetsBucketPrefix}source/web-client/app/styles/main.scss + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/confirm.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/login.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/main.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/order-add.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/order-delete.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/order-edit.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/order-nav.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/orders.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/product-add.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/product-delete.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/product-edit.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/product-nav.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/product-view.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/products.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/register.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/tenant-delete.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/tenant-edit.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/tenants.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/user-add.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/user-delete.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/user-edit.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/user-enable.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/user-nav.html + - !Sub ${AssetsBucketPrefix}source/web-client/app/views/users.html + - !Sub ${AssetsBucketPrefix}source/web-client/bower.json + - !Sub ${AssetsBucketPrefix}source/web-client/package.json ClearS3BucketLogs: Type: AWS::Logs::LogGroup Properties: @@ -343,7 +369,7 @@ Resources: - ClearS3BucketLogs Properties: ServiceToken: !GetAtt ClearS3Bucket.Arn - Bucket: !Ref BootcampBucket + Bucket: !Ref WorkshopBucket InvokeLambdaClearArtifactBucket: Type: Custom::CustomResource DependsOn: @@ -362,10 +388,11 @@ Resources: Type: AWS::CloudFormation::Stack DependsOn: InvokeLambdaCopyS3Objects Properties: - TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${BootcampBucket}/resources/baseline.yml + TemplateURL: !Sub https://s3.${AWS::Region}.amazonaws.com/${WorkshopBucket}/${AssetsBucketPrefix}resources/baseline.yml Parameters: ParticipantAssumedRoleArn: !Ref ParticipantAssumedRoleArn - BootcampBucket: !Ref BootcampBucket + WorkshopBucket: !Ref WorkshopBucket + AssetsBucketPrefix: !Ref AssetsBucketPrefix ArtifactBucket: !Ref ArtifactBucket WebsiteBucket: !Ref WebsiteBucket Outputs: @@ -381,4 +408,4 @@ Outputs: ParticipantAssumedRoleArn: Description: ParticipantAssumedRoleArn Value: !Ref ParticipantAssumedRoleArn -... \ No newline at end of file +...