導入
背景・目的
- Amazon Inspectorは継続的に AWS ワークロードをスキャンする自動脆弱性管理サービスです。
- サービスの1機能を用いることで、Dockerイメージに対する脆弱性検査が可能です。
- CodeシリーズとInspectorとを組み合わせて、脆弱性検査をPassした安全なDockerイメージのみをデプロイする、CICDパイプラインを構築してみます。
読者に想定する知識レベル
- CodeシリーズやCDKの概要を理解している前提で記載します。
CICDパイプライン構築
アーキテクチャ紹介
- CodeBuild内でDockerイメージに対する脆弱性検査を実施します。
- 重大な脆弱性を検知しなかった場合のみ、DockerイメージをECRへPushします。
buildspecの作成
- まずは、CodeBuildのビルド仕様ファイルである
buildspec.yml
を作成します。- inspectorのSbomgenを用いてDockerイメージに対する脆弱性検査を実施します。
- critical若しくはhighに分類される脆弱性を検知した場合にはECRへのPushを中止します。
version: 0.2
phases:
install:
commands:
- echo "Setting timezone to Japan Standard Time (JST)..."
- cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
- echo "Installing Amazon Inspector SBOM Generator..."
- wget https://amazon-inspector-sbomgen.s3.amazonaws.com/latest/linux/amd64/inspector-sbomgen.zip
- unzip inspector-sbomgen.zip
- mv inspector-sbomgen-* inspector-sbomgen
- chmod +x ./inspector-sbomgen/linux/amd64/inspector-sbomgen
- ./inspector-sbomgen/linux/amd64/inspector-sbomgen --version
- echo "Logging in to Amazon ECR..."
- aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
- echo "Installing jq for JSON parsing..."
- curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
- apt-get update -y
- apt-get install -y jq
build:
commands:
- echo "Building Docker image..."
- TIMESTAMP=$(date +%Y%m%d%H%M%S)
- IMAGE_TAG="$(echo ${CODEBUILD_RESOLVED_SOURCE_VERSION} | head -c 7)-${TIMESTAMP}"
- echo "Tagging the image as ${IMAGE_TAG}..."
- docker build -t ${IMAGE_NAME}:${IMAGE_TAG} .
post_build:
commands:
- echo "Generating SBOM and scanning for vulnerabilities..."
- ./inspector-sbomgen/linux/amd64/inspector-sbomgen container --image ${IMAGE_NAME}:${IMAGE_TAG} --scan-sbom -o /tmp/sbom.json
- echo "Checking for critical and high vulnerabilities..."
- |
critical_vulnerabilities=$(jq -r '.metadata.properties[] | select(.name=="amazon:inspector:sbom_scanner:critical_vulnerabilities") | .value' /tmp/sbom.json)
high_vulnerabilities=$(jq -r '.metadata.properties[] | select(.name=="amazon:inspector:sbom_scanner:high_vulnerabilities") | .value' /tmp/sbom.json)
if [ "$critical_vulnerabilities" -ne 0 ] || [ "$high_vulnerabilities" -ne 0 ]; then
echo "Critical or high vulnerabilities detected. Failing the build."
exit 1
else
echo "No critical or high vulnerabilities found."
echo "Tagging and pushing the Docker image..."
docker tag ${IMAGE_NAME}:${IMAGE_TAG} ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/${IMAGE_NAME}:${IMAGE_TAG}
docker push ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/${IMAGE_NAME}:${IMAGE_TAG}
fi
artifacts:
files:
- /tmp/sbom.json
ECRの構築
- Dockerイメージ格納用にECRを構築します。
// ------------ Amazon ECR ---------------
const ecrRepo = new ecr.Repository(this, "EcrRepo", {
repositoryName: `poc-python-app`,
imageTagMutability: ecr.TagMutability.IMMUTABLE,
removalPolicy: cdk.RemovalPolicy.DESTROY // 検証用のため、スタック削除時にECR削除
})
Codeシリーズの構築
- 前述のbuildspec.ymlを用いて、Dockerイメージのビルド及び脆弱性検査を実施するCodeBuildを構築します。
- CodePipelineを構築し、CodeCommit及びCodeBuildを組み込みます。
// ------------ AWS CodeSeries ---------------
// ---- AWS CodeCommit
const gitRepo = codecommit.Repository.fromRepositoryArn(this, "GitRepo", props.codecommitArn)
// ---- AWS CodeBuild
// Create IAM Role
const buildRole = new iam.Role(this, 'BuildRole', {
roleName: `${props.prefix}-${props.envName}-role-build-docker`,
assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com'),
});
// 検証用のため、広めの権限を付与
buildRole.addToPolicy(new iam.PolicyStatement({
actions: [
'inspector-scan:*',
'ecr:*',
],
resources: ['*'],
}));
// Create Docker Build Project
const dockerBuildProject = new codebuild.Project(this, 'DockerBuildProject', {
projectName: `${props.prefix}-${props.envName}-build-docker`,
buildSpec: codebuild.BuildSpec.fromAsset(path.join(__dirname, "../../assets/buildspec.yml")),
role: buildRole,
environment: {
privileged: true, // Dockerビルド用に特権付与
buildImage: codebuild.LinuxBuildImage.STANDARD_7_0,
},
environmentVariables: {
ACCOUNT_ID: {
type: codebuild.BuildEnvironmentVariableType.PLAINTEXT,
value: props.env?.account
},
IMAGE_NAME: {
type: codebuild.BuildEnvironmentVariableType.PLAINTEXT,
value: ecrRepo.repositoryName
}
},
});
// ---- AWS CodePipeline
const pipeline = new codepipeline.Pipeline(this, 'Pipeline', {
pipelineName: `${props.prefix}-${props.envName}-pipeline`,
});
// Add Source Stage
const sourceOutput = new codepipeline.Artifact();
pipeline.addStage({
stageName: 'Source',
actions: [
new codepipeline_actions.CodeCommitSourceAction({
actionName: 'CodeCommit_Source',
repository: gitRepo,
branch: "main",
output: sourceOutput,
}),
],
});
// Add Build Stage
const scanOutput = new codepipeline.Artifact();
pipeline.addStage({
stageName: 'Scan_Build',
actions: [
new codepipeline_actions.CodeBuildAction({
actionName: 'CodeBuild_Scan_Build_Docker',
project: dockerBuildProject,
input: sourceOutput,
outputs: [scanOutput]
}),
],
});
動作確認
CodeCommitへのPushをトリガにCodePipelineを実行し、動作確認してみます。
なお、CodeCommitにはDockerfileを格納しておき、イメージ作成時にhighに分類される脆弱性を検出するようにしておきます。
- CodePipelineから呼び出されたCodeBuild内で、Dockerイメージに対する脆弱性検査を実施します。highに分類される脆弱性を検知したことから、パイプライン実行及びECRへのPushが失敗します。
Critical or high vulnerabilities detected. Failing the build.
- buildspecを修正して、Push中止対象とする脆弱性をcriticalに限定してみます。すると、パイプライン実行及びECRへのPushに成功します。
- echo "Generating SBOM and scanning for vulnerabilities..."
- ./inspector-sbomgen/linux/amd64/inspector-sbomgen container --image ${IMAGE_NAME}:${IMAGE_TAG} --scan-sbom -o /tmp/sbom.json
- echo "Checking for critical vulnerabilities..."
- |
critical_vulnerabilities=$(jq -r '.metadata.properties[] | select(.name=="amazon:inspector:sbom_scanner:critical_vulnerabilities") | .value' /tmp/sbom.json)
if [ "$critical_vulnerabilities" -ne 0 ]; then
echo "Critical vulnerabilities detected. Failing the build."
exit 1
else
echo "No critical vulnerabilities found."
echo "Tagging and pushing the Docker image..."
docker tag ${IMAGE_NAME}:${IMAGE_TAG} ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/${IMAGE_NAME}:${IMAGE_TAG}
docker push ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/${IMAGE_NAME}:${IMAGE_TAG}
fi
No critical vulnerabilities found.
Tagging and pushing the Docker image...
- 脆弱性検査結果はCodeBuildのArtifactとしてS3にアップロードされます。CycloneDX形式のSBOMファイルになります。
{
"bomFormat": "CycloneDX",
"components": [
(一部略)
],
"metadata": {
"properties": [
{
"name": "amazon:inspector:sbom_scanner:critical_vulnerabilities",
"value": "0"
},
{
"name": "amazon:inspector:sbom_scanner:high_vulnerabilities",
"value": "3"
},
{
"name": "amazon:inspector:sbom_scanner:medium_vulnerabilities",
"value": "2"
},
{
"name": "amazon:inspector:sbom_scanner:low_vulnerabilities",
"value": "0"
},
{
"name": "amazon:inspector:sbom_scanner:other_vulnerabilities",
"value": "0"
}
],
(一部略)
"vulnerabilities": [
]
}
参考資料
- https://aws.amazon.com/jp/inspector/
- https://docs.aws.amazon.com/inspector/latest/user/cicd-custom.html
- https://docs.aws.amazon.com/inspector/latest/user/sbom-generator.html#install-sbomgen