我试图创建一个ListenerRule,只接受从Secrets Manager加载的某些IP地址。这是我的原始代码。
LoadBalancerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- TargetGroupArn: !Ref 'TargetGroup'
Type: 'forward'
Conditions:
Fn::If:
- IsProdEnvironment
- - Field: host-header
Values:
- !Ref 'BaseUrl'
- - Field: host-header
Values:
- !Ref 'BaseUrl'
- Field: source-ip
SourceIpConfig:
Values:
- !Split [ ';', !Sub '{{resolve:secretsmanager:/${ProjectName}/${EnvType}/${ServiceName}:SecretString:ALLOWED_IPS}}' ]
上面的Resolve似乎可以正常工作,并被解析成一个字符串,如: 1.2.3.4/32;2.3.4.5/32;4.5.6.7/29;5.6.7.8/32
(地址明显被混淆了,但数量和子网掩码是一样的)。
然而当我尝试部署模板时,我得到一个错误。
The specified value '1.2.3.4/32;2.3.4.5/32;4.5.6.7/29;5.6.7.8/32' is not a valid CIDR block (Service: AmazonElasticLoadBalancingV2; Status Code: 400; Error Code: ValidationError; Request ID: error-id)
这个错误本身表明 !Split
因为CloudFormation没有报告错误,所以做了一些事情。Value of property Values must be of type List of String
. 很明显,字符串被转换为包含一个元素的列表,但它没有通过 ;
字符变成4个字符串的列表。
此外,当我尝试运行非常类似的代码,但用硬编码值而不是秘密,它工作正常。
LoadBalancerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- TargetGroupArn: !Ref 'TargetGroup'
Type: 'forward'
Conditions:
Fn::If:
- IsProdEnvironment
- - Field: host-header
Values:
- !Ref 'BaseUrl'
- - Field: host-header
Values:
- !Ref 'BaseUrl'
- Field: source-ip
SourceIpConfig:
Values:
!Split [';', '1.2.3.4/32;2.3.4.5/32;4.5.6.7/29;5.6.7.8/32' ]
我还检查了没有 !Sub
但有硬编码的Secret值的路径。
LoadBalancerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- TargetGroupArn: !Ref 'TargetGroup'
Type: 'forward'
Conditions:
Fn::If:
- IsProdEnvironment
- - Field: host-header
Values:
- !Ref 'BaseUrl'
- - Field: host-header
Values:
- !Ref 'BaseUrl'
- Field: source-ip
SourceIpConfig:
Values: !Split [';', '{{resolve:secretsmanager:/dummy-project/dev/foo:SecretString:ALLOWED_IPS}}']
结果我得到了和第一种情况一样的错误:长字符串没有被分割成更小的部分。
更奇怪的是......这是一个相当大的模板的一部分,但当我把这个资源复制到一个简单的 test.yaml
它需要一个参数列表来生成SecretManager路径,它似乎可以正常工作......。
我在这里做错了什么?
我不能提供完整的答案,因为我同意@OleksiiDonoha和我相信,我相信 resolve:secretsmanager
是在创建变更集的过程中,在所有固有函数执行后最后解析的。
但是,我想澄清一下这句话。
这个错误本身就表明 !"分割 "做了些什么,因为CloudFormation没有报告错误 属性值的值必须是字符串的List类型。
!Split
只使用 String
,而不是字符串列表,不像 Select
. 此外,如果你提供了错误的定界符,它将只返回原始字符串。
那么发生在 Split
,我认为是以下内容。
在表达式中:
Values:
- !Split [ ';', !Sub '{{resolve:secretsmanager:/${ProjectName}/${EnvType}/${ServiceName}:SecretString:ALLOWED_IPS}}' ]
!Sub
先执行,你最终会得到(例如)。
Values:
- !Split [ ';', '{{resolve:secretsmanager:/MyProject/TestType/MyService:SecretString:ALLOWED_IPS}}' ]
然后... !Split
执行并尝试拆分字符串。'{{resolve:secretsmanager:/MyProject/TestType/MyService:SecretString:ALLOWED_IPS}}'
由 ;
. 它不能,因此你最终的结果是: 。
Values:
- '{{resolve:secretsmanager:/MyProject/TestType/MyService:SecretString:ALLOWED_IPS}}'
最后,这个问题得到解决,结果是:
Values:
- "1.2.3.4/32;2.3.4.5/32;4.5.6.7/29;5.6.7.8/32"
这就可以解释你的错误了
目前我看到的唯一的解决方案是使用自定义资源,在固有函数评估之前或通过内部栈获得秘密。
或者,你是链式堆栈(一个堆栈产生的输出进入下一个堆栈的参数),你可以在第一个堆栈中解析秘密,然后将CIDRs字符串列表作为参数传递给第二个堆栈。
希望能帮到你。