AWSTemplateFormatVersion: '2010-09-09' Transform: 'AWS::Serverless-2016-10-31' Description: Template to create BikeNow Code-star pipeline Parameters: EnvironmentName: Description: Environment stage name Type: String S3BucketWeb: Description: Name of S3 bucket hosting web application Type: String ApiDatabase: Description: ID of API Gateway used for database application Type: String ApiAiml: Description: ID of API Gateway used for AIML application Type: String CognitoUserPool: Description: Cognito user pool Type: String CognitoUserPoolClient: Description: Cognito user pool client Type: String CognityIdentityPool: Description: Cognito identity pool Type: String WebsiteCDN: Description: CloudFront CDN for distributing web application Type: String Conditions: DefaultRegion: !Equals [!Ref "AWS::Region", "us-east-1"] Mappings: S3Buckets: us-east-1: Bucket: aws-bikenow-demo-us-east-1 SeederFunctionBucket: fsd-aws-wildrydes-us-east-1 us-west-2: Bucket: aws-bikenow-demo-us-west-2 SeederFunctionBucket: fsd-aws-wildrydes-us-west-2 eu-central-1: Bucket: aws-bikenow-demo-eu-central-1 SeederFunctionBucket: fsd-aws-wildrydes-eu-central-1 eu-west-1: Bucket: aws-bikenow-demo-eu-west-1 SeederFunctionBucket: fsd-aws-wildrydes-eu-west-1 Constants: AppKeys: SeedRepository: https://s3.amazonaws.com/aws-bikenow-demo-us-east-1/aws-bikenow-demo.zip S3Keys: SeederFunctionCode: aws-serverless-codecommit-seeder.zip Resources: # -------------------------------- CODE PIPELINE STUFF AssetsCodeRepository: Type: 'AWS::CodeCommit::Repository' Properties: RepositoryDescription: Code repository for web application RepositoryName: Bikenow-WebAssets CodeBuildRole: Description: Creating service role in IAM for AWS CodeBuild Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: - codebuild.amazonaws.com Action: 'sts:AssumeRole' Policies: - PolicyName: codebuild-policy PolicyDocument: Statement: - Action: - 's3:PutObject' - 's3:GetObject' - 's3:GetObjectVersion' - 's3:GetBucketVersioning' Resource: - !Sub 'arn:aws:s3:::${S3BucketWeb}/*' - !Sub 'arn:aws:s3:::${PipelineArtifactsBucket}/*' Effect: Allow - PolicyName: codebuild-logs PolicyDocument: Statement: - Action: - 'logs:CreateLogStream' - 'logs:PutLogEvents' - 'logs:CreateLogGroup' - 'cloudfront:CreateInvalidation' Resource: '*' Effect: Allow Path: / CodePipelineRole: Description: Creating service role in IAM for AWS CodePipeline Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: - codepipeline.amazonaws.com Action: 'sts:AssumeRole' Policies: - PolicyName: codecommit-for-codepipeline PolicyDocument: Statement: - Action: - 'codecommit:GetBranch' - 'codecommit:GetCommit' - 'codecommit:UploadArchive' - 'codecommit:GetUploadArchiveStatus' - 'codecommit:CancelUploadArchive' Resource: !GetAtt AssetsCodeRepository.Arn Effect: Allow - PolicyName: artifacts-for-pipeline PolicyDocument: Statement: - Action: - 's3:PutObject' - 's3:GetObject' Resource: 'Fn::Join': - '' - - 'Fn::GetAtt': - PipelineArtifactsBucket - Arn - /* Effect: Allow - PolicyName: codebuild-for-pipeline PolicyDocument: Statement: - Action: - 'codebuild:BatchGetBuilds' - 'codebuild:StartBuild' Resource: !GetAtt - CodeBuildProject - Arn Effect: Allow Path: / PipelineArtifactsBucket: Type: 'AWS::S3::Bucket' Properties: AccessControl: Private Metadata: 'AWS::CloudFormation::Designer': id: bbbc886f-d307-45dc-a6e3-63353f40a4f4 CodeBuildProject: DependsOn: - PipelineArtifactsBucket Description: Creating AWS CodeBuild project Type: 'AWS::CodeBuild::Project' Properties: Artifacts: Type: CODEPIPELINE Description: Building stage for Bikenow. Environment: ComputeType: BUILD_GENERAL1_SMALL EnvironmentVariables: - Name: S3_BUCKET Value: !Ref PipelineArtifactsBucket Image: 'aws/codebuild/standard:2.0' Type: LINUX_CONTAINER Name: Bikenow-build ServiceRole: !Ref CodeBuildRole Source: Type: CODEPIPELINE BuildSpec: !Sub | version: 0.2 phases: install: runtime-versions: nodejs: 10 pre_build: commands: - echo Installing NPM dependencies... - npm install build: commands: - npm run build post_build: commands: - echo Uploading to S3BucketWeb - aws s3 cp --recursive ./build s3://${S3BucketWeb}/ - aws s3 cp --cache-control="max-age=0, no-cache, no-store, must-revalidate" ./build/service-worker.js s3://${S3BucketWeb}/ - aws s3 cp --cache-control="max-age=0, no-cache, no-store, must-revalidate" ./build/index.html s3://${S3BucketWeb}/ - aws cloudfront create-invalidation --distribution-id ${WebsiteCDN} --paths /index.html - aws cloudfront create-invalidation --distribution-id ${WebsiteCDN} --paths /index.html /service-worker.js artifacts: files: - '**/*' base-directory: build TimeoutInMinutes: 15 AssetsCodePipeline: Type: 'AWS::CodePipeline::Pipeline' Properties: RoleArn: !GetAtt - CodePipelineRole - Arn ArtifactStore: Location: !Ref PipelineArtifactsBucket Type: S3 Stages: - Name: Source Actions: - Name: Source InputArtifacts: [] ActionTypeId: Version: '1' Category: Source Owner: AWS Provider: CodeCommit Configuration: BranchName: master RepositoryName: Bikenow-WebAssets OutputArtifacts: - Name: Bikenow-SourceArtifact - Name: Build Actions: - Name: build-and-deploy InputArtifacts: - Name: Bikenow-SourceArtifact ActionTypeId: Category: Build Owner: AWS Version: '1' Provider: CodeBuild OutputArtifacts: - Name: Bikenow-BuildArtifact Configuration: ProjectName: Bikenow-build RunOrder: 1 DependsOn: - PipelineArtifactsBucket SeederFunction: Properties: Code: S3Bucket: !FindInMap - S3Buckets - !Ref 'AWS::Region' - SeederFunctionBucket S3Key: !FindInMap - Constants - S3Keys - SeederFunctionCode Description: CodeCommit repository seeder Handler: seeder.SeedRepositoryHandler MemorySize: 3008 Role: 'Fn::GetAtt': - SeederRole - Arn Runtime: java8 Timeout: 900 Type: 'AWS::Lambda::Function' DependsOn: - AssetsCodeRepository UpdateConfigFunction: Properties: CodeUri: ../lambdas/setup_update_config Description: Update config for CodeCommit repository Handler: index.handler Role: 'Fn::GetAtt': - SeederRole - Arn Runtime: nodejs12.x Timeout: 300 Environment: Variables: DB_API_URL: !Sub 'https://${ApiDatabase}.execute-api.${AWS::Region}.amazonaws.com/${EnvironmentName}' ML_API_URL: !Sub 'https://${ApiAiml}.execute-api.${AWS::Region}.amazonaws.com/${EnvironmentName}' BRANCH_NAME: master REGION: !Ref 'AWS::Region' REPOSITORY_NAME: Bikenow-WebAssets USER_POOL_ID: !Ref CognitoUserPool APP_CLIENT_ID: !Ref CognitoUserPoolClient IDENTITY_POOL_ID: !Ref CognityIdentityPool Type: AWS::Serverless::Function DependsOn: - AssetsCodeRepository - SeederFunction - RepositorySeeder SeederRole: Properties: AssumeRolePolicyDocument: Statement: - Action: - 'sts:AssumeRole' Effect: Allow Principal: Service: - lambda.amazonaws.com Version: 2012-10-17 ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' Policies: - PolicyDocument: Statement: - Action: - 'codecommit:GetRepository' - 'codecommit:GitPush' - 'codecommit:GetBranch' - 'codecommit:PutFile' Effect: Allow Resource: !GetAtt AssetsCodeRepository.Arn Version: 2012-10-17 PolicyName: SeederRolePolicy - PolicyDocument: Statement: - Action: - 'logs:*' Effect: Allow Resource: 'arn:aws:logs:*:*:*' Version: 2012-10-17 PolicyName: LogsPolicy Type: 'AWS::IAM::Role' RepositorySeeder: Properties: ServiceToken: 'Fn::GetAtt': - SeederFunction - Arn sourceUrl: !FindInMap [Constants, AppKeys, SeedRepository] targetRepositoryName: Bikenow-WebAssets targetRepositoryRegion: '${AWS::Region}' Type: 'Custom::RepositorySeeder' RepositoryUpdater: Type: 'Custom::CustomResource' Properties: ServiceToken: !GetAtt UpdateConfigFunction.Arn ParameterOne: Parameter to pass into Custom Lambda Function DependsOn: UpdateConfigFunction # -------------------------------- CLEANUP STEPS RoleSetupEmptyBucket: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: RoleSetupRdsDdlLambdaPolicy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogStream - logs:CreateLogGroup - logs:PutLogEvents Resource: - arn:aws:logs:*:*:* - Effect: Allow Action: - s3:* Resource: - !GetAtt PipelineArtifactsBucket.Arn - Fn::Join: - "/" - - !GetAtt PipelineArtifactsBucket.Arn - "*" LambdaSetupEmptyArtifactsBucket: Type: AWS::Serverless::Function Properties: Handler: index.lambda_handler Runtime: python3.8 CodeUri: ../lambdas/setup_empty_bucket Role: !GetAtt RoleSetupEmptyBucket.Arn Description: Empty artifacts bucket upon deletion MemorySize: 128 Timeout: 300 Environment: Variables: SCRIPT_BUCKET: !Ref PipelineArtifactsBucket SetupEmptyArtifactsBucket: Type: Custom::SetupFunction DependsOn: - PipelineArtifactsBucket - RoleSetupEmptyBucket - LambdaSetupEmptyArtifactsBucket Properties: ServiceToken: !GetAtt LambdaSetupEmptyArtifactsBucket.Arn