GitHub連携を含んだCodeBuildのCloudFormationテンプレート生成を試してみた
はじめに
CICD環境作成の非属人化を目指して、AWS CodeBuild / AWS CodeDeploy / AWS CodePipelineの組み合わせで構築し、更にCloudFormationテンプレート化を検討していました。が、調べるうちに担当プロジェクトではAWS CodeBuildで事足りることに気が付きました。
実際のCodeBuild上でのCICD処理までは手が届いていないものの、前準備として、GitHubとの連携を含めつつAWS CodeBuild単体でのCloudFormationを作成するまでの手続きをまとめてみました。
CodeBuildとGitHubの連携
CodeBuildとGitHubとの連携は別途事前に管理コンソール上で行う必要があります。
- GitHub上でPersonal access tokensを発行する
- CodeBuildの新規作成でTokenを登録する
といった手続きですが、CodeBuildの新規作成はあくまでToken登録目的となります。
GitHub上でPersonal access tokensを発行する
Developer settingsにてPersonal access tokensから「Generate new token」を選択し、今回扱うトークンを作成します。
CodeBuildの新規作成でTokenを登録する
CodeBuildにて新規プロジェクト作成を選択します。
送信元を以下の構成にて選択・入力します。
- ソースプロバイダ
- GitHub
- リポジトリ
- GitHub の個人用アクセストークンで接続する
- GitHub の個人用アクセストークン
- 生成したTokenを入力して「トークンの保存」を選択
下図のようにGitHubリポジトリが参照できれば成功です。
フォーム最下にある「キャンセル」を選択します。
CloudFormationテンプレートを作成する
CodeBuildの設定テンプレートを作成します。テンプレート設定項目については以下公式ドキュメントを参考にします。
先ずは管理コンソール上で完成させる
公式ドキュメントの項目を見ても分かりづらいため、管理コンソールにてビルドプロジェクトを作成し、実際にビルドを成功させます。
BuildSpecについては以下のような内容でも問題ありません。
version: 0.2 phases: install: runtime-versions: docker: 18 python: 3.7 build: commands: - git status
プロジェクト設定を見ながらテンプレートを作成する
ビルドが成功したプロジェクトの各設定と、公式ドキュメント上の設定項目を見比べながら入力していきます。
AWS::IAM::Roleにて今回設定したAssumeRolePolicyDocumentは以下の通りです。
Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: "Allow" Action: 'sts:AssumeRole' Principal: Service: codebuild.amazonaws.com
AWS::CodeBuild::ProjectのSource → Authはドキュメントを読むと入力に迷うところですが、今回はType: OAUTH
のみで問題ありませんでした。
Source: Auth: Type: OAUTH Location: 'https://github.com/xxxxxxxxxxxxxxxxxxxx/xxxx.git' Type: GITHUB ReportBuildStatus: true BuildSpec: | version: 0.2 phases: install: runtime-versions: docker: 18 python: 3.7 build: commands: - git status
AWS::CodeBuild::ProjectのTriggers → FilterGroupsについては配列の配列という入れ子にする必要があります。これも公式ドキュメントを読んだ限りでは把握し難い箇所です。
Triggers: Webhook: true FilterGroups: - - Type: EVENT Pattern: PUSH - Type: HEAD_REF Pattern: ^refs/tags/pre-release-v.*
利用するポリシーについて
必要となるポリシーがはっきりとはしないため、公式ドキュメントを参考にしています。
- 'ecr:GetAuthorizationToken' - 'ecr:BatchCheckLayerAvailability' - 'ecr:GetDownloadUrlForLayer' - 'ecr:GetRepositoryPolicy' - 'ecr:DescribeRepositories' - 'ecr:ListImages' - 'ecr:DescribeImages' - 'ecr:BatchGetImage' - 'ecr:InitiateLayerUpload' - 'ecr:UploadLayerPart' - 'ecr:CompleteLayerUpload' - 'ecr:PutImage' - 'codepipeline:*' - 'codebuild:*' - 'events:*' - 's3:CreateBucket' - 's3:GetBucket*' - 's3:PutBucket*' - 's3:GetObject*' - 's3:ListAllMyBuckets' - 's3:ListBucket*' - 's3:PutObject*' - 'logs:CreateLogGroup' - 'logs:CreateLogStream' - 'logs:PutLogEvents' - 'iam:AddRoleToInstanceProfile' - 'iam:AttachRolePolicy' - 'iam:AttachGroupPolicy' - 'iam:AttachUserPolicy' - 'iam:CreateInstanceProfile' - 'iam:CreatePolicy' - 'iam:CreateRole' - 'iam:GetRole' - 'iam:ListAttachedGroupPolicies' - 'iam:ListAttachedUserPolicies' - 'iam:ListGroups' - 'iam:ListPolicies' - 'iam:ListUsers' - 'iam:ListRoles' - 'iam:PutRolePolicy' - 'iam:PassRole' - 'iam:UpdateAssumeRolePolicy' - 'logs:*'
テンプレート全体
今回作成したテンプレートです。buildspecについては今後組み立てることとして仮入力にしています。
AWSTemplateFormatVersion: '2010-09-09' Resources: BuildRole: Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: "Allow" Action: 'sts:AssumeRole' Principal: Service: codebuild.amazonaws.com BuildPolicies: Type: "AWS::IAM::Policy" Properties: PolicyName: Polocy PolicyDocument: Version: "2012-10-17" Statement: - Action: - logs:* Resource: '*' Effect: Allow - Resource: "*" Effect: Allow Action: - 'ecr:GetAuthorizationToken' - 'ecr:BatchCheckLayerAvailability' - 'ecr:GetDownloadUrlForLayer' - 'ecr:GetRepositoryPolicy' - 'ecr:DescribeRepositories' - 'ecr:ListImages' - 'ecr:DescribeImages' - 'ecr:BatchGetImage' - 'ecr:InitiateLayerUpload' - 'ecr:UploadLayerPart' - 'ecr:CompleteLayerUpload' - 'ecr:PutImage' - 'codepipeline:*' - 'codebuild:*' - 'events:*' - 's3:CreateBucket' - 's3:GetBucket*' - 's3:PutBucket*' - 's3:GetObject*' - 's3:ListAllMyBuckets' - 's3:ListBucket*' - 's3:PutObject*' - 'logs:CreateLogGroup' - 'logs:CreateLogStream' - 'logs:PutLogEvents' - 'iam:AddRoleToInstanceProfile' - 'iam:AttachRolePolicy' - 'iam:AttachGroupPolicy' - 'iam:AttachUserPolicy' - 'iam:CreateInstanceProfile' - 'iam:CreatePolicy' - 'iam:CreateRole' - 'iam:GetRole' - 'iam:ListAttachedGroupPolicies' - 'iam:ListAttachedUserPolicies' - 'iam:ListGroups' - 'iam:ListPolicies' - 'iam:ListUsers' - 'iam:ListRoles' - 'iam:PutRolePolicy' - 'iam:PassRole' - 'iam:UpdateAssumeRolePolicy' Roles: - Ref: "BuildRole" LogBucket: Type: 'AWS::S3::Bucket' Build: Type: 'AWS::CodeBuild::Project' Properties: Artifacts: Type: NO_ARTIFACTS Name: CodeTest ServiceRole: !GetAtt BuildRole.Arn Environment: ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/amazonlinux2-x86_64-standard:1.0-1.13.0 Type: LINUX_CONTAINER Triggers: Webhook: true FilterGroups: - - Type: EVENT Pattern: PUSH - Type: HEAD_REF Pattern: ^refs/tags/pre-release-v.* Source: Auth: Type: OAUTH Location: 'https://github.com/xxxxxxxxxxx/xxxx.git' Type: GITHUB ReportBuildStatus: true BuildSpec: | version: 0.2 phases: install: runtime-versions: docker: 18 python: 3.7 build: commands: - git status LogsConfig: S3Logs: Status: ENABLED Location: !GetAtt LogBucket.Arn
あとがき
CloudFormationの設定入力はリソース毎にページが別れていることと、想定しているテンプレート例もなかなか見つからないため、入力のvalidateのチェック及びStackの試作が不可欠です。また、今回はGitHubのOAuth接続もあり、本当に正常にいっているのか検証を只管繰り返していました。
一度出来上がってしまえば、メンテナンスコストや属人性排除の点で大きなメリットが出てきます。CodeBuild単体でのCICDを検討されている方はあまり多くないかもしれませんが、今回の手続きが参考になれば幸いです。