メインコンテンツへスキップ
友田 陽大
Amazon GuardDuty 本番運用
セキュリティ
AWS
GuardDuty
Security Lake
OCSF

GuardDuty の finding を Amazon Security Lake に集約する:OCSF で長期保管・横断分析・SIEM 連携を本番設計する

GuardDuty の finding は『いま』には強いが、コンプライアンスの長期保管・finding × CloudTrail × VPC Flow の横断クエリ・SIEM 供給には向きません。Amazon Security Lake は自分の S3 上に OCSF + Apache Parquet の管理データレイクを作り、数年スパンで保管・SQL 分析・SIEM 連携を可能にします。決定的な正確さの勘所——Security Lake に GuardDuty の直接ソースは無く、findingは『AWS Security Hub CSPM findings(SH_FINDINGS)』経由で OCSF 化される——を軸に、ネイティブソース・ロールアップリージョン・2種類のサブスクライバ(クエリ/データアクセス)・Athena の実 SQL・Terraform 実装まで、公式ドキュメント(2026年6月)に基づき通します。

公開日
読了時間
34分
著者
友田 陽大
シェア
目次

「1年前の不正アクセス、GuardDuty のコンソールでもう追えますか?」——AWS のセキュリティ監査の場で、私がよく投げる質問です。

答えは多くの場合「いいえ」です。GuardDuty の finding はいまの脅威を知らせるのには最適ですが、流れて、いずれ視界から消えます。アーカイブされ、コンソールの既定のビューから外れ、半年後・1年後に「あの時の finding を、CloudTrail のイベントや VPC Flow Logs と突き合わせて、影響範囲を SQL で出してくれ」と監査人に言われたとき——GuardDuty のコンソールだけでは、もう手が届きません。

これは GuardDuty の欠陥ではありません。GuardDuty は検知エンジンであって、長期保管庫でも分析基盤でもないからです。けれど現実の運用には、検知の「いま」とは別に、3つの要求があります——(1) コンプライアンスのための長期保管(数年)、(2) finding × CloudTrail × VPC Flow を1つのクエリで突き合わせる横断相関、(3) finding を SIEM に流す供給線。この3つに答えるのが Amazon Security Lake です。

この記事は、GuardDuty の finding を Amazon Security Lake に集約し、OCSF(Open Cybersecurity Schema Framework)で長期保管・横断分析・SIEM 連携するための実装ガイドです。題材として、私がマルチアカウント AWS 上のサーバーレス決済プラットフォームで IAM・可観測性・DR を横断実装した経験——実際の金銭・カーボンクレジット・地域通貨を扱うため、「いつ・誰が・何をしたか」を数年スパンで再現可能にし、監査に耐える形で残す必要があった——という視点も交えます。

この記事のルール:Security Lake の定義・ネイティブソース・ソース識別子・OCSF 変換・サブスクライバの種類・Terraform 引数は AWS 公式ドキュメントおよび Terraform AWS Provider(2026年6月時点) に基づきます。対応ソース・スキーマバージョン・料金は改定されるため、本番投入前に必ず公式の最新情報を確認してください。そして本記事で最も重要な正確さの勘所——Security Lake に「GuardDuty 直接ソース」は存在しません。GuardDuty の finding は「GuardDuty → Security Hub(GuardDuty 統合)→ Security Lake の AWS Security Hub CSPM findings(SH_FINDINGS)」という経路でしか入りません。ここを取り違えると「Security Lake を作ったのに GuardDuty の finding が1件も入っていない」という事故になります。コードは実運用に近い形に整えていますが、Security Lake は検知(GuardDuty)・調査(Detective)・防御(WAF・最小権限 IAM)を代替しません


0. メンタルモデル:detect → investigate → 長期集約・分析の3層

設計を始める前に、セキュリティ運用を3つの時間軸で固定します。これが本記事のすべての土台です。

GuardDuty が DETECT(検知=いま)し、Detective が INVESTIGATE(調査=対話的に最大1年)し、Security Lake が AGGREGATE & ANALYZE(集約・正規化・長期保管=数年・SQL/SIEM)する。 この3層は時間軸が違うだけで、競合ではありません。

時間軸サービス答える問いデータの形
DETECT(検知)いま(リアルタイム)GuardDuty「いま、悪いことが起きているか?」finding(GuardDuty 独自形式)
INVESTIGATE(調査)最大1年・対話的Amazon Detective「なぜ起きて、どこまで侵されたか?」行動グラフ(可視化・ピボット)
AGGREGATE & ANALYZE(集約・分析)数年・SQL/SIEMAmazon Security Lake「過去横断で何が起きていたか? 監査にどう出すか?」OCSF + Parquet(自分の S3)

多くの「GuardDuty 入れました」案件は DETECT で止まっています。少し進んだ現場でも、Detective を足して INVESTIGATEGuardDuty × Detective の調査ワークフロー)までは行きます。けれど Detective は対話的な調査ツールであり、その行動グラフが見せるのは最大1年。「3年分の finding を CloudTrail と JOIN して、コンプライアンスレポートを SQL で出す」「finding を Splunk/QRadar に流して既存 SIEM のルールに乗せる」——これは Detective の守備範囲ではありません。

ここから3つの帰結が出ます。

  1. Detective と Security Lake は別レイヤーで、別の問いに答える。 Detective は 「この1件を、対話的に・グラフで・最大1年さかのぼって調べる」。Security Lake は 「全 finding を CloudTrail・VPC Flow と同じスキーマ(OCSF)に正規化して、自分の S3 に数年貯め、SQL や SIEM で横断分析する」。前者は深さ(1件の文脈)、後者は広さと永続性(全体・長期・機械可読)
  2. Security Lake は「検知」も「調査」もしない。新しい脅威を見つけるのは GuardDuty、対話的に追うのは Detective、止めるのは WAF・最小権限 IAM の仕事。 Security Lake が担うのは 「集めて・正規化して・長く持って・配る」 だけです。だから安全に全社・全リージョンの土台として置けます。
  3. GuardDuty の finding は Security Lake に「直接」は入らない。 これが本記事最大の落とし穴です。次章で配線を正確に押さえます——ここを外すと、何も入っていないデータレイクが出来上がります。

この3点を押さえると、「Security Lake を入れる」という作業が、実は 「①GuardDuty → Security Hub → Security Lake の経路を正しく配線する → ②ネイティブソースとマルチリージョンを設計する → ③サブスクライバ(SQL か SIEM か)を切る」 の3つの設計だと分かります。順に作ります。


1. Amazon Security Lake とは:自分の S3 上に建つ「OCSF 正規化済み」のセキュリティデータレイク

まず Security Lake が何で、何でないかを一行で固定します。

Amazon Security Lake = AWS・SaaS・オンプレ・サードパーティのセキュリティログ/イベントを、自分の AWS アカウントの S3 上の専用データレイクに自動集約し、Apache Parquet + OCSF(標準スキーマ)に正規化して、長期保管とサブスクライバへの配信を一元管理するフルマネージドサービス。

公式の定義はこうです——"Amazon Security Lake is a fully managed security data lake service." そして決定的に重要なのが所有権——"The data lake is backed by Amazon Simple Storage Service (Amazon S3) buckets, and you retain ownership over your data." つまりデータはあなたの S3 に残り、あなたが所有します。ベンダーロックインの効いた外部 SaaS に吸い上げられるのとは構造が違います。

1.1 4つの核心機能

機能公式の要点これが効く場面
自分のアカウントへ集約クラウド・オンプレ・カスタムのログをアカウント/リージョン横断で収集。S3 backed・所有権はあなた「監査データを自社管理下に置きたい」要件をそのまま満たす
正規化(OCSF + Parquet)ネイティブソースを自動でパーティション化・Parquet 化・OCSF へ変換。後処理不要finding も CloudTrail も VPC Flow も同じスキーマで JOIN できる
サブスクライバへの多段アクセスソース単位・リージョン単位でアクセスを付与。新規オブジェクトの通知クエリを選べるSQL 分析にも SIEM 供給にも、必要な分だけ配れる
マルチアカウント・マルチリージョン全リージョン・全アカウントで一括有効化。ロールアップリージョンで集約(データレジデンシー対応)組織全体の finding を1か所に・データ所在を制御
ライフサイクル管理カスタム保持設定 + 自動ストレージ階層化でコスト最適化数年保管を S3 階層化で安く回す

1.2 「正規化(OCSF)」が効く理由——同じスキーマで JOIN できる

Security Lake の真価は OCSF への正規化にあります。公式いわく——"Security Lake automatically partitions incoming data from natively supported AWS services and converts it to a storage- and query-efficient Parquet format. It also transforms data from natively supported AWS services to the Open Cybersecurity Schema Framework (OCSF) open-source schema."

何が嬉しいか。GuardDuty の finding、CloudTrail の API コール、VPC Flow Logs のネットワーク記録——生のままなら全部フォーマットが違います。これらを横断クエリしようとすると、本来は各ログを Athena 用にパースし、JOIN 用の ETL を書く羽目になります(まさに Detective が「自分でやらなくていい」と謳う作業)。Security Lake は、これらをOCSF という共通スキーマ+ Parquet 列指向に揃えて貯めます。だから——

-- イメージ:OCSF に正規化されているから、finding と API 活動を「同じ語彙」で扱える
-- (具体的なテーブル名・カラムは 5 章で実物を出します)
SELECT ...
FROM security_hub_findings_ocsf  AS f        -- GuardDuty 由来の finding(SH_FINDINGS)
JOIN cloudtrail_management_ocsf  AS c        -- 同じ OCSF の語彙で結合できる
  ON  f.<actor> = c.<actor>

——こういう「finding を起点に、その主体が同時刻に叩いていた API を引く」横断分析が、ETL を書かずに SQL だけで成立します。これが「集めただけのログ置き場」と「正規化されたデータレイク」の決定的な差です。

1.3 Security Lake が内部で使う AWS サービス(仕組みを知ると運用が読める)

Security Lake は複数の AWS サービスの上に組まれた管理サービスです。公式が挙げる内部依存:

サービスSecurity Lake での役割(公式)
Amazon EventBridge"to notify subscribers when objects are written to the data lake."(オブジェクト書き込みの通知)
AWS Glueクローラで Glue Data Catalog テーブルを作成・更新。Lake Formation テーブルのパーティションメタデータを保持
AWS Lake Formationソースごとに別テーブルを作成(スキーマ・パーティション・データ位置)。サブスクライバはこれをクエリできる
AWS Lambda生データへの ETL ジョブ、Glue へのパーティション登録
Amazon S3データ本体の保管(ストレージクラス・保持は S3 のものに準拠。S3 Select は非対応
Amazon SQSイベント駆動処理と通知の管理

「ソースごとに Lake Formation テーブルが1つできる」——この一文が、後で SQL を書くときの土台になります(finding 用テーブル・CloudTrail 用テーブル……と分かれる)。

1.4 Security Lake が「やらないこと」(境界の明示)

混同を防ぐため、境界を明示します。

  • 新しい脅威を検知しない。 それは GuardDuty・Inspector・Macie の仕事。Security Lake は検知済みの結果(finding)を含むログを集約・保管するだけ。
  • 攻撃を止めない。 封じ込めは EventBridge → 自動対応や runbook(GuardDuty 本編の自動対応)。
  • 対話的な調査グラフを描かない。 それは Amazon Detective。Security Lake は正規化された生データの貯蔵・配信であって、可視化された行動グラフではない。
  • finding の「集約・正規化ビュー(single pane)」そのものは Security Hub の役割。 5つのセキュリティサービスの役割分担は比較記事で扱いました。Security Hub が机に並べ、Security Lake がその findings を OCSF で長期の倉庫に収める——という前後関係です。

2. 【最重要】配線:GuardDuty の finding は「Security Hub 経由」でしか Security Lake に入らない

ここが本記事で絶対に外してはいけない一点です。

2.1 Security Lake に「GuardDuty 直接ソース」は存在しない

Security Lake がネイティブ対応する AWS サービスは、公式に列挙されている次の6系統だけです。

ネイティブソース(公式)何のログか
AWS CloudTrail management and data events (S3, Lambda)管理イベント+ S3/Lambda のデータイベント
Amazon EKS Audit LogsKubernetes コントロールプレーンの監査ログ
Amazon Route 53 resolver query logsDNS 名前解決クエリ
AWS Security Hub CSPM findingsSecurity Hub に集約された findings(← ここに GuardDuty が入る)
Amazon VPC Flow Logsネットワークトラフィック
AWS WAFv2 logsWAF のリクエストログ

この一覧に「GuardDuty」はありません。 GuardDuty を Security Lake のソースとして直接追加する手段は存在しないのです。では finding はどこから来るか——AWS Security Hub CSPM findings です。

2.2 正しい経路:GuardDuty → Security Hub → Security Lake

GuardDuty は Security Hub と統合しており、GuardDuty の finding は Security Hub に取り込まれます。そして Security Hub の findings は Security Lake のネイティブソースです。したがって、finding が Security Lake に届くまでの配線は次の3段です。

  [1] GuardDuty を有効化(detector ON)
        │   finding を生成
        ▼
  [2] Security Hub(CSPM)を有効化し、GuardDuty 統合を ON
        │   GuardDuty finding を ASFF として取り込む
        ▼
  [3] Security Lake で「AWS Security Hub CSPM findings(SH_FINDINGS)」をソース追加
        │   Security Hub の findings を OCSF + Parquet に正規化
        ▼
  自分の S3 上のデータレイク(Lake Formation テーブル:Security Hub findings)
        → Athena/Redshift/OpenSearch(クエリ)/ SQS 通知 → SIEM(データ)

この3段が揃って初めて、GuardDuty の finding が Security Lake に着地します。 どこかが欠けると——

  • [2] を飛ばす(Security Hub なし、または GuardDuty 統合 OFF)→ Security Hub に finding が無いので、Security Lake にも入らない。
  • [3] で SH_FINDINGS を追加し忘れる→ CloudTrail や VPC Flow は入っても、finding だけが永久に空

配線ミスの検知:本番では「SH_FINDINGS を有効化したのに、GetDataLakeSourcesaws securitylake get-data-lake-sources)で当該リージョンの収集が始まっているか」と「Security Hub 側に GuardDuty finding が実在するか」を両方確認します。Security Lake は『Security Hub に入っている findings』を引くだけなので、上流(Security Hub の GuardDuty 統合)が空なら下流も空です。GuardDuty の create-sample-findings でサンプルを出し、Security Hub → Security Lake と流れることを end-to-end で検証するのが確実です。

2.3 OCSF 上でどう見えるか(クラス名は正規化バージョン依存——要注意)

正規化後、Security Hub CSPM findings は OCSF のどのイベントクラスにマップされるか。公式の「OCSF source identification」表によれば、正規化バージョンによってクラスが異なります

ソースバージョンSecurity Hub CSPM の class_name(公式)
Version 1metadata.version 1.0.0-rc.2Security Finding
Version 2metadata.version 1.1.0Vulnerability Finding, Compliance Finding, または Detection Finding(ASFF の値に応じて)

つまり、どの source_version で取り込むかによって、finding が落ちる OCSF クラスが変わります。GuardDuty の脅威検知 finding は性質上 ASFF の検知系に当たるため、Version 2 では Detection Finding クラスに整理されるのが自然ですが、実際のクラス分類は finding の中身(ASFF の ProductFields 等)に依存します。

正直な注記(要確認):OCSF のクラス分類は正規化バージョンと finding の内容で変わるため、本記事では「Version 1 = Security Finding / Version 2 = Vulnerability/Compliance/Detection Finding」という公式表の記述までを確定情報として扱い、「GuardDuty finding は必ず Detection Finding になる」と断定はしません。本番では、自分のレイクに実際に落ちたレコードの metadata.versionclass_nameclass_uid)を Athena で確認してからクエリを書いてください(5.3 で実際に確認するクエリを示します)。


3. ネイティブソースと識別子:Terraform/CLI で使う「正確な名前」

Security Lake にソースを足すとき、API・CLI・Terraform で使う識別子は決まった文字列です。曖昧に書くと弾かれるので、ここで確定させます。

3.1 ソース識別子の一覧(Terraform AWS Provider で検証済み)

aws_securitylake_aws_log_source(および CreateAwsLogSource)の source_name に渡せる値は、Terraform AWS Provider のドキュメント上、次の8つです。

source_name対応する AWS ソース備考
SH_FINDINGSAWS Security Hub CSPM findings← GuardDuty finding はここ経由で入る(2 章)
CLOUD_TRAIL_MGMTCloudTrail 管理イベント唯一「別途ログ設定が要る」例外(CloudTrail 証跡)
LAMBDA_EXECUTIONCloudTrail の Lambda データイベント
S3_DATACloudTrail の S3 データイベント
VPC_FLOWVPC Flow Logs
ROUTE53Route 53 リゾルバクエリログ
EKS_AUDITEKS 監査ログ
WAFWAFv2 ログ

GuardDuty 集約が目的なら、まず SH_FINDINGS を入れる。横断相関を効かせたいなら、CLOUD_TRAIL_MGMT(誰が何の API を叩いたか)と VPC_FLOW(どの IP と通信したか)を併せて入れる——これで「finding を起点に、API とネットワークを突き合わせる」材料が揃います。

3.2 「別途ログ設定は不要」——独立した複製ストリーム

ここは GuardDuty 本体と同じ思想で、運用が楽になる重要な事実です。公式いわく——"To add one or more of the preceding services as a log source in Security Lake, you don't need to separately configure logging in these services, except CloudTrail management events. ... Security Lake pulls data directly from these services through an independent and duplicated stream of events."

つまり——

  • SH_FINDINGSVPC_FLOWROUTE53EKS_AUDITWAF などは、それぞれのサービス側でログ出力を別途設定する必要がない。Security Lake が独立した複製ストリームで直接引きます。すでにログ設定がある場合も、変える必要はありません。
  • 唯一の例外が CLOUD_TRAIL_MGMT——CloudTrail 管理イベントだけは、別途 CloudTrail 証跡の設定が前提になります。

この「複製ストリーム」設計のおかげで、既存のログ運用を壊さずにソースを足せます。GuardDuty 本体が「CloudTrail / VPC Flow / DNS を自分で有効化・保存・課金しなくていい」のと同じ発想です(本編ガイドのメンタルモデル)。

3.3 CLI でソースを足す(finding の経路を1コマンドで)

Terraform に落とす前に、CLI で挙動を掴みます。sourceNameregions が必須、accountssourceVersion は任意です。

# Security Hub findings(= GuardDuty finding の入口)をソース追加する。
# - sourceName=SH_FINDINGS が GuardDuty finding を OCSF 化して取り込む唯一の口
# - accounts 省略時は「組織の全アカウント」が対象になる(公式仕様)
# - regions は Security Lake を有効化済みのリージョンだけを指定する(未有効化はエラー)
aws securitylake create-aws-log-source \
  --sources sourceName=SH_FINDINGS,accounts='["123456789012","111122223333"]',regions='["ap-northeast-1"]',sourceVersion="2.0"

# 横断相関の材料も併せて入れる(CloudTrail 管理イベント・VPC Flow)。
aws securitylake create-aws-log-source \
  --sources sourceName=CLOUD_TRAIL_MGMT,regions='["ap-northeast-1"]'
aws securitylake create-aws-log-source \
  --sources sourceName=VPC_FLOW,regions='["ap-northeast-1"]'

# 収集が始まったか確認(finding が本当に入る経路かを早期に検証)。
aws securitylake get-data-lake-sources --accounts "123456789012"

accounts 省略の罠:公式は明言します——"if you don't provide the accounts parameter, the command applies to the entire set of accounts in your organization." 未指定=組織全体です。意図せず全アカウントに広げないよう、段階導入では accounts を明示するのが安全です。


4. マルチアカウント・マルチリージョンと保管:委任管理者・ロールアップリージョン・ライフサイクル

アカウントが複数あるなら、Security Lake も組織で集中管理します。GuardDuty・Detective と同じく、**セキュリティ専用アカウントを委任管理者(delegated administrator)**にして、そこに集約するのが定石です(GuardDuty の委任管理者設計で security-tooling アカウントを管理者にしたなら、Security Lake も同じアカウントに揃えると運用が一貫します)。

4.1 ロールアップリージョン——データを1か所に寄せ、レジデンシーも守る

マルチリージョン設計の核が ロールアップリージョン(rollup Region) です。公式いわく——"you can also designate rollup Regions to consolidate security log and event data from multiple Regions. This can help you comply with data residency compliance requirements."

  • 複数の「貢献リージョン(contributing Regions)」のデータを、指定した「ロールアップリージョン」に集約できる。各リージョンに散ったレイクを別々にクエリせず、1リージョンで横断できます。
  • 同時にデータレジデンシーにも効く——「EU のデータは EU 内のロールアップリージョンに寄せる」といった所在制御が可能。
  • サブスクライバも、ロールアップリージョンで作れば複数リージョンのデータにまとめてアクセスできます(公式:"To give a subscriber access to data from multiple Regions, you can specify the Region where you create the subscriber as a rollup Region and have other Regions contribute data to it.")。

GuardDuty は「グローバルイベントの取りこぼしを防ぐため全リージョン有効化」が推奨でした。その全リージョンの finding(= Security Hub findings)を、ロールアップリージョンに寄せて1か所で SQL する——これがマルチリージョン finding 分析の素直な形です。

4.2 ライフサイクル:S3 階層化+有効期限で「数年保管」を安く回す

長期保管のコスト管理は S3 のストレージクラス遷移+有効期限で行います。Security Lake は公式に "customizable retention settings""automated storage tiering" を提供します。Parquet(列指向・圧縮効率が高い)に正規化されている分、素のログをそのまま貯めるより容量効率が良いのも効きます。

設計の勘所:直近はクエリ頻度が高いので標準クラス、古くなるほど安いクラスへ遷移し、保持期限で自動削除。たとえば「31日で STANDARD_IA、80日で ONEZONE_IA、300日で削除」のような階層を、次章の Terraform lifecycle_configuration で宣言します。コンプライアンス要件が「N 年保管」なら、expiration をその期間に合わせます。

コスト注記(参考・要確認):Parquet + S3 階層化は数年スパンの保管に対して費用効率が良い設計です。ただし Security Lake 自体・Athena のスキャン量・Glue のクローラ/カタログにはそれぞれ課金があります。「貯めるコスト」は安く抑えられても「クエリのコスト」は SQL のスキャン量次第で増えるため、パーティション(リージョン・日付)で絞るのが鉄則です(5 章)。具体的な単価は地域・時期で変わるため、本番見積もりは公式の料金で確認してください。FinOps 観点の考え方はGuardDuty のコスト最適化記事と同じ——**「全部を最長保管」ではなく「要件に必要な分だけ」**です。


5. 実践:Athena で「直近90日の高重大度 GuardDuty finding」を SQL で引く

ここが分析側の山場です。OCSF に正規化された Security Hub findings テーブル(= GuardDuty finding の着地点)を、Athena で SQL する——これが Security Lake を入れる最大の見返りです。

5.1 テキストアーキテクチャ図(detect → 集約 → 分析/SIEM)

  [ DETECT ]  GuardDuty(全リージョン)
      │   finding 生成
      ▼
  Security Hub(CSPM・GuardDuty 統合 ON)
      │   finding を ASFF として集約
      ▼
  [ AGGREGATE ]  Amazon Security Lake(自分の S3)
      │   ソース: SH_FINDINGS(+ CLOUD_TRAIL_MGMT, VPC_FLOW …)
      │   変換: OCSF + Apache Parquet(ソースごとに Lake Formation テーブル)
      │   集約: ロールアップリージョン / ライフサイクル: S3 階層化+有効期限
      ▼
  ┌──────────────────────────────┬───────────────────────────────┐
  │ ① クエリアクセス(query)      │ ② データアクセス(data)        │
  │   Lake Formation テーブル      │   新規 S3 オブジェクトを          │
  │   → Athena / Redshift /        │   SQS(or HTTPS)で通知          │
  │     OpenSearch で SQL          │   → サードパーティ SIEM が消費    │
  │   (横断分析・監査レポート)    │   (Splunk / QRadar / 既存基盤) │
  └──────────────────────────────┴───────────────────────────────┘

5.2 まず「実際のテーブルとカラムを確認」してからクエリする

OCSF のテーブル名・カラムは正規化バージョンや環境(データベース名)で差が出るため、いきなり本番クエリを書かず、まず実体を確認します。これは「検証経路を先に作る」原則そのものです。

-- ① Security Lake が作った Glue データベース/テーブルを確認する。
--    (Security Hub findings 用のテーブルが SH_FINDINGS に対応して作られている)
SHOW TABLES IN amazon_security_lake_glue_db_ap_northeast_1;

-- ② finding テーブルの実カラムと、落ちている OCSF クラス/バージョンを先に確かめる。
--    2.3 で述べた「class_name はバージョン依存」を、ここで実データで固定する。
SELECT metadata.product.name      AS product,
       metadata.version           AS ocsf_version,
       class_name,
       count(*)                   AS n
FROM amazon_security_lake_glue_db_ap_northeast_1.amazon_security_lake_table_ap_northeast_1_sh_findings_2_0
GROUP BY 1, 2, 3
ORDER BY n DESC;

テーブル名は環境で変わる(要確認):上記のデータベース名(amazon_security_lake_glue_db_<region>)・テーブル名(..._sh_findings_<version> 等)は一般的な命名パターンに基づく雛形です。実際の名称は自分のレイクで SHOW DATABASES / SHOW TABLES を実行して確認してください(リージョン・ソースバージョンで差が出ます)。本記事では「まず実体を SHOW/DESCRIBE で確認 → カラムを SELECT * で1行覗く → 本クエリを書く」という順序を強く推奨します。

5.3 本クエリ:直近90日・高重大度・アカウント別・finding 型別

実カラムを確認したら、横断分析の本体を書きます。パーティション(リージョン・日付)で必ず絞るのがコスト鉄則です。

-- 直近90日の「高重大度な GuardDuty 由来 finding」を、アカウント別・finding 型別に集計する。
-- - SH_FINDINGS テーブル = GuardDuty finding の着地点(2 章)
-- - パーティション列(region/eventday 等)で先に絞り、Athena のスキャン量=課金を抑える
-- - severity / finding の型名カラムは OCSF バージョンで位置が違うため 5.2 で確認した実カラムに合わせる
SELECT
    cloud.account_uid                          AS account_id,   -- どのアカウントの finding か
    finding_info.title                         AS finding_title,-- finding 種別(GuardDuty 型名相当)
    severity                                   AS severity,     -- OCSF の severity(文字列ラベル)
    count(*)                                   AS occurrences,
    max(time)                                  AS last_seen     -- 直近の発生時刻
FROM amazon_security_lake_glue_db_ap_northeast_1.amazon_security_lake_table_ap_northeast_1_sh_findings_2_0
WHERE
    -- ① パーティションで先に絞る(フルスキャン=高額を避ける)
    region   = 'ap-northeast-1'
    AND eventday >= date_format(current_date - interval '90' day, '%Y%m%d')
    -- ② GuardDuty 由来に限定(Security Hub の製品名で絞る/環境のカラムに合わせる)
    AND metadata.product.name = 'GuardDuty'
    -- ③ 高重大度のみ(Critical/High。ラベルは実データで確認した値に合わせる)
    AND severity IN ('Critical', 'High')
GROUP BY 1, 2, 3
ORDER BY occurrences DESC, last_seen DESC
LIMIT 100;

カラム名は OCSF スキーマと環境で変わる(要確認):上の cloud.account_uid / finding_info.title / severity / time / metadata.product.nameOCSF の代表的なフィールドに基づく雛形です。SH_FINDINGS の実テーブルでは、ASFF からの変換の都合でカラムの入れ子位置や名称が異なることがあります。必ず 5.2 で DESCRIBESELECT * してから、実カラムに合わせて書き換えてください。「GuardDuty 由来かどうか」も、環境によっては metadata.product.name ではなく finding_info 配下や metadata.product.feature.name で判別する場合があります。

5.4 横断クエリの威力:finding × CloudTrail を JOIN する

Security Lake の本領は、finding 単体ではなく他ソースと突き合わせるところに出ます。CLOUD_TRAIL_MGMT も入れてあれば、「Critical finding の主体(IAM)が、同じ時間帯に叩いていた API」を1クエリで引けます。

-- Critical finding を起点に、その主体(account)が前後1時間に叩いた API を突き合わせる。
-- finding(SH_FINDINGS)と CloudTrail 管理イベント(CLOUD_TRAIL_MGMT)を OCSF の語彙で JOIN。
WITH critical_findings AS (
    SELECT cloud.account_uid AS account_id, time AS finding_time
    FROM amazon_security_lake_glue_db_ap_northeast_1.amazon_security_lake_table_ap_northeast_1_sh_findings_2_0
    WHERE region = 'ap-northeast-1'
      AND eventday >= date_format(current_date - interval '7' day, '%Y%m%d')
      AND metadata.product.name = 'GuardDuty'
      AND severity = 'Critical'
)
SELECT f.account_id,
       c.api.operation        AS api_called,   -- 同時間帯に呼ばれた API
       c.actor.user.uid       AS actor,
       c.time                 AS api_time
FROM critical_findings AS f
JOIN amazon_security_lake_glue_db_ap_northeast_1.amazon_security_lake_table_ap_northeast_1_cloud_trail_mgmt_2_0 AS c
  ON  c.cloud.account_uid = f.account_id
  -- finding 発生の前後1時間に絞る(攻撃の文脈に焦点を当て、ノイズとスキャン量を抑える)
  AND c.time BETWEEN f.finding_time - 3600000 AND f.finding_time + 3600000
WHERE c.region = 'ap-northeast-1'
ORDER BY f.account_id, api_time;

これが「GuardDuty コンソールだけでは絶対にできない」分析です——finding を点で見るのではなく、ログ全体の中に置いて文脈を引く。Detective が対話的なグラフでやることを、Security Lake では**再現可能な SQL(=監査に出せる成果物)**でやります。


6. サブスクライバ:クエリアクセス(SQL)かデータアクセス(SIEM)か

Security Lake のデータを「使う側」がサブスクライバ(subscriber)です。公式は2種類のアクセスを定義します——どちらを選ぶかで設計が分かれます。

6.1 2種類のアクセスタイプ(公式の定義)

アクセスタイプ公式の挙動何に使うか
クエリアクセス(Query access)"Subscribers with query access can query data that Security Lake collects. These subscribers directly query AWS Lake Formation tables in your S3 bucket with services like Amazon Athena."自社で SQL 分析——Athena / Redshift / OpenSearch でレイクを直接クエリ。監査レポート・横断相関(5 章)
データアクセス(Data access)"Subscribers with data access ... are notified of new objects ... as the data is written to the S3 bucket. By default, ... through an HTTPS endpoint ... Alternatively, ... by polling an Amazon SQS queue."外部 SIEM へ供給——新規 S3 オブジェクトを SQS/HTTPS で通知し、サードパーティ(Splunk/QRadar 等)が消費

使い分けの原則

  • 「自分たちが SQL で分析したい」→ クエリアクセス。 Lake Formation のテーブルをそのまま Athena で叩く。新たなデータコピーを作らず、レイクの実体をクエリします。
  • 「既存の SIEM に finding を流し込みたい」→ データアクセス。 SIEM 側は「新しい Parquet オブジェクトが書かれた」という SQS 通知を受けて、S3 から OCSF レコードを取りに行きます。finding を SIEM のルール/相関エンジンに乗せたいときの正攻法です。

6.2 最小権限の徹底——ソース単位・リージョン単位で配る

公式は明言します——"To control costs and adhere to least privilege access best practices, you provide subscribers access to data on a per-source basis." かつ "Subscribers only have access to the source data in the AWS Region that you select."

つまり——「finding(SH_FINDINGS)だけを、ap-northeast-1 だけ、SIEM チームに渡す」という粒度でアクセスを絞れます。VPC Flow や CloudTrail を渡さずに finding だけ、特定リージョンだけ——という最小権限が設計できます。決済基盤のようにデータ機密度が高い環境では、この粒度が効きます(SIEM ベンダーに渡すのは finding だけ、生の VPC Flow は社内クエリアクセスに留める、等)。

制約(公式)"The maximum number of sources that Security Lake allows to add per subscriber is 10." 1サブスクライバに足せるソースは最大10(AWS ソース+カスタムソースの合計)。用途別にサブスクライバを分ける設計(SIEM 用・社内分析用)が、この制約とも相性が良いです。


7. Terraform:data lake → ソース → サブスクライバを宣言する

ここまでの設計を Terraform に落とします。aws_securitylake_data_lake(レイク本体)→ aws_securitylake_aws_log_source(ソース)→ aws_securitylake_subscriber(サブスクライバ) の順です。引数名は Terraform AWS Provider のドキュメントで検証していますが、プロバイダのバージョンで差が出る可能性があるため、適用前に terraform plan で確認してください。

7.1 データレイク本体(暗号化・ライフサイクル・リージョン)

# ── 委任管理者(security-tooling)アカウントで実行 ──
# データレイク本体。configuration はリージョン単位で複数指定できる。
resource "aws_securitylake_data_lake" "this" {
  # Glue テーブルの作成・更新に使うロール(Security Lake が引き受ける)。
  meta_store_manager_role_arn = aws_iam_role.meta_store_manager.arn

  configuration {
    region = "ap-northeast-1" # 例: ここをロールアップリージョンにする

    # 暗号化。"S3_MANAGED_KEY" で SSE-S3、または KMS キー ID を指定して SSE-KMS。
    encryption_configuration {
      kms_key_id = "S3_MANAGED_KEY"
    }

    # ライフサイクル:古いデータを安いクラスへ遷移し、保持期限で自動削除。
    # 「直近は標準・古いほど安く・N日で削除」で長期保管コストを抑える(4.2)。
    lifecycle_configuration {
      transition {
        days          = 31
        storage_class = "STANDARD_IA"
      }
      transition {
        days          = 80
        storage_class = "ONEZONE_IA"
      }
      expiration {
        days = 365 # コンプライアンス要件に合わせて保持期間を設定
      }
    }
  }
}

7.2 ソース追加:SH_FINDINGS(= GuardDuty finding の入口)+相関の材料

# Security Hub findings = GuardDuty finding の唯一の入口(2 章)。
# 単一の aws_securitylake_aws_log_source で「全リージョン・全アカウント」を表現するのが公式の推奨。
resource "aws_securitylake_aws_log_source" "sh_findings" {
  source {
    source_name    = "SH_FINDINGS"        # ← GuardDuty 直接ソースは存在しない。ここ経由のみ
    source_version = "2.0"                 # OCSF クラスはバージョン依存(2.3)。適用前に確認
    regions        = ["ap-northeast-1"]
    accounts       = ["123456789012"]      # 省略すると組織全体(3.3 の罠)
  }

  # レイク本体が先に出来ていること。
  depends_on = [aws_securitylake_data_lake.this]
}

# 横断相関の材料:CloudTrail 管理イベント(誰が何の API を叩いたか)。
resource "aws_securitylake_aws_log_source" "cloudtrail_mgmt" {
  source {
    source_name = "CLOUD_TRAIL_MGMT"       # 唯一「別途ログ設定が要る」例外(3.2)
    regions     = ["ap-northeast-1"]
  }
  depends_on = [aws_securitylake_data_lake.this]
}

# 横断相関の材料:VPC Flow Logs(どの IP と通信したか)。
resource "aws_securitylake_aws_log_source" "vpc_flow" {
  source {
    source_name = "VPC_FLOW"
    regions     = ["ap-northeast-1"]
  }
  depends_on = [aws_securitylake_data_lake.this]
}

7.3 サブスクライバ:社内 SQL 分析(クエリアクセス)の例

# 社内のセキュリティ分析チームに「finding を SQL で読む」権限を与える(クエリアクセス)。
# access_type = "LAKEFORMATION" で Lake Formation テーブルを Athena から直接クエリできる。
resource "aws_securitylake_subscriber" "internal_analytics" {
  subscriber_name = "internal-sec-analytics"
  access_type     = "LAKEFORMATION" # クエリアクセス。SIEM 供給なら "S3"(データアクセス)

  # 渡すソースを finding に絞る=最小権限(6.2)。1 サブスクライバ最大10ソース。
  source {
    aws_log_source_resource {
      source_name    = "SH_FINDINGS"
      source_version = "2.0"
    }
  }

  # サブスクライバ側の AWS アイデンティティ(クロスアカウントの信頼確立)。
  subscriber_identity {
    external_id = "internal-analytics-ext-id" # 混乱した代理を防ぐ external_id
    principal   = "123456789012"              # 分析チームのアカウント/ロール
  }

  depends_on = [aws_securitylake_data_lake.this]
}

Terraform 引数の注意(要確認)access_type はドキュメント上 「Amazon S3 または Lake Formation のアクセスタイプ」(= データアクセス/クエリアクセス)を表しますが、受理する文字列リテラル("S3" / "LAKEFORMATION")はプロバイダのバージョンで表記が異なる可能性があります。replication_configuration の内部フィールド(regions / role_arn)も含め、適用前に必ず terraform plan と該当プロバイダ版のドキュメントで確認してください。本記事は Terraform AWS Provider(2026年6月時点)の記載に基づく雛形です。


8. 運用:検証・コスト・過信しないこと

8.1 「finding が本当に入っているか」を end-to-end で検証する

最大の事故は 「レイクは出来たが finding が空」 です。配線(2 章)が3段あるため、各段を順に確かめます。

  1. GuardDutyaws guardduty create-sample-findings でサンプル finding を発火(本編ガイドの 5.3)。
  2. Security Hub:その finding が Security Hub に取り込まれているか(GuardDuty 統合が ON か)を確認。
  3. Security Lakeaws securitylake get-data-lake-sourcesSH_FINDINGS の収集状態を確認 → Athena で実レコードを SELECT(5.2)。

この3点が緑になって初めて「集約が動いている」と言えます。型チェックや terraform apply の成功は『配線が正しい』証明にはならない——実データが Athena で引けることが証明です。

8.2 コストの考え方(参考・要確認)

  • 貯めるコスト:Parquet + S3 階層化で抑える(4.2)。expiration を要件ぴったりに。
  • クエリのコスト:Athena はスキャン量課金。パーティション(region / eventday)で必ず絞る(5.3)。SELECT * の全期間スキャンは厳禁。
  • 付随コスト:Security Lake 本体・Glue クローラ/カタログ・Lambda ETL にもそれぞれ課金。「とりあえず全ソース・全リージョン・最長保管」は請求を膨らませる——GuardDuty の FinOpsと同じく、要件から逆算して必要分だけ。具体的単価は地域・時期で変わるため公式の料金で確認してください。

8.3 Security Lake を過信しない——3層の中の「集約・分析」レイヤー

最後に 0 章へ戻ります。Security Lake は検知でも調査でも防御でもありません。

  • 新しい脅威を見つけるのは GuardDuty(本編ガイド)。Security Lake は finding を生まない
  • 「なぜ・どこまで」を対話的に追うのは Detective(最大1年・グラフ)。Security Lake は数年・SQL/SIEM——役割が違う。
  • finding を集約・正規化して机に並べるのは Security Hub。Security Lake はその findings を OCSF の長期倉庫に収め、横断クエリと SIEM 供給を可能にする

Security Lake が担うのは 「検知と調査の結果を、機械可読・横断可能・長期保管な形で残し、配る」 層です。GuardDuty・Detective・Security Hub・Security Lake は競合ではなく、時間軸と用途で分担する補完関係——これが正しい設計の出発点です。


まとめ:GuardDuty × Security Lake 長期集約チートシート

迷ったときの早見表です。

  • 3層で考えるGuardDuty=DETECT(いま)→ Detective=INVESTIGATE(最大1年・対話的グラフ)→ Security Lake=AGGREGATE & ANALYZE(数年・OCSF/Parquet・SQL/SIEM)。Security Lake は検知でも調査でも防御でもない。
  • 【最重要】配線Security Lake に「GuardDuty 直接ソース」は無い。経路は GuardDuty → Security Hub(GuardDuty 統合 ON)→ Security Lake の SH_FINDINGS のみ。どこかが欠けると finding は1件も入らない。
  • ネイティブソース(6系統):CloudTrail(管理+S3/Lambda データ)・EKS 監査・Route 53・Security Hub CSPM findings・VPC Flow・WAFv2。識別子は CLOUD_TRAIL_MGMT / S3_DATA / LAMBDA_EXECUTION / EKS_AUDIT / ROUTE53 / SH_FINDINGS / VPC_FLOW / WAFCloudTrail 管理イベント以外は別途ログ設定不要(独立した複製ストリーム)
  • 正規化:すべて OCSF + Apache Parquet に変換、ソースごとに Lake Formation テーブル。だから finding × CloudTrail × VPC Flow を同じ語彙で JOINできる。OCSF クラスはバージョン依存(V1=Security Finding / V2=Vulnerability/Compliance/Detection Finding)——実データで確認してからクエリを書く
  • マルチアカウント・リージョン委任管理者に集約、ロールアップリージョンで複数リージョンを1か所へ(データレジデンシー対応)。
  • 保管:**S3 階層化(transition)+有効期限(expiration)**で数年保管を安く。Parquet で容量効率も良い。
  • サブスクライバ(2種)クエリアクセス(Lake Formation → Athena/Redshift/OpenSearch で SQL =自社分析)と データアクセス(新規 S3 オブジェクトを SQS/HTTPS 通知 = SIEM 供給)。ソース単位・リージョン単位で最小権限、1サブスクライバ最大10ソース。
  • 検証create-sample-findings → Security Hub → get-data-lake-sources → Athena SELECTend-to-end で「finding が実際に入っている」ことを確認。型チェックや apply 成功は証明にならない。
  • コスト(要確認):貯めるは安く・クエリはスキャン量課金なのでパーティションで絞る。Security Lake/Glue/Athena に各課金。要件から逆算。

GuardDuty の finding は「いま赤く光る」ことには強い。けれど1年後の監査・横断相関・SIEM 連携に応えるには、それを OCSF で正規化し、自分の S3 に数年残し、SQL と SIEM に配る土台が要ります。最大のレバレッジは検知そのものより、検知の結果を「流れて消える通知」から「再現可能なデータ資産」に変える集約設計にあります。

私はマルチアカウントのサーバーレス決済プラットフォームで、実際の金銭・カーボンクレジット・地域通貨を扱う基盤の IAM・可観測性・DR を横断実装し、「いつ・誰が・何をしたか」をコードの構造とデータパイプラインで再現可能にしてきました。Security Lake を named project で運用したと主張するつもりはありません。ですが、この detect → investigate → 長期集約・分析の一気通貫を、あなたの AWS 環境向けに設計・実装することはできます——マルチアカウント AWS の可観測性・DR・データパイプラインを横断してきた実体験を土台に。

「GuardDuty は入れたが、過去横断の分析・コンプライアンスの長期保管・SIEM 連携の土台が無い」——その集約レイヤーを、GuardDuty→Security Hub→Security Lake の正確な配線から、OCSF 横断クエリ・ロールアップリージョン・サブスクライバ設計・Terraform 実装・コスト最適化まで、一人 ×生成AI(Claude Code)で速く・安全に伴走できます。 要件の整理段階からでも、お気軽にご相談ください。


参考(公式ドキュメント)

  • What is Amazon Security Lake? — フルマネージドのセキュリティデータレイク・自分の S3・所有権保持・OCSF + Parquet 正規化・ロールアップリージョン・内部依存サービス(EventBridge/Glue/Lake Formation/Lambda/S3/SQS)
  • Collecting data from AWS services in Security Lake — ネイティブソース6系統・「CloudTrail 管理イベント以外は別途ログ設定不要/独立した複製ストリーム」・CreateAwsLogSourcesourceName/regions 必須・accounts/sourceVersion 任意)
  • Subscriber management in Security Lake — 2種類のアクセス(データアクセス=SQS/HTTPS 通知/クエリアクセス=Lake Formation テーブルを Athena 等でクエリ)・ソース単位の最小権限・1サブスクライバ最大10ソース
  • OCSF in Security Lake — OCSF 変換・ソースごとの class_name(Security Hub CSPM:V1=Security Finding / V2=Vulnerability・Compliance・Detection Finding)・ソース識別の metadata 値
  • aws_securitylake_data_lake(Terraform AWS Provider)meta_store_manager_role_arn / configuration {region, encryption_configuration, lifecycle_configuration {transition, expiration}, replication_configuration}
  • aws_securitylake_aws_log_source(Terraform AWS Provider)source {source_name, source_version, accounts, regions}・有効な source_name(ROUTE53/VPC_FLOW/SH_FINDINGS/CLOUD_TRAIL_MGMT/LAMBDA_EXECUTION/S3_DATA/EKS_AUDIT/WAF)
  • aws_securitylake_subscriber(Terraform AWS Provider)subscriber_name / access_type(S3 or Lake Formation)/ source {aws_log_source_resource {source_name, source_version}} / subscriber_identity {external_id, principal}
  • Amazon Security Lake pricing — 取り込み量・保管・付随サービス課金(具体単価は地域・時期で要確認)
友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・ 実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

この記事の実装を、案件として承ります

検知後の調査・長期集約(Detective / Security Lake)基盤

GuardDuty の検知を、Amazon Detective での根本原因調査と Security Lake(OCSF)への長期集約・横断分析・SIEM 連携へつなぎます。『検知 → 調査 → 集約』の運用フローを設計します。

プロジェクト単位(請負)・技術顧問のどちらにも対応可能です。まずは30分の無料技術相談から。