CloudWatch Logs に Lookup Tables が追加 ― CSVデータでログをエンリッチメントする新機能を試してみた

AWSAmazon CloudWatchCloudWatch LogsLogs Insightsログエンリッチメントセキュリティ

CloudWatch Logs に Lookup Tables 機能が追加されました。CSV形式のリファレンスデータを登録しておき、Logs Insights のクエリ時にログイベントと突合して情報を付与(エンリッチメント)できる機能です。

AWS CLI v2.34.20 の CHANGELOG に以下の記載があります。

Adds Lookup Tables to CloudWatch Logs for log enrichment using CSV key-value data with KMS encryption support.

専用の What’s New 記事は出ておらず静かにリリースされた機能ですが、ここは注意が必要です。ログ分析の実務で地味に効いてくる機能なので、実際に試してみました。

どういう場面で使うのか

セキュリティログやアプリケーションログを分析していると、こういう場面に頻繁に出くわします。

  • CloudTrail のログに userIdentity.accountId はあるけど、どのアカウントか分からない
  • アプリケーションログに userId はあるけど、誰なのか分からない
  • VPC Flow Logs に送信元IPはあるけど、どの拠点からのアクセスか分からない

これまでは、ログをエクスポートして外部ツールで突合するか、Logs Insights のクエリ内で case 文を延々と書くか、という対応が必要でした。Lookup Tables を使えば、あらかじめCSVでマッピングデータを登録しておくだけで、クエリ時に自動的にフィールドを付与できます。

Lookup Tables の仕組み

登録

CSVファイル(ヘッダー行付き、UTF-8、最大10MB)をテーブルとして登録します。1アカウント・1リージョンあたり最大100テーブルまで作成可能です。

クエリ

Logs Insights のクエリで lookup コマンドを使い、ログのフィールドとCSVのキーを突合します。マッチした行の値がクエリ結果に追加されます。

暗号化

KMSキーを指定して暗号化が可能です。指定しない場合はAWSマネージドキーで暗号化されます。

実際に試してみた

検証環境

  • AWS CLI: aws-cli/2.34.20
  • リージョン: ap-northeast-1(東京)

注意: この機能は AWS CLI v2.34.20 以降で利用可能です。それ以前のバージョンでは create-lookup-table コマンドが認識されません。自分の環境も v2.34.8 では使えず、v2.34.20 にアップデートして確認しました。

テーブルの作成

AWSアカウントIDからアカウント名・チーム名を引く Lookup Table を作成してみます。

aws logs create-lookup-table \
  --lookup-table-name aws_account_lookup \
  --description "AWS account ID to name and team mapping" \
  --table-body "accountId,accountName,team,environment
123456789012,prod-main,platform,production
234567890123,dev-app,application,development
345678901234,staging-data,data,staging
456789012345,security-audit,security,production" \
  --profile your-profile
{
    "lookupTableArn": "arn:aws:logs:ap-northeast-1:123456789012:lookup-table:aws_account_lookup",
    "createdAt": 1774928087654
}

ARNが返ってきて、テーブルが作成されました。

テーブルの確認

describe-lookup-tables で一覧を確認できます。

aws logs describe-lookup-tables --profile your-profile
{
    "lookupTables": [
        {
            "lookupTableArn": "arn:aws:logs:ap-northeast-1:123456789012:lookup-table:aws_account_lookup",
            "lookupTableName": "aws_account_lookup",
            "description": "AWS account ID to name and team mapping",
            "tableFields": [
                "accountId",
                "accountName",
                "team",
                "environment"
            ],
            "recordsCount": 4,
            "sizeBytes": 213,
            "lastUpdatedTime": 1774928087654
        }
    ]
}

tableFields にCSVのヘッダー行が認識されていること、recordsCount が4件(データ行の数)になっていることが分かります。

get-lookup-table を使うと、登録したCSVデータの中身も確認できます。

aws logs get-lookup-table \
  --lookup-table-arn arn:aws:logs:ap-northeast-1:123456789012:lookup-table:aws_account_lookup \
  --profile your-profile
{
    "lookupTableArn": "arn:aws:logs:ap-northeast-1:123456789012:lookup-table:aws_account_lookup",
    "lookupTableName": "aws_account_lookup",
    "description": "AWS account ID to name and team mapping",
    "tableBody": "accountId,accountName,team,environment\n123456789012,prod-main,platform,production\n234567890123,dev-app,application,development\n345678901234,staging-data,data,staging\n456789012345,security-audit,security,production",
    "sizeBytes": 213,
    "lastUpdatedTime": 1774928087654
}

tableBody にCSVの内容がそのまま格納されています。

テーブルの更新

行を追加する場合は update-lookup-table を使います。ここは注意が必要です。差分更新ではなく、CSVの全置換です。

aws logs update-lookup-table \
  --lookup-table-arn arn:aws:logs:ap-northeast-1:123456789012:lookup-table:aws_account_lookup \
  --table-body "accountId,accountName,team,environment
123456789012,prod-main,platform,production
234567890123,dev-app,application,development
345678901234,staging-data,data,staging
456789012345,security-audit,security,production
567890123456,ml-training,ai-ml,development" \
  --profile your-profile
{
    "lookupTableArn": "arn:aws:logs:ap-northeast-1:123456789012:lookup-table:aws_account_lookup",
    "lastUpdatedTime": 1774928104811
}

更新後に確認すると、recordsCount が4 → 5に増えていました。既存のデータに1行追加したい場合でも、全データを含むCSVを渡す必要があります。運用上は、CSVファイルをS3やGitで管理して丸ごとアップロードする形がよいと思います。

テーブルの削除

aws logs delete-lookup-table \
  --lookup-table-arn arn:aws:logs:ap-northeast-1:123456789012:lookup-table:aws_account_lookup \
  --profile your-profile

出力なしで成功します。削除は不可逆で、削除されたテーブルを参照するクエリはエラーになります。

Logs Insights でのクエリ構文

lookup コマンドの基本構文は以下のとおりです(AWS Documentation)。

lookup `テーブル名` `テーブルのキーフィールド` as `ログのフィールド` OUTPUT `出力フィールド1`, `出力フィールド2`, ...

CloudTrail ログでアカウント名を引くクエリ例

fields userIdentity.accountId, eventName, eventSource
| lookup aws_account_lookup accountId as userIdentity.accountId OUTPUT accountName, team, environment
| filter environment = "production"
| stats count(*) by accountName, eventName

このクエリでは、CloudTrail ログの userIdentity.accountId を Lookup Table の accountId と突合し、accountNameteamenvironment を結果に追加しています。その上で environment = "production" でフィルタし、アカウント名ごとにイベント数を集計しています。

マッチングの注意点

  • 完全一致かつ大文字小文字を区別します。部分一致や正規表現は使えません
  • ログのフィールドに同名のフィールドが既に存在する場合、Lookup Table の値で上書きされます
  • マッチしなかった行は、出力フィールドが空(null)になります

セキュリティ分析での活用パターン

Lookup Tables はログ分析全般で使えますが、セキュリティの観点で特に有効だと感じるパターンをいくつか挙げます。

1. AWSアカウントID → アカウント名の解決

マルチアカウント環境では、CloudTrail のログに12桁のアカウントIDしか記録されません。Lookup Table でアカウント名と担当チームを引けば、「このAPIコールはどのチームの環境で発生したのか」がすぐに分かります。Organizations のアカウント一覧をCSVに変換して登録しておけば、インシデント対応時の初動が格段に速くなります。

2. IAMユーザー/ロール → 担当者の特定

CloudTrail の userIdentity.arn からIAMユーザー名やロール名は分かりますが、「実際にそのロールを使っているのは誰か」は別途管理が必要です。ロールと担当者のマッピングを Lookup Table として登録しておけば、監査ログのレビューが効率化されます。

3. 既知の脅威IPリストとの突合

VPC Flow Logs や ALB のアクセスログに含まれる送信元IPを、脅威インテリジェンスのIPリストと突合するパターンです。CSVに既知の悪意あるIPアドレスとその分類(botnet、scanner等)を登録しておけば、Logs Insights のクエリだけで簡易的な脅威検出ができます。

4. エラーコード → 対応手順のマッピング

アプリケーションログのエラーコードに対して、エラーの説明や初動対応手順をマッピングしておくパターンです。オンコール時に「このエラーコードは何だっけ」と調べる手間が省けます。

制限事項

項目制約
テーブル数100/アカウント/リージョン
CSVサイズ最大10MB
テーブル名最大256文字、英数字とアンダースコアのみ
説明文最大1,024文字
タグ最大50個
マッチング方式完全一致、大文字小文字区別
更新方式CSV全置換(差分更新不可)
暗号化KMSキー指定可(省略時はAWSマネージドキー)

10MBの上限は、行数にすると数万〜十数万行程度は格納できる計算です。ユーザーリストやアカウントリストであれば十分なサイズだと思います。ただし、IPアドレスの脅威リストのように大量のレコードが必要な場合は、対象を絞り込んで登録する工夫が必要です。

料金

Lookup Tables 単体の追加料金は、現時点のCloudWatch料金ページに明示されていません。Logs Insights のクエリスキャン料金($0.005/GBスキャンデータ)に含まれる形と考えられます。テーブルの作成・保持自体に追加課金が発生するかは明確ではありませんが、現時点では追加課金なしの可能性が高いです。

Terraform の対応状況

現時点で aws_cloudwatch_log_lookup_table リソースは Terraform AWS Provider に存在しません。IaC で管理したい場合は、AWS CLI を null_resource + local-exec で呼び出す形が現実的な回避策です。

CLIの対応バージョン

この機能は AWS CLI v2.34.20 で追加されました。それ以前のバージョンでは create-lookup-table コマンドが認識されません(CHANGELOG 2.34.20)。

まとめ

Lookup Tables は派手な新機能ではありませんが、ログ分析の実務では確実に役立つ機能です。

特に注目しているのは以下の点です。

  • 外部ツール不要でログエンリッチメントが完結する: これまで Splunk や Datadog でやっていたようなルックアップを、CloudWatch Logs Insights の中だけで実現できます。ログをエクスポートする必要がなくなるのは大きいです
  • セキュリティ分析の初動が速くなる: アカウントID、ユーザー名、IPアドレスを「これは誰?これはどこ?」と別システムで調べる手間がなくなります。インシデント対応では、この数分の差が重要です
  • KMS暗号化対応: リファレンスデータに個人情報や機密情報が含まれる場合でも、KMSキーで暗号化して保護できます。ここは見落としがちですが、コンプライアンス上重要なポイントです

CSV の全置換更新や Terraform 未対応など、運用面で改善してほしい点はありますが、まずは「使えるようになった」こと自体が嬉しいアップデートです。マルチアカウント環境のアカウント名解決あたりから試してみることをおすすめします。