AWS WAFのログをAmazon OpenSearch Serviceで可視化する

2021.09.14

はじめに

こんにちは。大阪オフィスの林です。

AWS WAFのログをAmazon OpenSearch Service(旧Amazon Elasticsearch Service)で可視化する機会がありましたので手順をまとめておきたいと思います。AWS WAFに限らずAWSの各種ログをイイ感じに可視化したい場合は下記のエントリも参照して頂ければと思います。

また、つい最近Amazon Elasticsearch ServiceAmazon OpenSearch Serviceへと名称が変わりました。Amazon OpenSearch Serviceというサービスの名称に耳馴染みのない方は、Amazon Elasticsearch Serviceのことを指しているとお考え頂ければと思います。

やってみた

今回のアーキテクチャ

至ってシンプルですが、下記のようなアーキテクチャを想定してAWS WAFのログをAmazon OpenSearch Serviceで可視化していきたいと思います。

Amazon OpenSearch Serviceの準備

Amazon OpenSearch Serviceのダッシュボードに移動し「新しいドメインの作成」を選択します。今回はCloudFrontへアタッチするAWS WAFのログを可視化するため、バージニアリージョン(us-east-1)でリソースを作成します。

検証用途のため「開発およびテスト」を選択します。バージョンは7.10とします。

ドメイン名に任意の名称を入力します。「カスタムエンドポイント」と「自動調整」の設定はデフォルトのままとします。

データノードにてインスタンスタイプを選択します。今回の検証では「t3.small.search」でノード数は「1」とし「データノードストレージ」と「専用マスターノード」の設定はデフォルトのままとします。

画面下部までスクロールし「次へ」を選択します。

今回は簡易的な検証を目的としているため、ネットワーク構成にて「パブリックアクセス」を選択し、「細かいアクセスコントロールを有効化」のチェックを外します。実際には、プロジェクトのセキュリティ要件に応じてアクセス制御の設定を実施してください。

アクセスポリシーにて「カスタムアクセスポリシー」を選択後、接続を行うIPアドレスを許可します。今回の検証では私の端末のグローバルIPアドレスを指定しています。

暗号化の設定はデフォルトのままとし「次へ」を選択します。

必要に応じてタグを設定し「次へ」を選択します。

内容を確認し問題が無ければ「確認」を選択します。

プロビジョニングが始まるので暫く待ちます。

ドメインのステータスが「アクティブ」に変わったことを確認します。

Kinesis Data Firehoseの準備

Amazon OpenSearch Serviceのダッシュボードに移動し「Create delivery stream」を選択します。今回はCloudFrontへアタッチするAWS WAFのログを可視化するため、Kinesis Data Firehoseもバージニアリージョン(us-east-1)でリソースを作成します。

Sourceに「Direct PUT」を、Distinationに「Amazon Elasticsearch Service」を選択します。

Delivery stream nameに「aws-waf-logs-」から始まる任意の名前を入力します。

Elasticsearch domainに先ほど作成したドメインを指定します。「Index」に任意の文字列(検証では「awswaf」とします)を入力し、「Index rotation」に任意のローテーション間隔を指定します。

必要に応じて、Bufferを調整します。検証ではデフォルトのままとします。

Backup settingsにてS3バケットを指定します。検証ではSource recordに「All data」を選択し、そのほかはデフォルトのままとします。

必要に応じて、Bufferを調整します。検証ではデフォルトのままとします。

必要に応じて、Advanced settingsを設定します。検証ではデフォルトのままとします。

プロビジョニングが始まるので暫く待ちます。

ステータスが「Active」になったことを確認します。

AWS WAFにKinesis Data Firehoseをアタッチ

AWS WAFのダッシュボードに移動し、対象のWeb ACLsを選択後「Logging and metrics」-「Enable logging」を選択します。

「Amazon Kinesis Data Firehose delivery stream」に先ほど作成した、Kinesis Data Firehoseのリソースを選択後「Save」を選択します。

「Logging」が「Enable」で、「Amazon Kinesis Data Firehose delivery stream」にKinesis Data Firehoseのリソースが割り当てられていることを確認します。

Kibanaの設定

Amazon OpenSearch Serviceのダッシュボードに移動し、KibanaのURLに接続します。

初回接続で下記画面が出た場合「Explore on my own」を選択します。

デフォルトではAWS WAFのUnix timestampをDate型として認識してくれないので、予めコマンドを実行しepoch_millisdata型に変換します。左のメニューから「Dev Tools」を選択します。

下記JSONを貼り付け「▶」を選択、結果がtrueとなることを確認します。3行目のawswaf*はKinesis Data Firehose作成時に指定したインデックスの名前を指定しています。シャード数は「1」としていますが、実際のワークロードに合わせて数を調整してください。

PUT _template/stg_template
{
  "template": "awswaf*",
  "mappings": {
      "properties":{
          "httpRequest": {
            "properties": {
              "clientIp": {
                "type": "keyword",
                "fields": {
                  "keyword": {
                    "type": "ip"
                  }
                }
              }
            }
          },
        "timestamp": {
          "type": "date",
          "format": "epoch_millis"
        }
      }
    },
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 1
    }
}

デフォルトではインデックスは蓄積され続けてしまい、放置しているとストレージを圧迫するので任意の間隔でインデックスのローテーションを計画しておきます。メニューから「Index Management」を選択します。

「Create Policy」を選択します。

任意の名前を入力し、下記のJSONを貼り付けます。16行目にローテーションさせたい間隔(検証では「7日」)を指定します。ちなみに1hと設定すると、1時間後に削除される動作となります。34行目のawswaf*はKinesis Data Firehose作成時に指定したインデックスの名前を指定しています。

{
    "policy": {
        "policy_id": "delpolicy",
        "description": "A policy to delete index by 1day.",
        "schema_version": 1,
        "error_notification": null,
        "default_state": "hot",
        "states": [
            {
                "name": "hot",
                "actions": [],
                "transitions": [
                    {
                        "state_name": "delete",
                        "conditions": {
                            "min_index_age": "7d"
                        }
                    }
                ]
            },
            {
                "name": "delete",
                "actions": [
                    {
                        "delete": {}
                    }
                ],
                "transitions": []
            }
        ],
        "ism_template": [
            {
                "index_patterns": [
                    "awswaf*"
                ],
                "priority": 100
            }
        ]
    }
}

「Create」を選択します。

左のメニューから「Stack Management」を選択します。※インデックスが作成されてない場合はインデックスが作成されるまで待ちます。

「Index Patternes」-「Create index pattern」を選択します。

「Index Patternes name」にawswaf*を入力し「Next step」を選択します。ここのawswaf*はKinesis Data Firehose作成時に指定したインデックスの名前を指定しています。

「Time field」に「timestamp」を選択し、「Create Index pattern」を選択します。epoch_millisdata型に変換されていない場合は選択肢に「timestamp」が表示されません。手順を遡り、再度変換のコマンドを実行してください。

下記画面に遷移すれば完了です。

ダッシュボードの整形

左メニューから「Visualize」を選択しダッシュボードに表示する可視化の設定をします。

「Create new visualization」を選択します。

ダッシュボードに表示したい可視化のタイプを選択します。

対象のインデックスを選択します。

表示したいデータを追加します。本検証のバーチャートの場合、httpRequest.clientipaction.keywordを選択しています。

タイプにRegion Mapを選択した場合は、httpRequest.country.keywordを選択しています。

4つくらい可視化のタイプを作ってみました。

ダッシュボードに表示していきます。左メニューから「Dashboard」を選択します。

「Create new dashboard」を選択します。

「Add」を選択し、先ほど作成した可視化のパネルをクリックします。(作成した可視化のタイプをクリックするだけで追加されます)

それっぽいダッシュボードが作れました。

ダッシュボードを保存しておきます。「Save」を選択します。

任意の「Title」を入力後、「Save」を選択します。

まとめ

手順としてまとめてみると少々長くなってしまいましたが、1つ1つは意外とシンプルな印象を受けました。AWS WAFのログを可視化したい方の参考になりましたら幸いです。
以上、大阪オフィスの林がお送りしました!