OPS

AWS Inspector v2の通知内容を日本語化してBacklogに起票する

AWS Inspector v2の通知内容を日本語化してBacklogに起票する

2022.11.15

本記事のポイント

AWS Inspector v2(以下、Inspector)の通知内容をできるだけ見やすく(日本語化、整形)して通知する方法をご紹介します。
実装するための詳細手順を載せてますので、宜しければお試しください。



はじめに

AWSのセキュリティを強化するためには、プラットフォーム上の脆弱性とOS内の脆弱性を診断するためにAWS Security HubやInspectorを使用したり、悪意のあるアクティビティ(操作)、不正な動作、不正なアカウント連携、サーバーの乗っ取り等を検知したりするためにAmazon GuardDutyやIAM AccessAnalyzerを使用するなどして、総合的に対策することが重要です。

今回は、その中の一つであるInspectorに焦点をあて、Inspectorの脆弱通知が英語で分かりづらい、とお困りの方に向けて 「脆弱性の通知内容を日本語化してbacklogに起票する」 という内容をご紹介いたします。

Inspectorのダッシュボードはとても見やすいですが、コンソールに定期的にログインして確認するのが意外と大変でした。Event Bridgeと連携することで通知は可能ですが、json形式かつ英語のため、できるだけ見やすく(日本語化、整形)した上で通知する仕組みを作ってみました。

Inspectorとは?

Inspector とは、Amazon EC2(以下、EC2)もしくはAmazon ECRのコンテナイメージに対して自動的にかつ継続的にスキャンを行い、脆弱性の影響を受けるリソースを検出するサービスとなります。

CVEに登録されている脆弱性を検知することができ、加えてEC2はネットワーク到達性等が考慮されたInspector Scoreが表示されるので、実際の環境に適したスコアを確認できます。 実行タイミングは新しい脆弱性が登録、ソフトウェアがインストール、もしくは脆弱性対象のソフトウェアがアップデートされたときに自動で実行されるので、ユーザ側で実行タイミングを考える必要はありません。

日本語化してバックログに起票する実装方法

全体のフロー図は以下となります。

AWS Inspector v2の通知内容を日本語化してBacklogに起票する

Backlog起票用のメールアドレスを発行

Backlog起票用のメールアドレスを発行は、 こちらの公式手順 を参照ください。

通知用SNSトピックの作成

SNSサービス画面を開き【トピック】から【トピックの作成】へ進み、タイプの選択を【スタンダード】に変更し、任意の名前を入力した上で【トピックの作成】をクリックします。
※ ここでは「inspector-notifications」としています

通知用SNSトピックの作成

【サブスクリプションの作成】よりプロトコルを「Eメール」に変更し、エンドポイントにバックログ起票用のメールアドレスを入力の上【サブスクリプションの作成】をクリックします。

エンドポイントにバックログ起票用のメールアドレスを入力の上【サブスクリプションの作成】をクリック

「Notification AWS – Subscription Confirmation」というメールが届いたら本文のリンクをクリックし、承認が完了します。 問題なく承認がされていればサブスクリプションのステータスが「確認済み」になっているかと思います。

Lambda関数の作成

Lambdaサービス画面を開き【関数の作成】を選択し、関数名に任意の名前を入力し、ランタイムはPythonの最新バージョンを選びます。
※ ここでは「send-mail-inspector-v2-result」としています。)その他はデフォルトのまま【関数の作成】をクリックします。

関数名に任意の名前を入力し、ランタイムはPythonの最新バージョンを選ぶ

関数の作成が完了したら、コード入力箇所に以下のコードを貼り付けし、【Deploy】を行います。

import os
import boto3
import json
import traceback
sns = boto3.client('sns')
inspector = boto3.client('inspector')
SNS_TOPIC_ARN = os.environ['SNS_TOPIC_ARN']
  
  
def sns_publish(subject, body):
    sns = boto3.client('sns')
    sns.publish(
        TopicArn = SNS_TOPIC_ARN,
        Subject = str(subject),
        Message = str(body)
        )
  
def translate_text(text):
    client = boto3.client('translate')
    response = client.translate_text(
        Text=text,
        SourceLanguageCode='auto',
        TargetLanguageCode='ja',
    )
      
    return response['TranslatedText']
 
def translate_score(scoringVector):
    # メトリクス一覧の定義
    AV = {'N': 'ネットワーク', 'A': '隣接', 'L': 'ローカル', 'P': '物理'}
    AC = {'L': '低', 'H': '高'}
    PR = {'N': '不要', 'L': '低', 'H': '高'}
    UI = {'N': '不要', 'R': '要'}
    S = {'U': '変更なし', 'C': '変更あり'}
    C = {'H': '高', 'L': '低', 'N': 'なし'}
    I = {'H': '高', 'L': '低', 'N': 'なし'}
    A = {'H': '高', 'L': '低', 'N': 'なし'}
      
    # スコアメトリクスを日本語化する
    # example) CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
    splitScoringVectors = scoringVector.split("/")
  
    score = splitScoringVectors[0].split(':')[1]
    av = splitScoringVectors[1].split(':')[1]
    ac = splitScoringVectors[2].split(':')[1]
    pr = splitScoringVectors[3].split(':')[1]
    ui = splitScoringVectors[4].split(':')[1]
    s = splitScoringVectors[5].split(':')[1]
    c = splitScoringVectors[6].split(':')[1]
    i = splitScoringVectors[7].split(':')[1]
    a = splitScoringVectors[8].split(':')[1]
 
    translateScoringVector = "攻撃元区分: "  + AV[av] \
                 + "\n攻撃条件の複雑さ:" + AC[ac] \
                 + "\n必要な特権レベル:" +   PR[pr] \
                 + "\nユーザ関与レベル:" +   UI[ui] \
                 + "\n機密性への影響:" +  C[c] \
                 + "\n完全性への影響:" +  I[i] \
                 + "\n可用性への影響:" +   A[a]
 
    return translateScoringVector
 
def lambda_handler(event, context): 
    try:
        # ec2 ecr 共通情報を取得
        time = event['time']
        detail = event['detail']
        description = detail['description']
        cvsses = detail['packageVulnerabilityDetails']['cvss']
        sourceUrl = detail['packageVulnerabilityDetails']['sourceUrl']
        vulnerabilityId = detail['packageVulnerabilityDetails']['vulnerabilityId']
        recommendation = detail['remediation']['recommendation']['text']
        resources = event['resources']
        severity = detail['severity']
        title = detail['title']
 
 
        existsInspectorScoreDetails = 'inspectorScoreDetails' in detail.keys()
         
        # ec2 は inspectorscore、ecr は cvss(3.1) を取得
        scoringVector = ""
        score = ""
        if (existsInspectorScoreDetails):
            scoringVector = detail['inspectorScoreDetails']['adjustedCvss']['scoringVector']
            score = detail['inspectorScoreDetails']['adjustedCvss']['score']
        else:
            for cvss in cvsses:
                source = cvss['source']
                version = cvss['version']
                if version == '3.1':
                    scoringVector = cvss['scoringVector']
                    score = cvss['baseScore']
                    break
 
        # description を和訳する
        translateDescription = translate_text(description)
          
        # recommendation を和訳する
        translateRecommendation = translate_text(recommendation)
          
        # score を和訳する
        translateScoringVector = translate_score(scoringVector)
 
        # 件名を作成
        subject = "【" + str(score) + "】" + title
          
        # 本文を作成
        messageBody = "【スコアメトリクス(ec2:inspectorscore/ecr:cvss(version:3.1))】" \
                    + "\nスコア:" + str(score) \
                    + "\n" + translateScoringVector \
                    + "\n\n【詳細】\n時間:" + str(time) \
                    + "\nリソース ID:" + ",".join(resources) \
                    + "\n重大性:" + severity \
                    + "\n脆弱性 ID:" + vulnerabilityId \
                    + "\n説明:" + translateDescription \
                    + "\n推奨:" + translateRecommendation \
                    + "\n\nソース url:" + sourceUrl
         
        # メール送信
        sns_publish(subject, messageBody)
  
    except:
        print(traceback.print_exc())
        title="Inspector Notifications (Extraction failure)"
        sns_publish(title, str(event))
      
    finally:
        print("event:",event)
  
    return 0

【設定】タブの【アクセス権限】から自動で作成された実行ロールをクリックし、ロールのページへ移動します。

ロールからポリシーをクリックし、【ポリシーの編集】より以下ポリシーを追記

ロールからポリシーをクリックし、【ポリシーの編集】より以下ポリシーを追記します。
※ 既存の閉じカッコ(})に「,」を入力する必要があります
※ 今回はテストのためリソースを「*」としていますので、必要に応じてリソースを絞ってください

{
    "Action": [
        "translate:TranslateText",
        "comprehend:DetectDominantLanguage",
        "SNS:Publish"
    ],
    "Effect": "Allow",
    "Resource": "*"
}
ロールからポリシーをクリックし、【ポリシーの編集】より以下ポリシーを追記

Lambdaサービス画面に戻り、【設定】タブの【環境変数】を開き、【編集】をクリックします。【環境変数の追加】を選択し、以下の内容で入力し、【保存】をクリックします。

  • キー:SNS_TOPIC_ARN
  • 値:先程作成したトピックのARNを入力
  • 【環境変数の追加】を選択し、以下の内容で入力し、【保存】

    EventBridgeの作成

    EventBridgeサービス画面を開き【ルールを作成】をクリックします。任意の名前を入力し、【次へ】をクリックします。
    ※ここでは「inspector-finding」としています。

    EventBridgeサービス画面を開き【ルールを作成】をクリック

    下までスクロールし、イベントパターン内の【パターンを編集】を選択し、以下を入力し、【次へ】をクリックします。

    {
      "source": ["aws.inspector2"],
      "detail-type": ["Inspector2 Finding"]
    }
    
    イベントパターン内の【パターンを編集】を選択

    ターゲットは「Lambda関数」に、機能を先程作成したLambda関数に変更し、【次へ】をクリックします。

    に、機能を先程作成したLambda関数に変更

    その他変更はないので、【次へ】で進んでいただき、【ルールの作成】をクリックします。

    SSMエージェントをインストール、有効化する

    SSMエージェントをインストールと有効化は、OSによって対応内容が変わりますので公式ユーザガイドのリンクを記載します。

  • まずはこちらの手順にて、SSMエージェントをインストールします
  • SSMエージェントが起動していることを確認します
  • ポリシー(AmazonSSMManagedInstanceCore)が付与されたロールを作成します
  • Inspectorを有効化したいインスタンスへロールをアタッチします
  • Inspector v2を有効化する

    Inspectorサービス画面を開き【使用を開始する】より【Inspector を有効化】をクリックします。

    Inspector v2を有効化する

    有効化後スキャンが自動で始まるので、脆弱性があるサーバであれば、しばらくするとInspectorの通知が届いているはずです!

    Backlogに起票された通知内容を確認する

    それでは、実際に起票された結果を確認してみます。日本語化された通知がbacklogに届いている事が確認できました。

    EC2の結果

    EC2の結果

    ECRコンテナイメージの結果

    ECRコンテナイメージの結果

    終わりに

    今回は、「AWS Inspector v2の通知内容を日本語化してバックログに起票する」をご紹介させていただきました。 実際に行ってみた感想としては、見やすく通知されるのでコンソール画面を確認しにいく回数が減り、backlogに起票することで脆弱性の管理もできて良いかなと思います。

    ただ、このままだと検知数が多いので、Event BridgeのイベントパターンをスコアがHIGH以上で検知させるなど範囲を絞ると良いかなと思います。

    また、脆弱性を診断するためのInspectorを利用するだけではAWSのセキュリティ強化としては不十分であるため、「脅威検出するためのGuardDutyやIAM AccessAnalyzerを活用したい」 や 「GuardDutyやIAM AccessAnalyzerの詳細や推奨される対応策も日本語化したい」、「各AWSセキュリティサービスの機能をまとめて管理したい」 という方には、AWSの脆弱性や攻撃をまとめて管理できるSaaSサービス「 Safing」など、便利なサービスを利用することがおすすめです。

    最後までお読みいただきありがとうございました。