强制以“ 00”开头的AWS帐号为字符串

时间:2020-09-18 16:39:30

标签: amazon-web-services amazon-cloudformation

有人知道将“ 00”开头的帐号转换为字符串的解决方法吗?我正在CFn模板中使用“映射”来根据帐号分配值。我将帐号放在引号中以将其转换为字符串,并且如果它不是以零开头的话,它会很好地工作,当它输入时,会出现以下错误。

[/ Mappings / EnvMap]映射键必须为字符串;收到数字[1.50xxx028E9]

Mappings:
  EnvMap:
    "8727xxxx0": 
      env: "dev"
    "707xxxx78":
      env: "test"
    "00150xxx280":
      env: "prod"


Resources:
  rS3Stack:
    Type: "AWS::CloudFormation::Stack"
    Properties:
      TemplateURL: "https://s3.amazonaws.com/some_bucket/nested_cfn/s3.yaml"
      Parameters:
        pEnvironment: !FindInMap
          - EnvMap
          - !Ref 'AWS::AccountId'
          - env

1 个答案:

答案 0 :(得分:0)

您的问题是由bug in PyYAML引起的,该问题由YAML 1.1规范中的某些歧义引起。根据YAML 1.1,整数不能以0开头,数字不能以0开头,并且被视为八进制数。因此,当PyYAML解析帐户ID时,它会认为该帐户ID不是整数,因为它以0开头,但也不是八进制数,因为它包含一个8。由于它既不是整数,也不是八进制数,因此PyYAML认为它是字符串,可以安全地将其转储而不用引号引起来。

一个重现此情况的最小示例如下:

>>> import sys
>>> import yaml
>>> yaml.dump(["1", "8", "01", "08"], sys.stdout)
- '1'
- '8'
- '01'
- 08

现在,您可能想知道为什么在只想部署CloudFormation堆栈时为何在这里提到PyYAML错误:

根据部署CloudFormation堆栈的方式,模板可能会在部署之前在本地进行转换。例如,在使用aws cloudformation packagesam packagesam build用S3中的路径替换本地代码位置时,就会发生这种情况。在使用PyYAML完成这些转换期间读写模板时,它会触发上述PyYAML错误。 AWS CLIAWS SAM CLI都有关于此问题的错误报告。

由于导致问题的帐户ID在您的情况下用作密钥,因此解决该问题的选项有限,因为您无法利用CloudFormation的固有功能。但是,仍然有可能的解决方法:

如果您使用的是AWS CLI,则可以切换到使用AWS CLI v2,因为它使用ruamel而不是PyYAML,因此不会出现此错误。 ruamel处理数字,正如人们期望的那样,因为它实现了YAML 1.2,在其规范中不包含歧义。

无论您使用的是AWS SAM CLI还是AWS CLI,都可以使用的方法是将转换后的模板从YAML转换为JSON,然后再转换回YAML,这也会“修复”该错误,因为这会导致问题数字再次被引用。 AWS提供了一个名为cfn-flip的工具。您必须在打包和部署之间运行两次。对于AWS SAM CLI,例如:

sam build
cfn-flip .aws-sam/build/template.yaml | cfn-flip > .aws-sam/build/template.tmp.yaml
mv .aws-sam/build/template.tmp.yaml .aws-sam/build/template.yaml
sam deploy

这样,我个人将建议一个完全不同的解决方法,那就是从模板中删除该映射。硬编码帐户ID和环境使模板的可移植性降低,因为它限制了该模板可用于的帐户/环境。相反,我将环境作为CloudFormation模板的参数提供,因此它根本不需要知道帐户ID。