BuildProjectを Terraform で構築する
試したバージョン
Name | Version |
---|---|
terraform | 1.1.5 |
aws | 4.0 |
必要リソース
CodeBuild でビルドを行う際に作成が必要となるAWSリソースは以下の通り
- CodeBuild ビルドプロジェクト
- S3 バケット or CodeCommit リポジトリ
- IAM ロール
- (オプション)CloudWatchLogs ロググループ,ログストリーム
手順
公式の手順
を参考にterraform tfファイルを作成していきます
AWS CodeBuild - 開始方法
1. ファイル準備
ビルド対象のソースファイルを作成します
ディレクトリ構成が以下の通りになるよう、公式手順を見ながら作成してください
$ tree tutorial/
tutorial/
├── buildspec.yaml
├── pom.xml
└── src
├── main
│ └── java
│ └── MessageUtil.java
└── test
└── java
└── TestMessageUtil.java
5 directories, 4 files
2. S3 バケット作成
ソースファイルの読み込み元として利用
するインプット用バケット、
ビルド完了したアーティファクトの保管先
となるアウトプット用バケットの2つを作成します
input,outputを同じバケットにすることもできますが、分かりやすくするために2つ作成します
input,output用バケットはそれぞれ1つずつだけでいいと思うので、こちらはmoduleには含めず
resource
で宣言します
# input用バケット
resource "aws_s3_bucket" "input" {
bucket = "tutorial-codebuild-input"
}
# output用バケット
resource "aws_s3_bucket" "output" {
bucket = "tutorial-codebuild-output"
}
3. IAMロール作成
ビルドプロジェクトがビルドする際に利用するIAMロールを作成します
IAMポリシーに関しては、ビルドプロジェクトの仕様によって付与する権限が大幅に変わるため、
自力で作成すると権限の過不足が発生しやすいと思います
コンソールで作成すると、IAMロールを自動で作成/権限付与を行ってくれるので、
この点ではTerraformだと不便、、
一応、IAMロールに必要な権限は、以下の通りです
- S3 バケットに対するアクセス権限
- inputバケットへの読み取り権限
- outputバケットへの書き込み権限
- CloudWatchLogに対するアクセス権限
- ロググループ作成権限
- ログストリーム作成権限
tfファイル
# IAM Role
resource "aws_iam_role" "codebuild_iam_role" {
name = "CodeBuildServiceRole"
assume_role_policy = data.aws_iam_policy_document.codebuild_assume_role_policy.json
}
# IAM Policy Document
data "aws_iam_policy_document" "codebuild_assume_role_policy" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["codebuild.amazonaws.com"]
}
}
}
# IAM Policy
resource "aws_iam_policy" "codebuild_base_policy" {
name = "CodeBuildBasePolicy"
policy = file("./codebuild_base_policy.json")
}
resource "aws_iam_policy" "codebuild_ro_policy" {
name = "CodeBuildReadOnlyPolicy"
policy = file("./codebuild_ro_policy.json")
}
# Policy Attachment
resource "aws_iam_role_policy_attachment" "codebuild_policy_attachment01" {
role = aws_iam_role.codebuild_iam_role.name
policy_arn = aws_iam_policy.codebuild_base_policy.arn
}
resource "aws_iam_role_policy_attachment" "codebuild_policy_attachment02" {
role = aws_iam_role.codebuild_iam_role.name
policy_arn = aws_iam_policy.codebuild_ro_policy.arn
}
IAMロールを一つと、ポリシーを2つ作成し、それぞれアタッチメントで関連付けを行っています
ポリシーのJSONは以下の通りです]
<your aws project id>
はご自身のAWS ProjectIDに置き換えてください
input用、output用bucket名
も、それぞれご自身が作成したものに合わせてください
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Resource": [
"*"
],
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
},
{
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::codepipeline-ap-northeast-1-*"
],
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:GetBucketAcl",
"s3:GetBucketLocation"
]
},
{
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::tutorial-codebuild-output",
"arn:aws:s3:::tutorial-codebuild-output/*"
],
"Action": [
"s3:PutObject",
"s3:GetBucketAcl",
"s3:GetBucketLocation"
]
},
{
"Effect": "Allow",
"Action": [
"codebuild:CreateReportGroup",
"codebuild:CreateReport",
"codebuild:UpdateReport",
"codebuild:BatchPutTestCases",
"codebuild:BatchPutCodeCoverages"
],
"Resource": [
"arn:aws:codebuild:ap-northeast-1:<your aws project id>:report-group/*"
]
}
]
}
- CloudWatchへの書き込み権限
- CodePipelineへの権限(多分今回は不要)
- Output用バケットへの書き込み権限
- codebuildレポートへの買い込み権限
を付与していますね
もう一つ、ReadOnlyは以下の通りです
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::tutorial-codebuild-input/MessageUtil.zip",
"arn:aws:s3:::tutorial-codebuild-input/MessageUtil.zip/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketAcl",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::tutorial-codebuild-input"
]
}
]
}
- Input用のバケットに対してGetBucket権限等
- Inputバケット内のソースZipファイルに対してGetObject権限等
だけ付与しています
ちなみに、このポリシーどうやって作ったかというと、
コンソールで試しに作ってみたときに自動作成されたロールのポリシーをまねして作りました(本末転倒)
4. Build Project 作成
buildproject本体をterraformで作っていきます
resource "aws_codebuild_project" "build_project01" {
name = "build-project01"
service_role = aws_iam_role.codebuild_iam_role.arn
source {
type = "S3"
location = "tutorial-codebuild-input/MessageUtil.zip"
}
environment {
compute_type = "BUILD_GENERAL1_SMALL"
image = "aws/codebuild/amazonlinux2-x86_64-standard:3.0"
type = "LINUX_CONTAINER"
}
artifacts {
type = "S3"
location = "tutorial-codebuild-output"
}
logs_config {
cloudwatch_logs {
group_name = "/aws/codebuild/build-project01"
stream_name = "build-log"
}
}
}
大きく分けて source
, artifact
, environment
の3つの項目を詳しく設定します
- name : ビルドプロジェクトの名前を付けます
- service_role : さっき作ったIAMのarnを指定します
- source : input sourceに関する設定です
- type :
S3
,CODECOMMIT
,GITHUB
などから選べます 今回はS3です - location : ↑で指定したソースの場所を指定します S3の場合はバケット名/ソースzipファイル とします
- type :
- artifact : output artifactに関する設定です
- type : source 同様 output先のタイプを指定します outputは
S3
,CODEPIPELINE
,NO_ARTIFACTS
が指定できます - location : output先の場所を指定します 今回はさっき作ったS3バケットです
- type : source 同様 output先のタイプを指定します outputは
- environment : ビルド処理を行うマシンに関する設定です
- compute_type : マシンのスペックです Amazon Linuxを利用する場合、
GENERAL1_SMALL
しか選べないようです - image : マシンのイメージです 今回は
aws/codebuild/amazonlinux2-x86_64-standard:3.0
にしました - type : Linux以外にも
Windows
マシンが選べたりします
- compute_type : マシンのスペックです Amazon Linuxを利用する場合、
- logs_config : CloudWatch Logsへのログ書き込みに関する設定です オプションの項目です
- group_name : ロググループ名を指定します
- stream_name : ログストリーム名を指定します
- status : ログの書き込みをやめたいときは、statusを追加して値をDISABLEDにします
作成
$ terraform plan
→ $ terraform apply
で作成します
問題なければビルドプロジェクトが作成されます
ソースファイル圧縮&アップロード
# カレントディレクトリ確認
$ ls
buildspec.yaml pom.xml src
# ソールファイル群をzip圧縮します
$ zip MessageUtil.zip *
# s3のインプット用バケットにアップロードします
$ aws s3 cp MessageUtil.zip s3://tutorial-codebuild-input
upload: ./MessageUtil.zip to s3://tutorial-codebuild-input/MessageUtil.zip
ソースのアップが完了したら、
作成されたビルドプロジェクトの詳細ページにアクセスして、ビルドも実行してみましょう
問題なくartifactがoutput用バケットに作成されていればこのチュートリアルは完了です
感想
CodeBuildのBuildProjectと、それに関連するリソースをterraformで作ってみました
BuildProjectのリソースを作成するためにIAMロールの指定が必須なのですが、
このIAMロールまでterraformでリソース作成するのは結構骨が折れました、、
IAMロールだけコンソールで作成、
もしくは、お試しでBuildProjectをコンソールで作成してみて、
自動生成されたIAMロールのARNをコピーしてcodebuild.tfにハードコーディングでもいいんじゃないかな
と思いました
この記事が誰かほかのterraformerのお役に立てれば幸いです
次は codepipelineをterraformで作る に挑んでみたいと思います