Coder Social home page Coder Social logo

cfn-lint's Introduction

Retirement Notice

This tool was developed before AWS released cfn-python-lint, available at https://github.com/awslabs/cfn-python-lint. The AWS tool is better supported, provides additional checks and has best practice recommendations - if you are looking at implementing a linting tool into your workflow, use https://github.com/awslabs/cfn-python-lint.

Due to the superiority of the alternative tool, this project, cfn-lint has been retired.

cfn-lint CircleCI npm version npm

A more friendly CloudFormation JSON and YAML Validator

cfn-lint is a tool used to improve your CloudFormation development cycle. If you are here, you are probably fed up of waiting for 10 minutes or more before CloudFormation gives you an error due to a typo. This tool aims to remove that waste of time. The tool takes the CloudFormation template, and resolves all the Intrinsic functions defined before checking the Properties of Resources defined.

The tool can be used over the commandline using cfn-lint, or can be used as a module within another JavaScript application.

Note: This tool is currently case-sensitive in relation to AWS CloudFormation types, for example aws::lambda::function != AWS::Lambda::Function.

Installation

You can install with npm:

$ npm install -g cfn-lint

If you get /usr/bin/env: 'node': No such file or directory ensure your system has NodeJs installed. On Debian systems you may need to symlink node to nodejs due to namespacing issues (ln -s /usr/bin/nodejs /usr/bin/node).

How to use?

cfn-lint validate my_template.yaml

cfn-lint validate my_template.json

cfn-lint validate my_template.yaml --parameters key="my value",key2=value2,key3=3

cfn-lint validate my_template.yaml --parameters key="my value",key2=value2 --no-guess-parameters

cfn-lint validate my_template.yaml --pseudo AWS::StackName="My-Stack"

cfn-lint validate my_template.yaml --parameters key="my value" --pseudo AWS::Region=ap-northeast-1,AWS::AccountId=000000000000

cfn-lint docs AWS::Lambda::Function

cfn-lint docs AWS::Lambda::Function.Code

cfn-lint docs AWS::Lambda::Function.Code.S3Bucket

Note: The order of --parameters and --pseudo currently matters. This should be addressed in a later release.

Example Output

0 infos
0 warn
2 crit
Resource: Resources > MyInstance > Properties
Message: Required property ImageId missing for type AWS::EC2::Instance
Documentation: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html

Resource: Resources > MyInstance > Properties
Message: Required property Value missing for type Tag
Documentation: http://docs.aws.amazon.com/search/doc-search.html?searchPath=documentation-guide&searchQuery=Tag&x=0&y=0&this_doc_product=AWS+CloudFormation&this_doc_guide=User+Guide&doc_locale=en_us#facet_doc_product=AWS%20CloudFormation&facet_doc_guide=User%20Guide

Template invalid!

Flags

Input Parameters

--parameters <param values>: Provide a list of comma-separated key=value pairs of parameters to use when validating your template. If a parameter is not specified here, cfn-lint will guess a mock value based on the Parameter's Type and AllowedValues. e.g.--parameters InstanceType=t2.micro,Memory=512

AWS Pseudo Parameter Override

--pseudo <psuedo param values>: Provide a list of comma-separated key=value pairs of CloudFormation pseudo-parameters to use when validating your template. e.g.--pseudo AWS::Region=ap-southeast-2

Import Values

--import-values <param values>: Provide a list of comma-separated key=value pairs of CloudFormation import values to use when validating your template. e.g.--import-values MyDeployedVPC=vpc-1a2b3c4d

Parameter Guessing

--guess-parameters: Guess any parameters if they don't have any Default value in the template. Parameters will be guessed/mocked based on their AllowedValues or Type. This is the default behaviour; it's only included as an option for explicitness.

--no-guess-parameters: Disable the guessing of parameters if they don't have a Default. If you don't provide them on the CLI in this situation, a critical error will be raised instead of the parameter value being mocked.

--only-guess-parameters <param names>: Only guess the provided parameters, and disable the guessing of all others without Defaults. A critical error will be raised for missing parameters, as above. e.g. --only-guess-parameters InstanceType,Memory

User-defined Resource Attributes

--custom-resource-attributes <attribute values>: Provide a list of comma-separated key=value pairs of resource attributes using either resource-type notation (e.g. AWS::CloudFormation::CustomResource.SomeAttribute) or logical-name notation (e.g. SomethingPretty.SomeAttribute) and their expected values, to use when validating your template. If a custom resource attribute is not specified here, cfn-lint will guess a mock value. e.g.--custom-resource-attributes AWS::CloudFormation::CustomResource.SomeAttribute=[1\\,2],Custom::Dooby.SomeAttribute=[1\\,2],SomethingPretty.SomeAttribute=123

Verbose Output

--verbose: Provide verbose output and stack traces when template parsing fails.

** Note ** : Parameter values that contain commas must be escaped using a backslash (e.g. Param1=[1\,2\,3]). Depending on your command-line interpreter you may have to use double backslashes or enclose the entire argument in quotes, such is the case with Bash and other Bourne-based shells (e.g. --parameters 'Param1=[1\,2\,3]').

What can cfn-lint do?

  • Read JSON + YAML (Including YAML short form)
  • Detect invalid property names
  • Detect invalid Ref
  • Detect invalid mappings
  • Detect invalid format
  • Missing or invalid AWSTemplateFormatVersion
  • Fn::FindInMap
  • Fn::GetAtt
  • Fn::GetAZs
  • Fn::Join
  • Fn::Base64
  • Fn::Sub
  • Fn::If
  • Fn::Equals
  • Fn::Not
  • Fn::Or
  • Fn::And
  • Fn::ImportValue
  • Fn::Select
  • Fn::Split
  • Fn::ImportValue
  • Condition support
  • Ref
  • Go to the documentation from Command Line (see above examples)
  • Detecting invalid property types
  • Detect missing required properties
  • SAM template validation (experimental support)

Feature backlog

  • Verbose parsing errors when reading invalid JSON
  • Test coverage for Conditions and Property checking
  • Refactor Property checking to be clearer
  • Circular dependency checking
  • Extended validation flag (calls AWS CloudFormation API)
  • Watch file flag to revalidate on file save
  • Download latest resources during build

Features that would be nice, but aren't currently possible

  • Detect conditional required properties (Information doesn't exist in AWS Resource Specification)

API

cfn-lint can also be used as a Node library:

const cfnLint = require('cfn-lint')

The following methods are considered public:

cfnLint.validateFile(fileName: string, options?: ValidationOptions): ValidationResult

Validates a file, and returns an ValidationResult with the results.

cfnLint.validateJsonObject(object: any, options?: ValidationOptions): ValidationResult

Validates an object, and returns an ValidationResult with the results. The object is what you might get from JSON.parseing a Cloudformation template.

interface ValidationOptions {
  parameters?: {
    Param1: Param1value,
    // ...
  }
  pseudoParameters?: {
    'AWS::Region': 'ap-southeast-2',
    // ...
  },
  guessParameters?: string[] | undefined // default undefined
}

parameters get passed into the template's Parameters before validation, and pseudoParameters are used to override AWS' pseudo-parameters, like AWS::Region, AWS::AccountId, etc.

If guessParameters is set to a list of parameter names, a critical error will be raised if any Parameter with no Default is not specified in the parameters or guessParameters options. An empty list can be used to enforce that all parameters must be specified in parameters. Leaving as undefined preserves the default loose behaviour, where parameters are guessed as needed without causing an error.

interface ErrorRecord {
  message: string,
  resource: string,
  documentation: string
}
interface ValidationResult {
  templateValid: boolean,
  errors: {
    crit: ErrorRecord[],
    warn: ErrorRecord[],
    info: ErrorRecord[]
  },
  outputs: {
      [outputName: string]: string;
  };
  exports: {
      [outputName: string]: string;
  };
}

Represents the result of a validation.

Deploying your template

CloudFormation tends to involve a bit of trail and error. To enable quick development, the following method can be used to prevent the annoying 'ROLLBACK' scenarios where the whole stack must be deleted and recreated.

Deploy a template with the following content, name it what you want your final stack to be called.

Resources:
  MyBucket:
    Type: AWS::S3::Bucket

After each change to your template, simply update the stack you just created. If the stack failed to deploy for some reason you can perform an 'Update Stack' operation, without needing to delete and recreate the stack from scratch. You can also use this method to keep parameters populated during the development phase. This method will work using the AWS Console or the CLI tools.

FAQ

No errors were thrown for my template but it still failed when deploying! Is this tool pointless?!

Hopefully cfn-lint caught some errors before you deployed your template, however, catching every single error before deployment is extremely tricky. Please help out the community by explaining how you managed to get an error from CloudFormation of which the validator did not detect, the following information will help in adding a check to the utility:

  • The Resource/Statement which caused the error
  • The error thrown from CloudFormation
  • The working Resource/Statement which resolves the error

You can add an issue on the Github Issue Page. Thanks for helping out!

Doesn't the AWS API provide this functionality?

Partially. The AWS API cloudformation validate-template only checks the validity of the template, this includes the expected parameters for intrinsic functions, resource types and general structure of the JSON or YAML template it has been given. The AWS API does not detect incorrect resource property names or incorrect resource property types (e.g. string, bool, list) which are typically only detected when CloudFormation attempts to deploy the resources with the incorrect configurations.

How does cfn-lint know what is valid?

AWS provide a CloudFormation specification file for each region. cfn-lint uses the US East (N. Virginia) CloudFormationResourceSpecification.json file available on the AWS CloudFormation Resource Specification page. Currently, updates of this JSON file are manual and baked into each major, minor or bug fix release as needed.

Got any other questions?

Ask a question on the Github Issue Page!

Development

Language

This project is written in TypeScript, a superset of JavaScript which allows for type checking at compile time. The project currently aims to support Node 4 and above.

Unit Tests

Tests can be run using npm test. There should be a test case for every template error, for example an invalid parameter for Fn::Join or an incorrect reference for Ref. The tests depend on Mocha and chai.

IDE Setup

If you use a JetBrains editor, the following Run Configuration can be setup for the Mocha test suite:

Node Options: None Extra Mocha Options: None Test Directory: /lib/test

Local testing of CLI

Environmental Variables

  • DEBUG - Set to receive runtime debug messages
$ npm link
$ cfn-lint <some command>

Resource Attribute Mocking

In order to simulate the intrinsic functions to catch errors before deployment, attributes for Properties and Resources are mocked. This can be seen within the assignResourcesOutputs() and assignParameterOutputs() of validator.es6. A resource will always have a Ref of mock-ref-RESOURCENAME and will be attached other attributes which can be used with the Fn::GetAtt function. This allows for checking if attributes exist for a specific resource before deploying the template for real.

Intrinsic Functions

Each intrinsic function has a signature of doIntrinsicXYZ(ref, key) and is called by the resolveIntrinsicFunction(ref, key) function. The doIntrinsic.. function should return the resolved value of the function. For example, for Fn::Sub, an input of "My ${MyInstance}" would return a string similar to "My i-0a0a0a0a0a.

Parameterized types

Type parameterization is a technique primarily used in cfn-lint for supporting SAM validation as well as user-defined resource attributes, by allowing a certain resource type or property type to have it's specification enhanced/overridden by another registered type, dynamically.

Prime examples for a parameterized resource type, property type and even a mixture of both would respectively be: AWS::S3::Bucket<somethingCool>, AWS::S3::Bucket.BucketEncryption<somethingAwesome> and AWS::S3::Bucket<somethingCool>.BucketEncryption<somethingAwesome>; where somethingCool and somethingAwesome can be any registered resource (e.g. AWS::CodeBuild::Project) or property type (e.g. AWS::CodeBuild::Project.Artifacts).

In regards to user-defined resource attributes that are applicable to a given resource based on its' logical ID, the parameter's value would be the logical ID (e.g. AWS::S3::Bucket<somethingCool>, where somethingCool is the logical ID that's present in the specific template), which has been previously registered as a type with it's respective specification.

Apart from the above mentioned, parameterization is also used for specifying the item type of an aggregate type (i.e. List or Map) and usually occurs within the Type attribute of property specifications when a property may take multiple forms such as in SAM templates.

SAM validation process

Due to the fact that SAM templates support various types or even a mixture of types for a given template property value and that cfn-lint's validation algorithm is designed for the CFN specification that does not, therefore, in order to attain compatibility between the different formats, a property type inference procedure was implemented, namely applySAMPropertyOverrides, that scans the template, attempts to determine the actual type of a given SAM property based on it's value type or shape in template, if applicable and if successful it then registers a logical name override for the resource in question with the disambiguated specification.

In addition, SAM templates also require a transformation process, entailing new resources to be generated according to the node-tree matching patterns defined in the data/sam_20161031_output_resources.json file and placed in a distinct section, namely SAMOutput, by the doSAMTransform procedure so that they can later be utilized within intrinsics.

cfn-lint supports SAM template validation by extending the current CFN specification with additional SAM specific resources that are defined in the data/sam_20161031_cfn.json file (i.e. applySpecificationOverrides), optionally enhancing the definitions of specific entries that reside under the Resources section of a to-be-validated template with definitions extracted from the Globals section of the aforementioned template (i.e. processSAMGlobals) and finally, before the actual template resource validation takes place, the template is recursively scanned and specific resources are generated under the SAMOutput section (i.e. doSAMTransform), in a two phase approach, one that occurs before values are assigned to parameters and resource properties/attributes as well as intrinsic resolution and another one after the aforementioned so that the inference process can disambiguate between an arbitrary number of SAM types that define a specific template resource property.

Known limitations:

  • Primitive types Integer, Long and Double are indistinguishable;
  • Primitive types String and Timestamp are indistinguishable;
  • SAM policy templates are not implemented;

Release Instructions

  1. For each PR, edit the CHANGELOG.md file, adding a fixed, changed or added message to the Unreleased block.
  2. Create a milestone in Github for all issues and PRs which will be included in the release, for example, v1.7.0.
  3. Create a PR for the release (branch release-VERSION), moving the contents of the CHANGELOG.md to a new version, update the links at the bottom of the file.
  4. Ensure the latest CFN Specification is present (AWS CloudFormation Resource Specification) in the data/aws_resources_specification.json file, update if required.
  5. Ensure the latest SAM Specification is present (SAM Schema) in the data/sam_20161031_schema.json file, update if required.
  6. Update the CFN compatible SAM specification file, namely data/sam_20161031_cfn.json, by executing:
cd lib && node sam2CFN.js && cd ..
  1. Verify changes and merge into master with the title Update CHANGELOG for VERSION (#PRNUM).
  2. Go to Releases and click "Draft a new release".
  3. Enter the tag of the version and the same for the release title, for example, v1.7.0.
  4. Copy the section of the CHANGELOG.md file for the release into the describe section.
  5. Click publish release. This will build a publish a package to npm.
  6. The unit tests can generally be trusted, however, a quick test will do no harm and might catch something missed. Next, test the release in a clean environment, ensuring the latest version is pulled.
> docker run -it node /bin/bash
$ npm install -g cfn-lint
$ cat <<EOF >working.yaml
Resources:
   MyBucket:
     Type: AWS::S3::Bucket
EOF
$ cfn-lint validate working.yaml
$ cat <<EOF >failure.yaml
Resources:
   MyBucket:
     Type: AWS::S3::Buckets
EOF
$ cfn-lint validate failure.yaml

Contributions

Please check out the Contributor's Guide for more information on how to get started.

Translations

This document is available in:

If you wish to translate this document to another language, we welcome your contribution!

cfn-lint's People

Contributors

acolombier avatar akdor1154 avatar ivanwills-optus avatar jonscheiding avatar kcculhwch avatar luigibaute avatar martysweet avatar naughtldy avatar nskoufis avatar razzm13 avatar rforte avatar tomdionysus avatar yshshrm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cfn-lint's Issues

Improper Type Checking + Invalid search string

  1. String checks should allow '-' in the regex.

  2. Template Formation Version is expecting a quoted "2010-09-09", for some reason, unquoted 2010-09-09 is throwing an error.

  3. The "Expected String type" error is giving 'String.IpProtocol' as a type, as opposed to 'SecurityGroup.IpProtocol', this is creating the invalid search

Resource: AWSTemplateFormatVersion
Message: AWSTemplateFormationVersion should be "2010-09-09"
Documentation: http://docs.aws.amazon.com/search/doc-search.html?searchPath=documentation-guide&searchQuery=AWSTemplateFormatVersion&x=0&y=0&this_doc_product=AWS+CloudFormation&this_doc_guide=User+Guide&doc_locale=en_us#facet_doc_product=AWS%20CloudFormation&facet_doc_guide=User%20Guide

Resource: Resources > SecurityGroup > Properties > IpProtocol
Message: Expected type String for IpProtocol, got value -1
Documentation: http://docs.aws.amazon.com/search/doc-search.html?searchPath=documentation-guide&searchQuery=String.IpProtocol&x=0&y=0&this_doc_product=AWS+CloudFormation&this_doc_guide=User+Guide&doc_locale=en_us#facet_doc_product=AWS%20CloudFormation&facet_doc_guide=User%20Guide

Extended validation flag

After validating, have the option to use the AWS API to do a final check

This ensures everything can be caught

Typescript?

Hey,
I'm trying to write a PR to add map support and I'm finding that there are a lot of extraneous checks in this project for whether properties exist or not, etc. It's always good to be careful with js, but I think the level you are going to here is leading to a quite difficult to read codebase.

Would you accept a PR to write this in Typescript instead of es6? I'm happy to do the work, you're already transpiling (it would replace Babel), and I think it would lead to much cleaner code (the typescript compiler is smart enough to know when certain checks are not required, so you can largely rely on build-time safety instead of the hand-written runtime checks you are using now).

I know this would be quite an invasive change, so that's why I'm checking instead of barging ahead and PR/forking. If you're unsure maybe we could chat over some IM medium?

Cheers
Jarrad

Improve CLI Interface

The CLI interface isn't great.

  • Allow for randomly ordered parameters
  • Attempt to mimic aws cloudformation validate-stack and parameters as closely as possible
  • Add help and hints (auto completion?)

Watch file

As this is a dev tool, watching a template could be useful

Validation without parameters

I'd like to be able to locally validate the syntax of my CloudFormation templates on PRs. I don't have any requirements to validate parameters and it's not realistic for me to document the parameters of all the templates I have. It would be quite useful to skip that option and any validation that depends on passing through parameters.

errorr: uncaughtException: toGet.slice when running validate

When i run the command: /usr/bin/cfn-lint validate idam-master-apps.yml

i get the following error:
root@bd9dd3ebbb6a:/home/jenkins/workspace/gehc-cft-idam/gehc-cft-idam# /usr/bin/cfn-lint validate idam-master-apps.yml
2017-07-26T13:42:37.586Z - error: uncaughtException: toGet.slice(...).join is not a function date=Wed Jul 26 2017 13:42:37 GMT+0000 (UTC), pid=708, uid=0, gid=0, cwd=/home/jenkins/workspace/gehc-cft-idam/gehc-cft-idam, execPath=/usr/local/nvm/versions/v7.4.0/bin/node, version=v7.4.0, argv=[/usr/local/nvm/versions/v7.4.0/bin/node, /usr/bin/cfn-lint, validate, idam-master-apps.yml], rss=36220928, heapTotal=18747392, heapUsed=10032080, external=61182, loadavg=[1.36962890625, 0.50634765625, 0.27392578125], uptime=1369536, trace=[column=40, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=doIntrinsicGetAtt, line=473, method=null, native=false, column=20, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=resolveIntrinsicFunction, line=375, method=null, native=false, column=38, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=recursiveDecent, line=327, method=null, native=false, column=13, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=recursiveDecent, line=337, method=null, native=false, column=13, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=recursiveDecent, line=337, method=null, native=false, column=13, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=recursiveDecent, line=337, method=null, native=false, column=13, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=recursiveDecent, line=337, method=null, native=false, column=13, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=recursiveDecent, line=337, method=null, native=false, column=5, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=resolveReferences, line=299, method=null, native=false, column=5, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=validateWorkingInput, line=108, method=null, native=false], stack=[TypeError: toGet.slice(...).join is not a function, at doIntrinsicGetAtt (/usr/lib/node_modules/cfn-lint/lib/validator.js:473:40), at resolveIntrinsicFunction (/usr/lib/node_modules/cfn-lint/lib/validator.js:375:20), at recursiveDecent (/usr/lib/node_modules/cfn-lint/lib/validator.js:327:38), at recursiveDecent (/usr/lib/node_modules/cfn-lint/lib/validator.js:337:13), at recursiveDecent (/usr/lib/node_modules/cfn-lint/lib/validator.js:337:13), at recursiveDecent (/usr/lib/node_modules/cfn-lint/lib/validator.js:337:13), at recursiveDecent (/usr/lib/node_modules/cfn-lint/lib/validator.js:337:13), at recursiveDecent (/usr/lib/node_modules/cfn-lint/lib/validator.js:337:13), at resolveReferences (/usr/lib/node_modules/cfn-lint/lib/validator.js:299:5), at validateWorkingInput (/usr/lib/node_modules/cfn-lint/lib/validator.js:108:5)]

It appears i have the npm libs installed but not sure why this is failing

GetAtt does not support attributes with double periods

Outputs:
  DBDNS:
    Description: DNS Name of the DB Instance
    Value: !GetAtt Database.Endpoint.Address

Results in

Resource: Outputs > DBDNS > Value
Message: Invalid parameters for Fn::GetAtt
Documentation: http://docs.aws.amazon.com/search/doc-search.html?searchPath=documentation-guide&searchQuery=Fn::GetAtt&x=0&y=0&this_doc_product=AWS+CloudFormation&this_doc_guide=User+Guide&doc_locale=en_us#facet_doc_product=AWS%20CloudFormation&facet_doc_guide=User%20Guide

However !GetAtt Database.Endpoint.Address is valid and works in CloudFormation.

CLI exit codes

Can the CLI provide a non-zero exit code for invalid templates, and optionally when crit and warn results exist?

This will allow cfn-lint to be used in a CI process that can abort/fail when invalid templates and/or critical errors are present

Double nested PropertyTypes are not checked correctly

A template such as

Resources:
  CloudFrontDistribution:
    Type: "AWS::CloudFront::Distribution"
    Properties:
      DistributionConfig:
        Aliases:
          - !Ref DomainName
        CacheBehaviors:
          CacheBehavior
        DefaultCacheBehavior:
          DefaultCacheBehavior
        DefaultRootObject: index.php"
        Enabled: true
        Logging:
          Bucket: mybucket
          IncludeCookies: false
          Prefix: !Sub "${DomainName}/"
       Origins:
          - Id: !Sub "Root-${OriginDomainName}"
            DomainName: !Ref OriginDomainName
            CustomOriginConfig:
              OriginProtocolPolicy: http-only
        PriceClass: String
        ViewerCertificate:
          AcmCertificateArn: !Ref CertificateArn

Will throw an error of:

Resource: Resources > CloudFrontDistribution > Properties > DistributionConfig
Message: Bucket is not a valid property of AWS::CloudFront::Distribution.DistributionConfig.Logging
Documentation: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distributionconfig.html#cfn-cloudfront-distributionconfig-logging

Resource: Resources > CloudFrontDistribution > Properties > DistributionConfig
Message: CustomOriginConfig is not a valid property of AWS::CloudFront::Distribution.DistributionConfig.Origin
Documentation: http://docs.aws.amazon.com/search/doc-search.html?searchPath=documentation-guide&searchQuery=AWS::CloudFront::Distribution.DistributionConfig.Origin&x=0&y=0&this_doc_product=AWS+CloudFormation&this_doc_guide=User+Guide&doc_locale=en_us#facet_doc_product=AWS%20CloudFormation&facet_doc_guide=User%20Guide

Among others...

This should be Resources > CloudFrontDistribution > Properties > DistributionConfig > Logging, however it looks like the PropertyType is correct.

Parameter type List<AWS::EC2::SecurityGroup::Id>

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  ExistingSecurityGroups:
    Type: List<AWS::EC2::SecurityGroup::Id>
Resources:
  Bucket:
    Type: AWS::S3::Bucket

Results in:

0 infos
0 warn
1 crit
Resource: Parameters > ExistingSecurityGroups
Message: Parameter ExistingSecurityGroups has an invalid type of List<AWS::EC2::SecurityGroup::Id>.
Documentation: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html

However List<AWS::EC2::SecurityGroup::Id> is valid.

[email protected]

Feature request - be able to call as a node library and access stack outputs

I am working to integrate this tool with Sceptre, which is a tool to orchestrate a set of stacks being deployed at once. I am not attempting to actually modify sceptre to call cfn-lint directly, but I am writing a local validation tool that runs cfn-lint on all stacks in a Sceptre environment.

It would be really helpful to be able to do require('cfn-lint') in a node bridging script, as it's difficult to parse CLI output (and I guess this is not maintained as part of the concept of stable API, which is fair enough..)

require('cfn-lint/validator') does currently work as a workaround.

In addition, and for the same reason, it would be great to have access to computed stack outputs in the errorObject.

I currently have a branch that does both of these; would this functionality be considered?

Tags is not a valid property of AWS::AutoScaling::AutoScalingGroup

Yes it is.

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-as-group.html#aws-properties-as-group-prop

For example:

ConsulAutoScalingGroup:
  Type: AWS::AutoScaling::AutoScalingGroup
  Properties:
    DesiredCapacity: 3
    MaxSize: 7
    MinSize: 3
    MetricsCollection:
      Granularity: 1Minute
    HealthCheckType: EC2
    LaunchConfigurationName: !Ref ConsulLaunchConfiguration
    VPCZoneIdentifier: !FindInMap [!Ref "AWS::AccountId", !Ref "AWS::Region", "PrivateSubnets"]
    Tags:
      - Key: Consul-Auto-Discover
        Value: !Sub "Consul-${AWS::AccountId}-${AWS::Region}-${AWS::StackName}"
        PropagateAtLaunch: true

Security group rule

Invalid value 'Must specify both from and to ports with ICMP.' for portRange.

ManagedPolicyName is not a valid property

  DeploymentIAMPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: DeploymentPolicyForMyApplication

Results in:

1 crit
Resource: Resources > DeploymentIAMPolicy > Properties
Message: ManagedPolicyName is not a valid property of AWS::IAM::ManagedPolicy
Documentation: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-managedpolicy.html

However "ManagedPolicyName" is specified here http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-managedpolicy.html

Exception when passing an AWS::ECS::TaskDefinition with LogConfiguration

task.yaml:

Resources:
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      ContainerDefinitions:
        - LogConfiguration:
            Options:
              awslogs-region: "region"

cfn-lint validate task.yaml

/usr/local/lib/node_modules/cfn-lint/lib/resourcesSpec.js:121
    return spec.hasOwnProperty('AdditionalProperties') && spec['AdditionalProperties'] === true;
               ^

TypeError: Cannot read property 'hasOwnProperty' of null
    at Object.isAdditionalPropertiesEnabled (/usr/local/lib/node_modules/cfn-lint/lib/resourcesSpec.js:122:16)
    at checkResourceProperty (/usr/local/lib/node_modules/cfn-lint/lib/validator.js:928:49)
    at checkProperty (/usr/local/lib/node_modules/cfn-lint/lib/validator.js:1049:21)
    at checkResourceProperty (/usr/local/lib/node_modules/cfn-lint/lib/validator.js:973:17)
    at checkProperty (/usr/local/lib/node_modules/cfn-lint/lib/validator.js:1049:21)
    at checkResourceProperty (/usr/local/lib/node_modules/cfn-lint/lib/validator.js:973:17)
    at checkProperty (/usr/local/lib/node_modules/cfn-lint/lib/validator.js:1049:21)
    at checkResourceProperty (/usr/local/lib/node_modules/cfn-lint/lib/validator.js:955:29)
    at /usr/local/lib/node_modules/cfn-lint/lib/validator.js:919:9
    at Array.forEach (native)

Numeric Parameters not being validated

It appears parameters with values of int are not being processed properly. This is probably getting picked up on tests but being ignored as the majority of tests only check critical errors.

Resource: Resources > ALBTargetGroup > Properties
Message: Unhandled property for HealthCheckIntervalSeconds
Documentation: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html#cfn-elasticloadbalancingv2-targetgroup-healthcheckintervalseconds

Resource: Resources > ALBTargetGroup > Properties
Message: Unhandled property for UnhealthyThresholdCount
Documentation: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html#cfn-elasticloadbalancingv2-targetgroup-unhealthythresholdcount

Resource: Resources > ALBTargetGroup > Properties
Message: Unhandled property for Port
Documentation: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html#cfn-elasticloadbalancingv2-targetgroup-port

Resource: Resources > DNSRecordInstance > Properties
Message: Unhandled property for TTL
Documentation: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-recordset.html#cfn-route53-recordset-ttl

GetAtt in Outputs not reporting template invalid

Template

Resources:
  Bucket:
    Type: AWS::S3::Bucket

Outputs:
  DBDNS:
    Description: DNS Name of the DB Instance
    Value: !GetAtt Database.Endpoint.Address

Results in a Valid Template, however Database is not defined in resources, so this template should be invalid.

Feature request - more control over parameter validation

It would be useful if cfn-lint could be ran in a sort of 'strict mode' that it would create an error if a parameter was missing and not provided as a Default or on the CLI, instead of (or maybe as well as) proceeding with a mocked value.

Perhaps an optional options argument passed to validateFile to switch behaviour.

Would you accept this?

Yaml shorthand !Fn::Sub

      UserData:
        - Fn::Base64
            !Fn::Sub "PERSCODE=${ProvisionKey}"

Does not throw any validation errors

!Fn is invalid, should be !Sub

CloudFormation Stack Resoure - Passing Parameters causes uncaughtException

When using an AWS::CloudFormation::Stack resource type, in both JSON and YAML, if parameters are passed under resource properties validation fails with error: uncaughtException: Cannot read property 'hasOwnProperty. From error messages and my own troubleshooting, I believe that this bug is from validator.js's function checkResourceProperties, when it attempts process each property for property validation with checkEachProperty(resourceType, resources[res], 'Properties');. I've been able to replicate this the CloudFormation templates in
replication.txt.

As a workaround, I've added a check for resource type prior to checkEachProperty that seems to resolve the error, but presumably removes the desired vetting of parameters for AWS::CloudFormation::Stack.

if (resourceType !== 'AWS::CloudFormation::Stack') {
                    checkEachProperty(resourceType, resources[res], 'Properties');
}

Update CONTRIBUTING.md and README.md

Update the files about the new branching strategy, brief project overview and status.

If all happy with TS, add TS documentation for newcomers to learn from.

Plan program workflow

COS

  • Resource nesting is shown in the error messages
  • Multiple error messages can be shown per run
  • YAML and JSON are supported
  • Uses the AWS API Spec for a knowledge base
  • First release only checks Resources
  • Give a link to the documentation for errors in an error summary once run
  • Debug should throw errors when found, and again at the end in the summary
cfn-lint --debug --region eu-west-1 mytemplate.yaml
  1. Validate users input
  2. For each resource defined, generate Outputs depending on type defined, throw error if invalid type
  3. Check for circular dependencies
  4. Resolve all !Ref and !Attr calls, then perform !Join
  5. Recursively descend through the template (if valid type)
    5.1. Take the resource type, store the resource name on a stack
    5.2. Check parameters for properties are valid, descending into them if type is not string
    5.3. Throw errors on type mismatch or where property is somethingArn and an Arn is not found to be it's value

Map picked up for Lambda ENV Vars

Resource: Resources > LambdaFunction > Properties > Environment > Variables
Message: HEALTHCHECK_BUCKET is not a valid property of AWS::Lambda::Function.Map
Documentation: http://docs.aws.amazon.com/search/doc-search.html?searchPath=documentation-guide&searchQuery=AWS::Lambda::Function.Map&x=0&y=0&this_doc_product=AWS+CloudFormation&this_doc_guide=User+Guide&doc_locale=en_us#facet_doc_product=AWS%20CloudFormation&facet_doc_guide=User%20Guide

Resource: Resources > LambdaFunction > Properties > Environment > Variables
Message: SOMETHING_ELSE is not a valid property of AWS::Lambda::Function.Map
Documentation: http://docs.aws.amazon.com/search/doc-search.html?searchPath=documentation-guide&searchQuery=AWS::Lambda::Function.Map&x=0&y=0&this_doc_product=AWS+CloudFormation&this_doc_guide=User+Guide&doc_locale=en_us#facet_doc_product=AWS%20CloudFormation&facet_doc_guide=User%20Guide

Could auto-mock Arn parameters

Currently, if a ResourceType has an Attribute with 'Arn' in its name, cfn-lint mocks the attribute value to be a valid arn.

Would it be acceptable to extend this behaviour to Parameters with 'Arn' in the name? I structure my templates like this already so it would certainly fit my needs. This would obviate the need to pass mock Arn parameters by hand. It is 'opinionated' behaviour though, so I'm not sure if you would accept it. (It certainly wouldn't break any existing behaviour though as far as I can guess, it just would only work for people if they write their templates in a certain way.))

Bucket Transitions non-array not detected

  S3LoggingBucket:
    Type: AWS::S3::Bucket
    Properties:
      LifecycleConfiguration:
        Rules:
          - Status: Enabled
            Transitions:
                StorageClass: GLACIER
                TransitionInDays: 60

is Invalid as Transitions should be array types (http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-lifecycleconfig-rule.html).

  S3LoggingBucket:
    Type: AWS::S3::Bucket
    Properties:
      LifecycleConfiguration:
        Rules:
          - Status: Enabled
            Transitions:
              - StorageClass: GLACIER
                TransitionInDays: 60

would be correct...

ALBRule does not like *

LoadBalancerListenerRule:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      Actions:
        - Type: forward
          TargetGroupArn: !Ref LoadBalancerTargetGroup
      Conditions:
        - Field: path-pattern
          Values:
            - "*"
      ListenerArn: !Ref LoadBalancerListener
      Priority: 1

Results in

Resource: Resources > LoadBalancerListenerRule > Properties > 0
Message: Expected type String for 0, got value '*'
Documentation: http://docs.aws.amazon.com/search/doc-search.html?searchPath=documentation-guide&searchQuery=AWS::ElasticLoadBalancingV2::ListenerRule.RuleCondition.0&x=0&y=0&this_doc_product=AWS+CloudFormation&this_doc_guide=User+Guide&doc_locale=en_us#facet_doc_product=AWS%20CloudFormation&facet_doc_guide=User%20Guide

However "*" is valid

Validation on properties of a parameter

An invalid property on a parameter doesn't seem to trigger an error (there's a typo in the Default key):

Parameters:
  MyPassword:
    Description: Password
    Type: String
    Defaut: hunter2
    NoEcho: True

This parameter was used in some UserData via Fn::Sub.

Raise a critical error when S3Bucket name have upper case.

This template will fail with the message "Bucket name should not contain uppercase characters
"

However cfn-lint is not able to catch this.
$ cfn-lint validate s3bucket_parameter.yaml
0 infos
0 warn
0 crit
Template valid!

Tonys-Mac-mini:~/cloudformation $  cat s3bucket_parameter.yaml
---
  AWSTemplateFormatVersion: "2010-09-09"
  Parameters:
    BucketName:
      Description: "Name of MyS3Bucket"
      Type: "String"
#      Default: "mys3bucketacloudgurutraining"
  Resources:
    S3Bucket:
      Type: "AWS::S3::Bucket"
      Properties:
        BucketName:
          Ref: "BucketName"
    S3Bucket2:
      Type: "AWS::S3::Bucket"
      Properties:
        BucketName: "Publicreadbucket220170703"
  Outputs:
    S3BucketName:
      Value:
        Ref: "S3Bucket"
      Description: "Name of S3 bucket"
    S3BucketName2:
      Value:
        Ref: "S3Bucket2"
      Description: "Name of S3 bucket"

Can not read property'hasOwnProperty' of null

Getting this error from a fresh install of cfn-lint version 1.1.7.

The cloudformation template i'm using is a valid json format template which has already been deployed successfully.

root@DESKTOP-9JIN1GI:/mnt/c/workspace/andover-pipelinebot# npm install -g cfn-lint
/usr/bin/cfn-lint -> /usr/lib/node_modules/cfn-lint/lib/index.js
/usr/lib
└── [email protected]

root@DESKTOP-9JIN1GI:/mnt/c/workspace/andover-pipelinebot# cfn-lint --version
1.1.7
root@DESKTOP-9JIN1GI:/mnt/c/workspace/andover-pipelinebot# cfn-lint validate .serverless/cloudformation-template-update-stack.json
2017-10-31T14:35:12.455Z - error: uncaughtException: Cannot read property 'hasOwnProperty' of null date=Tue Oct 31 2017 14:35:12 GMT+0000 (STD), pid=1178, uid=0, gid=0, cwd=/mnt/c/workspace/andover-pipelinebot, execPath=/usr/bin/node, version=v6.11.3, argv=[/usr/bin/node, /usr/bin/cfn-lint, validate, .serverless/cloudformation-template-update-stack.json], rss=26845184, heapTotal=19972096, heapUsed=10396944, external=69450, loadavg=[0.5185546875, 0.57763671875, 0.5859375], uptime=103911, trace=[column=16, file=/usr/lib/node_modules/cfn-lint/lib/resourcesSpec.js, function=Object.isAdditionalPropertiesEnabled, line=121, method=isAdditionalPropertiesEnabled, native=false, column=49, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=checkResourceProperty, line=928, method=null, native=false, column=21, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=checkProperty, line=1049, method=null, native=false, column=17, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=checkResourceProperty, line=973, method=null, native=false, column=21, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=checkProperty, line=1049, method=null, native=false, column=17, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=checkResourceProperty, line=973, method=null, native=false, column=9, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=null, line=919, method=null, native=false, column=null, file=null, function=Array.forEach, line=null, method=forEach, native=true, column=27, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=checkEachProperty, line=918, method=null, native=false, column=17, file=/usr/lib/node_modules/cfn-lint/lib/validator.js, function=checkResourceProperties, line=902, method=null, native=false], stack=[TypeError: Cannot read property 'hasOwnProperty' of null,     at Object.isAdditionalPropertiesEnabled (/usr/lib/node_modules/cfn-lint/lib/resourcesSpec.js:121:16),     at checkResourceProperty (/usr/lib/node_modules/cfn-lint/lib/validator.js:928:49),     at checkProperty (/usr/lib/node_modules/cfn-lint/lib/validator.js:1049:21),     at checkResourceProperty (/usr/lib/node_modules/cfn-lint/lib/validator.js:973:17),     at checkProperty (/usr/lib/node_modules/cfn-lint/lib/validator.js:1049:21),     at checkResourceProperty (/usr/lib/node_modules/cfn-lint/lib/validator.js:973:17),     at /usr/lib/node_modules/cfn-lint/lib/validator.js:919:9,     at Array.forEach (native),     at checkEachProperty (/usr/lib/node_modules/cfn-lint/lib/validator.js:918:27),     at checkResourceProperties (/usr/lib/node_modules/cfn-lint/lib/validator.js:902:17)]
root@DESKTOP-9JIN1GI:/mnt/c/workspace/andover-pipelinebot# cfn-lint validate .serverless/cloudformation-template-update-stack.json --pseudo AWS::Region=eu-west-1,AWS::AccountId=12345

API Gateway Support

We're getting a bunch of critical issues on our API Gateway definitions, which we believe are not actually issues.

They are mostly variations on these 3 issues:

API Gateway Resource PathPart
Resource: Resources > APIGatewayResource > Properties > PathPart
Message: Expected type String for PathPart, got value '{myPathPart}'

API Gateway Integration Responses
Resource: Resources > APIGatewayGetMethod > Properties > Integration > application/json
Message: Expected type String for application/json, got value '#set($inputRoot = $input.path('$'))

API Gateway Selection Pattern
Resource: Resources > APIGatewayGetMethod > Properties > Integration > SelectionPattern
Message: Expected type String for SelectionPattern, got value '.InternalServerError.'

This is a snippet of the offending cfn:

    APIGatewayResource:
      Type: "AWS::ApiGateway::Resource"
      Properties:
        PathPart: "{myPathPart}"
        RestApiId:
          Ref: APIGateway
    APIGatewayGetMethod:
      Type: "AWS::ApiGateway::Method"
      Properties:
        ApiKeyRequired: false
        AuthorizationType: "NONE"
        HttpMethod: GET
        Integration:
          Type: "AWS"
          PassthroughBehavior: WHEN_NO_TEMPLATES
          IntegrationHttpMethod: POST
          IntegrationResponses:
            - StatusCode: 200
            - StatusCode: 500
              ResponseTemplates:
                application/json:
                  Fn::FindInMap: [CustomVariables, responseTemplates, error]
              SelectionPattern: .*InternalServerError.*
            - StatusCode: 400
              SelectionPattern: .*BadRequest.*
              ResponseTemplates:
                application/json:
                  Fn::FindInMap: [CustomVariables, responseTemplates, error]
            - StatusCode: 404
              SelectionPattern: .*NotFound.*
              ResponseTemplates:
                application/json:
                  Fn::FindInMap: [CustomVariables, responseTemplates, error]
          RequestTemplates:
            application/json:
              Fn::FindInMap: [CustomVariables, requestTemplates, valid]
          Uri:
            Fn::Sub:
              - "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Lambda}/invocations"
              - Lambda:
                  Fn::GetAtt: [LambdaFunction, Arn]
        MethodResponses:
          - StatusCode: 200
            ResponseModels:
              application/json:
                Ref: ResponseModel
          - StatusCode: 500
          - StatusCode: 400
          - StatusCode: 404
        ResourceId:
          Ref: APIGatewayResource
        RestApiId:
          Ref: APIGateway

Conditional properties failing to evaluate

I'm not sure if this is currently supported, but I have some conditionals that are empty after being evaluated:

Parameters:
  Env:
    Description: Which Environment
    Type: String
    Default: Dev
    AllowedValues:
      - Dev
      - QA
      - PreProd
      - Production

Conditions:
  isProd: !Equals [!Ref Env, Production]
  isPreProd: !Equals [!Ref Env, PreProd]
  isProdOrPreProd: !Or
    - Condition: isProd
    - Condition: isPreProd
  isNotProdOrPreProd: !Not
    - Condition: isProdOrPreProd

Mappings:
  App:
    Dev:
      CertificateId: NA
      CertificateArn: arn:aws:acm:us-east-1:etc
    Production:
      CertificateId: 09187234234
      CertificateArn: NA

# ... CloudFront config
        ViewerCertificate:
          IamCertificateId: !If
             - isProd
             - !FindInMap [App, !Ref Env, CertificateId]
             - !Ref "AWS::NoValue"
          AcmCertificateArn: !If
             - isPreProd
             - !FindInMap [App, !Ref Env, CertificateArn]
             - !Ref "AWS::NoValue"

cfn-lint validate myapp.yml --pseudo AWS::Region=ap-southeast-2

Results in:

3 crit
Resource: Resources > cloudfrontDistribution > Properties > DistributionConfig > ViewerCertificate > IamCertificateId
Message: Expected type String for IamCertificateId, got value '' instead
Documentation: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distributionconfig-viewercertificate.html#cfn-cloudfront-distributionconfig-viewercertificate-iamcertificateid

Resource: Resources > cloudfrontDistribution > Properties > DistributionConfig > ViewerCertificate > AcmCertificateArn
Message: AcmCertificateArn is expecting an Arn, '' given. If this is a parameter, has it been specified with --parameters?
Documentation: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distributionconfig-viewercertificate.html#cfn-cloudfront-distributionconfig-viewercertificate-acmcertificatearn

Resource: Resources > cloudfrontDistribution > Properties > DistributionConfig > ViewerCertificate > AcmCertificateArn
Message: Expected type String for AcmCertificateArn, got value '' instead
Documentation: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distributionconfig-viewercertificate.html#cfn-cloudfront-distributionconfig-viewercertificate-acmcertificatearn

GetAZs function is unknown

Check your template is not malformed. unknown tag !<!GetAZs>

Usage: SubAStack: Properties: Parameters: AvailabilityZone: !Select ['0', !GetAZs {Ref: 'AWS::Region'}] Type: AWS::CloudFormation::Stack

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.