RDS.1
概要
RDS.1 は RDS DB インスタンススナップショットがパブリック化されている場合に FAILED となる Security Hub CSPM コントロール。本記事では、Security Hub finding を EventBridge でフィルタし、SSM Automation の AWSSupport-ModifyRDSSnapshotPermission を起動してスナップショットを自動的にプライベートに戻す構成を検証する。
自動修復の構成
RDS スナップショットがパブリック化(modify-db-snapshot-attribute --values-to-add all)
→ Config ルール securityhub-rds-snapshots-public-prohibited-<サフィックス> が NON_COMPLIANT
→ Security Hub finding RDS.1 が FAILED
→ EventBridge ルールが finding をフィルタ(Input Transformer でスナップショット ID 抽出)
→ SSM Automation AWSSupport-ModifyRDSSnapshotPermission を起動(Private=Yes)
→ modify-db-snapshot-attribute --values-to-remove all 実行
→ スナップショットがプライベートに戻る
→ Config 再評価 → COMPLIANT
→ Security Hub finding → PASSEDSecurity Hub Findings - Imported イベントは発行されないため、EventBridge の発火タイミングは「コンプライアンス状態の変化点」に限られる(実機検証で確認)。本番運用では新規パブリック化時の PASSED → FAILED 変化で発火するため問題にならないが、本記事の検証では FAILED finding の観測タイミングを確保するために EventBridge を一時的に DISABLED にしているため、後述のステップ 5.3〜5.6 で「PASSED → FAILED」の状態変化を意図的に起こしている。使用するランブック
AWSSupport-ModifyRDSSnapshotPermission(AWS マネージド)を使用する。RDS DB インスタンススナップショット(AwsRdsDbSnapshot)のみ対応で、Aurora / DocumentDB / Neptune のクラスタースナップショット(AwsRdsDbClusterSnapshot)には別途カスタムランブックが必要(DocumentDB.3 / Neptune.3 で対応予定)。
| パラメータ | 型 | 役割 |
|---|---|---|
SnapshotIdentifiers | StringList | 修復対象スナップショット ID(finding から抽出して渡す) |
Private | String | Yes 固定 |
AutomationAssumeRole | ARN | SSM Automation が rds:ModifyDBSnapshotAttribute を呼ぶための IAM ロール |
Security Hub finding 構造
Security Hub finding の Resources[0].Details.AwsRdsDbSnapshot.DbSnapshotIdentifier にスナップショット ID が ID 形式(ARN ではない)で含まれる。EventBridge Input Transformer で直接抽出可能。
{
"Resources": [{
"Type": "AwsRdsDbSnapshot",
"Id": "arn:aws:rds:<リージョン>:<アカウント ID>:snapshot:<スナップショット ID>",
"Details": {
"AwsRdsDbSnapshot": {
"DbSnapshotIdentifier": "<スナップショット ID>",
...
}
}
}]
}検証環境
本記事のコマンドは、--profile 指定がない場合は Workload アカウントで実行する。事前に export AWS_PROFILE=Workload でデフォルトを設定しておくと便利。
結果
| 検証項目 | 結果 |
|---|---|
| Security Hub finding(FAILED)から EventBridge へのトリガー | ✓ 状態変化(PASSED → FAILED)で発火確認 |
| Input Transformer でスナップショット ID 抽出 | ✓ Resources[0].Details.AwsRdsDbSnapshot.DbSnapshotIdentifier から取得 |
| SSM Automation 起動と修復実行 | ✓ Status: Success |
| スナップショットのパブリック共有解除 | ✓ restore 属性が空 |
| Config / Security Hub PASSED 復帰 | ✓ Compliance: PASSED, Workflow: RESOLVED |
実測時間:
- 設定変更 → Security Hub finding 反映: 約 3〜5 分(初回パブリック化時 5 分、再パブリック化時 3 分)
- finding 発行 → EventBridge 発火 → SSM Automation 実行完了: 約 19 秒
- 修復完了 → Security Hub PASSED 復帰: 約 2 分
検証の流れ
flowchart LR
A[1. 事前確認] --> B[2. 修復用 IAM ロール作成]
B --> C[3. EventBridge ルール作成<br>DISABLED 状態]
C --> D[4. RDS インスタンス・<br>スナップショット作成]
D --> E[5.1 パブリック化<br>5.2 FAILED 観測]
E --> F[5.3 プライベートに戻す<br>5.4 PASSED 観測]
F --> G[5.5 EventBridge 有効化<br>5.6 再パブリック化]
G --> H[6. 自動修復実行確認]
H --> I[7. PASSED 復帰確認]
I --> J[8. クリーンアップ]
1. 事前確認
Config ルールの存在確認
aws configservice describe-config-rules \
--query "ConfigRules[?contains(ConfigRuleName, 'rds-snapshots-public-prohibited')].ConfigRuleName" \
--output text \
--region ap-northeast-1securityhub-rds-snapshots-public-prohibited-<サフィックス>既存の EventBridge ルール確認
aws events list-rules \
--name-prefix "rds-1-auto-remediation" \
--region ap-northeast-1 \
--query 'Rules[].Name' \
--output json[]既存の IAM ロール確認
aws iam list-roles \
--query "Roles[?starts_with(RoleName, 'rds-1-')].RoleName" \
--output json[]過去の検証で残っているロールがあれば事前に削除する。
2. 修復用 IAM ロール作成
SSM Automation が rds:ModifyDBSnapshotAttribute を呼ぶための IAM ロールと、EventBridge が SSM Automation を起動するための IAM ロールの 2 つを作成する。
2.1 SSM Automation 実行ロール
cat <<'EOF' > /tmp/ssm-automation-trust.json
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "ssm.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}
EOF
aws iam create-role \
--role-name rds-1-automation-role \
--assume-role-policy-document file:///tmp/ssm-automation-trust.json \
--query 'Role.Arn' \
--output textarn:aws:iam::<アカウント ID>:role/rds-1-automation-rolecat <<'EOF' > /tmp/rds-snapshot-policy.json
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"ssm:StartAutomationExecution",
"ssm:GetAutomationExecution",
"rds:DescribeDBSnapshots",
"rds:DescribeDBSnapshotAttributes",
"rds:ModifyDBSnapshotAttribute"
],
"Resource": "*"
}]
}
EOF
aws iam put-role-policy \
--role-name rds-1-automation-role \
--policy-name rds-snapshot-permission \
--policy-document file:///tmp/rds-snapshot-policy.json(出力なし)
AWSSupport-ModifyRDSSnapshotPermission の AWS 公式ドキュメント に従い、AutomationAssumeRole には ssm:StartAutomationExecution / ssm:GetAutomationExecution も含めている。本検証ではこの構成で動作確認している。
なお、DocumentDB.3 / Neptune.3 で作成するカスタムランブック(aws:executeAwsApi で rds:ModifyDBClusterSnapshotAttribute を直接呼ぶ単純な構成)は rds:* のみで動作することを実機確認している。本ランブックは AWS マネージドで内部実装が不明のため、ssm:* を含めた構成で検証した結果をそのまま記載しているが、実際には rds:* のみで動作する可能性がある(未検証)。
2.2 EventBridge から SSM Automation 起動するロール
cat <<'EOF' > /tmp/eventbridge-trust.json
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "events.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}
EOF
aws iam create-role \
--role-name rds-1-eventbridge-role \
--assume-role-policy-document file:///tmp/eventbridge-trust.json \
--query 'Role.Arn' \
--output textarn:aws:iam::<アカウント ID>:role/rds-1-eventbridge-rolecat <<'EOF' > /tmp/eventbridge-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ssm:StartAutomationExecution",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::<アカウント ID>:role/rds-1-automation-role",
"Condition": {
"StringEquals": {
"iam:PassedToService": "ssm.amazonaws.com"
}
}
}
]
}
EOF
aws iam put-role-policy \
--role-name rds-1-eventbridge-role \
--policy-name eventbridge-ssm-automation \
--policy-document file:///tmp/eventbridge-policy.json(出力なし)
3. EventBridge ルール作成
3.1 ルール本体作成(DISABLED 状態)
Security Hub finding のうち、RDS.1 で FAILED かつ Workflow.Status が NEW のものをフィルタする。検証手順では FAILED finding の観測タイミングを確保するため、最初は DISABLED 状態で作成し、ステップ 5 で FAILED を観測した後に有効化する。
cat <<'EOF' > /tmp/eventbridge-pattern.json
{
"source": ["aws.securityhub"],
"detail-type": ["Security Hub Findings - Imported"],
"detail": {
"findings": {
"Compliance": {
"SecurityControlId": ["RDS.1"],
"Status": ["FAILED"]
},
"Workflow": {
"Status": ["NEW"]
},
"Resources": {
"Type": ["AwsRdsDbSnapshot"]
}
}
}
}
EOF
aws events put-rule \
--name rds-1-auto-remediation \
--event-pattern file:///tmp/eventbridge-pattern.json \
--state DISABLED \
--region ap-northeast-1 \
--query 'RuleArn' \
--output textarn:aws:events:ap-northeast-1:<アカウント ID>:rule/rds-1-auto-remediation3.2 ターゲット設定(Input Transformer 付き)
EVENTBRIDGE_ROLE_ARN=$(aws iam get-role \
--role-name rds-1-eventbridge-role \
--query 'Role.Arn' \
--output text)
AUTOMATION_ROLE_ARN=$(aws iam get-role \
--role-name rds-1-automation-role \
--query 'Role.Arn' \
--output text)
cat <<EOF > /tmp/eventbridge-target.json
[
{
"Id": "ssm-automation-target",
"Arn": "arn:aws:ssm:ap-northeast-1::automation-definition/AWSSupport-ModifyRDSSnapshotPermission:\$DEFAULT",
"RoleArn": "$EVENTBRIDGE_ROLE_ARN",
"InputTransformer": {
"InputPathsMap": {
"snapshotId": "\$.detail.findings[0].Resources[0].Details.AwsRdsDbSnapshot.DbSnapshotIdentifier"
},
"InputTemplate": "{\"SnapshotIdentifiers\": [\"<snapshotId>\"], \"Private\": [\"Yes\"], \"AutomationAssumeRole\": [\"$AUTOMATION_ROLE_ARN\"]}"
}
}
]
EOF
aws events put-targets \
--rule rds-1-auto-remediation \
--targets file:///tmp/eventbridge-target.json \
--region ap-northeast-1{
"FailedEntryCount": 0,
"FailedEntries": []
}automation-definition/AWSSupport-ModifyRDSSnapshotPermission:$DEFAULT で最新バージョンを参照している。本番運用では AWS によるランブック更新で挙動が変わるリスクを避けるため、特定バージョン(例: :1)に pin する選択肢もある。4. RDS インスタンス・スナップショット作成
4.1 RDS インスタンス作成
aws rds create-db-instance \
--db-instance-identifier rds1-remediation-test \
--db-instance-class db.t3.micro \
--engine mysql \
--master-username admin \
--master-user-password '<パスワード>' \
--allocated-storage 20 \
--no-publicly-accessible \
--db-subnet-group-name default \
--no-multi-az \
--backup-retention-period 0 \
--region ap-northeast-1 \
--query 'DBInstance.{DBInstanceIdentifier:DBInstanceIdentifier,Status:DBInstanceStatus}' \
--output json{
"DBInstanceIdentifier": "rds1-remediation-test",
"Status": "creating"
}available 待ち(約 5〜7 分)。
while true; do
STATUS=$(aws rds describe-db-instances \
--db-instance-identifier rds1-remediation-test \
--query 'DBInstances[0].DBInstanceStatus' \
--output text \
--region ap-northeast-1)
echo "$(date '+%H:%M:%S') status: $STATUS"
case "$STATUS" in
available) break ;;
failed) echo "失敗"; break ;;
*) sleep 60 ;;
esac
doneHH:MM:SS status: creating
(数分間 creating を繰り返す)
HH:MM:SS status: available4.2 スナップショット作成
aws rds create-db-snapshot \
--db-instance-identifier rds1-remediation-test \
--db-snapshot-identifier rds1-remediation-snapshot \
--region ap-northeast-1 \
--query 'DBSnapshot.{DBSnapshotIdentifier:DBSnapshotIdentifier,Status:Status}' \
--output json{
"DBSnapshotIdentifier": "rds1-remediation-snapshot",
"Status": "creating"
}available 待ち(約 3 分)。
while true; do
STATUS=$(aws rds describe-db-snapshots \
--db-snapshot-identifier rds1-remediation-snapshot \
--query 'DBSnapshots[0].Status' \
--output text \
--region ap-northeast-1)
echo "$(date '+%H:%M:%S') snapshot: $STATUS"
case "$STATUS" in
available) break ;;
failed) echo "失敗"; break ;;
*) sleep 30 ;;
esac
doneHH:MM:SS snapshot: creating
(数分間 creating を繰り返す)
HH:MM:SS snapshot: available5. FAILED 観測と自動修復の起動準備
5.1 スナップショットをパブリック化
aws rds modify-db-snapshot-attribute \
--db-snapshot-identifier rds1-remediation-snapshot \
--attribute-name restore \
--values-to-add all \
--region ap-northeast-1 \
--query 'DBSnapshotAttributesResult.DBSnapshotAttributes' \
--output json[
{
"AttributeName": "restore",
"AttributeValues": [
"all"
]
}
]describe-db-snapshot-attributes でも restore 属性に all が含まれるパブリック状態であることを確認する。修復後(ステップ 7.1)と比較する基準値となる。
aws rds describe-db-snapshot-attributes \
--db-snapshot-identifier rds1-remediation-snapshot \
--region ap-northeast-1 \
--query 'DBSnapshotAttributesResult.DBSnapshotAttributes' \
--output json[
{
"AttributeName": "restore",
"AttributeValues": [
"all"
]
}
]5.2 Security Hub finding が FAILED になることを確認
Security Hub への反映には数分かかる。Compliance.Status と Workflow.Status の両方を確認する(EventBridge フィルタは Workflow.Status: NEW を要求するため、NOTIFIED 等になっていると 5.3 でルールを有効化しても発火しない)。
sleep 300
aws securityhub get-findings \
--filters '{"ComplianceSecurityControlId":[{"Comparison":"EQUALS","Value":"RDS.1"}],"ComplianceStatus":[{"Comparison":"EQUALS","Value":"FAILED"}],"ResourceId":[{"Comparison":"PREFIX","Value":"arn:aws:rds:ap-northeast-1:<アカウント ID>:snapshot:rds1-remediation-snapshot"}]}' \
--region ap-northeast-1 \
--query 'Findings[0].{Compliance:Compliance.Status,Workflow:Workflow.Status,SnapshotId:Resources[0].Details.AwsRdsDbSnapshot.DbSnapshotIdentifier}' \
--output json{
"Compliance": "FAILED",
"Workflow": "NEW",
"SnapshotId": "rds1-remediation-snapshot"
}5.3 一度プライベートに戻して finding の状態を変化させる
Config 手動トリガーだけでは Security Hub finding の再 import が発火しない: 実機検証で確認した挙動。Config の start-config-rules-evaluation を実行しても、コンプライアンス状態が「FAILED → FAILED」で変わらない場合、Security Hub への新規 import イベントが発火しない。EventBridge は Security Hub Findings - Imported イベントを待つため、状態変化を起こす必要がある。
回避策として、一度プライベート化して PASSED に戻し、再度パブリック化することで「PASSED → FAILED」の状態変化を発生させ、新規 import イベントを起こす。
本番運用ではこの workaround は不要: EventBridge ルールが常時 ENABLED であれば、新規スナップショットがパブリック化された瞬間(初回の FAILED 検知時)に PASSED → FAILED 変化として発火する。本検証では FAILED finding を確実に観測するために EventBridge を DISABLED で作成して FAILED を発生させたため、後から ENABLED にしても既存 finding は再 import されず、状態変化を起こす必要が生じた。
スナップショットを一旦プライベートに戻す。
aws rds modify-db-snapshot-attribute \
--db-snapshot-identifier rds1-remediation-snapshot \
--attribute-name restore \
--values-to-remove all \
--region ap-northeast-1 \
--query 'DBSnapshotAttributesResult.DBSnapshotAttributes' \
--output json[
{
"AttributeName": "restore",
"AttributeValues": []
}
]5.4 PASSED を観測
Security Hub finding が PASSED に戻ることを確認する(約 5 分)。
sleep 300
aws securityhub get-findings \
--filters '{"ComplianceSecurityControlId":[{"Comparison":"EQUALS","Value":"RDS.1"}],"ResourceId":[{"Comparison":"PREFIX","Value":"arn:aws:rds:ap-northeast-1:<アカウント ID>:snapshot:rds1-remediation-snapshot"}]}' \
--region ap-northeast-1 \
--query 'Findings[0].{Compliance:Compliance.Status,Workflow:Workflow.Status}' \
--output json{
"Compliance": "PASSED",
"Workflow": "RESOLVED"
}Compliance: FAILED → PASSED への変化が Security Hub に反映され、Workflow.Status も自動的に NEW → RESOLVED に遷移する。
5.5 EventBridge ルールを有効化
aws events enable-rule \
--name rds-1-auto-remediation \
--region ap-northeast-1
aws events describe-rule \
--name rds-1-auto-remediation \
--region ap-northeast-1 \
--query 'State'"ENABLED"5.6 再度パブリック化(自動修復の起動)
aws rds modify-db-snapshot-attribute \
--db-snapshot-identifier rds1-remediation-snapshot \
--attribute-name restore \
--values-to-add all \
--region ap-northeast-1 \
--query 'DBSnapshotAttributesResult.DBSnapshotAttributes' \
--output json[
{
"AttributeName": "restore",
"AttributeValues": [
"all"
]
}
]Compliance: PASSED → FAILED の状態変化が発生し、Security Hub が新規 import イベントを発行する。EventBridge ルールが捕捉して SSM Automation を起動する。
6. 自動修復の実行確認
EventBridge が finding を捕捉して SSM Automation を起動するはず。SSM Automation の実行履歴を確認する。
sleep 60
aws ssm describe-automation-executions \
--filters Key=DocumentNamePrefix,Values=AWSSupport-ModifyRDSSnapshotPermission \
--max-results 5 \
--region ap-northeast-1 \
--query 'AutomationExecutionMetadataList[].{Status:AutomationExecutionStatus,ExecutionStartTime:ExecutionStartTime,ExecutionId:AutomationExecutionId}' \
--output json[
{
"Status": "Success",
"ExecutionStartTime": "<開始時刻>",
"ExecutionId": "<実行 ID>"
}
]7. PASSED 復帰確認
7.1 スナップショットがプライベートに戻ったことを確認
aws rds describe-db-snapshot-attributes \
--db-snapshot-identifier rds1-remediation-snapshot \
--region ap-northeast-1 \
--query 'DBSnapshotAttributesResult.DBSnapshotAttributes' \
--output json[
{
"AttributeName": "restore",
"AttributeValues": []
}
]restore 属性が空になっていれば、自動修復によりプライベートに戻った状態。
7.2 Config / Security Hub finding 確認
修復後、Security Hub finding が PASSED に戻ることを確認する。
sleep 120
aws securityhub get-findings \
--filters '{"ComplianceSecurityControlId":[{"Comparison":"EQUALS","Value":"RDS.1"}],"ResourceId":[{"Comparison":"PREFIX","Value":"arn:aws:rds:ap-northeast-1:<アカウント ID>:snapshot:rds1-remediation-snapshot"}]}' \
--region ap-northeast-1 \
--query 'Findings[0].{Compliance:Compliance.Status,Workflow:Workflow.Status,UpdatedAt:UpdatedAt}' \
--output json{
"Compliance": "PASSED",
"Workflow": "RESOLVED",
"UpdatedAt": "<更新時刻>"
}修復から約 2 分で Security Hub finding が PASSED に反映される。Workflow.Status も自動的に RESOLVED に遷移する。
8. クリーンアップ
RDS スナップショット削除
aws rds delete-db-snapshot \
--db-snapshot-identifier rds1-remediation-snapshot \
--region ap-northeast-1 \
--query 'DBSnapshot.{DBSnapshotIdentifier:DBSnapshotIdentifier,Status:Status}' \
--output json{
"DBSnapshotIdentifier": "rds1-remediation-snapshot",
"Status": "deleted"
}RDS インスタンス削除
aws rds delete-db-instance \
--db-instance-identifier rds1-remediation-test \
--skip-final-snapshot \
--delete-automated-backups \
--region ap-northeast-1 \
--query 'DBInstance.{DBInstanceIdentifier:DBInstanceIdentifier,Status:DBInstanceStatus}' \
--output json{
"DBInstanceIdentifier": "rds1-remediation-test",
"Status": "deleting"
}削除完了を確認する。
while true; do
COUNT=$(aws rds describe-db-instances \
--query "length(DBInstances[?DBInstanceIdentifier=='rds1-remediation-test'])" \
--output text \
--region ap-northeast-1 2>/dev/null || echo 0)
echo "$(date '+%H:%M:%S') 残存インスタンス数: $COUNT"
[ "$COUNT" = "0" ] && echo "削除完了" && break
sleep 60
doneHH:MM:SS 残存インスタンス数: 1
HH:MM:SS 残存インスタンス数: 0
削除完了EventBridge ルール削除
aws events remove-targets \
--rule rds-1-auto-remediation \
--ids ssm-automation-target \
--region ap-northeast-1 \
--query '{FailedEntryCount:FailedEntryCount,FailedEntries:FailedEntries}' \
--output json{
"FailedEntryCount": 0,
"FailedEntries": []
}aws events delete-rule \
--name rds-1-auto-remediation \
--region ap-northeast-1(出力なし)
IAM ロール削除
aws iam delete-role-policy \
--role-name rds-1-automation-role \
--policy-name rds-snapshot-permission
aws iam delete-role \
--role-name rds-1-automation-role
aws iam delete-role-policy \
--role-name rds-1-eventbridge-role \
--policy-name eventbridge-ssm-automation
aws iam delete-role \
--role-name rds-1-eventbridge-role(4 つとも出力なし)
aws iam list-roles \
--query "Roles[?starts_with(RoleName, 'rds-1-')].RoleName" \
--output json[]参考
- RDS.1 RDS スナップショットがプライベートであること - コントロール自体の検証
- 自動修復の概要 - 全コントロールの一覧と方針
- AWSSupport-ModifyRDSSnapshotPermission - SSM Automation ドキュメント