Description: Common infrastructure for all CICD pipelines Parameters: Env: Type: String Description: The environment, alpha, beta, or prod. In a sandbox these are all in one account, but the actual deployment is to three different accounts. AllowedValues: ["alpha", "beta", "prod"] GitUrl: Type: String Description: The URL to the Git repo to clone GitBranch: Type: String Description: The branch to clone GitHubSecretArn: Type: String Description: The arn to the github webhook secret Conditions: IsNotProd: !Not - !Equals - !Ref Env - prod IsProd: !Equals - !Ref Env - prod Resources: HandlerBucket: Type: AWS::S3::Bucket Condition: IsProd Metadata: Comment: This bucket holds the handler package and logs for extension publishing. Properties: BucketName: !Sub "cep-handler-${AWS::AccountId}" CommonBuildProjectPolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: Common build policy for community registry extensions PolicyDocument: Statement: - Action: - s3:* Effect: Allow Resource: "*" - Action: - kms:CreateKey - kms:DeleteKey - kms:Create* - kms:Describe* - kms:Enable* - kms:List* - kms:Put* - kms:Update* - kms:Revoke* - kms:Disable* - kms:Get* - kms:Delete* - kms:ScheduleKeyDeletion - kms:CancelKeyDeletion - kms:Encrypt - kms:Decrypt - kms:ReEncrypt* - kms:GenerateDataKey* Effect: Allow Resource: "*" - Action: - iam:CreateRole - iam:DeleteRole - iam:GetRole - iam:PutRolePolicy - iam:DeleteRolePolicy - iam:GetRolePolicy - iam:PassRole - iam:UpdateAssumeRolePolicyDocument - iam:UpdateAssumeRolePolicy Effect: Allow Resource: - !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/*' - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*' - Action: - codebuild:CreateReportGroup - codebuild:CreateReport - codebuild:UpdateReport - codebuild:BatchPutTestCases - codebuild:BatchPutCodeCoverages Effect: Allow Resource: - !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/*' - Action: - cloudformation:* Effect: Allow Resource: "*" - Action: - ecr:GetDownloadUrlForLayer - ecr:BatchGetImage - ecr:BatchCheckLayerAvailability - ecr:GetAuthorizationToken Effect: Allow Resource: "*" - Action: - ssm:GetParameters Effect: Allow Resource: !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/cep-*" - Action: - secretsmanager:GetSecretValue Effect: Allow Resource: !Sub "arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:cep*" Version: '2012-10-17' # The webhook is invoked by GitHub when there is a push to a repo. # There is a webhook in the alpha account and in the beta account. # There is only one webhook for all namespaces in each env. # We don't replicate this in the templates for each 3rd party like Okta, etc. # The webhook handler and the CodeBuild it invokes clone the correct repo # and drop the source into the correct bucket, which starts an independenent # pipeline for each namespace. WebHookBuildProjectRole: Type: AWS::IAM::Role Condition: IsNotProd Metadata: Comment: Note that we give this project access to the source buckets for all 3rd parties, since we only have one instance of the webhook to start all pipelines when there is a push to one of the repos. Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: codebuild.amazonaws.com Version: '2012-10-17' Policies: - PolicyDocument: Statement: - Action: - s3:PutObject Effect: Allow Resource: - !Sub "arn:aws:s3:::cep-source-${AWS::AccountId}-${Env}-*" - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*' - Action: - codebuild:CreateReportGroup - codebuild:CreateReport - codebuild:UpdateReport - codebuild:BatchPutTestCases - codebuild:BatchPutCodeCoverages Effect: Allow Resource: - !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/*' Version: '2012-10-17' PolicyName: webhook-build-project-policy WebHookBuildProject: Type: AWS::CodeBuild::Project Condition: IsNotProd Metadata: Comment: | This build project is invoked by a Lambda that is called from GitHub webhooks configured on the repos handled by this build process. The lambda maps repos to the extension prefix, which is what determines the bucket to drop the source into. A bucket notification starts the related pipeline. Properties: Name: !Sub "cep-${Env}-common-webhook" Artifacts: Type: NO_ARTIFACTS Environment: ComputeType: BUILD_GENERAL1_LARGE Image: aws/codebuild/standard:3.0 ImagePullCredentialsType: CODEBUILD PrivilegedMode: false Type: LINUX_CONTAINER EnvironmentVariables: - Name: GIT_URL Type: PLAINTEXT Value: "Placeholder - lambda will provide when it invokes" - Name: GIT_BRANCH Type: PLAINTEXT Value: !Ref GitBranch - Name: SOURCE_BUCKET_PREFIX Type: PLAINTEXT Value: !Sub "cep-source-${AWS::AccountId}-${Env}-" - Name: SOURCE_KEY Type: PLAINTEXT Value: "source.zip" - Name: COMMIT_MESSAGE Type: PLAINTEXT Value: "Placeholder - lambda will provide when it invokes" - Name: REPO Type: PLAINTEXT Value: "Placeholder - lambda will provide when it invokes" - Name: EXTENSION_PREFIX Type: PLAINTEXT Value: "Placeholder - lambda will provide when it invokes" ServiceRole: !GetAtt WebHookBuildProjectRole.Arn Source: Type: NO_SOURCE BuildSpec: | version: 0.2 phases: build: commands: - echo $GIT_URL - echo $GIT_BRANCH - echo $SOURCE_BUCKET - git clone --depth=1 --branch=$GIT_BRANCH $GIT_URL /tmp/source - cd /tmp/source - zip -r source.zip * - echo "COMMIT_MESSAGE is $COMMIT_MESSAGE" - METADATA="{\"codepipeline-artifact-revision-summary\":\"" - METADATA="${METADATA}${COMMIT_MESSAGE}" - METADATA="${METADATA}\"}" - echo "METADATA is $METADATA" - aws s3 cp source.zip s3://${SOURCE_BUCKET_PREFIX}${EXTENSION_PREFIX}/ --metadata "${METADATA}" WebHookHandlerRole: Type: AWS::IAM::Role Condition: IsNotProd Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: lambda.amazonaws.com Policies: - PolicyName: lambdaexec PolicyDocument: Version: 2012-10-17 Statement: - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: "*" - Action: - codebuild:StartBuild Effect: Allow Resource: !GetAtt WebHookBuildProject.Arn - Action: - secretsmanager:GetSecretValue Effect: Allow Resource: !Ref GitHubSecretArn WebHookHandler: Type: AWS::Lambda::Function Condition: IsNotProd Properties: Code: !Rain::S3 Path: webhook.py Zip: true BucketProperty: S3Bucket KeyProperty: S3Key Role: !GetAtt WebHookHandlerRole.Arn Handler: webhook.handler Runtime: python3.7 MemorySize: 1024 Environment: Variables: GIT_URL: !Ref GitUrl GIT_BRANCH: !Ref GitBranch BUILD_PROJECT: !Ref WebHookBuildProject SECRET_ARN: !Ref GitHubSecretArn WebHookRestApi: Type: AWS::ApiGateway::RestApi Condition: IsNotProd Properties: Name: !Sub "cep-${Env}-github-webhook" WebHookCloudWatchRole: Type: AWS::IAM::Role Condition: IsNotProd Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: apigateway.amazonaws.com Path: / Policies: - PolicyName: cwlogsapigateway PolicyDocument: Version: 2012-10-17 Statement: - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:DescribeLogGroups - logs:DescribeLogStreams - logs:PutLogEvents - logs:GetLogEvents - logs:FilterLogEvents Effect: Allow Resource: "*" WebHookAccount: Type: AWS::ApiGateway::Account Condition: IsNotProd Properties: CloudWatchRoleArn: !GetAtt WebHookCloudWatchRole.Arn DependsOn: WebHookRestApi WebHookDeployment: Type: AWS::ApiGateway::Deployment Condition: IsNotProd Properties: RestApiId: !Ref WebHookRestApi DependsOn: - WebHookANYProxy - WebHookANYRoot WebHookStage: Type: AWS::ApiGateway::Stage Condition: IsNotProd Properties: RestApiId: !Ref WebHookRestApi DeploymentId: !Ref WebHookDeployment StageName: prod WebHookProxy: Type: AWS::ApiGateway::Resource Condition: IsNotProd Properties: ParentId: !GetAtt WebHookRestApi.RootResourceId PathPart: "{proxy+}" RestApiId: !Ref WebHookRestApi WebHookRestApiPermission: Type: AWS::Lambda::Permission Condition: IsNotProd Properties: Action: lambda:InvokeFunction FunctionName: !GetAtt WebHookHandler.Arn Principal: apigateway.amazonaws.com SourceArn: !Sub "arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${WebHookRestApi}/*/*/*" WebHookRestApiRootPermission: Type: AWS::Lambda::Permission Condition: IsNotProd Properties: Action: lambda:InvokeFunction FunctionName: !GetAtt WebHookHandler.Arn Principal: apigateway.amazonaws.com SourceArn: !Sub "arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${WebHookRestApi}/*/*/" WebHookANYRoot: Type: AWS::ApiGateway::Method Condition: IsNotProd Properties: HttpMethod: ANY ResourceId: !GetAtt WebHookRestApi.RootResourceId RestApiId: !Ref WebHookRestApi AuthorizationType: NONE Integration: IntegrationHttpMethod: POST Type: AWS_PROXY Uri: !Sub "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${WebHookHandler.Arn}/invocations" WebHookANYProxy: Type: AWS::ApiGateway::Method Condition: IsNotProd Properties: HttpMethod: ANY ResourceId: !Ref WebHookProxy RestApiId: !Ref WebHookRestApi AuthorizationType: NONE Integration: IntegrationHttpMethod: POST Type: AWS_PROXY Uri: !Sub "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${WebHookHandler.Arn}/invocations" Outputs: CommonBuildProjectPolicyArn: Description: The ARN to the common build policy for community registry extensions Value: !Ref CommonBuildProjectPolicy Export: Name: !Sub "cep-${Env}-common-build-project-policy" WebHookInvokeURL: Value: !Sub https://${WebHookRestApi}.execute-api.${AWS::Region}.amazonaws.com/${WebHookStage} Condition: IsNotProd