跳至內容

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

5 分的閱讀內容
0

我想要驗證我的 AWS CloudFormation 範本,以確認沒有語法錯誤。

解決方法

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

根據您收到的錯誤訊息,完成以下任務。

「JSON not well-formed」或「YAML not well-formed」錯誤

如果您沒有正確格式化 CloudFormation 範本,則您會收到以下其中一個錯誤訊息:

「JSON not well-formed」

「YAML not well-formed」

請確保在您的 CloudFormation 範本中遵循 JSON 或 YAML 語法最佳實務。若要解決此錯誤,請採取以下行動:

  • 使用基礎結構編輯器建立您的堆疊。
  • 使用 validate-template AWS CLI 命令驗證您的 JSON 與 YAML 語法。
  • 若要使用 AWS CloudFormation linter 驗證您的 JSON 或 YAML 範本,請參閱 GitHub 網站上的 cfn-lint

「Unresolved resource dependencies [XXXXXXXX] in the Resources block of the template」錯誤

如果您的 CloudFormation 範本未指定 資源邏輯 ID 或參數,則您會收到以下錯誤訊息:

「Unresolved resource dependencies [test] in the Resources block of the template.」。

若要解決此錯誤,請指定資源邏輯 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

「Unrecognized parameter type: XXXXXXXX」或「Invalid template parameter property 'XXXXXXXX'」錯誤

如果您的 JSON 與 YAML 範本將 ParameterC 的預設值包含為內建函數 Fn::Sub,則您會收到以下錯誤訊息:

「Every Default member must be a string.」

參數不支援內建函數。使用 Fn::Sub 函數來指定 ParameterAParameterB 的值。若要解決此錯誤,請移除 ParameterC

若要在您的 CloudFormation 範本中移除 ParameterC,請完成以下步驟:

  1. Type 設定為以下支援的屬性之一:StringNumberListCommaDelimitedList
  2. 驗證參數僅包含允許的屬性
  3. 確認 Parameters (參數) 區段不包含任何內建函數

範例 JSON:

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

範例 YAML:

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

「Every Condition member must be a string」錯誤

您的 JSON 與 YAML 範本可能會將資源 EC2RouteA 中的條件指定為字串清單而非單一字串。若是如此,則會收到以下錯誤訊息:

「Every Condition member must be a string.」

若要解決此錯誤,請將 ConditionAandB 新增至範本的 Conditions (條件) 區段。然後,使用 ConditionAandB 作為 EC2RouteA 資源的條件。

範例 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:

「Unrecognized resource types: [XXXXXXXX]」錯誤

並非所有資源類型都適用於每個 AWS 區域。如果您的範本包含不適用於您區域的資源類型,則您會收到以下錯誤訊息:

「Unrecognized resource types: [XXXXXXXX].」

若要解決此錯誤,請確認您的資源是否適用於您的區域。如果您的範本由任何無伺服器資源組成,請包含 Transform 宣告。

範例 JSON:

{
    "Transform": "AWS::Serverless-2016-10-31", #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 #Make sure to include this.
Resources:
  MyServerlessFunctionLogicalID:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs8.10
      CodeUri: 's3://testBucket/mySourceCode.zip'

「The [environmental resource] 'XXXXXXXX' does not exist」錯誤

如果堆疊中的 AWS::EC2::Instance 資源指定了安全群組,則您會收到以下錯誤訊息:

「The sg-1234567890 does not exist.」

如果安全群組不存在,或安全群組不存在於堆疊的區域中,則堆疊會失敗。若要解決此錯誤,請將 SecurityGroupIDs 新增至您的範本。

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 堆疊之外的資源或 Amazon Resource Name (ARN) 進行硬式編碼,請驗證以下內容:

  • 資源名稱或 ARN 正確。
  • 資源存在。
  • 資源與堆疊存在於相同區域。某些資源接受跨區域或帳戶的屬性。

「Invalid template property or properties [XXXXXXXX]」錯誤

如果您在 JSON 與 YAML 範本中,將儲存貯體資源設定在與 Resources (資源) 區段相同的層級,則您會收到以下錯誤訊息:

「Template validation error: Invalid template property or properties [Bucket].」

當 CloudFormation 範本驗證程式將儲存貯體資源識別為區段層級規格時,就會發生此錯誤。區段層級規格不允許作為範本屬性。最佳實務是僅在 CloudFormation 範本中使用允許的範本屬性

若要解決此錯誤,請在 Resources (資源) 區段內指定儲存貯體資源。

範例 JSON:

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

**注意:**將 BucketName 替換為您的儲存貯體名稱。

範例 YAML:

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

**注意:**將 BucketName 替換為您的儲存貯體名稱。

「Invalid policy syntax」或「MalformedPolicy」錯誤

當您建立身分政策、資源政策、服務控制政策或資源控制政策時,驗證會分為兩個步驟。這些步驟包含 AWS Identity and Access Management (IAM) 驗證與 CloudFormation 驗證。

若要驗證政策,請建立您的政策,然後執行以下 validate-policy AWS CLI 命令:

➜  aws accessanalyzer validate-policy --policy-document file://policy-document.json --policy-type IDENTITY_POLICY

**注意:**將 policy-document.json 替換為您 JSON 檔案的檔案路徑。

如果您執行 validate-policy AWS CLI 命令,則會收到「Invalid policy syntax」或「MalformedPolicy」錯誤訊息。若要解決此問題,請將 Action 變更為 s3:DeleteObject 並再次執行命令。

範例 JSON:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyObjectDeletionForAllExceptRolePrefix",
      "Effect": "Deny",
      "Action": [
        "s3:DeleteObject",
        "s3:DeleteObjectVersion",
        "s3:PutLifecycleConfiguration"
      ],
      "Resource": ["arn:aws:s3:::BUCKET_NAME/*"]
    }
  ]
}

**注意:**將 BUCKET_NAME 替換為您的儲存貯體名稱。

將驗證後的政策新增至您的 CloudFormation 範本,並指定參數或資源。

如果 sub 函數參考了範本中不存在的參數,則會收到以下錯誤訊息:

「An error occurred (ValidationError) when calling the ValidateTemplate operation: Template format error: Unresolved resource dependencies [Bucket] in the Resources block of the template」

若要解決此錯誤,請在範本中將 Resource 更新為 arn:aws:s3:::${BucketName}/*

範例 JSON:

{
  "Parameters": {
    "BucketName": {
      "Type": "String"
    },
    "RoleName": {
      "Type": "String"
    }
  },
  "Resources": {
    "ManagedPolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "Roles": [
          {
            "Ref": "RoleName"
          }
        ],
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "DenyObjectDeletionForAllExceptRolePrefix",
              "Effect": "Deny",
              "Action": [
                "s3:DeleteObject",
                "s3:DeleteObjectVersion",
                "s3:PutLifecycleConfiguration"
              ],
              "Resource": [
                {
                  "Fn::Sub": "arn:aws:s3:::${BucketName}/*"
                }
              ]
            }
          ]
        }
      }
    }
  }
}

**注意:**將 BucketName 替換為您的儲存貯體名稱。

手動驗證 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 替換為您的服務名稱,並將 API_action 替換為所選服務的 API 動作。如需更多資訊,請參閱 IAM JSON 政策元素參考

將您的 JSON 政策文件與 YAML 格式範本整合

如果您將 JSON 政策文件與 YAML 格式範本整合以佈建 CloudFormation,則您可以變更文件在範本中的呈現方式。這可以避免 YAML 與 JSON 混合區塊。整合後,政策元素會類似下列範例範本:

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: <...>

**注意:**將 IamPolicyName 替換為您的 IAM 政策名稱。