AWS

AthenaでS3に溜まったGuardDutyのログを分析してみた!

kim

おはようございます!DWSのkimです!

今回Athenaを使って、GuardDutyのログ分析をしてみたので、その方法について紹介します!

構成図

今回はS3に溜まったGuardDutyのログを、Athenaで分析し、Highのアラートが何件あったか確認できるようにしたいと思います。

1. 事前準備

1-1. S3バケットの作成

作成するバケットは下記の2つ必要になります。

  • GuardDutyのログ格納用のS3バケット
  • Athenaのクエリ結果を格納するためのS3バケット

作成方法は下記AWS公式ページを参考にしてください。

汎用バケットの作成

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/create-bucket-overview.html

1-2. KMSの作成

GuardDutyのログをS3に格納するときにKMSを使用しないといけません。

作成方法は下記AWS公式ページを参考にしてください。設定は一旦全てデフォルトでOKです!項番1-3で修正しますので!

対称暗号化 KMS キーを作成する

https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/create-symmetric-cmk.html

1-3. GuardDutyからS3にログを出力する設定

作成方法は下記AWS公式ページを参考にしてください。

この時にS3のバケットポリシーと、KMSのキーポリシーを修正します。

生成された GuardDuty の検出結果を Amazon S3 バケットにエクスポートする

https://docs.aws.amazon.com/ja_jp/guardduty/latest/ug/guardduty_exportfindings.html

2. Athenaのクエリの保存先を指定する

2-1. Athenaのコンソール画面へ移動する

以下のURLから Athena コンソールを開きます。

https://ap-northeast-1.console.aws.amazon.com/athena

2-2. Athenaコンソールでクエリエディタを起動する

2-3. 「クエリ設定」タブ→「管理」をクリックする

2-4. クエリ結果の保存先として1-1で作ったS3バケットを指定して、「保存」をクリックする

3. AthenaのDBを作成する

以下クエリを実行してください。

CREATE DATABASE IF NOT EXISTS <任意のDB名>;

<任意のDB名>に値を入力してから、実行してください

※クエリの実行場所は下記画像を参照してください(次項以降は画像を省略します)

4. Athenaのテーブルを作成する

以下クエリを実行して、Athenaのテーブルを作成してください。後ほどコードの詳細について解説させていただきます。

CREATE EXTERNAL TABLE IF NOT EXISTS <任意のDB名>.<任意のTable名> (
  schemaversion string,
  accountid     string,
  region        string,
  id            string,
  arn           string,
  type          string,
  resource      string,
  service       string,
  severity      string,
  createdat     string,
  updatedat     string,
  title         string,
  description   string
)
PARTITIONED BY (
  day string
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://<バケット名>/AWSLogs/<アカウントID>/GuardDuty/<リージョン>/'
TBLPROPERTIES (
  'projection.enabled' = 'true',
  'projection.day.type' = 'date',
  'projection.day.format' = 'yyyy/MM/dd',
  'projection.day.range' = '2025/01/01,NOW',
  'projection.day.interval' = '1',
  'projection.day.interval.unit' = 'DAYS',
  'storage.location.template' = 
    's3://<バケット名>/AWSLogs/<アカウントID>/GuardDuty/<リージョン>/${day}/'
);

※上記<任意のDB名><任意のTable名>は修正して実行してください
※上記<バケット名><アカウントID><リージョン>は修正して実行してください

テーブル作成に使われているSQLコードの解説

テーブルの作成

CREATE EXTERNAL TABLE IF NOT EXISTS <任意のDB名>.<任意のTable名> (
  schemaversion string,
  accountid     string,

 -- (省略)

  description   string
)

<任意のDB名>の中に<任意のTable名>を作成するといったクエリになります。

また、schemaversion stringaccountid string等はGuardDutyからS3に出力されるJSON 形式の検出結果になります。どんな項目があるかは、AWS公式ページに記載がありますので、下記をご参照ください。

Amazon GuardDuty の検出結果をクエリする

https://docs.aws.amazon.com/ja_jp/athena/latest/ug/querying-guardduty.html

パーティションの作成

PARTITIONED BY (
  day string
)

パーティションとはデータを「日付」「年」「地域」などの値ごとに区切って整理したものになります。

今回は下記S3の日付に関するオブジェクト部分をdayとして区切るつもりで、パーティションを設定します。

この後説明するTBLPROPERTIESのところで「パーティションのdayってS3の/2025/12/26の部分のことだよ〜」っていう設定を行います。

ROW FORMAT SERDE

ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'

JSON データを読み込むためライブラリ(JSON SerDe ライブラリ)を指定している部分になります。AthenaはJSON の文字列をそのままだと読み取れないので、SQLのカラムに変換する仕組みが必要になります。

他にもAthenaではCSVやApache Parquetなどを変換することができます。詳しくは下記AWS公式ページをご参照ください。

データ用に SerDe を選択する

https://docs.aws.amazon.com/ja_jp/athena/latest/ug/supported-serdes.html?utm_source=chatgpt.com

LOCATION 's3://.../<リージョン>/'

LOCATION 's3://<バケット名>/AWSLogs/<アカウントID>/GuardDuty/<リージョン>/'

Athenaが実際に読み込むデータが置いてある S3 のディレクトリを指定している部分です。

TBLPROPERTIES

TBLPROPERTIES (
  'projection.enabled' = 'true',
  'projection.day.type' = 'date',
  'projection.day.format' = 'yyyy/MM/dd',
  'projection.day.range' = '2025/01/01,NOW',
  'projection.day.interval' = '1',
  'projection.day.interval.unit' = 'DAYS',
  'storage.location.template' = 
    's3://<バケット名>/AWSLogs/<アカウントID>/GuardDuty/<リージョン>/${day}/'
);

TBLPROPERTIESとはAthenaのテーブルに紐づく補助の設定項目(プロパティ)の集合です。今回だと「dayと言うパーティションはこういうルール(型、範囲、フォーマット)で扱ってね!」と言うような設定をしています。細かい設定内容は下記に記載させていただきます。

  • 'projection.enabled' = 'true'
    • Partition Projection を有効にしています
  • 'projection.day.type' = 'date'
    • パーティション(day)が「日付型」だよと指定しています
  • 'projection.day.format' = 'yyyy/MM/dd'
    • パーティション値のフォーマットを指定しています
  • 'projection.day.range' = '2025/01/01,NOW'
    • 日付の範囲を指定しています
      • 今回のクエリの内容だと2025/01/01〜NOW(このテーブルにクエリを叩く日付)で指定しています
  • 'projection.day.interval' = '1'
    • 日付間隔を指定するプロパティです。今回だと1日刻みでパーティションを推論すると言う設定になっています。
  • 'projection.day.interval.unit' = 'DAYS'
    • intervalの単位を指定しています。今回の設定だと日単位(DAYS)で間隔を刻む ことを指定しています。
  • 'storage.location.template' ='s3://<バケット名>/AWSLogs/<アカウントID>/GuardDuty/<リージョン>/${day}/'
    • Athena がパーティション値を S3 パスに変換するルールになります。「S3の'/2025/12/26/'が${day}のパーティション部分になるよ〜」と言う指定をしている部分になります。

5. クエリを実行する

クエリは自身が分析したい内容のクエリを実行してください。今回は冒頭で示した通り、下記シナリオでクエリを実行します。

例)2025/08/15〜2025/08/21の発生しているGuardDutyの重要度Highのアラート件数を検索する

SELECT
  COUNT(*) AS critical_count
FROM <DB名>.<Table名>
WHERE day BETWEEN '2025/08/15' AND '2025/08/21'
  AND CAST(severity AS DOUBLE) BETWEEN 7 AND 8.9;

※<DB名>、<Table名>はそれぞれ作成したDB、Tableの値を記載してください。

まとめ

いかがでしょうか?

今回はGuardDutyのログ分析をAthenaを用いて行ってみました。応用すれば、S3に溜まっている、他のサービスのログも分析できると思いますので、ぜひ色々試してください!

AUTHOR
kim
kim
記事URLをコピーしました