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 → PASSED使用するランブック
AWSSupport-ModifyRDSSnapshotPermission(AWS マネージド)を使用する。RDS DB インスタンススナップショットのみ対応で、クラスタースナップショット(DocumentDB / Neptune)には別途カスタムランブックが必要。
| パラメータ | 型 | 役割 |
|---|---|---|
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 でデフォルトを設定しておくと便利。
検証の流れ
flowchart LR
A[1. 事前確認] --> B[2. 修復用 IAM ロール作成]
B --> C[3. EventBridge ルール作成]
C --> D[4. RDS インスタンス・<br>スナップショット作成]
D --> E[5. パブリック化<br>FAILED 検知]
E --> F[6. 自動修復実行確認]
F --> G[7. PASSED 復帰確認]
G --> H[8. クリーンアップ]
結果
| 検証項目 | 結果 |
|---|---|
| Security Hub finding(FAILED)から EventBridge へのトリガー | TBD |
| Input Transformer でスナップショット ID 抽出 | TBD |
| SSM Automation 起動と修復実行 | TBD |
| スナップショットのパブリック共有解除 | TBD |
| Config / Security Hub PASSED 復帰 | TBD |
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[]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": [
"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(出力なし)
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 ルール本体作成
Security Hub finding のうち、RDS.1 で FAILED のものをフィルタする。
cat <<'EOF' > /tmp/eventbridge-pattern.json
{
"source": ["aws.securityhub"],
"detail-type": ["Security Hub Findings - Imported"],
"detail": {
"findings": {
"Compliance": {
"SecurityControlId": ["RDS.1"],
"Status": ["FAILED"]
},
"Resources": {
"Type": ["AwsRdsDbSnapshot"]
}
}
}
}
EOF
aws events put-rule \
--name rds-1-auto-remediation \
--event-pattern file:///tmp/eventbridge-pattern.json \
--state ENABLED \
--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": []
}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
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
done5. パブリック化して 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"
]
}
]5.2 Security Hub finding が FAILED になることを確認
Security Hub への反映には数分かかる。
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].{Status:Compliance.Status,SnapshotId:Resources[0].Details.AwsRdsDbSnapshot.DbSnapshotIdentifier}' \
--output json{
"Status": "FAILED",
"SnapshotId": "rds1-remediation-snapshot"
}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 確認
RULE_NAME=$(aws configservice describe-config-rules \
--query "ConfigRules[?contains(ConfigRuleName, 'rds-snapshots-public-prohibited')].ConfigRuleName" \
--output text \
--region ap-northeast-1)
aws configservice start-config-rules-evaluation \
--config-rule-names $RULE_NAME \
--region ap-northeast-1
sleep 60
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].{Status:Compliance.Status,UpdatedAt:UpdatedAt}' \
--output json{
"Status": "PASSED",
"UpdatedAt": "<更新時刻>"
}8. クリーンアップ
# RDS スナップショット削除
aws rds delete-db-snapshot \
--db-snapshot-identifier rds1-remediation-snapshot \
--region ap-northeast-1
# RDS インスタンス削除
aws rds delete-db-instance \
--db-instance-identifier rds1-remediation-test \
--skip-final-snapshot \
--delete-automated-backups \
--region ap-northeast-1
# EventBridge ルール削除(ターゲットも削除)
aws events remove-targets \
--rule rds-1-auto-remediation \
--ids ssm-automation-target \
--region ap-northeast-1
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参考
- RDS.1 RDS スナップショットがプライベートであること - コントロール自体の検証
- 自動修復の概要 - 全コントロールの一覧と方針
- AWSSupport-ModifyRDSSnapshotPermission - SSM Automation ドキュメント