はじめに
これまでの記事でいくつものAWSのDevToolsについて紹介していますが、今回はAWSCodeBuildの紹介をします。
AWSCodeBuildはテストやソースコードのコンパイルなどの、作成物をデプロイする前のお決まりの作業を自動化するためによく利用されます。
以前の私の記事でAWSCodeCommmitやAWSCodeDeployについて紹介していますが、AWSCodeBuildも同じCodeシリーズとしてよく紹介されます。
※日本で12月に行われているQiitaアドベントカレンダーの枠が埋まったため、今回はアドベントカレンダーとは関連付けはありません。
前提
AWSCodePipelineやGitHubActionsなどで自動実行される設定をされることが多いと思いますが、今回の記事ではDevToolsの布教活動が目的のため、ツールの基本の使い方を紹介しています。
AWS CodeBuild とは
AWSCodeBuildはS3やAWSCodeCommit,GiTHubに保存されたソースコードのコンパイルや、ユニットテストの実行などを行います。
CI/CDを実現する際に成果物のリポジトリの反映やデプロイ前のテストやコンパイルによく使われます。
↓ イメージ図はこのようになります(GoogleGeminiで生成しています)

この記事で試すこと
CloudFormationに対するテスト( AWS CloudFormation Guard)をCodeBuildで実行する
AWS CloudFormation Guard とは
CloudFormationテンプレートの定義内容が意図した内容になっているかをテストするツール。
yaml形式で定義のルールを記載して、そのルールとテンプレートの内容が一致しているか判定します。
例えば、Lambda関数の「タイムアウト設定」が「90秒であること」や「90秒以下であること」などをルールとして定義できます。
CodeBuildの設定
CodeBuildプロジェクトの作成
AWS CodeBuildのコンソール画面で「プロジェクトを作成する」を選択します
プロジェクト名を入力し、今回はデフォルトプロジェクトの設定を選択します。
ソースプロバイダは前回作成したAWSCodeCommitリポジトリを使用します。
今回は最小限の設定でプロジェクトを作成したいため、環境イメージはマネージド型イメージ、コンピューティングはLambdaを選択します。
AWSCodeCommitのリポジトリで管理しているbuildspecファイルに従ってビルドを実行するため、「builspecファイルを使用する」を選択します

テスト対象物の作成
今回はCloudFormationテンプレートに対してCfn-guardのテストを行うようにしたいので、CloudFormationテンプレートとCfn-guardのルールファイル、CodeBuild用のBuildSpecファイルを作成します。
CloudFormationテンプレート
今回はLambda関数の定義のみを定義しておきます
このLambda関数は以下の定義が行われています
- タイムアウト設定: 30(秒)
- ランタイムバージョン: python3.9
- ポリシーは: AWSLambdaBasicExecutionRole
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Lambda function CloudFormation template'
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: MyLambdaFunction
Runtime: python3.9
Handler: index.lambda_handler
Role: !GetAtt LambdaExecutionRole.Arn
Timeout: 30
Code:
ZipFile: |
def lambda_handler(event, context):
return {
'statusCode': 200,
'body': 'Hello from Lambda!'
}
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Outputs:
LambdaFunctionArn:
Description: 'Lambda Function ARN'
Value: !GetAtt MyLambdaFunction.Arn
Cfn-guard ルールファイル
今回はLambda関数について、以下の定義になっていることをチェックしています
- タイムアウト設定:900秒以下
- ランタイムバージョン:"python3.9", "python3.10", "python3.11", "nodejs18.x", "nodejs20.x"のいずれか
- ポリシー:PowerUserAccess、AdministratorAccessなど過度に強いポリシーが設定されていない
# Lambda function security and best practices rules
# Ensure Lambda function has a timeout set
rule lambda_timeout_check {
Resources.*[ Type == "AWS::Lambda::Function" ] {
Properties.Timeout exists
Properties.Timeout <= 900
}
}
# Ensure Lambda function uses supported runtime
rule lambda_runtime_check {
Resources.*[ Type == "AWS::Lambda::Function" ] {
Properties.Runtime in ["python3.9", "python3.10", "python3.11", "nodejs18.x", "nodejs20.x"]
}
}
# Ensure IAM role follows least privilege
rule iam_role_managed_policy_check {
Resources.*[ Type == "AWS::IAM::Role" ] {
Properties.ManagedPolicyArns exists
Properties.ManagedPolicyArns.* != "arn:aws:iam::aws:policy/PowerUserAccess"
Properties.ManagedPolicyArns.* != "arn:aws:iam::aws:policy/AdministratorAccess"
}
}
BuildSpec
ビルドスペックではCodeBuildの実行内容を定義しています。
今回は以下の定義を行っています。
install(インストールフェーズ)
- Rust をインストール(CloudFormation Guard は Rust で書かれています)
- Cargo(Rust のパッケージマネージャー)の環境変数を設定
- cfn-guard をインストール
phases:
install:
runtime-versions:
rust: 1.70
commands:
- echo "Installing CloudFormation Guard..."
- cargo install cfn-guard
pre_build(ビルド前フェーズ)
- 開始時刻を出力
- cfn-guard のバージョンを確認
- 正しくインストールされたか検証
pre_build:
commands:
- echo "Pre-build phase started on `date`"
- cfn-guard --version
build(ビルドフェーズ)
- CloudFormation Guard の検証を実行
- lambda-rules.guard のルールを使って lambda-template.yaml を検証
- --show-summary all で詳細なサマリーを表示
build:
commands:
- echo "Build phase started on `date`"
- echo "Running CloudFormation Guard validation..."
- cfn-guard validate --rules lambda-rules.guard --data lambda-template.yaml --show-summary all
post_build(ビルド後フェーズ)
- 完了時刻と完了メッセージを出力
post_build:
commands:
- echo "Post-build phase completed on `date`"
- echo "CloudFormation Guard validation completed"
reports セクション
- cfn-guard-report という名前でレポートを生成
- カレントディレクトリのすべてのファイルを含める
- パス構造を保持
reports:
cfn-guard-report:
files:
- '**/*'
base-directory: '.'
discard-paths: no
リポジトリの内容
フォルダ分けしてテンプレートとルールファイルを分けるなどを行ってもよいですが、今回は同じ階層に3つのファイルを配置しました。
ビルドを実行
「ビルドを開始」ボタンからビルドを実行します。
実行時エラーが発生
私の環境ではクォータに関するエラーが発生しました
AWSサポートに連絡し、数日経つと解決しました(原因は不明)
Cannot have more than 0 concurrent builds on LINUX_LAMBDA_CONTAINER machines with the BUILD_LAMBDA_2GB compute type for the account
ビルドの履歴
ビルドの状況は「ビルド履歴」に表示される「進行中」「成功」「失敗」のステータスで確認できます。
ビルドログ
ビルド履歴の詳細ではビルドログが確認できます。
↓ ビルドログでCfn-guardのチェックがPASSしていることが確認できます。


さいごに
今回の記事ではAWS CodeBuildを紹介しました。
AWSCodeCommitで管理されているアセットに対してあらかじめ設定したテストを自動でテストできるので、デプロイ前の自動テストに有効です。
AWSCodeCommit内のアセットの変更に連動してAWSCodeBUildでテストをして、場合によってはAWSCodeDeployによるデプロイを自動化するパイプラインの構成も実現できますが、それはまた別の記事で紹介します。
参考
↓ AWS CodeBuild の公式ドキュメント
↓ AWS CodeBuild のBlackBelt資料(日本語)
過去の関連記事
↓ AWS CodeCommit
↓ AWS CodeDeploy







