LoginSignup
1
1

ECRイメージスキャンを重要度でフィルターして通知(CDK)

Last updated at Posted at 2023-06-23

概要

AWS Lambdaを使用せずにEventBridge + SNSでECRイメージスキャン結果のメール通知を行うCDKサンプルコード(TypeScript)を紹介します。

フィルター範囲

severityはECRイメージスキャンで定義されている重要度レベルを示しており、重要度は以下の通りです。

  • UNDEFINED
  • CRITICAL
  • HIGH
  • MEDIUM
  • LOW
  • INFORMATIONAL

本記事の例では重要度HIGH以上を通知対象としています。

ファイル構成

ファイル構成は以下です。

  • bin/
    • main.ts
  • lib/
    • ImageScan/
      • ImageScanStack.ts

サンプルコード

bin/main.ts

bin/main.ts
#!/usr/bin/env node

import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { Environment } from 'aws-cdk-lib';
import { ImageScanStack } from '../lib/ImageScan/ImageScanStack';

if (process.env['NODE_ENV'] == null || process.env['NODE_ENV'] === '') {
    throw new Error('NODE_ENV is not set');
}
if (process.env['AWS_PROFILE'] == null || process.env['AWS_PROFILE'] === '') {
    throw new Error('AWS_PROFILE is not set');
}

const app = new cdk.App();

const env: Environment = {
    account: '<AWSアカウント番号>',
    region: '<AWSリージョン>',
};

new ImageScanStack(app, {
    env: env,
});

lib/ImageScan/ImageScanStack.ts

lib/ImageScan/ImageScanStack.ts
import * as cdk from 'aws-cdk-lib';
import { Rule } from 'aws-cdk-lib/aws-events';
import { Topic } from 'aws-cdk-lib/aws-sns';
import { EmailSubscription } from 'aws-cdk-lib/aws-sns-subscriptions';
import { SnsTopic } from 'aws-cdk-lib/aws-events-targets';
import { Construct } from 'constructs';

/**
 * 構築プロパティ。
 */
export interface ImageScanProps extends cdk.StackProps {}

export class ImageScanStack extends cdk.Stack {
    private readonly _props: ImageScanProps;

    constructor(scope: Construct, props: ImageScanProps) {
        super(scope);

        // SNSアラートトピック作成
        const snsTopic = new Topic(this, 'SNSTopic', {
            displayName: 'ImageScanResultAlert',
            topicName: 'ImageScanResultTopic',
        });
        snsTopic.addSubscription(new EmailSubscription('user@example.com'));

        // イメージスキャン結果通知イベント作成
        const imageScanResultEvent = new Rule(this, 'ImageScanResultEvent', {
            ruleName: 'ImageScanResultEvent',
            description: 'ECR Image Scan Result Alert for ExampleRepositoryName',
            eventPattern: {
                source: ['aws.ecr'],
                detailType: ['ECR Image Scan'],
                detail: {
                    'repository-name': ['ExampleRepositoryName'], // イメージスキャン対象のリポジトリ名
                    'scan-status': ['COMPLETE'],
                    'finding-severity-counts': {
                        $or: [
                            // 重要度HIGH以上のみ通知するようにフィルタリング
                            {
                                CRITICAL: [{ numeric: ['>', 0] }],
                            },
                            {
                                HIGH: [{ numeric: ['>', 0] }],
                            },
                        ],
                    },
                },
            },
        });

        // ターゲット追加
        imageScanResultEvent.addTarget(new SnsTopic(snsTopic));
    }
}

メール通知の発砲

重要度HIGH以上のイメージがプッシュされた際に以下のような内容のメール通知が発砲されます。

{"version":"0","id":"93d88051-2270-f8b7-ad0b-efea5b962e2b","detail-type":"ECR Image Scan","source":"aws.ecr","account":"<AWSアカウント番号>","time":"2023-06-24T02:00:00Z","region":"<AWSリージョン>","resources":["arn:aws:ecr:<AWSリージョン>:<AWSアカウント番号>:repository/ExampleRepositoryName"],"detail":{"scan-status":"COMPLETE","repository-name":"ExampleRepositoryName","image-digest":"sha256:b8a5bc211d11fa35c0074cfc64cb8f783356eeda0f242017e1e7efcd562a38d4","image-tags":["e7e685b","latest"],"finding-severity-counts":{"HIGH":9,"MEDIUM":0,"INFORMATIONAL":44,"LOW":0}}}

メールの本文は改行されていないJSONでそのまま出力されるため、必要に応じてEventBridgeの入力トランスフォーマー等で整形して下さい。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1