# GuardDuty RDS Protection と Lambda Protection：DBログイン異常とサーバーレスのネットワーク脅威を、インフラ変更ゼロ・エージェントレスで検知する

> Amazon GuardDuty の RDS Protection と Lambda Protection を本番設計する実装ガイド。Aurora/RDS のログイン異常(成功・失敗・ブルートフォース・悪性IP・Tor)を直接監視し、Lambda の全関数(非VPC含む)のネットワーク活動から暗号資産マイニング・C&C 通信を検知する——どちらもエージェントレス・インフラ変更ゼロ・コード変更不要。対応エンジン、finding 型、最大2週間の学習期間、料金と30日無料トライアル、Terraform 有効化、EventBridge 自動対応までを公式準拠で解説します。

- 公開日: 2026-06-27
- 著者: 友田 陽大
- タグ: セキュリティ, AWS, GuardDuty, RDS, Lambda
- URL: https://tomodahinata.com/blog/aws-guardduty-rds-lambda-protection-database-login-network-threats-guide
- カテゴリ: Amazon GuardDuty 本番運用
- 総合ガイド: https://tomodahinata.com/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide

## 要点

- RDS Protection は Aurora/RDS の『ログインアクティビティ』を AWS 側から直接・エージェントレスで監視する。追加インフラ不要・DB 性能に影響なし。ただし新規有効化・新規インスタンスは『ベースライン学習』に最大2週間かかり、その間は異常 finding が出ない
- Lambda Protection は『全 Lambda 関数のネットワーク活動ログ（VPC を使わない関数も含む）』を解析する。VPC 設定済み関数の ENI 用に自分で VPC Flow Logs を有効化する必要はない。Lambda@Edge は対象外
- RDS の finding 型は9種（AnomalousBehavior 系・MaliciousIPCaller 系・TorIPCaller 系）。Lambda は7種（C&CActivity・BitcoinTool・BlackholeTraffic・DropPoint・MaliciousIPCaller.Custom・TorClient・TorRelay）。型名から脅威の中身が読める
- どちらも『コード変更ゼロ・インフラ変更ゼロ』で足せる検知層。RDS は『対応する Aurora/RDS を使っている時』、Lambda は『外向き通信する関数がある時』に有効化する。判断は資産ベース（YAGNI）
- 検知は出発点。EventBridge → 冪等な自動対応（認証情報ローテーション・SG 制限・関数の無効化）まで繋いで初めて MTTR が縮む。両プランとも30日無料トライアルで請求額を事前に把握できる

---

「DB への不審なログインや、Lambda が勝手に外と通信してるのって、気づけるんですか？ ——でもエージェント入れたり、ログ基盤を作り直したりはしたくないんです」。サーバーレスやマネージド DB 中心の構成を運用しているチームから、よく受ける相談です。

答えは「**インフラを一切いじらず、コードも変えず、エージェントも入れずに検知できます**」。それが GuardDuty の **RDS Protection** と **Lambda Protection** という2つの保護プランです。両者に共通するのは、**完全にエージェントレスで、追加インフラを要求しない**こと。RDS Protection は Aurora/RDS の**ログインアクティビティ**を AWS 側から直接読み取り、Lambda Protection は**すべての Lambda 関数のネットワーク活動**を解析します。あなたが DB に監査拡張を仕込む必要も、Lambda の ENI に VPC Flow Logs を張る必要もありません。

この記事は、この2つの「**インフラ変更ゼロ・エージェントレス**」な保護プランを、**本番品質**で設計・運用するための実装ガイドです。GuardDuty 全体の設計（基盤検知・組織統制・EventBridge 自動対応）は[ピラー記事](/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide)に譲り、本稿は**そのピラーの「RDS Protection」「Lambda Protection」の2行を、対応エンジン・finding 型・学習期間・コスト・自動対応まで一段深く掘り下げる**ことに集中します。私はマルチアカウント AWS 上の[サーバーレス決済プラットフォーム](/case-studies/payment-platform-reliability)で IAM・可観測性・DR を横断実装し、[Lambda を本番運用](/blog/aws-lambda-production-guide)してきました——その視点から、「**あなたの DB と関数に、この2層をどう設計・実装するか**」を語ります。

> **この記事のルール**：仕様・対応エンジン・finding の型／重大度・料金体系は **AWS 公式ドキュメント（2026年6月時点）** に基づきます。対応データベースエンジンの**バージョン**は公式の対応表が随時更新されるため、本文では具体的なバージョンを断定せず**確認手順を示します**——本番投入前に必ず公式の最新表を確認してください。そしてもう一つの前提——**GuardDuty は「検知」であって「防御」ではありません**。RDS Protection も Lambda Protection も、最小権限の IAM・IAM データベース認証・暗号化・ネットワーク分離・入力検証を**代替しません**。これらは多層防御の中で「侵害の兆候を早く知らせる層」を担います。そして「エージェントレス」は「無料」を意味しません——どちらも使用量に応じた**従量課金**です（料金は7章）。

---

## 0. メンタルモデル：2つの「インフラ変更ゼロ」検知層

設計を始める前に、この2プランが何で・何でないかを一行ずつ固定します。

> **RDS Protection ＝ Aurora/RDS の「ログインアクティビティ（成功・失敗）」を、AWS 側から直接・エージェントレスで取り込み、ML で異常ログインを検知する保護プラン。**
>
> **Lambda Protection ＝ アカウント内の「すべての Lambda 関数のネットワーク活動ログ（VPC を使わない関数も含む）」を解析し、悪性ホストとの通信・暗号資産マイニングなど、関数の侵害を示す通信を検知する保護プラン。**

ここから、この2つを束ねる **3つの共通する帰結** が出ます。これが設計判断の土台です。

1. **どちらもエージェントレスで、インフラ変更を要求しない。** RDS Protection は「GuardDuty が Aurora/RDS サービスから**直接**ログインアクティビティを監視する」もので、あなたが DB に監査ログ拡張を入れたり、性能チューニングを気にしたりする必要はありません（公式：*"RDS Protection doesn't require additional infrastructure; it is designed so as not to affect the performance of your database instances."*）。Lambda Protection も同様で、**VPC 設定済み関数の ENI 用に自分で VPC Flow Logs を有効化する必要はありません**。[Runtime Monitoring](/blog/aws-guardduty-runtime-monitoring-eks-ecs-fargate-ec2-guide) のようにワークロードへエージェントを配る必要も**ありません**。
2. **どちらも「ログ本体はあなたに渡らない」。** GuardDuty はログインアクティビティ／ネットワーク活動を内部で解析し、**それをあなたのアカウントで利用可能にはしません**（RDS：*"GuardDuty doesn't ... make RDS login activity available to you."* / Lambda：*"GuardDuty doesn't manage your Lambda network activity logs ..., or make them accessible in your account."*）。「検知のためにログを保存・課金する」のは GuardDuty 側の責務で、あなたのログ設定とは独立しています。
3. **finding は「出発点」であって「終点」ではない。** どちらも構造化された finding を生成し、それを EventBridge で受けて自動対応に繋いで初めて運用に載ります。**本記事の山場は 6 章（EventBridge → 冪等な自動対応）**です。

この3点を押さえると、2プランの導入は **「①対応する資産があるか（有効化判断）→ ②finding 型をどう読むか → ③どう行動に変えるか（自動対応）」** の設計だと分かります。順に作ります。

---

## 1. RDS Protection：何を・どう監視するか

### 1.1 監視対象は「ログインアクティビティ」だけ——クエリ内容ではない

まず誤解を解きます。RDS Protection が見るのは **DB へのログインアクティビティ（成功・失敗の認証イベント）** であって、**SQL クエリの中身やテーブルの読み書きではありません**。公式の定義はこうです——*"RDS Protection in Amazon GuardDuty analyzes and profiles RDS login activity for potential access threats."*

つまり狙いは **「誰が・どこから・どうログインしようとしたか」の異常検知**です。具体的には：

- **未知の外部アクターが初めてログインに成功した**（これまで見たことのないユーザー／IP）。
- **パスワード総当たり（ブルートフォース）を試みている**。
- **既知の悪性 IP や Tor 出口ノードからのログイン試行**。

RDS login activity は **成功・失敗の両方のログイン試行**を捕捉します（*"RDS login activity captures both successful and failed login attempts."*）。GuardDuty の ML モデルが「リクエストしたユーザー・接続元の位置・接続の詳細」といった要素を学習し、ベースラインから外れた挙動を異常として検知します。

### 1.2 対応エンジン（バージョンは公式の対応表で要確認）

RDS Protection が対応する**エンジン**は、公式の対応表で次のとおりです。

| 対応エンジン | 補足 |
| --- | --- |
| **Aurora MySQL-Compatible Edition** | Aurora の MySQL 互換 |
| **Aurora PostgreSQL-Compatible Edition** | Aurora の PostgreSQL 互換 |
| **RDS for PostgreSQL** | リードレプリカは「プライマリが対応バージョンであること」が条件 |
| **RDS for MySQL** | — |
| **RDS for MariaDB** | — |
| **Aurora PostgreSQL Limitless Database** | RDS Protection 有効済みアカウントは**自動で**監視対象に追加される |

> **バージョンは断定しません（公式準拠）**：上記は**エンジンの種類**の一覧です。各エンジンの**サポート対象バージョン**は公式ドキュメントの「Supported Amazon Aurora, Amazon RDS, and Aurora Limitless databases」の表で管理され、随時更新されます。本記事で個別バージョンを列挙すると陳腐化するため、**本番投入前に必ず公式の対応表を確認**してください。なお **RDS for PostgreSQL のリードレプリカ**は、プライマリが対応バージョンで、かつプライマリから正常にレプリケーションされていることが前提になります。

> **Limitless Database の注意（課金の落とし穴）**：すでに RDS Protection を有効化しているアカウントでは、**Aurora PostgreSQL Limitless Database が自動で監視対象に追加**されます。もし RDS Protection の30日無料トライアルが既に終了している場合、Limitless Database の監視分の**使用料が即座に発生**します。「いつのまにか課金対象が増えていた」を避けるため、Limitless を採用する際は課金影響を確認してください。

### 1.3 「最大2週間」の学習期間——ここが運用の落とし穴

RDS Protection 固有の、**設計時に必ず織り込むべき事実**がこれです。RDS Protection を**初めて有効化したとき**、または**新しく作成した DB インスタンス**については、**正常挙動のベースラインを学習する期間**があります。公式の原文：

> *When you enable RDS Protection for the first time or you have a newly created database instance, there is a learning period to baseline normal behavior. For this reason, newly enabled or newly created database instances may not have an associated anomalous login finding for up to two weeks.*

つまり——**有効化直後・新規インスタンス作成直後は、最大2週間、異常ログイン finding が出ない**可能性があります。これは欠陥ではなく仕様です。ML が「このユーザーが・この IP から・この接続詳細で入るのは正常」というベースラインを作るのに時間が要るためです。

ここから2つの設計上の含意が出ます。

- **「有効化したのに finding が来ない＝安全」とは限らない**。学習期間中かもしれません。「有効化した日付」と「監視対象として安定する日付（およそ2週間後）」を運用ドキュメントに記録しておくべきです。
- **`MaliciousIPCaller`／`TorIPCaller` 系は学習を待たない**。これらは ML の異常検知（`AnomalousBehavior` 系）ではなく、**既知の悪性 IP／Tor 出口ノードリストとの突合**で発火するため、ベースライン学習に依存しません。つまり**有効化直後でも「悪性 IP からのログイン」は検知され得ます**。学習期間が効くのは `AnomalousBehavior.*`（ML ベース）の方だ、と区別して理解するのが正確です。

### 1.4 finding に含まれる情報

RDS Protection の finding には、**潜在的に侵害された DB の詳細**が含まれます。**Resource Type** は `RDSDBInstance`（通常の Aurora/RDS）または `RDSLimitlessDB`（Limitless Database）です。ML ベースの finding には、ベースラインから逸脱した「RDS login activity-based anomalies」——どのユーザーが、どこから、どんな接続詳細でログインしたか——が付与され、トリアージで「誰のどのアクセスが異常だったか」を読めます。これが自動対応で「どの DB ユーザーの認証情報をローテーションすべきか」を決める材料になります。

---

## 2. RDS Protection の finding 型：9種を読み解く

RDS Protection の finding 型は **9種類**です。型名の構造は GuardDuty 共通の `ThreatPurpose:ResourceType/Family.Mechanism` で、**型名を見るだけで「何が起きたか」が分かる**のが秀逸な点です（型フォーマットの詳細は[ピラー記事の5章](/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide)）。

| finding 型 | デフォルト重大度 | 何を検知するか |
| --- | --- | --- |
| `CredentialAccess:RDS/AnomalousBehavior.SuccessfulLogin` | **Variable**（Low/Medium/High） | ML が「異常」と判断した**成功**ログイン（未知のユーザー／IP からの初ログイン等） |
| `CredentialAccess:RDS/AnomalousBehavior.FailedLogin` | **Low** | ML が「異常」と判断した**失敗**ログイン（ブルートフォースの試行を示唆し得る） |
| `CredentialAccess:RDS/AnomalousBehavior.SuccessfulBruteForce` | **High** | 異常な失敗ログインの連続の**後に**成功——ブルートフォース成功の疑い |
| `CredentialAccess:RDS/MaliciousIPCaller.SuccessfulLogin` | **High** | **既知の悪性 IP** からの**成功**ログイン |
| `CredentialAccess:RDS/MaliciousIPCaller.FailedLogin` | **Medium** | **既知の悪性 IP** からの**失敗**ログイン |
| `Discovery:RDS/MaliciousIPCaller` | **Medium** | 既知の悪性 IP が DB を**プローブ**した（ログイン試行はなし＝偵察） |
| `CredentialAccess:RDS/TorIPCaller.SuccessfulLogin` | **High** | **Tor 出口ノード**からの**成功**ログイン（身元秘匿の意図） |
| `CredentialAccess:RDS/TorIPCaller.FailedLogin` | **Medium** | **Tor 出口ノード**からの**失敗**ログイン |
| `Discovery:RDS/TorIPCaller` | **Medium** | Tor 出口ノードが DB を**プローブ**した（ログイン試行はなし） |

読み解きの要点を整理します。

- **`AnomalousBehavior.*` は ML ベース、`MaliciousIPCaller.*`／`TorIPCaller.*` は脅威インテリジェンスベース**。前者は1.3で述べた**最大2週間の学習**に依存し、後者は既知リストとの突合なので学習不要——この区別が、有効化直後にどの検知が効くかを決めます。
- **`SuccessfulLogin`（成功）と `FailedLogin`（失敗）と `Discovery`（プローブのみ）で重大度が違う**。成功ログイン（特に悪性 IP / Tor / ブルートフォース成功）は **High**、失敗やプローブは **Medium / Low**。自動対応の閾値はこの数値で切れます（6章）。
- **`AnomalousBehavior.SuccessfulLogin` だけは Variable**。同じ型でも、ログイン元がプライベート IP なら **Low**、パブリック IP なら **Medium**、失敗の連続パターンを伴うなら **High**——と文脈で重大度が変わります。「型名だけで一律に扱わず、`severity` の数値で判断する」のが正しい設計です。

> **対応の定石（公式の remediation に基づく）**：成功ログイン系（`SuccessfulLogin` / `SuccessfulBruteForce`）が出たら——**①該当 DB ユーザーのパスワードをローテーション**し、**②監査ログでそのユーザーの操作を確認**します。失敗・プローブ系が出たら、**③DB をプライベート VPC に置き、セキュリティグループを必要な送信元だけに絞る**（公開状態・過剰に緩いアクセスポリシーの是正）。根本対策としては、**パスワード認証より [IAM データベース認証](/blog/aws-lambda-rds-aurora-connection-management-rds-proxy-vpc-guide) を優先**し、漏洩し得る長期パスワードそのものを減らすのが王道です。

---

## 3. Lambda Protection：全関数のネットワーク活動を見る

### 3.1 「VPC を使わない関数も含めて」監視する

Lambda Protection の核心は、**監視範囲の広さ**です。公式の定義：

> *When you enable Lambda Protection, GuardDuty starts monitoring Lambda network activity logs. This includes VPC Flow Logs from all Lambda functions for your account (including those logs that don't use VPC networking) and logs that get generated when Lambda function gets invoked.*

ここで決定的なのは **"all Lambda functions ... (including those logs that don't use VPC networking)"**——**VPC ネットワーキングを使っていない関数も含めて、アカウント内の全 Lambda 関数のネットワーク活動を監視する**点です。「VPC に置いていない Lambda は対象外では？」という直感は**誤り**で、GuardDuty は関数の VPC 構成に関係なくネットワーク活動を見ます。

そして運用負荷の観点で重要なのが——**VPC 設定済み関数の ENI（Lambda が作る Elastic Network Interface）用に、自分で VPC Flow Logs を有効化する必要はない**こと：

> *For Lambda functions that are configured to use VPC networking, you don't need to enable VPC flow logs for the elastic network interfaces (ENI) created by Lambda for GuardDuty.*

つまり **「フローログ基盤を自分で作る」作業はゼロ**。GuardDuty が内部で必要なネットワーク活動ログを取り込みます。

### 3.2 何を検知するか——「侵害された関数コード」の通信

Lambda Protection が探すのは、**「関数の中に悪意あるコードが潜んでいることを示す、不審なネットワーク通信」**です。公式：*"When GuardDuty identifies suspicious network traffic that is indicative of the presence of a potentially malicious piece of code in your Lambda function ..."*

具体的なシナリオはこうです——サプライチェーン攻撃で汚染された依存パッケージ、漏洩した認証情報経由で書き換えられた関数コード、などが**外部の悪性ホストと通信し始める**。Lambda Protection はその通信を捉えます：

- **暗号資産マイニング**：攻撃者が関数を乗っ取り、Bitcoin 等のマイニングに**流用**する（`CryptoCurrency:Lambda/BitcoinTool.B`）。
- **C&C（指令制御）サーバとの通信**：ボットネットの一員として外部から指令を受ける（`Backdoor:Lambda/C&CActivity.B`）。
- **悪性ホスト／Tor との通信**：盗んだ認証情報の送信先（DropPoint）、ブラックホール、Tor 中継／クライアントなど。

### 3.3 Lambda@Edge は対象外（重要な除外）

設計時に必ず押さえる除外があります——**Lambda@Edge 関数のログは Lambda Protection の対象に含まれません**。公式：*"Lambda Network Activity Monitoring doesn't include the logs for Lambda@Edge functions."*

CloudFront のエッジで動く Lambda@Edge を使っているなら、**それは Lambda Protection ではカバーされない**ことを認識してください。エッジの保護は [WAF](/blog/waf-defense-in-depth-aws-waf-cloud-armor-owasp-guide) など別の層で考える必要があります。

### 3.4 finding に含まれる情報

Lambda Protection の finding の **Resource Type** は `Lambda` です。finding には、**通信していた Lambda 関数名**と**通信先 IP**（および脅威リストの詳細）が含まれます。これが自動対応で「どの関数を隔離・無効化すべきか」「どの依存を疑うべきか」を決める材料になります。

---

## 4. Lambda Protection の finding 型：7種を読み解く

Lambda Protection の finding 型は **7種類**です。すべて `resourceType` が `Lambda` で、リソースセグメントが `Lambda` であることで一目で識別できます。

| finding 型 | デフォルト重大度 | 何を検知するか |
| --- | --- | --- |
| `Backdoor:Lambda/C&CActivity.B` | **High** | 関数が**既知の C&C サーバ**の IP に問い合わせている（ボットネットの一員の疑い） |
| `CryptoCurrency:Lambda/BitcoinTool.B` | **High** | 関数が**暗号資産関連 IP**に問い合わせている（マイニングへの流用の疑い） |
| `Trojan:Lambda/BlackholeTraffic` | **Medium** | 関数が**ブラックホール（sinkhole）IP**と通信しようとしている |
| `Trojan:Lambda/DropPoint` | **Medium** | 関数が、**マルウェアが盗んだ認証情報等を集積するホスト**と通信しようとしている |
| `UnauthorizedAccess:Lambda/MaliciousIPCaller.Custom` | **Medium** | 関数が、**あなたがアップロードした脅威リスト**に載る IP と通信している |
| `UnauthorizedAccess:Lambda/TorClient` | **High** | 関数が **Tor の Guard／Authority ノード**に接続（Tor クライアント化の疑い） |
| `UnauthorizedAccess:Lambda/TorRelay` | **High** | 関数が **Tor 中継（relay）**として振る舞っている |

読み解きの要点：

- **`.Custom` の意味**：`UnauthorizedAccess:Lambda/MaliciousIPCaller.Custom` の `.Custom` は「**あなた自身がアップロードした脅威リスト**との一致」を示す検知メカニズムです（GuardDuty の脅威リスト機能。詳細は[ピラー記事の7章](/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide)）。自社で「これは悪性」と判断した IP を登録しておけば、Lambda がそこと通信した瞬間に検知できます。
- **重大度の二極化**：C&C・暗号資産・Tor 系は **High**、ブラックホール・DropPoint・カスタムリスト系は **Medium**。**High はほぼ確実に「関数が侵害されている」前提**で動くべきシグナルです。
- **`BitcoinTool.B` には正規の例外があり得る**：もし関数が**正規に**ブロックチェーン関連処理（マイニング・暗号資産管理）をしているなら、これは誤検知になります。公式は、その場合「**finding 型 ＝ `CryptoCurrency:Lambda/BitcoinTool.B`** ＋ **対象の関数名**」の2条件で[抑制ルール（Suppression Rule）](/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide)を作ることを推奨しています。

> **対応の定石（公式の remediation に基づく）**：Lambda の finding が**想定外**なら、公式は「**その関数は侵害されたと仮定して対応する**」ことを推奨します（*"assume that Lambda has been potentially compromised"*）。具体的には——**①関数を一時的に無効化／同時実行数を 0 に絞って通信を止める**、**②関数コードと依存パッケージをレビュー**（サプライチェーン汚染を疑う）、**③関数が握っていた認証情報・環境変数の秘密を漏洩前提でローテーション**。これは私が[Lambda 本番運用](/blog/aws-lambda-production-guide)で重視する「最小権限の実行ロール × 秘密の最小化」と一貫します——侵害時に**奪われるものを最初から減らしておく**設計です。

---

## 5. 意思決定表：いつ・どちらを有効化するか

ここまでを実務の判断に落とし込みます。**どちらも「コード変更ゼロ・インフラ変更ゼロ・エージェントレス」**なので、判断軸はシンプルに **「対応する資産があるか」** です。

| あなたの状況 | 有効化すべきか | プラン | 理由 |
| --- | --- | --- | --- |
| 対応エンジンの Aurora/RDS（PostgreSQL/MySQL/MariaDB）を本番で使っている | **有効化する** | RDS Protection | ログイン異常を AWS 側から直接検知。DB 性能に影響なし |
| Aurora PostgreSQL Limitless Database を使っている | **有効化する**（課金注意） | RDS Protection | 自動で監視対象に。トライアル終了済みなら即課金 |
| インターネット／外部 API に**外向き通信する** Lambda 関数がある | **有効化する** | Lambda Protection | C&C・マイニング・悪性ホスト通信を検知 |
| 機密データ・認証情報を扱う Lambda 関数がある | **有効化する** | Lambda Protection | 侵害時のインパクトが大きい。流用・持ち出しの通信を捉える |
| サードパーティ依存（npm/pip 等）の多い Lambda がある | **有効化を推奨** | Lambda Protection | サプライチェーン汚染後の不審通信を検知 |
| **Lambda@Edge のみ**を使っている | **対象外** | — | Lambda@Edge は Lambda Protection の監視対象外 |
| DB を一切使っていない（DynamoDB のみ等） | RDS は**不要** | — | 監視対象がない（YAGNI）。DynamoDB の保護は IAM 等で |
| Lambda を一切使っていない | Lambda は**不要** | — | 監視対象がない（YAGNI） |

**設計の勘所は「資産に合わせて足す（YAGNI）」**です。DynamoDB ベースのサーバーレス構成（私の[決済プラットフォーム](/case-studies/payment-platform-reliability)はこの形でした）なら、**RDS Protection は有効化しても検知対象がゼロ**——コストだけ増えます。一方、外向き通信する Lambda が並ぶ構成なら、Lambda Protection は**コード変更ゼロで侵害検知を一層足せる**、費用対効果の高い選択です。

> **正直な前提（誇張しない）**：私の実際のケーススタディは **DynamoDB ベースのサーバーレス決済基盤**で、RDS を本番の中核に据えてはいません。だからここで RDS Protection を「実プロジェクトで回した」とは言いません。語れるのは——**マルチアカウント AWS の IAM・可観測性・DR を横断実装し、Lambda を本番運用してきた**経験を土台に、**あなたの Aurora/RDS と Lambda にこの2層をどう設計・実装するか**を、公式仕様と一般的な RDS/Aurora の知識に基づいて伴走できる、ということです。

---

## 6. Terraform で有効化し、EventBridge で行動に変える

### 6.1 有効化（驚くほど短い）

両プランとも、`aws_guardduty_detector` 本体とは別の **`aws_guardduty_detector_feature`** リソースで足します。機能名は **RDS Protection ＝ `RDS_LOGIN_EVENTS`**、**Lambda Protection ＝ `LAMBDA_NETWORK_LOGS`** です。

```hcl
# detector 本体は別途定義済みとする（ピラー記事の 2 章を参照）。
# 基盤検知 + Extended Threat Detection は detector 有効化の時点で動いている。

# ── RDS Protection ──
# 対応する Aurora/RDS を使っている時だけ有効化する（YAGNI）。
# エージェントレス・インフラ変更ゼロ。有効化直後〜新規インスタンスは
# 最大2週間の学習期間があり、その間 AnomalousBehavior 系 finding は出ない。
resource "aws_guardduty_detector_feature" "rds_login_events" {
  detector_id = aws_guardduty_detector.this.id
  name        = "RDS_LOGIN_EVENTS"
  status      = "ENABLED"
}

# ── Lambda Protection ──
# 外向き通信する Lambda がある時に有効化する。
# 全関数(非VPC含む)のネットワーク活動を解析。Lambda@Edge は対象外。
# ENI 用の VPC Flow Logs を自分で張る必要はない。
resource "aws_guardduty_detector_feature" "lambda_network_logs" {
  detector_id = aws_guardduty_detector.this.id
  name        = "LAMBDA_NETWORK_LOGS"
  status      = "ENABLED"
}
```

組織全体で一括有効化するなら、ピラー記事の `aws_guardduty_organization_configuration_feature` と同じ構造で、同じ機能名（`RDS_LOGIN_EVENTS` / `LAMBDA_NETWORK_LOGS`）を委任管理者アカウントから展開できます。

```hcl
# ── 委任管理者アカウントで実行：組織全体に自動展開 ──
# 「対応資産を持つアカウントが多い」場合は組織一括が漏れを防ぐ。
# ただし対応資産ゼロのアカウントにも課金は基本発生しない(監視対象がないため)。
resource "aws_guardduty_organization_configuration_feature" "rds_org" {
  detector_id = aws_guardduty_detector.security.id
  name        = "RDS_LOGIN_EVENTS"
  auto_enable = "ALL" # 既存 + 新規すべて。取りこぼしを構造的に消す
}

resource "aws_guardduty_organization_configuration_feature" "lambda_org" {
  detector_id = aws_guardduty_detector.security.id
  name        = "LAMBDA_NETWORK_LOGS"
  auto_enable = "ALL"
}
```

> **`auto_enable = "ALL"` を選ぶ理由**：`NEW`（今後 join するアカウントのみ）だと、設定時点で既に存在するアカウントが永久に対象外になり得ます——これは「全社で漏れなく検知する」目的に対する**サイレントな穴**です。RDS/Lambda は監視対象（DB / 外向き Lambda）がないアカウントでは検知も課金も発生しにくいため、**ALL で広く有効化し、資産のある所だけが実際に動く**——という設計が安全側に倒れます。

### 6.2 EventBridge ルーティング：型と重大度で振り分ける

検知を行動に変える土台は **EventBridge** です（詳細な自動対応設計はピラー記事の6章）。RDS/Lambda の finding も他の GuardDuty finding と同じく、ほぼリアルタイムで EventBridge に流れます。**型のプレフィックスと `severity` の数値**で振り分けるのが定石です。

```json
{
  "source": ["aws.guardduty"],
  "detail-type": ["GuardDuty Finding"],
  "detail": {
    "type": [
      { "prefix": "CredentialAccess:RDS/" },
      { "prefix": "Discovery:RDS/" },
      { "prefix": "Backdoor:Lambda/" },
      { "prefix": "CryptoCurrency:Lambda/" },
      { "prefix": "Trojan:Lambda/" },
      { "prefix": "UnauthorizedAccess:Lambda/" }
    ],
    "severity": [{ "numeric": [">=", 7] }]
  }
}
```

`type` の **`prefix` マッチ**で「RDS 由来／Lambda 由来」をまとめて拾い、`severity >= 7`（High 以上）で**封じ込め候補**に絞ります。これにより、`AnomalousBehavior.FailedLogin`（Low）のようなノイズになりやすい型は封じ込めから外れ、`SuccessfulBruteForce` / `MaliciousIPCaller.SuccessfulLogin` / `BitcoinTool.B`（いずれも High）だけが対応パイプラインに乗ります。

### 6.3 冪等な自動対応 Lambda（Python）——RDS と Lambda で対応が違う

ここが本記事の山場です。RDS の finding と Lambda の finding では、**取るべきアクションが根本的に違います**：

- **RDS の侵害** → 認証情報のローテーション、DB のネットワーク露出の是正（人間のレビューを挟むべき領域）。
- **Lambda の侵害** → 関数の通信を止める（同時実行数を 0 に絞る）、コード・依存・秘密のレビュー。

そして両者に共通する鉄則——**[EventBridge は at-least-once 配信](/blog/aws-guardduty-eventbridge-automated-remediation-incident-response-guide)**なので、同じ finding で Lambda が2回起動し得ます。決済基盤で二重課金を防ぐのと同じ発想で、**自動対応も冪等**でなければなりません。

```python
"""GuardDuty の RDS/Lambda Protection finding に応答する自動対応 Lambda。

設計原則:
  - 冪等: EventBridge は at-least-once。同じ finding を2回受けても副作用は1回分。
  - スコープを絞る: 自動アクションは「取り消せる・スコープが狭い」ものに限定。
  - RDS は通知中心: DB の認証情報ローテーションは破壊的なので人間のレビューを挟む。
  - Lambda は封じ込め可: 同時実行数を 0 に絞るのは取り消し可能(後で戻せる)。
  - 入力はサニタイズ: finding フィールド(関数名・ユーザー名等)は信頼しない外部入力として扱う。
"""
from __future__ import annotations

import json
import logging
import os
from typing import Any, Final

import boto3

logger = logging.getLogger()
logger.setLevel(logging.INFO)

lambda_client = boto3.client("lambda")
sns = boto3.client("sns")

ALERT_TOPIC_ARN: Final[str] = os.environ["ALERT_TOPIC_ARN"]
# 破壊的操作を避け、まず観察したい段階では DRY_RUN=true で封じ込めを抑止。
DRY_RUN: Final[bool] = os.environ.get("DRY_RUN", "false").lower() == "true"

# Lambda 関数を自動で封じ込める(同時実行=0)対象の finding 型。
# High 確度の「侵害ほぼ確実」な型に限定する。
LAMBDA_CONTAIN_ALLOWLIST: Final[frozenset[str]] = frozenset(
    {
        "Backdoor:Lambda/C&CActivity.B",
        "CryptoCurrency:Lambda/BitcoinTool.B",
        "UnauthorizedAccess:Lambda/TorClient",
        "UnauthorizedAccess:Lambda/TorRelay",
    }
)


def handler(event: dict[str, Any], _context: object) -> dict[str, str]:
    detail = event["detail"]
    finding_type: str = detail["type"]
    severity: float = float(detail["severity"])
    finding_id: str = detail["id"]

    if finding_type.endswith("/") or "/" not in finding_type:
        # 想定外フォーマットは通知だけして安全側に倒す。
        action = _route_unknown(finding_type, severity, finding_id)
    elif "Lambda/" in finding_type:
        action = _handle_lambda(detail, finding_type, severity, finding_id)
    elif "RDS/" in finding_type:
        action = _handle_rds(detail, finding_type, severity, finding_id)
    else:
        action = _route_unknown(finding_type, severity, finding_id)

    logger.info(
        json.dumps({"finding_id": finding_id, "type": finding_type, "action": action})
    )
    return {"action": action}


def _handle_lambda(
    detail: dict[str, Any], finding_type: str, severity: float, finding_id: str
) -> str:
    """Lambda の侵害: 高確度なら同時実行を 0 に絞って通信を止める(取り消し可能)。"""
    # finding から関数名を取り出す(構造はリソース種別に依存。存在チェックを厳格に)。
    resource = detail.get("resource", {})
    func_name = resource.get("lambdaDetails", {}).get("functionName")

    should_contain = (
        finding_type in LAMBDA_CONTAIN_ALLOWLIST
        and severity >= 7.0
        and bool(func_name)
    )

    if should_contain and not DRY_RUN:
        action = _throttle_function(func_name)  # 冪等
    else:
        action = "dry-run" if (should_contain and DRY_RUN) else "notify-only"

    _notify("Lambda", finding_type, severity, finding_id, func_name, action)
    return action


def _throttle_function(func_name: str) -> str:
    """関数の予約済み同時実行数を 0 にして即時に通信を止める。
    冪等: 既に 0 ならそのまま(2回目の起動は no-op)。後で削除すれば原状復帰。"""
    current = lambda_client.get_function_concurrency(FunctionName=func_name)
    if current.get("ReservedConcurrentExecutions") == 0:
        return "already-contained"
    lambda_client.put_function_concurrency(
        FunctionName=func_name, ReservedConcurrentExecutions=0
    )
    return "contained-throttled-to-zero"


def _handle_rds(
    detail: dict[str, Any], finding_type: str, severity: float, finding_id: str
) -> str:
    """RDS の侵害: 認証情報ローテーション/SG 変更は破壊的。
    自動では『チケット化 + 人間のレビュー依頼』にとどめ、手は出さない。"""
    resource = detail.get("resource", {})
    db = resource.get("rdsDbInstanceDetails", {})
    db_id = db.get("dbInstanceIdentifier")
    # 異常ログインの DB ユーザー(誰の認証情報を疑うか)を通知に含める。
    db_user = (
        resource.get("rdsDbUserDetails", {}).get("user")
        if "rdsDbUserDetails" in resource
        else None
    )
    _notify(
        "RDS", finding_type, severity, finding_id, f"{db_id} (user={db_user})", "review-required"
    )
    # 破壊的操作(パスワードローテーション等)は人間の承認フローへ。ここでは実行しない。
    return "review-required"


def _route_unknown(finding_type: str, severity: float, finding_id: str) -> str:
    _notify("Other", finding_type, severity, finding_id, None, "notify-only")
    return "notify-only"


def _notify(
    kind: str,
    finding_type: str,
    severity: float,
    finding_id: str,
    resource_ref: str | None,
    action: str,
) -> None:
    region = os.environ.get("AWS_REGION", "ap-northeast-1")
    console = (
        f"https://{region}.console.aws.amazon.com/guardduty/home"
        f"?region={region}#/findings?fId={finding_id}"
    )
    sns.publish(
        TopicArn=ALERT_TOPIC_ARN,
        Subject=f"[GuardDuty][{kind}][{severity}] {finding_type}",
        Message="\n".join(
            [
                f"type: {finding_type}",
                f"severity: {severity}",
                # resource_ref は finding 由来＝信頼しない入力。Web 表示時は
                # 受け手側で HTML エスケープする(ここでは生のまま SNS へ)。
                f"resource: {resource_ref or 'n/a'}",
                f"action: {action}",
                f"console: {console}",
            ]
        ),
    )
```

このコードの設計判断を明示します。

- **RDS と Lambda で対応を分岐**：Lambda は「同時実行 0 で通信を止める」という**取り消し可能な封じ込め**を自動化できますが、RDS の「認証情報ローテーション・SG 変更」は**破壊的（正規ユーザーを締め出し得る）**なので、自動では**チケット化と人間のレビュー依頼**にとどめます。これは「破壊的操作は人間を挟む」という鉄則の実装です。
- **冪等**：Lambda の封じ込めは「既に同時実行 0 なら no-op」でガード。at-least-once 配信で2回起動しても副作用は1回分です。
- **取り消し可能**：`put_function_concurrency(0)` は予約済み同時実行を**削除すれば原状復帰**します。関数の削除やコード書き換えのような不可逆な操作はしません。
- **入力をサニタイズ前提で扱う**：finding に含まれる**関数名・DB ユーザー名は攻撃者が影響し得る外部入力**です。Web ダッシュボードや Slack に転送する側で **HTML エスケープ等のサニタイズを必ず通す**——[Runtime Monitoring の記事](/blog/aws-guardduty-runtime-monitoring-eks-ecs-fargate-ec2-guide)でも触れた通り、finding フィールドは信頼しない入力です。
- **最小権限**：この Lambda の実行ロールは `lambda:GetFunctionConcurrency` / `lambda:PutFunctionConcurrency`（封じ込め対象の関数 ARN に絞る）と `sns:Publish` に限定します。RDS への破壊的権限は**与えません**（人間のフロー側に置く）。

より本格的なインシデント対応の配線（SOAR・チケット連携・Step Functions による承認フロー）は、[EventBridge 自動対応の専用記事](/blog/aws-guardduty-eventbridge-automated-remediation-incident-response-guide)で深掘りしています。

---

## 7. コスト：エージェントレスでも「無料」ではない

「エージェントレス・インフラ変更ゼロ」は魅力ですが、**従量課金**である事実は変わりません。両プランの課金単位を押さえます。

| プラン | 課金の考え方 |
| --- | --- |
| **RDS Protection** | 監視した RDS login activity の量に応じた従量課金（リージョン別・公式の料金ページで要確認） |
| **Lambda Protection** | 処理した **Lambda ネットワーク活動ログの GB** に対する従量課金。GuardDuty が**スマートフィルタで脅威検知に関連する部分集合だけ**を解析しコストを最適化 |

Lambda Protection について公式が明言する重要点：*"GuardDuty only charges for the amount of Lambda network activity logs data processed (in GB) to generate a finding. GuardDuty optimizes cost by applying smart filters and analyzing a subset of Lambda network activity logs that are relevant to threat detection."*——つまり**全ログを丸ごと課金するのではなく、脅威検知に関連する部分集合だけ**を処理します。

> **将来の課金拡大に注意（Lambda）**：公式は、Lambda のネットワーク活動監視が**将来 DNS クエリデータなど他の活動へ拡張され得る**こと、その場合**処理データ量＝コストが増える**こと、そして**拡張時には少なくとも30日前に通知する**ことを明記しています。「いま安いから」と固定視せず、拡張通知を見落とさない運用を。

両プランとも、**新規リージョンで初めて有効化すると30日無料トライアル**が付きます。この間に**本番量での想定請求額**を把握できます。GuardDuty 全体のコスト最適化（基盤・他プラン含む）は[専用記事](/blog/aws-guardduty-cost-optimization-pricing-finops-guide)に譲りますが、この2プランの鉄則は5章の繰り返し——**資産（対応 DB／外向き Lambda）がある所だけ有効化する**。対応資産がなければ検知ゼロ＝払う価値ゼロです。

> **トライアル終了は自動停止しない**：30日経過後、両プランとも**自動で無効化されません**。そのまま使用料が発生し続けます。「トライアルで試して、不要なら明示的に disable」までを運用に組み込んでください。RDS の Limitless Database 自動追加（1.2）も、トライアル終了済みなら即課金される点に注意です。

---

## 8. まとめ：RDS / Lambda Protection 本番チートシート

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

- **共通する性質**：どちらも **エージェントレス・インフラ変更ゼロ・コード変更ゼロ**で足せる検知層。GuardDuty が AWS 側から直接ログを取り込み、**ログ本体はあなたに渡らない**（自分でログ基盤を作らない）。ただし**従量課金**であり「無料」ではない。
- **RDS Protection（監視対象＝ログインアクティビティ）**：Aurora（MySQL/PostgreSQL 互換）・RDS for PostgreSQL/MySQL/MariaDB・Aurora PostgreSQL Limitless を対応。**エンジンの種類は確定、バージョンは公式の対応表で要確認**。**成功・失敗の両ログイン**を捕捉。**新規有効化・新規インスタンスは最大2週間の学習期間**があり、その間 `AnomalousBehavior.*`（ML 系）の finding は出ない（`MaliciousIPCaller`／`TorIPCaller` 系は学習不要）。
- **RDS finding 型（9種）**：`AnomalousBehavior.{SuccessfulLogin(Variable)/FailedLogin(Low)/SuccessfulBruteForce(High)}`、`MaliciousIPCaller.{SuccessfulLogin(High)/FailedLogin(Medium)}`、`Discovery:RDS/MaliciousIPCaller(Medium)`、`TorIPCaller.{SuccessfulLogin(High)/FailedLogin(Medium)}`、`Discovery:RDS/TorIPCaller(Medium)`。Resource Type は `RDSDBInstance` / `RDSLimitlessDB`。
- **RDS 対応**：成功ログイン系は**認証情報ローテーション＋監査ログ確認**。失敗・プローブ系は**プライベート VPC ＋ SG 制限**。根本対策は **IAM データベース認証**でパスワードを減らすこと。
- **Lambda Protection（監視対象＝ネットワーク活動）**：**全 Lambda 関数（VPC を使わない関数も含む）**のネットワーク活動を解析。**ENI 用に自分で VPC Flow Logs を張る必要はない**。**Lambda@Edge は対象外**。Resource Type は `Lambda`。
- **Lambda finding 型（7種）**：`Backdoor:Lambda/C&CActivity.B(High)`、`CryptoCurrency:Lambda/BitcoinTool.B(High)`、`Trojan:Lambda/BlackholeTraffic(Medium)`、`Trojan:Lambda/DropPoint(Medium)`、`UnauthorizedAccess:Lambda/MaliciousIPCaller.Custom(Medium)`、`UnauthorizedAccess:Lambda/TorClient(High)`、`UnauthorizedAccess:Lambda/TorRelay(High)`。
- **Lambda 対応**：想定外なら**関数は侵害された前提**で——**同時実行 0 で封じ込め → コード・依存レビュー → 秘密のローテーション**。正規のブロックチェーン処理は「型＋関数名」の2条件で抑制ルール。
- **有効化（Terraform）**：`aws_guardduty_detector_feature` の **`RDS_LOGIN_EVENTS`** / **`LAMBDA_NETWORK_LOGS`**。組織一括は `aws_guardduty_organization_configuration_feature` ＋ `auto_enable = "ALL"`。
- **自動対応**：EventBridge の **型 `prefix` ＋ `severity` 数値**で振り分け。**Lambda は同時実行 0 で取り消し可能な封じ込め**、**RDS は破壊的なので人間のレビューを挟む**。**at-least-once → 冪等必須**。finding フィールドは信頼しない入力＝サニタイズ。
- **コスト**：RDS は login activity 量、Lambda は処理 GB（スマートフィルタで部分集合）。**30日無料トライアル**で請求額を事前把握。**終了後も自動停止しない**。Lambda は将来 DNS 等へ拡張＝課金増の可能性（30日前通知あり）。

RDS Protection と Lambda Protection は、「有効化すれば守ってくれる箱」ではなく、**「①対応資産を見極めて足し（YAGNI）、②finding 型を正しく読み、③EventBridge → 冪等・スコープを絞った自動対応に繋ぐ」**ことで価値が出る検知層です。最大の魅力は——**コードもインフラも一切変えずに、DB ログイン異常とサーバーレスのネットワーク脅威を一層足せる**こと。最大のレバレッジは、検知そのものより **finding を安全な自動対応に変える配管**にあります。

私はマルチアカウントの[サーバーレス決済プラットフォーム](/case-studies/payment-platform-reliability)で IAM・可観測性・DR を横断実装し、**「正しさ」を運用の注意深さではなくコードの構造と冪等性で担保**してきました。RDS/Lambda Protection の導入も同じ思想で設計します——**①対応資産に合わせて最小コストで有効化し、②finding 型ごとに対応を分岐させ（RDS は人間レビュー、Lambda は取り消し可能な封じ込め）、③EventBridge → 冪等な自動対応で MTTR を縮める**。検知を「赤いダッシュボード」で終わらせず、運用に載る対応の仕組みまで作り切ります。

**「自社の Aurora/RDS と Lambda に、RDS Protection と Lambda Protection をどう設計し、どこまで自動対応を任せ、どうコストを抑えるか」——対応資産の棚卸しから Terraform 実装、EventBridge 自動対応、組織統制、誤検知チューニングまで、一人 ×生成AI（Claude Code）で速く・安全に伴走できます。** 要件の整理段階からでも、お気軽にご相談ください。

---

### 参考（公式ドキュメント）

- [GuardDuty RDS Protection](https://docs.aws.amazon.com/guardduty/latest/ug/rds-protection.html) — RDS Protection の定義・対応エンジン表・ログインアクティビティ・最大2週間の学習期間・30日無料トライアル・Limitless 自動追加
- [RDS Protection finding types](https://docs.aws.amazon.com/guardduty/latest/ug/findings-rds-protection.html) — 9種の finding 型・重大度・remediation（Resource Type `RDSDBInstance` / `RDSLimitlessDB`）
- [GuardDuty Lambda Protection](https://docs.aws.amazon.com/guardduty/latest/ug/lambda-protection.html) — 全関数（非VPC含む）のネットワーク活動監視・ENI フローログ不要・Lambda@Edge 除外・スマートフィルタ課金・30日無料トライアル
- [Lambda Protection finding types](https://docs.aws.amazon.com/guardduty/latest/ug/lambda-protection-finding-types.html) — 7種の finding 型・重大度・remediation（Resource Type `Lambda`）
- [Amazon GuardDuty pricing](https://aws.amazon.com/guardduty/pricing/) — RDS Protection / Lambda Protection の従量課金・リージョン別・30日無料トライアル
