从SecretsManager加载的分割字符串

问题描述 投票:0回答:1

我试图创建一个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路径,它似乎可以正常工作......。

我在这里做错了什么?

amazon-web-services amazon-cloudformation
1个回答
0
投票

我不能提供完整的答案,因为我同意@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字符串列表作为参数传递给第二个堆栈。

希望能帮到你。

© www.soinside.com 2019 - 2024. All rights reserved.