CloudFormation部署SNS主题报错:Subscription需数组而非对象
AWS CloudFormation SNS订阅格式错误解决方案
报错原因
CloudFormation要求SNS主题的Subscription属性必须是JSON数组,你的模板写法将其定义为JSON对象,导致模型验证失败:
Model validation failed (#/Subscription: expected type: JSONArray, found: JSONObject)
修复模板中的Subscription格式
方案1:使用列表参数直接传递订阅数组
将原有的Endpoint1、Endpoint2单值参数替换为List<String>类型的集合参数,天然兼容单个/多个邮箱场景:
Parameters: Subscribers: Type: List<String> Description: 订阅邮箱地址列表(支持单个或多个) Resources: MyFirstSNSTopic: Type: AWS::SNS::Topic Properties: Subscription: - Protocol: email Endpoint: !Ref Subscribers MySecondSNSTopic: Type: AWS::SNS::Topic Properties: Subscription: - Protocol: email Endpoint: !Ref Subscribers
方案2:保留单Endpoint参数,动态拼接数组
若必须保留Endpoint1、Endpoint2参数,可通过CloudFormation内置函数过滤空值并生成数组:
Parameters: Endpoint1: Type: String Default: "" Endpoint2: Type: String Default: "" Resources: MyFirstSNSTopic: Type: AWS::SNS::Topic Properties: Subscription: !Split - "|" - !Join - "|" - - !If [ !Not [!Equals [!Ref Endpoint1, ""]], !Sub '{"Protocol": "email", "Endpoint": "${Endpoint1}"}', "" ] - !If [ !Not [!Equals [!Ref Endpoint2, ""]], !Sub '{"Protocol": "email", "Endpoint": "${Endpoint2}"}', "" ]
注:用|作为分隔符避免和邮箱地址冲突,最终会自动解析为合法数组。
Python传递参数的正确姿势
用Python字典传递参数时,需确保对应参数为数组格式:
对应列表参数的传递方式
import boto3 cf_client = boto3.client('cloudformation') cf_client.create_stack( StackName='MySNSService', TemplateBody=open('sns-template.yaml').read(), Parameters=[ { 'ParameterKey': 'Subscribers', 'ParameterValue': 'user1@example.com,user2@example.com' # 多邮箱用逗号分隔 } ] )
单邮箱场景的数组兼容
如果模板直接接收订阅数组参数,单邮箱也要包装成数组格式:
Parameters=[ { 'ParameterKey': 'SubscriptionArray', 'ParameterValue': '[{"Protocol": "email", "Endpoint": "user@example.com"}]' } ]
更可靠的实现建议
- 优先用列表参数:减少冗余参数,逻辑更简洁,天然支持动态数量的订阅地址。
- 提前参数校验:在Python代码中先验证邮箱格式、过滤空值,避免部署时的验证错误。
- 使用CloudFormation宏:复杂场景下(如按环境生成订阅),自定义宏可灵活处理参数并生成合法的
Subscription数组。
内容的提问来源于stack exchange,提问作者CanAnyOneHelpMe
相关产品推荐
相关产品推荐

