如何解決 CloudFormation 中的範本驗證或範本格式錯誤?

6 分的閱讀內容
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" 錯誤,請參閱確認條件已指定為字串部分。
  • 對於 "Unrecognized resource types: [XXXXXXXX]" 錯誤,請參閱驗證資源類型的可用性部分。
  • 對於 "The [environmental resource] 'XXXXXXXX' does not exist" 錯誤,請參閱確認您的資源存在於堆疊之外,或驗證相同堆疊中資源的相依性部分。
  • 對於 "Invalid template property or properties [XXXXXXXX]" 錯誤,請參閱驗證範本屬性部分。
  • 對於 "Invalid policy syntax" or "MalformedPolicy" 錯誤,請參閱驗證任何 IAM 政策相關資源的政策語法部分。

解決方法

如果您在執行 AWS Command Line Interface (AWS CLI) 命令時收到錯誤,請參閱對 AWS CLI 錯誤進行疑難排解。此外,請確定您使用的是最新的 AWS CLI 版本

驗證範本語法

若要在 CloudFormation 範本中遵循正確的 JSON 或 YAML 語法,請考慮下列事項:

驗證邏輯 ID 和參數

確認您的範本中定義了資源邏輯 ID 和參數。

在下列 JSON 和 YAML 範本中,ImageId 屬性參考了 test。但是,範本既不包含資源邏輯 ID,也不包含名為 test 的參數。這些範本會傳回下列錯誤: "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.如果您的範本包含任何無伺服器資源,則會包含 Transform 聲明。請參閱下列範例 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 Resource Name (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 政策

將 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 個月前