![【Security Hub CSPM修復手順】 [RDS.46] RDS DB インスタンスは、インターネットゲートウェイへのルートを持つパブリックサブネットにデプロイすべきではありません](https://devio2024-media.developers.io/image/upload/f_auto,q_auto,w_3840/f_auto,q_auto/v1790871196/eyecatch/wr309ednrjrbdx9mtsnl.png)
【Security Hub CSPM修復手順】 [RDS.46] RDS DB インスタンスは、インターネットゲートウェイへのルートを持つパブリックサブネットにデプロイすべきではありません
こんにちは、クラスメソッドオペレーションズの watabo です。
今回は、Security Hub CSPM のコントロール [RDS.46] RDS DB instances should not be deployed in public subnets with routes to internet gateways への対処方法を紹介します。
本記事は Security Hub CSPM で「AWS基礎セキュリティのベストプラクティススタンダード」を利用されている方向けの内容となります。
AWS Security Hubの詳細についてはこちらのブログをご覧ください。
対象コントロールの説明
[RDS.46] RDS DB インスタンスは、インターネットゲートウェイへのルートを持つパブリックサブネットにデプロイすべきではありません
このコントロールは、RDS DBインスタンスがインターネットゲートウェイへのルートを持つサブネットに配置されているかチェックします。
DBインスタンスが配置されたサブネットのルートテーブルに、送信先が0.0.0.0/0または::/0でインターネットゲートウェイ宛のルートが存在する場合、このコントロールはFAILEDになります。
DBインスタンスをプライベートサブネット(インターネットゲートウェイへのルートを持たないサブネット)に配置することで、このコントロールはPASSEDになります。
DBインスタンスがインターネットゲートウェイへのルートを持つサブネットに配置されている場合、セキュリティグループの設定次第でパブリックインターネットから直接アクセスできる状態になり得ます。
セキュリティグループの設定ミスや変更によって意図せずパブリックアクセスが許可されると、不正アクセスやデータ流出のリスクにつながります。
ネットワーク層でアクセス経路を断つと、アプリケーション層の設定不備があっても、被害を防げる可能性が高まります。
そのため、本コントロールへの対応を推奨します。
検証環境
今回は、次の環境で実際に手順を試しました。
- リージョン:東京リージョン(ap-northeast-1)
- DBエンジン:RDS for MySQL 8.0.46(db.t4g.micro)
- 開始時の構成:シングルAZ、パブリックアクセス不可、パブリックサブネットに配置
- DBサブネットグループ:パブリックサブネット2つ(1a、1c)で構成
Step 3 でパブリックサブネットを削除せずに Step 4 へ進んだ場合と、削除してから進んだ場合の両方で、スタンバイの配置先を確認しました。
検知条件の詳細
検出結果は、AWS Configのマネージドルールrds-instance-subnet-igw-checkの評価結果にもとづいて出力されます。
本記事では、このルールの評価結果(COMPLIANTまたはNON_COMPLIANT)も確認しました。
この検知条件は、サブネットのルートテーブルのみで判定されます。
DBインスタンスの「パブリックアクセス可能」設定を無効にしていても、配置先のサブネットにインターネットゲートウェイへのルートが存在する限り、このコントロールはFAILEDのままです。
実際に、パブリックアクセス不可のDBインスタンスでも、Security HubでFAILEDと表示されました。
また、DBインスタンスの配置先がプライベートサブネットに移っても、DBサブネットグループにパブリックサブネットが残っている間は、Configルールの評価結果がNON_COMPLIANTのままでした(Step 7 で確認します)。
修復手順
コントロールの確認方法
- Security Hubコンソールを開く
- 左メニューから「コントロール」を選択
- フィルターで「ID」に「RDS.46」を入力して検索する
- 「RDS.46」のリンクをクリックし、コントロールの詳細を確認する
検出結果の一覧に、インターネットゲートウェイへのルートを持つサブネットに配置されているDBインスタンスのリソース名が表示されます。

ステークホルダーに確認
修復を行う前に、以下の点をステークホルダーに確認してください。
- 対象のDBインスタンスに接続しているアプリケーションやクライアントの接続元(VPC内、オンプレミス、インターネット経由など)を把握しているか
- DBインスタンスをパブリックサブネットからプライベートサブネットに移行するにあたり、プライベートサブネットが用意されているか(同一VPC内に2つ以上のアベイラビリティゾーンでプライベートサブネットが必要)
- インターネット経由で直接DBインスタンスに接続しているクライアントが存在する場合、VPN、Direct Connect、踏み台サーバーなど、移行後の代替接続経路を確保できるか
- 移行後にDBインスタンスのプライベートIPアドレスが変わる可能性があるため、接続文字列やDNS名での接続に統一されているか
同一VPC内でのサブネットグループ切り替えはできない
RDSのDBインスタンスは、同一VPC内で別のDBサブネットグループへ切り替えられません。
DBインスタンスの変更画面で、プライベートサブネットだけのDBサブネットグループへの切り替えを試したところ、次のエラーになりました。
You cannot move DB instance sh-test-rds-46-db to subnet group sh-test-rds-46-private-sg. The specified DB subnet group and DB instance are in the same VPC. Choose a DB subnet group in different VPC than the specified DB instance and try again.
AWSのナレッジセンター (re:Post) の記事にも、同じ制約が書かれています。
その記事で紹介されている回避策は、次の流れです。
- 既存のDBサブネットグループにプライベートサブネットを追加する
- Multi-AZフェイルオーバーで、プライベートサブネットへ移行する
- パブリックサブネットを取り除く
以下の修復手順は、この回避策を実際に試し、分かったことを加えたものです。
フェイルオーバーの発生時には、短時間の接続断が生じます。
修復手順の流れ
| Step | 内容 | 目的 |
|---|---|---|
| 1 | Multi-AZ配置とパブリックアクセスを無効化する | 元がマルチAZの場合のみ。パブリックサブネット側のスタンバイをなくす |
| 2 | 現在のプライマリのサブネットを特定する | 現状の把握 |
| 3 | DBサブネットグループにプライベートサブネットを追加し、プライマリが使用しているもの以外のパブリックサブネットを削除する | 移行先を用意し、スタンバイがプライベートサブネットに作られるようにする |
| 4 | Multi-AZ配置を有効化する | プライベートサブネット側にスタンバイを作る |
| 5 | フェイルオーバーを実行する | プライベートサブネット側をプライマリにする |
| 6 | Multi-AZ配置を無効化する | パブリックサブネットに残ったスタンバイをなくす |
| 7 | パブリックサブネットをDBサブネットグループから削除する | コントロールをPASSEDにする |
| 8 | Multi-AZ配置を再有効化する | 元がマルチAZの場合のみ |
各Stepの操作
Step 1: Multi-AZ配置とパブリックアクセスを無効化する
すでにシングルAZ構成で、パブリックアクセスが無効になっている場合はこの手順をスキップしてください(Step 2 へ進んでください)。
元がマルチAZ構成の場合、スタンバイインスタンスはパブリックサブネットにいます。
Step 4 でスタンバイをプライベートサブネットに作り直すため、ここでいったんマルチAZ配置を無効にします。
AWSのナレッジセンターの手順は、DBインスタンスを非公開にすることも目的としているため、パブリックアクセスもあわせて無効にします。
パブリックアクセス可能の設定は、RDS.46 の判定には影響しません。
- RDSコンソールを開く
- 左メニューから「データベース」を選択し、対象のDBインスタンスを選択する
- 右上の「変更」をクリックする

- 「可用性と耐久性」セクションで「マルチAZ配置」を「スタンバイインスタンスを作成しないでください」に変更する

- 「接続」セクションで「パブリックアクセス可能」を「パブリックアクセス不可」に変更する

- 画面下部で「続行」→「すぐに適用」を選択し、「DBインスタンスの変更」をクリックする
変更中は、DBインスタンスのステータスが「変更中」になります。
Step 2: 現在のプライマリインスタンスが使用しているサブネットを特定する
DBインスタンスのエンドポイントに対してdigコマンドを実行し、DNS名が解決される先のIPアドレスからサブネットを特定します。
パブリックアクセスが有効なDBインスタンスでは、VPCの外から実行すると公開IPアドレスが返ります。
パブリックアクセスが無効であれば、プライベートIPアドレスが返ります。
このコマンドは、Step 5 の後でも、プライマリの位置を確認するために使います。
dig +short <DBインスタンスのエンドポイント>
Windows の場合はnslookupになります。
nslookup <DBインスタンスのエンドポイント>
出力されたIPアドレスと、既存のDBサブネットグループに登録されている各サブネットのCIDRブロックを比較し、プライマリインスタンスが使用しているサブネットを確認してください。
Step 3: DBサブネットグループにプライベートサブネットを追加し、不要なパブリックサブネットを削除する
プライベートサブネットを追加します。
あわせて、Step 2 で特定した、プライマリが使用しているサブネット以外のパブリックサブネットを、グループから削除します。
プライマリが使用中のサブネットは、削除できません。
- RDSコンソールの左メニューから「サブネットグループ」を選択する
- 対象のDBサブネットグループを選択し、「編集」をクリックする

- 「サブネットの追加」セクションで、追加したいアベイラビリティゾーンとプライベートサブネット(インターネットゲートウェイへのルートを持たないもの)を選択する
- グループ内のサブネットのうち、プライマリが使用しているもの以外のパブリックサブネットを選択解除する

- 「保存」をクリックする
この時点で、グループは、プライマリが使用しているパブリックサブネットと、プライベートサブネットだけで構成されます。
他のパブリックサブネットを削除する理由は、Step 4 のスタンバイの配置先を、プライベートサブネットだけに絞るためです。
今回の検証では、パブリックサブネットを残したまま Step 4 に進んだところ、同じ構成で2回試して、1回目はプライベートサブネット、2回目はパブリックサブネットにスタンバイが作成されました。
AWSドキュメントには、配置先の選ばれ方の記載がありません。
Step 4: マルチAZ配置を有効化する
元がシングルAZ、マルチAZのどちらの場合も、この手順は必要です。
Step 5 のフェイルオーバーで、プライベートサブネット側へ切り替えるために、スタンバイインスタンスを作成します。
- 対象のDBインスタンスの詳細画面で「変更」をクリックする
- 「可用性と耐久性」セクションで「マルチAZ配置」を「スタンバイインスタンスを作成する」に変更する
- 「すぐに適用」を選択し、「DBインスタンスの変更」をクリックする
今回の環境では、変更が完了するまで10分前後(長いときは30分前後)かかりました。
スタンバイインスタンスは、プライマリとは別のアベイラビリティゾーンに作成されます。
Step 3 でパブリックサブネットを削除してあれば、そのAZにはプライベートサブネットしか残っていないため、スタンバイはプライベートサブネットに作成されます。
フェイルオーバーの前に、スタンバイインスタンスのサブネットを次の手順で確認してください。
- EC2コンソールの左メニューから「ネットワークインターフェイス」を選択する
- フィルターで、説明が「RDSNetworkInterface」で、DBインスタンスと同じVPCのものを探す
- プライマリとスタンバイの、それぞれのサブネットIDを確認する

スタンバイがパブリックサブネットに作成されていた場合は、フェイルオーバーしてもプライマリはプライベートサブネットに移りません。
この場合は、マルチAZ配置を無効にしてスタンバイを削除し、そのAZのパブリックサブネットをDBサブネットグループから削除してから、もう一度マルチAZ配置を有効にします。
今回の検証では、この方法でスタンバイがプライベートサブネットに作成されました。
Step 5: フェイルオーバーを実行してプライベートサブネット側に切り替える
- 対象のDBインスタンスを選択し、「アクション」→「再起動」をクリックする

- 「フェイルオーバーで再起動しますか?」で「はい」を選択して再起動する

フェイルオーバー完了後、それまでのセカンダリインスタンス(プライベートサブネット側)がプライマリに切り替わります。
RDSのイベントで確認した、フェイルオーバーの開始から完了までの時間は、2回の検証で30秒から45秒ほどでした。
プライマリの位置は、Step 2 のdigコマンドで確認できます。
エンドポイントが、プライベートサブネットのIPアドレスに解決されれば、切り替えは完了です。
なお、AWS CLIのdescribe-db-instancesが示すAZは、フェイルオーバー完了の直後には更新されていませんでした。
プライマリの確認には、digの結果を使うのが確実です。
Step 6: Multi-AZ配置を無効化する
フェイルオーバーでは、プライマリとスタンバイの役割が入れ替わるだけで、インスタンスの場所は変わりません。
それまでのプライマリは、パブリックサブネットに配置されたまま、スタンバイになっています。
この状態で、Step 7 のようにパブリックサブネットをDBサブネットグループから削除しようとすると、次のエラーになりました。
Some of the subnets to be deleted are currently in use: subnet-xxxxxxxxxxxxxxxxx
そこで、マルチAZ配置を無効にして、パブリックサブネット側のスタンバイを削除します。
- 対象のDBインスタンスの詳細画面で「変更」をクリックする
- 「可用性と耐久性」セクションで「マルチAZ配置」を「スタンバイインスタンスを作成しないでください」に変更する
- 「すぐに適用」を選択し、「DBインスタンスの変更」をクリックする
今回の環境では、完了まで数分かかりました。
Step 7: パブリックサブネットをDBサブネットグループから削除する
- RDSコンソールの左メニューから「サブネットグループ」を選択し、対象のサブネットグループを選択する
- 「編集」をクリックし、残っているパブリックサブネットを選択解除する
- 「保存」をクリックする
これで、DBサブネットグループにはプライベートサブネットのみが登録された状態になります。
今回の検証では、Configルール(rds-instance-subnet-igw-check)の評価結果が、次のように変わりました。
| タイミング | DBインスタンスの位置 | DBサブネットグループ | 評価結果 |
|---|---|---|---|
| 開始時 | パブリックサブネット | パブリック+プライベート | NON_COMPLIANT |
| Step 5 の後 | プライマリはプライベート、スタンバイはパブリック | パブリック+プライベート | NON_COMPLIANT |
| Step 6 の後 | プライベート(シングルAZ) | パブリック+プライベート | NON_COMPLIANT |
| Step 7 の後 | プライベート(シングルAZ) | プライベートのみ | COMPLIANT |
DBインスタンスが実際にプライベートサブネットだけにいても、DBサブネットグループにパブリックサブネットが残っている間は、NON_COMPLIANTのままでした。
この挙動は、AWSドキュメントに記載がありません。
上の表は、今回の環境で観測した結果です。
Step 8: マルチAZ配置を再有効化する
元がマルチAZ構成だった場合は、マルチAZ配置を「スタンバイインスタンスを作成する」に戻してください。
DBサブネットグループにはプライベートサブネットだけが残っているため、スタンバイもプライベートサブネットに作成されます。
元がシングルAZ構成だった場合は、この手順は不要です。
Step 6 でシングルAZ構成に戻っています。
修復確認
修復後、Security Hubで検出結果が「PASSED」になることを確認します。
- Security Hubコンソールを開く
- 左メニューから「コントロール」を選択
- フィルターで「ID」に「RDS.46」を入力して検索する
- 「RDS.46」のリンクをクリックし、コントロールの詳細を確認する

注意:RDS.46はスケジュールタイプが「定期的(Periodic)」のため、設定変更後すぐには検出結果に反映されません。
定期的なチェックは、前回の実行から12時間または24時間以内に自動で実行されます。
実行間隔は変更できません。
参考:
最後に
他のコントロールに比べるとやや手順が煩雑ですが、パブリックアクセスを封じる目的からすると意義は大きいと考えます。
コントロールを修正して、お使いのAWS環境のセキュリティスコアの改善につなげましょう。
本エントリがどなたかの助けになれば幸いです。






