SSM Block Public Sharing
カスタム SCP の説明
背景: SSM ドキュメントのパブリック共有と Block Public Sharing 設定
AWS Systems Manager(SSM)ドキュメントは、ssm:ModifyDocumentPermission API を使って他の AWS アカウントと共有できる。共有先に all を指定すると、世界中の任意の AWS アカウントから参照できるパブリック共有状態となる。SSM ドキュメントには Lambda 関数の値や API トークン等の機密情報が含まれていることがあり、誤ってパブリック共有された場合の影響は大きい。
これを防ぐため、SSM はアカウント・リージョン単位で Block Public Sharing(以下 BPA)という設定を提供している。BPA を有効化すると、ssm:ModifyDocumentPermission で all を指定する操作が API レベルで拒否され、新規のパブリック共有を防げる。
BPA 設定は SSM の Service Setting として管理されており、設定 ID は /ssm/documents/console/public-sharing-permission、設定値は Enable(パブリック共有を許可、つまり BPA 無効)または Disable(パブリック共有をブロック、つまり BPA 有効)の 2 値を取る(公式ドキュメント)。
設定値の名前と意味が反転している点に注意が必要。詳細は SSM.7 を参照。
Security Hub CSPM SSM.7 との関係
Security Hub CSPM の SSM.7 は、このアカウント・リージョン単位の BPA 設定が有効か(Disable になっているか)をチェックするコントロールである。AWS のデフォルトでは BPA は無効(Enable)であり、SSM.7 は新規アカウントで FAILED となる。
このカスタム SCP の役割
組織として「BPA を有効化した状態を維持したい」場合、メンバーアカウントの管理者が誤って(または意図的に)BPA を無効化する操作(update-service-setting --setting-value Enable)を防ぐ必要がある。Control Tower の標準予防コントロールには SSM BPA 設定変更を制御するものが存在しないため、カスタム SCP で対応する。
本記事のカスタム SCP は、ssm:UpdateServiceSetting API を SSM BPA 設定の ARN(servicesetting/ssm/documents/console/public-sharing-permission)に対して Deny する。これにより、メンバーアカウント側で SSM BPA 設定が変更(無効化)されることを防げる。
適用順序の注意
SSM.7 はデフォルトで FAILED(BPA 無効)の状態で開始するため、本 SCP を適用する前に各アカウント・各 Region で update-service-setting --setting-value Disable を実行して BPA を有効化しておく必要がある。
SCP を先に適用してしまうと、update-service-setting 自体が Deny されるため、BPA を有効化することができなくなる(FAILED のまま固定される)。本検証はこの「BPA 有効化 → SCP 適用」の正しい順序を前提とする。
SCP の内容
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenySSMDocumentPublicSharingChanges",
"Effect": "Deny",
"Action": [
"ssm:UpdateServiceSetting"
],
"Resource": "arn:aws:ssm:*:*:servicesetting/ssm/documents/console/public-sharing-permission"
}
]
}Resource で SSM Block Public Sharing 設定の ARN(servicesetting/ssm/documents/console/public-sharing-permission)に絞り込んでいるため、他の ssm:UpdateServiceSetting 操作(Parameter Store の高スループットモード切り替え等)には影響しない。
検証環境
本記事のコマンドは、--profile 指定がない場合は Workload アカウントで実行する。Master アカウントでの操作には --profile Master を指定する。事前に export AWS_PROFILE=Workload でデフォルトを設定しておくと便利。
検証の流れ
flowchart LR
A[1. 事前準備<br>BPA 有効化<br>SSM.7 PASSED 確認] --> B[2. SCP 適用前<br>BPA 設定変更が成功]
B --> C[3. BPA 再有効化]
C --> D[4. SCP 作成]
D --> E[5. OU にアタッチ]
E --> F[6. BPA 設定変更が<br>Deny されることを確認]
F --> G[7. 別の SSM 設定変更が<br>影響を受けないことを確認]
G --> H[8. SCP デタッチ]
H --> I[9. BPA 設定変更が再び成功<br>SSM.7 FAILED 復帰確認]
I --> J[10. クリーンアップ]
結果
- SCP 適用前は、メンバーアカウントの管理者が
update-service-settingで SSM Block Public Sharing 設定を変更できることを確認できた - BPA 有効化後、Security Hub SSM.7 が PASSED になることを確認できた(検証の前提条件成立)
- SCP 適用後、メンバーアカウントの管理者が SSM Block Public Sharing 設定を変更しようとすると
AccessDeniedExceptionで拒否されることを確認できた。エラーメッセージにexplicit deny in a service control policyが含まれることから、SCP による拒否であることを確認できた - SCP の
Resourceで SSM Block Public Sharing 設定の ARN に絞り込んでいるため、他のssm:UpdateServiceSetting操作(Parameter Store の高スループットモード切り替え等)には影響しないことを確認できた - SCP デタッチ後は再び BPA 設定を変更できることを確認できた。
Enableに戻した後 SSM.7 が FAILED に戻ることも確認した(検証中に SCP 以外の要因で SSM.7 が変動していないことの裏取り)
1. 事前準備(BPA 有効化)
SCP を適用する前に、Workload アカウントで SSM Block Public Sharing を有効化(Disable に設定)する。これを忘れると、SCP 適用後に有効化できなくなる。
現状確認
aws ssm get-service-setting \
--setting-id /ssm/documents/console/public-sharing-permission \
--query 'ServiceSetting.{SettingValue:SettingValue,Status:Status}' \
--region ap-northeast-1{
"SettingValue": "Enable",
"Status": "Default"
}Enable の場合、Block Public Sharing は無効(パブリック共有を許可している状態)。Status は初期状態では Default、過去に手動変更された環境では Customized になる。いずれの場合も SettingValue: Enable であれば本検証の前提条件を満たす。
BPA を有効化(Disable に設定)
aws ssm update-service-setting \
--setting-id /ssm/documents/console/public-sharing-permission \
--setting-value Disable \
--region ap-northeast-1(出力なし)設定値を確認
aws ssm get-service-setting \
--setting-id /ssm/documents/console/public-sharing-permission \
--query 'ServiceSetting.{SettingValue:SettingValue,Status:Status}' \
--region ap-northeast-1{
"SettingValue": "Disable",
"Status": "Customized"
}SettingValue: Disable、Status: Customized であれば Block Public Sharing が有効化された状態。
Security Hub SSM.7 finding 確認(PASSED であること)
本検証の前提として「BPA 有効化済み = SSM.7 PASSED」が成立していることを確認する。Config ルールを手動トリガーして即座に評価させる。
まず Config ルール名のサフィックスを確認する。
aws configservice describe-config-rules \
--query 'ConfigRules[?contains(ConfigRuleName,`ssm-automation-block-public-sharing`)].ConfigRuleName' \
--output text \
--region ap-northeast-1securityhub-ssm-automation-block-public-sharing-<サフィックス>aws configservice start-config-rules-evaluation \
--config-rule-names securityhub-ssm-automation-block-public-sharing-<サフィックス> \
--region ap-northeast-1(出力なし)1〜2 分待ってから評価結果を確認する。ResourceId はアカウント ID(数字のみ)のため、JMESPath フィルタではシングルクォートで囲む。
sleep 90
aws configservice get-compliance-details-by-config-rule \
--config-rule-name securityhub-ssm-automation-block-public-sharing-<サフィックス> \
--query "EvaluationResults[?EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId=='<アカウント ID>'].{ResourceId:EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId,ComplianceType:ComplianceType,ResultRecordedTime:ResultRecordedTime}" \
--region ap-northeast-1[
{
"ResourceId": "<アカウント ID>",
"ComplianceType": "COMPLIANT",
"ResultRecordedTime": "<評価時刻>"
}
]Security Hub への反映を待ってから finding を確認する。
sleep 120
aws securityhub get-findings \
--filters '{
"ComplianceSecurityControlId": [{"Comparison": "EQUALS", "Value": "SSM.7"}],
"AwsAccountId": [{"Comparison": "EQUALS", "Value": "<アカウント ID>"}],
"ResourceId": [{"Comparison": "EQUALS", "Value": "AWS::::Account:<アカウント ID>"}],
"RecordState": [{"Comparison": "EQUALS", "Value": "ACTIVE"}]
}' \
--query 'Findings[].{Status:Compliance.Status,ResourceId:Resources[0].Id,UpdatedAt:UpdatedAt}' \
--region ap-northeast-1[
{
"Status": "PASSED",
"ResourceId": "AWS::::Account:<アカウント ID>",
"UpdatedAt": "<更新時刻>"
}
]SSM.7 が PASSED であることを確認できた。古い finding が残っている場合は複数件返ることがあるが、最新の UpdatedAt のものが現在の状態を示す。これで検証の前提条件が成立した。
2. SCP 適用前のベースライン確認
メンバーアカウントの管理者として、BPA 設定が変更可能であることを確認する。一度 Enable に戻して、再度 Disable に設定し直す。
Enable に変更
aws ssm update-service-setting \
--setting-id /ssm/documents/console/public-sharing-permission \
--setting-value Enable \
--region ap-northeast-1(出力なし)設定値を確認
aws ssm get-service-setting \
--setting-id /ssm/documents/console/public-sharing-permission \
--query 'ServiceSetting.{SettingValue:SettingValue,Status:Status}' \
--region ap-northeast-1{
"SettingValue": "Enable",
"Status": "Customized"
}SCP 適用前は変更が成功する。
3. BPA 再有効化
SCP 適用後に BPA を有効化できなくなるため、ここで再度 Disable に戻す。
aws ssm update-service-setting \
--setting-id /ssm/documents/console/public-sharing-permission \
--setting-value Disable \
--region ap-northeast-1(出力なし)aws ssm get-service-setting \
--setting-id /ssm/documents/console/public-sharing-permission \
--query 'ServiceSetting.{SettingValue:SettingValue,Status:Status}' \
--region ap-northeast-1{
"SettingValue": "Disable",
"Status": "Customized"
}4. カスタム SCP 作成
Master アカウントで SCP を作成する。
ポリシー JSON ファイル作成
cat > /tmp/scp-ssm-block-public-sharing.json <<'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenySSMDocumentPublicSharingChanges",
"Effect": "Deny",
"Action": [
"ssm:UpdateServiceSetting"
],
"Resource": "arn:aws:ssm:*:*:servicesetting/ssm/documents/console/public-sharing-permission"
}
]
}
EOFSCP 作成
aws organizations create-policy \
--name DenySSMBlockPublicSharingChanges \
--description "Deny changes to SSM Block Public Sharing setting" \
--type SERVICE_CONTROL_POLICY \
--content file:///tmp/scp-ssm-block-public-sharing.json \
--query 'Policy.PolicySummary.{Id:Id,Name:Name,Type:Type}' \
--profile Master{
"Id": "<ポリシー ID>",
"Name": "DenySSMBlockPublicSharingChanges",
"Type": "SERVICE_CONTROL_POLICY"
}5. OU にアタッチ
Workload アカウントが所属する OU に SCP をアタッチする。
aws organizations attach-policy \
--policy-id <ポリシー ID> \
--target-id <OU ID> \
--profile Master(出力なし)アタッチを確認
aws organizations list-policies-for-target \
--target-id <OU ID> \
--filter SERVICE_CONTROL_POLICY \
--query 'Policies[?Name==`DenySSMBlockPublicSharingChanges`]' \
--profile Master[
{
"Id": "<ポリシー ID>",
"Arn": "arn:aws:organizations::<Master アカウント ID>:policy/o-<組織 ID>/service_control_policy/<ポリシー ID>",
"Name": "DenySSMBlockPublicSharingChanges",
"Description": "Deny changes to SSM Block Public Sharing setting",
"Type": "SERVICE_CONTROL_POLICY",
"AwsManaged": false
}
]SCP の適用には数秒〜数十秒のラグがある。
6. BPA 設定変更が Deny されることを確認
Workload アカウントから BPA 設定を変更しようとして、Deny されることを確認する。
Enable に戻そうとする → Deny
aws ssm update-service-setting \
--setting-id /ssm/documents/console/public-sharing-permission \
--setting-value Enable \
--region ap-northeast-1 2>&1An error occurred (AccessDeniedException) when calling the UpdateServiceSetting operation: User: arn:aws:sts::<Workload アカウント ID>:assumed-role/<ロール名>/<セッション名> is not authorized to perform: ssm:UpdateServiceSetting on resource: arn:aws:ssm:ap-northeast-1:<Workload アカウント ID>:servicesetting/ssm/documents/console/public-sharing-permission with an explicit deny in a service control policy: arn:aws:organizations::<Master アカウント ID>:policy/o-<組織 ID>/service_control_policy/<ポリシー ID>explicit deny in a service control policy というメッセージが含まれることから、SCP による拒否であることを確認できる。
設定値が変わっていないことを確認
aws ssm get-service-setting \
--setting-id /ssm/documents/console/public-sharing-permission \
--query 'ServiceSetting.{SettingValue:SettingValue,Status:Status}' \
--region ap-northeast-1{
"SettingValue": "Disable",
"Status": "Customized"
}設定値は Disable のまま維持されている。
7. 別の SSM 設定変更が影響を受けないことを確認
SCP の Resource で SSM Block Public Sharing 設定の ARN に絞り込んでいるため、他の ssm:UpdateServiceSetting 操作には影響しないことを確認する。Parameter Store の高スループットモード設定(/ssm/parameter-store/high-throughput-enabled)を例に試す。
現状確認
aws ssm get-service-setting \
--setting-id /ssm/parameter-store/high-throughput-enabled \
--query 'ServiceSetting.{SettingValue:SettingValue,Status:Status}' \
--region ap-northeast-1{
"SettingValue": "false",
"Status": "Default"
}true に変更(SCP に阻まれず成功するはず)
aws ssm update-service-setting \
--setting-id /ssm/parameter-store/high-throughput-enabled \
--setting-value true \
--region ap-northeast-1(出力なし)設定値を確認
aws ssm get-service-setting \
--setting-id /ssm/parameter-store/high-throughput-enabled \
--query 'ServiceSetting.{SettingValue:SettingValue,Status:Status}' \
--region ap-northeast-1{
"SettingValue": "true",
"Status": "Customized"
}SCP の対象外であるため変更が成功する。
元に戻す
aws ssm update-service-setting \
--setting-id /ssm/parameter-store/high-throughput-enabled \
--setting-value false \
--region ap-northeast-1(出力なし)8. SCP デタッチ
aws organizations detach-policy \
--policy-id <ポリシー ID> \
--target-id <OU ID> \
--profile Master(出力なし)9. BPA 設定変更が再び成功することを確認
aws ssm update-service-setting \
--setting-id /ssm/documents/console/public-sharing-permission \
--setting-value Enable \
--region ap-northeast-1(出力なし)aws ssm get-service-setting \
--setting-id /ssm/documents/console/public-sharing-permission \
--query 'ServiceSetting.{SettingValue:SettingValue,Status:Status}' \
--region ap-northeast-1{
"SettingValue": "Enable",
"Status": "Customized"
}SCP デタッチ後は再び設定変更ができる。SCP のデタッチには数分のラグがある場合があるため、Deny が続く場合は数分待ってから再試行する。
Security Hub SSM.7 finding 確認(FAILED に戻ること)
Enable(BPA 無効)に戻したので、SSM.7 は FAILED に戻るはず。これを確認することで、検証中に SCP 以外の何かが SSM.7 の評価に影響していないことの証明になる。
aws configservice start-config-rules-evaluation \
--config-rule-names securityhub-ssm-automation-block-public-sharing-<サフィックス> \
--region ap-northeast-1(出力なし)sleep 90
aws configservice get-compliance-details-by-config-rule \
--config-rule-name securityhub-ssm-automation-block-public-sharing-<サフィックス> \
--query "EvaluationResults[?EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId=='<アカウント ID>'].{ResourceId:EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId,ComplianceType:ComplianceType,ResultRecordedTime:ResultRecordedTime}" \
--region ap-northeast-1[
{
"ResourceId": "<アカウント ID>",
"ComplianceType": "NON_COMPLIANT",
"ResultRecordedTime": "<評価時刻>"
}
]sleep 120
aws securityhub get-findings \
--filters '{
"ComplianceSecurityControlId": [{"Comparison": "EQUALS", "Value": "SSM.7"}],
"AwsAccountId": [{"Comparison": "EQUALS", "Value": "<アカウント ID>"}],
"ResourceId": [{"Comparison": "EQUALS", "Value": "AWS::::Account:<アカウント ID>"}],
"RecordState": [{"Comparison": "EQUALS", "Value": "ACTIVE"}]
}' \
--query 'Findings[].{Status:Compliance.Status,ResourceId:Resources[0].Id,UpdatedAt:UpdatedAt}' \
--region ap-northeast-1[
{
"Status": "FAILED",
"ResourceId": "AWS::::Account:<アカウント ID>",
"UpdatedAt": "<更新時刻>"
}
]SSM.7 が FAILED に戻った。SCP の効果が解除され、想定通りの状態になっていることを確認できた。
10. クリーンアップ
SCP 削除
aws organizations delete-policy \
--policy-id <ポリシー ID> \
--profile Master(出力なし)BPA 設定を Disable に戻す(任意)
検証で Enable に変更した SSM Block Public Sharing 設定を、本番環境で運用するつもりであれば Disable に戻しておく。
aws ssm update-service-setting \
--setting-id /ssm/documents/console/public-sharing-permission \
--setting-value Disable \
--region ap-northeast-1(出力なし)