如何解决 CloudFormation 中的模板验证或模板格式错误?

5 分钟阅读
0

我想验证 AWS CloudFormation 模板以确保没有语法错误。

简短描述

请根据收到的错误消息从下列解决方案中选择一种:

  • 对于“JSON not well-formed”或“YAML not well-formed”错误,请参阅验证模板语法部分。
  • 对于“Unresolved resource dependencies [XXXXXXXX] in the Resources block of the template”错误,请参阅验证逻辑 ID 和参数部分。
  • 对于“Unrecognized parameter type: XXXXXXXX”或“Invalid template parameter property 'XXXXXXXX'”错误,请参阅验证参数定义部分。
  • 对于“Every Condition member must be a string”错误,请参阅确认已将“Conditions”指定为字符串部分。
  • 对于“Unrecognized resource types: [XXXXXXXX]”错误,请参阅验证资源类型的可用性部分。
  • 对于“The [environmental resource] 'XXXXXXXX' does not exist”错误,请参阅验证资源是否位于堆栈外,或验证同一堆栈中资源的依赖关系部分。
  • 对于“Invalid template property or properties [XXXXXXXX]”错误,请参阅验证模板属性部分。
  • 对于“Invalid policy syntax”或“MalformedPolicy”错误,请参阅验证 IAM 策略相关资源的策略语法部分。

解决方法

如果在运行 AWS 命令行界面(AWS CLI)命令时收到错误,请参阅排查 AWS CLI 错误。此外,确保您使用的是最新版本的 AWS CLI

验证模板语法

要正确遵循 CloudFormation 模板中的 JSON 或 YAML 语法,请考虑以下几点:

验证逻辑 ID 和参数

请确认您的模板中定义了资源逻辑 ID 和参数。

在以下 JSON 和 YAML 模板中,test 被引用为 ImageId 的属性。但是,这两个模板都不包含名为 test 的资源逻辑 ID 或参数。这些模板会返回以下错误: “Unresolved resource dependencies [test] in the Resources block of the template.” 有关资源定义及其语法的更多信息,请参阅资源

示例 JSON(不正确):

{
  "Resources" : {
    "EC2Instance01" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : {"Ref": "test"}
      }
    }
  }
}

示例 YAML(不正确):

Resources:
  EC2Instance01:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref test

要解决此问题,请添加名为 test 的资源逻辑 ID。或者,创建一个名为 test 的参数,其引用返回 ImageId 值。以下示例 JSON 和 YAML 模板包含一个名为 test 的参数,其值为 ImageId

示例 JSON(正确):

{
  "Parameters": {
     "test": {
         "Type": "String",
         "Default": "ami-xxx"
       }
  },
  "Resources" : {
    "EC2Instance01" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : {"Ref": "test"}
      }
    }
  }
}

示例 YAML(正确):

Parameters:
  test:
    Type: String
    Default: ami-xxx
Resources:
  EC2Instance01:
    Type: 'AWS::EC2::Instance'
    Properties:
      ImageId: !Ref test

验证参数定义

  1. Type 设置为以下任一支持的属性:
  2. 在 CloudFormation 模板中,验证参数是否仅包含以下允许的属性。有关允许的属性的更多信息,请参阅属性
  3. 在 CloudFormation 模板中,确认 Parameters 部分不包含任何内置函数

在以下 JSON 和 YAML 模板示例中,ParameterC 的默认值具有内置函数 Fn::Sub。这个内置函数会导致验证错误: “Every Default member must be a string.”

示例 JSON(不正确):

{
  "Parameters": {
    "ParameterA": {
      "Type": "String",
      "Default": "abc"
    },
    "ParameterB": {
      "Type": "String",
      "Default": "def"
    },
    "ParameterC": {
      "Type": "String",
      "Default": {
        "Fn::Sub": "${ParameterA}-${ParameterB}"
      }
    }
  },
  "Resources": {
    "MyS3Bucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "BucketName": {
          "Ref": "ParameterC"
        }
      }
    }
  }
}

示例 YAML(不正确):

Parameters:
 ParameterA:
  Type: String
  Default: abc
 ParameterB:
  Type: String
  Default: def
 ParameterC:
  Type: String
  Default: !Sub '${ParameterA}-${ParameterB}'
Resources:
 MyS3Bucket:
  Type: 'AWS::S3::Bucket'
  Properties:
   BucketName: !Ref ParameterC

确认已将“Conditions”指定为字符串

在 CloudFormation 模板中,将 Conditions 指定为字符串。

以下示例 JSON 和 YAML 模板将资源 EC2RouteA 中的条件指定为一系列字符串,而不是单个字符串。这些模板会导致以下验证错误: “Every Condition member must be a string.”

示例 JSON(不正确):

{
  "Conditions": {
    "ConditionA": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            "",
            "Sample"
          ]
        }
      ]
    },
    "ConditionB": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            "",
            "Sample"
          ]
        }
      ]
    }
  },
  "Resources": {
    "EC2RouteA": {
      "Type": "AWS::EC2::Route",
      "Condition": [
        "ConditionA",
        "ConditionB"
      ],
      "Properties": {
       ...
      }
    }
  }
}

示例 YAML(不正确):

Conditions:
 ConditionA: !Not
  - !Equals
   - ''
   - Sample
 ConditionB: !Not
  - !Equals
   - ''
   - Sample
Resources:
  EC2RouteA:
  Type: 'AWS::EC2::Route'
  Condition:
   - ConditionA
   - ConditionB
  Properties:

要解决此错误,请将 ConditionAandB 添加到模板的 Conditions 部分,然后将 ConditionAandB 用作 EC2RouteA 资源的条件。请参阅以下 JSON 和 YAML 模板示例。

示例 JSON(正确):

{
  "Conditions": {
    "ConditionA": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            "",
            "Sample"
          ]
        }
      ]
    },
    "ConditionB": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            "",
            "Sample"
          ]
        }
      ]
    },
    "ConditionAandB": {
      "Fn::And": [
        {
          "Condition": "ConditionA"
        },
        {
          "Condition": "ConditionB"
        }
      ]
    }
  },
  "Resources": {
    "EC2RouteA": {
      "Type": "AWS::EC2::Route",
      "Condition": "ConditionAandB",
      "Properties": {
        ...
      }
    }
  }
}

示例 YAML(正确):

Conditions:
  ConditionA:
    Fn::Not:
    - Fn::Equals:
      - ''
      - Sample
  ConditionB:
    Fn::Not:
    - Fn::Equals:
      - ''
      - Sample
  ConditionAandB:
    Fn::And:
    - Condition: ConditionA
    - Condition: ConditionB
Resources:
  EC2RouteA:
    Type: AWS::EC2::Route
    Condition: ConditionAandB
    Properties:

验证资源类型的可用性

1.验证您的资源在您的 AWS 区域可用。

并非所有资源类型在每个 AWS 区域都可用。如果模板中存在对您的 AWS 区域不可用的资源类型,会导致以下错误: “Unrecognized resource types: [XXXXXXXX].”

2.如果您的模板包含任何无服务器资源,则应包含一个转换声明。请参阅以下 JSON 和 YAML 模板示例。

JSON 示例:

{
    "Transform": "AWS::Serverless-2016-10-31", #Please make sure to include this.
    "Resources": {
        "MyServerlessFunctionLogicalID": {
            "Type": "AWS::Serverless::Function",
            "Properties": {
                "Handler": "index.handler",
                "Runtime": "nodejs8.10",
                "CodeUri": "s3://testBucket/mySourceCode.zip"
            }
        }
   }
}

YAML 示例:

Transform: AWS::Serverless-2016-10-31 #Please make sure to include this.
Resources:
  MyServerlessFunctionLogicalID:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs8.10
      CodeUri: 's3://testBucket/mySourceCode.zip'

验证资源是否位于堆栈外,或验证同一堆栈中资源的依赖关系

如果您将某资源或 Amazon 资源名称(ARN)硬编码为位于 CloudFormation 堆栈之外的堆栈资源,请验证以下内容:

  • 资源名称或 ARN 正确无误。
  • 该资源确实存在。
  • 该资源与堆栈位于同一 AWS 区域中。注意某些资源接受跨 AWS 区域或账户的属性。

例如,在以下情况下,堆栈中指定安全组(sg-1234567890)的 AWS::EC2::Instance 资源会失败:

  • 该安全组不存在。
  • 堆栈的 AWS 区域中没有该安全组。

因此,您会收到错误消息: “The sg-1234567890 does not exist.” 请参阅以下示例:

LinuxInstance:
    Type: AWS::EC2::Instance
    Properties:
      SubnetId: !Ref ServerSubnetID
      KeyName: !Ref EC2KeyPairName
      SecurityGroupIds: sg-1234567890 #<This resource must exist and be in the same AWS Region as the stack.>

验证模板属性

在 CloudFormation 模板中仅使用允许的模板属性

以下示例 JSON 和 YAML 模板将存储桶资源的层级设置为与 Resources 部分的层级相同。此设置会返回以下错误: “Template validation error: Invalid template property or properties [Bucket].” 当 CloudFormation 模板验证器将存储桶资源视为部分层级规范时,会引发此错误。不允许将部分层级规范作为模板属性。

示例 JSON(不正确):

{
  "Resources": {
    "WaitCondition": {
      "Type": "AWS::CloudFormation::WaitCondition"
    }
  },  #<There is an extra '}' causing the Resources section to be closed off after the WaitCondition resource.>
  "Bucket": {
    "Type": "AWS::S3::Bucket",
    "Properties": {
      "Name": "BucketName"
    }
  }
}

示例 YAML(不正确):

Resources:
  WaitCondition:
    Type: AWS::CloudFormation::WaitCondition
Bucket: # <The spacing for the entire Bucket resource is incorrect and needs to be shifted 2 spaces to the right.>
  Type: AWS::S3::Bucket
  Properties:
    Name: BucketName

要解决此问题,请更正相关格式,在 Resources 部分内指定存储桶资源。请参阅以下格式正确的 JSON 和 YAML 示例模板。

示例 JSON(正确):

{
  "Resources": {
    "WaitCondition": {
      "Type": "AWS::CloudFormation::WaitCondition"
    },
    "Bucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "Name": "BucketName"
      }
    }
  }
}

示例 YAML(正确):

Resources:
  WaitCondition:
    Type: 'AWS::CloudFormation::WaitCondition'
  Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      Name: BucketName

验证 IAM 策略相关资源的策略语法

如果要在资源属性中创建 Identity and Access Management(IAM)策略资源或相关配置,请验证该策略在此结构基础中是否有效。

{  
    "Resources": {  
        "Policy": {  
            "Type": "AWS::IAM::Policy",  
            "Properties": {  
                "PolicyName": "IamPolicyName",  
                "PolicyDocument": {  
                    "Version": "2012-10-17",  
                    "Statement": [  
                        {  
                            "Effect": "effect",  
                            "Action": [  
                                "<service>:<API_action>",  
                                "<...>"  
                            ],  
                            "Resource": "desiredResourceARN",  
                            "Condition": {  
                                "ConditionConfiguration": {  
                                    "conditionKey": [  
                                        "values"  
                                    ]  
                                },  
                                "ConditionConfiguration2": "<...>"  
                            }  
                        }  
                    ]  
                }  
            }  
        }  
    }  
}

**注意:**将 <service> 替换为您选择的服务名称。将 <APIaction> 替换为所选服务的 API 操作。有关详细信息,请参阅 IAM JSON policy

将您的 JSON 策略文档与 YAML 格式集成

您可能希望将 JSON 策略文档与 YAML 格式模板相集成,用于配置 CloudFormation。为此,您需要根据模板修改文档。

集成后,策略元素与下图类似:

Resources:  
  Policy:  
    Type: 'AWS::IAM::Policy'  
    Properties:  
      PolicyName: IamPolicyName  
      PolicyDocument:  
        Version: 2012-10-17  
        Statement:  
          - Effect: effect  
            Action:  
              - '<service>:<API_action>'  
              - <...>  
            Resource: desiredResourceARN  
            Condition:  
              ConditionConfiguration:  
                conditionKey:  
                  - values  
              ConditionConfiguration2: <...>
AWS 官方
AWS 官方已更新 2 个月前