Block public sharing of SSM documents using CloudFormation StackSets to address Security Hub CSPM SSM.7 across all accounts
This page has been translated by machine translation. View original
Introduction
Hello everyone, this is Akaike.
Have you ever wanted to configure Security Hub CSPM control SSM.7 across all accounts at once? I have.
So this time, I'll summarize how to automatically deploy this setting to all AWS accounts using CloudFormation StackSets and address SSM.7.
About SSM.7
What SSM.7 requires is enabling the "block public sharing" setting for SSM documents.
This setting also needs to be configured individually for each region.
Due to the per-account and per-region nature of this setting, the cost of manual work grows as the number of targets increases.
It's also a hassle to configure this every time a new account is created.
So I wanted to use CloudFormation StackSets for bulk deployment, and by also using StackSets' automatic deployment for new accounts, free myself from having to manually configure this each time.
I Was Planning to Use AWS::SSM::ServiceSetting
SSM account-level settings can be configured using the CloudFormation resource AWS::SSM::ServiceSetting.
Internally, it appears to execute the UpdateServiceSetting API.
In other words, the following settings that can be configured with the UpdateServiceSetting API can be set using this resource.
- /ssm/appmanager/appmanager-enabled
- /ssm/automation/customer-script-log-destination
- /ssm/automation/customer-script-log-group-name
- /ssm/automation/enable-adaptive-concurrency
- /ssm/documents/console/public-sharing-permission
- /ssm/managed-instance/activation-tier
- /ssm/managed-instance/default-ec2-instance-management-role
- /ssm/opsinsights/opscenter
- /ssm/parameter-store/default-parameter-tier
- /ssm/parameter-store/high-throughput-enabled
And among these, /ssm/documents/console/public-sharing-permission corresponds to the SSM document public sharing block setting, so setting it to Disable should do the trick.
AWSTemplateFormatVersion: '2010-09-09'
Description: Block public sharing setting for SSM documents. Deployed via StackSets to all member accounts (per Region).
Resources:
BlockPublicDocumentSharing:
Type: AWS::SSM::ServiceSetting
Properties:
SettingId: /ssm/documents/console/public-sharing-permission
SettingValue: Disable
I thought this would work! But a mysterious error occurred…
Template format error: Unrecognized resource types: [AWS::SSM::ServiceSetting]

AWS::SSM::ServiceSetting Was Not Available in the Tokyo Region
After investigating the cause, I found that AWS::SSM::ServiceSetting was not registered in the CloudFormation registry for the Tokyo region (ap-northeast-1).
When checking with describe-type, TypeNotFoundException is returned for the Tokyo region, while it can be retrieved normally in the Virginia region (us-east-1).
% aws cloudformation describe-type \
--type RESOURCE \
--type-name AWS::SSM::ServiceSetting \
--region ap-northeast-1
aws: [ERROR]: An error occurred (TypeNotFoundException) when calling the DescribeType operation: The type 'AWS::SSM::ServiceSetting' cannot be found.
Additional error details:
Type: Sender
% aws cloudformation describe-type --type RESOURCE --type-name AWS::SSM::ServiceSetting --region us-east-1
{
"Arn": "arn:aws:cloudformation:us-east-1::type/resource/AWS-SSM-ServiceSetting",
"Type": "RESOURCE",
"TypeName": "AWS::SSM::ServiceSetting",
"IsDefaultVersion": true,
"Description": "Resource Type definition for AWS::SSM::ServiceSetting. ServiceSetting is an account-level setting for an AWS service that defines how a user interacts with or uses a service or feature.",
"ProvisioningType": "FULLY_MUTABLE",
"DeprecatedStatus": "LIVE",
"Visibility": "PUBLIC",
"TimeCreated": "2026-06-18T17:38:19.655000+00:00"
}
Since the TimeCreated on the Virginia region side is 2026-06-18, which is quite recent, it may not have rolled out to all regions yet…
I'd like to hope that it will eventually become available in the Tokyo region as well.
Just to be safe, I tried deploying StackSets from the Virginia region of the management account, but while the stack set itself was created successfully, stack instance creation in the Tokyo region still failed.

Handling All Regions with a Custom Resource
Since there are regions where AWS::SSM::ServiceSetting cannot be used, the only way to handle all regions together is to directly call the UpdateServiceSetting API using a custom resource.
So here is the custom resource version.
AWSTemplateFormatVersion: '2010-09-09'
Description: Block public sharing setting for SSM documents via custom resource (for Regions without AWS::SSM::ServiceSetting, e.g. ap-northeast-1). Deployed via StackSets to all member accounts (per Region).
Resources:
BlockPublicSharingFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: manage-ssm-public-sharing-setting
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ssm:UpdateServiceSetting
- ssm:GetServiceSetting
Resource: !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:servicesetting/ssm/documents/console/public-sharing-permission'
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*'
BlockPublicSharingFunction:
Type: AWS::Lambda::Function
Properties:
Description: Sets SSM documents public-sharing-permission to Disable (SSM.7).
Runtime: python3.14
Handler: index.handler
Timeout: 30
Role: !GetAtt BlockPublicSharingFunctionRole.Arn
Code:
ZipFile: |
import boto3
import cfnresponse
SETTING_ID = "/ssm/documents/console/public-sharing-permission"
def handler(event, context):
try:
ssm = boto3.client("ssm")
if event["RequestType"] in ("Create", "Update"):
ssm.update_service_setting(
SettingId=SETTING_ID, SettingValue="Disable"
)
cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
except Exception as exc:
cfnresponse.send(event, context, cfnresponse.FAILED, {"Error": str(exc)})
BlockPublicSharing:
Type: AWS::CloudFormation::CustomResource
Properties:
ServiceToken: !GetAtt BlockPublicSharingFunction.Arn
What it does is simple — it just sets Disable using update_service_setting.
Note that nothing is done on Delete.
When a stack is deleted, reverting the setting to Enable (allowing public sharing) would unintentionally bring SSM.7 back to a failing state, so I intentionally left the behavior to retain the block setting.
Verification
Let me try deploying this template to the Tokyo region and Virginia region.

The stack creation completed without any issues.

After deployment, I'll check the settings on the account side.
The Tokyo region and Virginia region I configured this time are set to Disable (blocking public sharing), and the Osaka region (ap-northeast-3), which was not configured, remains at the default Enable, so that looks correct.
$ for region in ap-northeast-1 us-east-1 ap-northeast-3; do
> value=$(aws ssm get-service-setting \
> --setting-id /ssm/documents/console/public-sharing-permission \
> --region "$region" \
> --query "ServiceSetting.SettingValue" \
> --output text)
> value=${value%$'\r'}
> printf '%-16s: %s\n' "$region" "$value"
> done
ap-northeast-1 : Disable
us-east-1 : Disable
ap-northeast-3 : Enable
After that, if the target regions for StackSets deployment have the desired regions configured and automatic deployment is enabled, the block setting will be automatically applied whenever a new account is added to the organization.
Conclusion
That's all for how to enable the SSM document public sharing block setting using CloudFormation StackSets and address Security Hub CSPM control SSM.7 across all AWS accounts.
I really hope AWS::SSM::ServiceSetting becomes available in all regions soon…
