Amazon Web Services ブログ

AWS Fargate と Prowler を使用して、AWS サービスに関するセキュリティ設定の検出結果を Security Hub に送信する

このブログ記事では、オープンソースのセキュリティツールである ProwlerAWS Security Hub と統合する方法を紹介します。Prowler は Amazon Redshift、Amazon ElasticCache、Amazon API Gateway および Amazon CloudFront などのサービスに関する多数のセキュリティ構成チェックを提供します。Prowler と Security Hub を統合すると、既存の Security Hub 連携、またはコンプライアンス標準で現在ではカバーされていないリソースに関する情報が提供されます。Prowler チェックを使用することで、Security Hub で既に提供されている既存の CIS AWS Foundations コンプライアンスや、パートナーソリューションから取り込むコンプライアンス関連の検出結果を補うことができます。
この記事では、Docker を使用して Prowler をコンテナ化し、サーバーレスコンテナサービス AWS Fargate でホストする方法について説明します。Prowler を Fargate で実行すると、インフラストラクチャのプロビジョニング、構成、拡張が不要になり、必要なときにのみ実行されます。コンテナはアプリケーションのコード、設定、および依存関係をどこでも実行できる1つのオブジェクトにパッケージ化する標準的な方法を提供します。サーバーレスアプリケーションは、サーバーのプロビジョニング、スケーリング、および管理を必要とせずに、ユーザーが定義したイベントに応じて自動的に実行およびスケーリングされます。

ソリューションの概要

次の図は、このブログ記事で説明するソリューションのイベントの流れを示しています。

Figure 1: Prowler on Fargate Architecture

図 1:Fargate アーキテクチャー上の Prowler

このインテグレーションは次のように動作します。

  1. 時間ベースの CloudWatch イベントは、定義したスケジュールに基づいて Fargate タスクを開始します。
  2. Fargate は Amazon Elastic Container Registry (ECR) から Prowler Docker イメージを取り出します。
  3. Prowler は AWS インフラストラクチャをスキャンし、スキャン結果を CSV ファイルに書き込みます。
  4. Prowler コンテナ内の Python スクリプトは CSV を JSON に変換し、フォーマットされた Prowler の結果を含む Amazon DynamoDB テーブルを読み込みます。
  5. DynamoDB ストリームAWS Lambda 関数を読み出します。
  6. Lambda 関数は Prowler の結果を AWS Security Finding 形式 (ASFF) にマッピングしてから、Security Hub にインポートします。

ECR リポジトリを除き、上記のすべてを AWS CloudFormation 経由でデプロイします。また、CloudFormation テンプレートのパラメーターとして指定するには、以下の前提条件も必要です。

前提条件

  • VPC にはインターネットにアクセスできるサブネットが 2 つ以上あり、ポート 443(HTTPS) でのアクセスを許可するセキュリティグループがあること。
  • ECS タスクロールは Prowler がスキャンを完了するために必要なアクセス許可を持つこと。これらの権限の詳細については、公式の Prowler GitHub サイトを参照して下さい。
  • ECS タスク実行 IAM ロールは Fargate が CloudWatch にログを発行し、Amazon ECR から Prowler イメージをダウンロードできる権限を持つこと。

ステップ 1: Amazon ECR リポジトリを作成する

このステップでは、ECR リポジトリを作成します。ここに、ステップ2の Docker イメージをアップロードします。

  1. Amazon ECR コンソールに移動し、[ レポジトリを作成 ]をクリックします。
  2. レポジトリの名前を入力し(この例では securityhub-prowler という名前を付けました(図 2 )、タグのイミュータビリティ設定を[ 有効 ]に選択し、[ レポジトリの作成 ]を選択します。

    Figure 2: ECR Repository Creation

    図 2: ECR レポジトリの作成

リポジトリを作成したブラウザタブを開いたままにして、次のステップで必要な Docker コマンドを簡単に参照できるようにします。

ステップ 2:Docker イメージをビルドしてプッシュする

このステップでは、Prowler の結果を DynamoDB にマッピングするスクリプトを含む Docker イメージを作成します。ステップ2を開始する前に、イメージを ECR にプッシュするために必要な権限がワークステーションにあることを確認します。

  1. お気に入りのテキストエディタを使用して Dockerfile を作成し、Dockerfile という名前で保存します。
    
    FROM python:latest
    
    # Declar Env Vars
    ENV MY_DYANMODB_TABLE=MY_DYANMODB_TABLE
    ENV AWS_REGION=AWS_REGION
    
    # Install Dependencies
    RUN \
        apt update && \
        apt upgrade -y && \
        pip install awscli && \
        pip install detect-secrets && \
        apt install jq -y && \
        apt install -y python3-pip
    
    # Place scripts
    ADD converter.py /root
    ADD loader.py /root
    ADD script.sh /root
    
    # Installs prowler, moves scripts into prowler directory
    RUN \
        git clone https://github.com/toniblyx/prowler && \
        mv root/converter.py /prowler && \
        mv root/loader.py /prowler && \
        mv root/script.sh /prowler
    
    # Runs prowler, ETLs ouput with converter and loads DynamoDB with loader
    WORKDIR /prowler
    RUN pip3 install boto3
    CMD bash script.sh
    
  2. script.sh という新しいファイルを作成し、以下のコードに貼り付けます。このスクリプトは、残りのスクリプトを特定の順序で呼び出します。

    注:3 行目の Prowler コマンドの AWS リージョンを、Security Hub を有効にしたリージョンに変更します。

    
    #!/bin/bash
    echo "Running Prowler Scans"
    ./prowler -b -n -f us-east-1 -g extras -M csv > prowler_report.csv
    echo "Converting Prowler Report from CSV to JSON"
    python converter.py
    echo "Loading JSON data into DynamoDB"
    python loader.py
    
  3. converter.py という新しいファイルを作成し、以下のコードに貼り付けます。この Python スクリプトは、Prowler CSV レポートを JSON に変換し、両方のバージョンを Prowler コンテナのローカルストレージに書き込みます。
    
    import csv
    import json
    
    # Set variables for within container
    CSV_PATH = 'prowler_report.csv'
    JSON_PATH = 'prowler_report.json'
    
    # Reads prowler CSV output
    csv_file = csv.DictReader(open(CSV_PATH, 'r'))
    
    # Create empty JSON list, read out rows from CSV into it
    json_list = []
    for row in csv_file:
        json_list.append(row)
    
    # Writes row into JSON file, writes out to docker from .dumps
    open(JSON_PATH, 'w').write(json.dumps(json_list))
    
    # open newly converted prowler output
    with open('prowler_report.json') as f:
        data = json.load(f)
    
    # remove data not needed for Security Hub BatchImportFindings    
    for element in data: 
        del element['PROFILE']
        del element['SCORED']
        del element['LEVEL']
        del element['ACCOUNT_NUM']
        del element['REGION']
    
    # writes out to a new file, prettified
    with open('format_prowler_report.json', 'w') as f:
        json.dump(data, f, indent=2)
    
  4. loader.py という最後のファイルを作成し、以下のコードに貼り付けます。この Python スクリプトは JSON ファイルから値を読み取り、DynamoDB に送信します。
    
    from __future__ import print_function # Python 2/3 compatibility
    import boto3
    import json
    import decimal
    import os
    
    awsRegion = os.environ['AWS_REGION']
    prowlerDynamoDBTable = os.environ['MY_DYANMODB_TABLE']
    
    dynamodb = boto3.resource('dynamodb', region_name=awsRegion)
    
    table = dynamodb.Table(prowlerDynamoDBTable)
    
    # CHANGE FILE AS NEEDED
    with open('format_prowler_report.json') as json_file:
        findings = json.load(json_file, parse_float = decimal.Decimal)
        for finding in findings:
            TITLE_ID = finding['TITLE_ID']
            TITLE_TEXT = finding['TITLE_TEXT']
            RESULT = finding['RESULT']
            NOTES = finding['NOTES']
    
            print("Adding finding:", TITLE_ID, TITLE_TEXT)
    
            table.put_item(
               Item={
                   'TITLE_ID': TITLE_ID,
                   'TITLE_TEXT': TITLE_TEXT,
                   'RESULT': RESULT,
                   'NOTES': NOTES,
                }
            )
    
  5. ECR コンソールのリポジトリ内で[ プッシュコマンドの表示 ]を選択し、オペレーティングシステム固有の指示と追加のリソースを取得して、Docker イメージを構築、タグ付け、プッシュします。例については、図 3 を参照してください。

    Figure 3: ECR Push Commands

    図 3: ECR プッシュコマンド

    注:もし以前にワークステーション内に Docker イメージを構築していた場合は、Docker のビルドコマンドで–no-cache フラグ docker ビルドコマンドで渡します。

  6. イメージをビルドしてプッシュした後、ECR コンソール内の[ URI ] (12345678910.dkr.ecr.us-east-1.amazonaws.com/my-repo など)を書き留めます。これは、ステップ3の CloudFormation パラメータで必要になります。

ステップ3: CloudFormation テンプレートをデプロイする

GitHub から CloudFormation テンプレートをダウンロードし、CloudFormation スタックを作成します。CloudFormationスタックの作成方法の詳細については、CloudFormation ユーザーガイドの AWS CloudFormation の使用開始を参照して下さい。

ステップ 2 および「ソリューションの概要」の前提条件でメモした値が必要になります。各パラメーターの説明は、CloudFormation デプロイの[ パラメータ ]ページに表示されます (図4 参照)。

Figure 4: CloudFormation Parameters

図 4: CloudFormation パラメータ

CloudFormationスタックのデプロイが完了したら、[ リソース ]タブをクリックして、タスク定義 (ProwlerECSTaskDefinition)を見つけます。これは、ステップ4で必要になります。

Figure 5: CloudFormation Resources

図 5: CloudFormation リソース

ステップ4: 手動で ECS タスクを実行する

このステップでは、ECS タスクを手動で実行して統合が機能することを確認します。(テストが完了すると、このステップは CloudWatchイベントに基づいて自動的に実行されます)。

  1. [ Amazon ECS コンソール ]に移動し、ナビゲーションペインから[ タスク定義 ]を選択します。
  2. 図 6 に示すように、CloudFormation を使用してデプロイしたタスク定義のチェックボックスを選択し、[ アクション ]ドロップメニューを選択して[ タスクの実行 ]を選択します。

    Figure 6: ECS Run Task

    図 6: ECS 実行タスク

  3. 以下の設定 (図 7 参照) を行い、[ タスクの実行 ]を選択します。
    1. 起動タイプ : FARGATE
    2. プラットフォームのバージョン : LATEST
    3. クラスター : CloudFormation によってデプロイされたクラスターを選択します。
    4. タスク数 : 1
    5. クラスター VPC : CloudFormation パラメータとして指定したサブネットの VPC を入力します。
    6. サブネット : VPC 内の 1 つ以上のサブネットを選択します。
    7. セキュリティグループ : CloudFormation パラメータで指定した同じセキュリティグループを入力します。
    8. パブリック IP の自動割り当て : ENABLED
      Figure 7: ECS Task Settings 1
      Figure 7: ECS Task Settings 2

      図 7: ECS タスク設定

  4. アカウントのサイズとアカウント内のリソースによって、タスクが完了するまでに最大 1 時間かかることがあります。タスクを選択してタスクビューの Logs タブ (図 8 ) を確認し進捗状況に従います。Prowler からの標準出力がログに表示されます。

    注 : タスクが完了すると、自動的に削除されます。これ以降の実行中に追加のアクションを実行する必要はありません。

     

    Figure 8: ECS Task Logs

    図 8: ECS タスクログ

  5. [ 詳細 ]タブでステータスを監視します。ステータスが [ 停止 ]になったら、DynamoDB コンソールに移動します。
  6. テーブルを選択し、[ アイテム ]タブを選択します。検出結果は図 9 に示すようにプライマリキー NOTES の下に索引付けされます。ここから新しい項目が Fargate から書き込まれるたびに Lambda 関数がトリガーされ、Security Hub にロードされます。

    Figure 9: DynamoDB Items

    図 9: DynamoDB アイテム

  7. 最後に、Security Hub コンソールに移動し、[ 検出結果 ]メニューを選択します。図 10 に示すように Prowler からの結果がダッシュボードに表示されるのを待ちます。

    Figure 10: Prowler Findings in Security Hub

    図 10: Security Hub の Prowler 検出結果

もし Fargate タスクの実行中にエラーが発生した場合は、Amazon ECS トラブルシューティングガイドを参照して下さい。通常、ログエラーは権限による設定ミスか、リージョンで無効化されていることに起因します。トラブルシューティング情報については、Prowler GitHub を参照して下さい。

まとめ

この記事では、Prowler をコンテナ化し、手動で実行し、CloudWatch イベントでスケジュールを設定し、DynamoDB ストリームおよび Lambda 関数と共にカスタム Python スクリプトを使用して Prowler の検出結果を Security Hub に読み込む方法について説明しました。Security Hub を使用すると、AWS およびパートナーサービスからの検出結果とともに、Prowler からのセキュリティ設定情報を一元化し、集約することができます。

Security Hub から、カスタムアクションを使用して、1つまたは複数の検出結果を Prowler からチケット発行システムなどのダウンストリームサービスに送信することや、カスタム修復アクションを実行することができます。Security Hub のカスタムインサイトを用いて、Prowler の検出結果を集計する保存された検索を作成することもできます。最後に Security Hub をマスターメンバー形式で使用することで、 複数のアカウント間で検出結果を集約し、一元的なレポートを作成することができます。

Jonathon Rau

Jonathan Rau

Jonathan は AWS Security Hub のシニア TPM です。彼は AWS 認定スペシャリティセキュリティ認定を取得しており、サイバーセキュリティ、データプライバシー、ブロックチェーンなどの新規テクノロジーに大変情熱を注いでいます。彼は同トピックについて研究と普及に個人的な時間を費やしています。

原文はこちら。翻訳は Professional Services 中田 が担当しました。