■ はじめに
https://dk521123.hatenablog.com/entry/2021/10/26/224812
https://dk521123.hatenablog.com/entry/2021/12/01/170326
https://dk521123.hatenablog.com/entry/2021/12/04/202519
https://dk521123.hatenablog.com/entry/2021/12/05/134313
の続き。 AWS CloudFormation (CFn) で学んだことを実践してみる。
目次
【0】今回で学べた教訓 【1】今回の仕様 - やりたいこと 【2】設計方針 1)Security Layer 2)Application Layer 【3】API仕様 1)Security Layer 2)Application Layer 【4】サンプル 1)Security Layer 2)Application Layer
【0】今回で学べた教訓
* 書き始めるのは、 Application Layer (CodePipeline/CodeBuild)で 後から、Security Layer(IAM Role/Policy)を 書いた方がいい。 * Input(入力値。例えば、Githubの情報) を考えて、 Parameters に書き込んでいく
【1】今回の仕様 - やりたいこと
1)以下「全体構成」のような作りをする 2)環境 EnviromemtType を定義する + dev (開発環境) + stage (検証環境) + prod (本番環境) 3)Githubブランチ 「${GithubBranch(e.g. release)}/${EnviromemtType}」が Pushした場合、CodePiplineで関知して発火する 4)環境「stage/prod」の場合は、 承認アクション(approval actions) が必要にする => dev はスルー
全体構成
Github ↓ <webhook> CodePipline ↓ <stage/prod の場合は、承認アクションが必要> CodeBuild
【2】設計方針
https://dk521123.hatenablog.com/entry/2021/12/01/170326
の「テンプレート管理 - スタック分割」で扱った スタック分割で作ってみる。 => 今回は、ネットワーク(VPCなど)は考えないものとする
1)Security Layer
* 以下のAWSサービスのIAM role および policy を設定する [1] CodePipeline [2] CodeBuild => Outputs で 2つのAWSサービスの RoleArn を出力し、 Application Layerに渡すようにする
2)Application Layer
* 以下を作成する [1] CodePipeline [2] CodeBuild の プロジェクト => RoleArn は、「1)Security Layer」で生成された値を Fn::ImportValueを使って取得し設定する
【3】API仕様
1)Security Layer
Type: AWS::IAM::Role
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html
Type: AWS::IAM::Policy
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html
2)Application Layer
Type: AWS::CodePipeline::Pipeline
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-codepipeline-pipeline.html
Type: AWS::CodeBuild::Project
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-codebuild-project.html
【4】サンプル
1)Security Layer
sample-security-layer-template.yaml
AWSTemplateFormatVersion: "2010-09-09" Description: "Security layer for Github/CodePipeline/CodeBuild" Parameters: EnvironmentType: Description: Enter environment type Type: String Default: dev AllowedValues: - dev - stage - prod ArtifactStoreBucket: Description: Enter s3 bucket name for ArtifactStore location Type: String Default: your-s3-bucket-name Conditions: IsStageOrProd: !Or [!Equals [stage, !Ref EnvironmentType], !Equals [prod, !Ref EnvironmentType]] Resources: # For CodeBuild CodeBuildServiceRole: Type: AWS::IAM::Role Properties: Description: 'IAM Role for CodeBuild' RoleName: CodeBuildServiceIamRole AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: sts:AssumeRole Principal: Service: codebuild.amazonaws.com Policies: - PolicyName: CodeBuildServiceIamPolicy PolicyDocument: Version: 2012-10-17 Statement: - Sid: codebuild-logs Resource: - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/* - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*:* Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - Sid: codebuild-s3 Resource: - !Sub arn:aws:s3:::${ArtifactStoreBucket}/* Effect: Allow Action: - s3:GetObject - s3:PutObject - s3:GetBucketLocation - s3:GetObjectVersion - s3:GetBucketVersioning - s3:GetBucketAcl - Sid: codebuild-codebuild Resource: "*" Effect: Allow Action: - codebuild:BatchGet* - codebuild:Get* - codebuild:List* - codebuild:CreateReportGroup - codebuild:CreateReport - codebuild:UpdateReport - codebuild:BatchPutTestCases - codebuild:BatchPutCodeCoverages - secretsmanager:DescribeSecret - secretsmanager:ListSecretVersionIds - secretsmanager:GetResourcePolicy - secretsmanager:GetSecretValue - Sid: codebuild-ssm Resource: "arn:aws:ssm:*:*:parameter/CodeBuild/*" Effect: Allow Action: - ssm:PutParameter # CodePipeline CodePipelineServiceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: codepipeline.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: CodePipelineServiceRole PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Resource: - !Sub arn:aws:s3:::${ArtifactStoreBucket}/* Action: - s3:PutObject - s3:GetObject - s3:GetObjectVersion - s3:GetBucketVersioning - Effect: Allow Resource: "*" Action: - codebuild:StartBuild - codebuild:StopBuild - codebuild:BatchGet* - codebuild:Get* - codebuild:List* - s3:GetBucketLocation - s3:ListAllMyBuckets - iam:PassRole - !If - IsStageOrProd - # See https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/approvals-iam-permissions.html PolicyName: Approval-CodePipelineServiceRole PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "codepipeline:ListPipelines" Resource: "*" - Effect: Allow Action: - "codepipeline:GetPipeline" - "codepipeline:GetPipelineState" - "codepipeline:GetPipelineExecution" # TODO: Need to modify Resource: !Sub arn:aws:codepipeline:${AWS::Region}:80398EXAMPLE:MyFirstPipeline - Effect: Allow - "codepipeline:PutApprovalResult" # TODO: Need to modify Resource: !Sub arn:aws:codepipeline:${AWS::Region}:80398EXAMPLE:MyFirstPipeline - !Ref AWS::NoValue Outputs: CodePipelineRoleArn: Description: ARN for Role of Code Pipeline. Value: !GetAtt CodePipelineServiceRole.Arn Export: Name: "CodePipelineRoleArn" CodeBuildRoleArn: Description: ARN for Role of Code Build. Value: !GetAtt CodeBuildServiceRole.Arn Export: Name: "CodeBuildRoleArn"
2)Application Layer
sample-application-layer-template.yaml
AWSTemplateFormatVersion: "2010-09-09" Description: "Application Layer For Github/CodePipeline/CodeBuild" Parameters: EnvironmentType: Description: Enter environment type Type: String Default: dev AllowedValues: - dev - stage - prod GithubOwner: Description: Enter your Github Owner Type: String Default: owner-name GithubRepository: Description: Enter Github Repository Type: String Default: your-github-repository-name GithubBranch: Description: Enter Github branch Type: String Default: release GithubToken: Description: Enter Github Token Type: String ArtifactStoreBucket: Description: Enter s3 bucket name for ArtifactStore location Type: String Default: your-s3-bucket-name CodeBuildProjectName: Description: Enter target CodeBuild Project name Type: String Default: CodeBuild-Project-Demo Conditions: IsStageOrProd: !Or [!Equals [stage, !Ref EnvironmentType], !Equals [prod, !Ref EnvironmentType]] Resources: # CodePipeline # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-codepipeline-pipeline.html CodePipeline: Type: AWS::CodePipeline::Pipeline Properties: Name: CodePipelineDemo ArtifactStore: Type: S3 Location: !Ref ArtifactStoreBucket RoleArn: !ImportValue CodePipelineRoleArn RestartExecutionOnUpdate: false Stages: - Name: Source Actions: - Name: SourceAction RunOrder: 1 ActionTypeId: Category: Source Owner: ThirdParty Provider: GitHub Version: 1 OutputArtifacts: - Name: SourceOutput Configuration: Owner: !Ref GithubOwner Repo: !Ref GithubRepository Branch: !Ref GithubBranch OAuthToken: !Ref GithubToken - !If - IsStageOrProd - Name: Approval Actions: - Name: Approval RunOrder: 2 ActionTypeId: Category: Approval Owner: AWS Provider: Manual Version: 1 - !Ref AWS::NoValue - Name: Build Actions: - Name: CodeBuild RunOrder: 3 InputArtifacts: - Name: SourceOutput ActionTypeId: Category: Build Owner: AWS Version: 1 Provider: CodeBuild Configuration: ProjectName: !Ref CodeBuildProjectName OutputArtifacts: - Name: CodebuildOutput Tags: - Key: Name Value: CodePipelineDemo - Key: Env Value: !Ref EnvironmentType # CodeBuild # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-codebuild-project.html CodeBuildProject: Type: AWS::CodeBuild::Project Properties: Name: !Ref CodeBuildProjectName Description: !Sub Building stage for ${GithubBranch} in ${EnvironmentType}. Artifacts: Type: CODEPIPELINE Source: Type: CODEPIPELINE Environment: Type: LINUX_CONTAINER ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/standard:1.0 # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-environmentvariable.html EnvironmentVariables: - Name: varName1 Value: varValue1 Type: PLAINTEXT - Name: varName2 Value: /CodeBuild/testSecretParameter Type: SECRETS_MANAGER - Name: varName3 Value: /CodeBuild/testParameter Type: PARAMETER_STORE ServiceRole: !ImportValue CodeBuildRoleArn ResourceAccessRole: String TimeoutInMinutes: 5 Tags: - Key: Name Value: !Ref CodeBuildProjectName - Key: Env Value: !Ref EnvironmentType LogsConfig: CloudWatchLogs: Status: 'ENABLED' Outputs: CodeBuildProjectArn: Description: ARN for Code Build Value: !GetAtt CodeBuildProject.Arn Export: Name: "CodeBuildProjectArn"
参考文献
https://dev.classmethod.jp/articles/create_codepipeline_in_cloudformation/
https://dev.classmethod.jp/articles/developing-cloudformation-ci-cd-pipeline-with-github-codebuild-codepipeline/
https://qiita.com/neruneruo/items/70f06323de44b901918d
関連記事
AWS CloudFormation ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2021/10/26/224812
AWS CloudFormation ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2021/12/01/170326
AWS CloudFormation ~ 組み込み関数 ~
https://dk521123.hatenablog.com/entry/2021/12/04/202519
AWS CloudFormation ~ 疑似パラメータ ~
https://dk521123.hatenablog.com/entry/2021/12/05/134313
AWS CloudFormation ~ DeletionPolicy 属性 ~
https://dk521123.hatenablog.com/entry/2021/12/27/211328
AWS CloudFormation ~ 認証情報の扱い ~
https://dk521123.hatenablog.com/entry/2021/12/28/224501
CodePipeline ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/01/23/231827
CodeBuild ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/01/21/221122
各開発フェーズにおける環境の呼び方
https://dk521123.hatenablog.com/entry/2020/04/16/113816