SSTエンジニアブログ

SSTのエンジニアによるWebセキュリティの技術を中心としたエンジニアブログです。

フルログのその先。腑に落ちるAWS WAFログ解析基盤を構築してみた。~見える化編~

はじめに

事業開発部と研究開発部に属している宇田川です。

今回の内容は、「フルログのその先。腑に落ちるAWS WAFログ解析基盤を構築してみた。~ログ保存編~」の続編となりますので、ご覧になっていない方は、ログ保存編から読み進めてください。

Glueでデータカタログの作成

Athenaでログのデータベース、テーブルの作成もできるのですが、Glueが、S3やRDS上にあるデータを自動で解析して Amazon Athena のデータベースとテーブルを作成してくれるクローラーという機能があるため、それを使ってみます。

Glue クローラ設定

AWS マネージメントコンソールのサービスで「AWS Glue」を選択。
左メニューで「クローラ」を選択し、「クローラの追加」をクリックします。

クローラの名前を入力します。
ここは「aws-waf-logs-custom-crawler」とします。
「次へ」をクリック

f:id:woodykedner:20181101170834p:plain

Choose a data storeは「S3」
クロールするデータの場所は「自分のアカウントで指定されたパス」
インクルードパスにログ保存編で作成したカスタムログ保存用のs3バケット「aws-waf-logs-custom-s3-jawstest」を選択します。
「次へ」をクリック

f:id:woodykedner:20181101170852p:plain

別のデータストアの追加は「いいえ」
「次へ」をクリック

「IAM ロールを作成する」にチェックを入れて、IAM ロールを作成します。
Glue用のIAMロールはAWSGlueServiceRole-が固定のようでそれ以後の名前を入れます。
ここでは「aws-waf-logs-custom-jawstest」とします。 全体だと「AWSGlueServiceRole-aws-waf-logs-custom-jawstest」となります。
「次へ」をクリック

f:id:woodykedner:20181101170915p:plain

クローラの実行頻度を決めます。
「オンデマンドで実行」とします。
「次へ」をクリック

クローラの出力を設定します。
「データベースの追加」をクリックし、作成するデータベース名を記入します。
任意ですが、ここでは「logdb」としておきます。

f:id:woodykedner:20181101170948p:plain

テーブルに追加されたプレフィックスは空のままでいいです。

設定オプションを選択します。
f:id:woodykedner:20181106170929p:plain

「クローラがデータストアのスキーマ変更を検出した場合に、AWS Glue はデータカタログでテーブルの更新をどのように取り扱いますか?」は、「新規列のみを追加します。」を設定します。
こちら「データカタログのテーブル定義を更新する。」としておくと、データ型の自動判定が間違っていた際に修正しても、クローラが動くたびに間違ったのデータ型で上書きされ戻ってしまったため、「新規列のみを追加します。」とします。

「すべての新規および既存のパーティションをテーブルからのメタデータで更新します。」にチェックを入れます。 これにチェックを入れておかないとAthenaでselectクエリーを実行する際にエラーとなります。

「AWS Glue でデータストアの削除後のオブジェクトはどのように取り扱いますか?」は、「データカタログで廃止されたテーブルにマーキングする。」のままとします。

「次へ」をクリック

設定内容を確認して、「完了」をクリック。

クローラの一覧画面で作成したクローラのステータスが「Ready」になるのを待ちます。
「Ready」になったら、作成したクローラにチェックを入れ、「クローラの実行」をクリックします。
ステータスが「Starting」になります。実行中です。「Stopping」になるまで待ちます。

「Stopping」になったら、作成したクローラの追加したテーブルが「1」になっていることを確認します。

f:id:woodykedner:20181101171941p:plain

Glue テーブル設定

左メニューで「テーブル」を選択します。
テーブルの一覧画面に、「aws_waf_logs_custom_s3_jawstest」があるのを確認します。
カスタムログ保存用のs3バケット「aws-waf-logs-custom-s3-jawstest」の「-」が「 _ 」になったものです。
この後、使うAthenaではテーブル名に「 - 」が使えず、使うとエラーとなるため、「 _ 」に変換してくれます。

f:id:woodykedner:20181101172004p:plain

「aws_waf_logs_custom_s3_jawstest」をクリックします。
テーブルの情報が表示されます。

f:id:woodykedner:20181105123212p:plain:w1000

f:id:woodykedner:20181105122250p:plain f:id:woodykedner:20181105122800p:plain

aws wafのログの要素がカラムとして登録され、データ型も自動判定されているのが分かります。
このデータ型の自動判定ですが、思い通りにいかないことがあります。

latitude(緯度)とlongitude(経度)が「float」か「double」になっているか確認してください。
私が試した際、「string」になってしまったことがありました。
latitude(緯度)とlongitude(経度)が「string」のままだと、世界地図にプロットされなかったので、必ず確認してください。

「string」を「double」への変更方法を説明します。
右上の「スキーマの編集」をクリック。
スキーマの編集画面で、latitude(緯度)とlongitude(経度)のデータ型「string」がリンクになっているので、それをクリックします。
データ型を変更できますので、「double」を選択します。
latitude(緯度)とlongitude(経度)のデータ型を「double」に変更したら、右上の「保存」をクリックします。

Athenaでデータ確認

Athenaでは特に設定はありませんがそれだと寂しいので、データ確認だけしてみます。

AWS マネージメントコンソールのサービスで「Athena」を選択。 左メニューで、データベースを「logdb」に変更

テーブルの先ほど、Glueで自動作成した「aws_waf_logs_custom_s3_jawstest」が現れるかと思います。

f:id:woodykedner:20181101172342p:plain

試しに、selectクエリーを実行してみます。 新しいクエリ1のtextareaに下記を記入します。

SELECT * FROM "logdb"."aws_waf_logs_custom_s3_jawstest" limit 10;

で、「クエリの実行」をクリック。 そうすると、「ログ保存編」のログ保存テストで行ったログが1つ要素カラム毎に表示されると思います。

f:id:woodykedner:20181101172437p:plain

ちなみにこのテーブルを作成するためのクエリーを見ることできます。

左メニューの「aws_waf_logs_custom_s3_jawstest」の右横の...が縦に並んでいるところがあります。 それをクリックして、「テーブル作成DDLの生成」をクリックします。 そうすると、新しいクエリ1のtextareaに下記が自動で記入され、クエリが実行されます。

SHOW CREATE TABLE aws_waf_logs_custom_s3_jawstest;

結果にCREATE EXTERNAL TABLEが表示されます。
Glueはjsonの構造と要素の型を解析し、自動でテーブルを作成してくれます。
Glueを知る前は、苦労して自分でこのCREATE EXTERNAL TABLEを作成しました。
それが自動でできてしまうので、Glueの凄さを感じました。

f:id:woodykedner:20181101172939p:plain

QuickSightで見える化設定

初期設定

QuickSightを初めて使う場合、初期設定が必要となります。下記のAWSドキュメントを参考に初期設定をお願いします。 docs.aws.amazon.com

アクセス権を設定

右上端のユーザ名を選択し、[Manage QuickSight] を選択します。

左メニューから[Account settings] を選択します。

[Manage QuickSight permissions]

[Account permissions] (アカウント権限) で、[Edit AWS Permissions] (AWS アクセス許可の編集) を選択します。

[Edit QuickSight read-only access to AWS resources]で、下記の3つにチェックを入れます。

  • Enable autodiscovery of data and users in your Amazon Redshift, Amazon RDS and AWS IAM services.
  • Amazon Athena
  • Amazon S3

f:id:woodykedner:20181026114351p:plain

[Choose S3 buckets]のリンクを選択し、「ログ保存編」で作成したカスタムログ保存用のs3バケット「aws-waf-logs-custom-s3-jawstest」にチェックを入れて、「Select buckets」で保存します。

docs.aws.amazon.com

データ設定

AWS マネージメントコンソールのサービスで「QuickSight」を選択。

「Manage data」をクリックします。

「New data set」をクリックします。
Create a Data Setで「Athena」をクリックします。
Data source nameを「aws-waf-logs-custom」として、「Create data source」をクリック。

データベースとテーブルを登録します。
Database:で先ほどGlueで作成した「logdb」を選択します。
そうすると、テーブル一覧が表示されるので、「aws_waf_logs_custom」にチェックを入れます。

Finish data set creationで、「Import to SPICE for quicker analytics」にチェックを入れます。
ここで、「Visualize」を押したくなりますが、「Edit/Preview data」をクリックします。

データの一覧画面が開きます。
ここでは、3点やることがあります。

  • 「timestamp」カラムのデータ型が「int」になっているので、「Date」に変更します。
  • 「latitude」カラムのデータ型が「latitude」として認識されているか確認
  • 「longitude」カラムのデータ型が「longitude」として認識されているか確認

f:id:woodykedner:20181026110154p:plain

上記が終わったら、画面上段のtextareaにこのデータ名として「aws_waf_logs_custom」を記入し、「Save&visualize」をクリックします。

そうすると「visualize」の画面に移動されます。
f:id:woodykedner:20181026110513p:plain

visual設定

世界地図

左の「Fields list」から、「latitude」、「longitude」を選択します。 また「Visual types」から、右下の地球儀のマーク(Point on map)を選択します。

そうすると世界地図上に紺の点が出てくると思います。 もうちょっと情報を追加します。actionの情報を入れてみましょう。

上部にField wellsがあると思います。 まず、「Geospatial」に「latitude」、「longitude」が登録されています。

左の「Fields list」から、「action」をクリックし、そのまま「Geospatial」横の「Size」で離します。 「Size」に「action」が追加されます。

同様に左の「Fields list」から、「action」をクリックし、そのまま「Size」横の「Color」で離します。

そうすると国別で「action」の比率が表示されます。

f:id:woodykedner:20181026110745p:plain

国別円グラフ

別のグラフを追加してみます。

左上の「+ Add」をクリックし、「Add visual」をクリックします。
f:id:woodykedner:20181026110919p:plain

左の「Fields list」から、「country」を選択します。 また「Visual types」から、円グラフ(Pie chart)を選択します。
f:id:woodykedner:20181026111155p:plain

ルール名時系列

左上の「+ Add」をクリックし、「Add visual」をクリックします。

左の「Fields list」から、「timestamp」を選択します。
また「Visual types」から、棒グラフ(Vertical bar chart)を選択します。
好みで、(Vertical stacked bar chart)、(Line chart)でも良いかと思います。

x軸が日単位の集計結果になっているので、これを分単位に直します。
timestampとなっているところをクリック、 メニューが開くのでAggregate:Dayをクリックして、「Minute」を選択します。
f:id:woodykedner:20181026111448p:plain

上部にField wellsを見ます。 まず、「X axis」には「timestamp(MINUTE)」が登録されています。

左の「Fields list」から、「terminatingrulename」をクリックし、そのまま「X axis」横の「Value」で離します。 「Value」に「terminatingrulename」が追加されます。

同様に左の「Fields list」から、「terminatingrulename」をクリックし、そのまま「Value」横の「Group/Color」で離します。

分単位での検知したルール別に名前入りで集計されるグラフが作成できました。
f:id:woodykedner:20181026111558p:plain

ルール名別円グラフ

時間関係なくルール名別の比率が見たいので円グラフを追加してみます。

左上の「+ Add」をクリックし、「Add visual」をクリックします。

左の「Fields list」から、「terminatingrulename」を選択します。
また「Visual types」から、円グラフ(Pie chart)を選択します。

f:id:woodykedner:20181026111735p:plain

出来上がり

グラフの大きさを調整して出来上がり! f:id:woodykedner:20181024163039j:plain

Filter機能で、ちょっと分析っぽいことをしてみる。

眺めているだけでも面白いんですが、Filter機能で、ちょっと分析っぽいことをしてみたいと思います。
国別で絞り込んでみます。

先ほど作成した国別の円グラフで、グラフ内のどこかの国をクリックしてみます。 ここでは「US」を選択してみます。 そうするとメニューが開きます。
その中の「Focus only on US」をクリックしてみます。 f:id:woodykedner:20181026105416p:plain

そうすると国別の円グラフだけ「US」に絞り込まれた状態となります。 また、左メニューが「Filter」に切り替わり、「Applied Filters」に「country Equels - US」と表示されています。 f:id:woodykedner:20181026105434p:plain 「country Equels - US」をクリックすると、filterの編集画面に切り替わります。 「Only this visual」となっているところをクリックし、「All visuals」をクリックします。 f:id:woodykedner:20181026105502p:plain

そうすると、他のグラフもUSで絞り込まれたグラフが表示されます。 f:id:woodykedner:20181026105517p:plain

グラフをもとに戻すときは、Filter一覧の「country Equels - US」横のチェックを外すか、filterの編集画面で「country Equels - US」横のごみ箱のマークをクリックして削除してください。

まとめ

今回紹介した方法がAWS WAFのフルログの解析環境に一番簡単に構築できる方法です。
AWS WAFのセルフマネージメントもしやすくなると思いますので、構築してみよっかなと思ってくれた人がいればハッピーです。

ちなみに、タイトルに「腑に落ちる」と書きましたが、構築した時点では腑に落ちていましたが、色々と使ううちに、改善した方がいいところが湧き出しており、引き続き、改善中です。
Lambdaのコードしかり…
改善内容は、またブログ等で紹介していきます。

今後もAWS WAFに関わる情報を発信していきますので、ご期待いただければと思います。