🛠️

GuardDutyのECS Runtime MonitoringがCodePipelineに対応していない件について

2024/03/15に公開

概要

以下の記事でも紹介されていますが、2023年11月末にFargateに対応したAWSマネージドなセキュリティ対策オプションがGuardDutyに追加されました。
https://dev.classmethod.jp/articles/ecs-fargate-runtime-detection/
私が管理している環境でも有効化してみたところ、しばらくしてサイドカーであるaws-guardduty-agentコンテナがいつの間にか消えていることが判明。

調べてみたところ、ECS Runtime Monitoringは現状(2024/03/15時点)CodePipelineによって起動されたタスクに対応していないとのこと。(マジか!)
https://docs.aws.amazon.com/guardduty/latest/ug/how-runtime-monitoring-works-ecs-fargate.html

Presently, Runtime Monitoring doesn't support the tasks launched by AWS Batch, AWS Step Functions, and AWS CodePipeline.

対応方法

リリースされたばかりの機能ということもあってしばらくしたらCodePipelineもサポートされるようにはなるとは思いますが、取り急ぎLambdaで対応することにしました。
https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/actions-invoke-lambda-function.html
対応自体は簡単で、上記のAWSユーザーガイドを参考にLambda用IAMロールとLambdaを作ります。そしてCodePipelineの最後(Deployステージの後)にステージを追加してそのLambdaを呼び出すようにするだけです。私が管理している環境ではECSをローリングアップデートしているので、以下情報はそういったケースに流用できるかと思います。

Lambda用IAMロールのポリシー

{
    "Statement": [
        {
            "Action": [
                "logs:PutLogEvents",
                "logs:CreateLogStream",
                "logs:CreateLogGroup"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Action": [
                "codepipeline:PutJobSuccessResult",
                "codepipeline:PutJobFailureResult"
            ],
            "Effect": "Allow",
            "Resource": "*"
        },
        {
            "Action": [
                "ecs:UpdateService",
                "ecs:RegisterTaskDefinition",
                "ecs:DescribeTaskDefinition",
                "ecs:DescribeServices"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ],
    "Version": "2012-10-17"
}

Lambda(Python)

import os
import json
import boto3

def lambda_handler(event, context):
    # Lambdaで定義している環境変数
    product_code = os.environ["PRODUCT_CODE"]
    deploy_env = os.environ["DEPLOY_ENV"]

    ecs = boto3.client('ecs')
    codepipeline = boto3.client('codepipeline')
    try:
        ecs.update_service(
            cluster=f"{product_code}-{deploy_env}-ecs-cluster",
            service=f"{product_code}-{deploy_env}-ecs-service",
            forceNewDeployment=True,
        )
        # https://qiita.com/hassoubeat/items/f2f89eae2c26cdc06433
        codepipeline.put_job_success_result(jobId = event['CodePipeline.job']['id'])
        print("ECS service update succeeded.")
    except ecs.exceptions.ResourceNotFoundException as e:
        codepipeline.put_job_failure_result(
            jobId = event['CodePipeline.job']['id'],
            failureDetails={
                'type': 'JobFailed',
                'message': str(e)
            }
        )
        print("ECS service update faild.")

    return {
        'statusCode': 200,
        'body': json.dumps('ECS service updated.')
    }

最後に

CodePipelineを利用してECSのデプロイサイクルを回している方は多いと思うので、早くCodePipelineもサポートされるといいですね。

Discussion