Secure AWS CloudFormation Templates with cnspec
Scan AWS CloudFormation templates for security misconfigurations with cnspec.
import IacScanOptions from './_iac-scan-options.mdx';
Catch insecure AWS resource configurations before they reach a stack. cnspec parses both YAML and JSON CloudFormation templates and exposes resources, parameters, outputs, and other template sections as queryable MQL resources. The Mondoo AWS Security policy ships CloudFormation variants of every check, so the same controls that evaluate your live AWS account also evaluate your CloudFormation templates in pull requests and CI pipelines. You can also use the CloudFormation provider inside your own policies to enforce additional standards.
Prerequisites
To scan CloudFormation templates with cnspec, you must have:
- cnspec installed on your workstation
- CloudFormation template files (
.yamlor.json) to scan
Scan a CloudFormation template
Scan a single template file:
cnspec scan cloudformation template.yamlcnspec automatically detects whether the template is YAML or JSON.
Explore CloudFormation templates
Run cnspec shell cloudformation template.yaml to open the interactive shell and explore your templates.
Retrieve template info
cnspec> cloudformation.template { version description }
cloudformation.template: {
version: "2010-09-09"
description: "Production infrastructure stack"
}List all resources
cnspec> cloudformation.template.resources
cloudformation.template.resources: [
0: cloudformation.resource type="AWS::EC2::Instance"
1: cloudformation.resource type="AWS::S3::Bucket"
...
]Retrieve resource details
cnspec> cloudformation.template.resources { name type properties }
cloudformation.template.resources: [
0: {
name: "WebServer"
type: "AWS::EC2::Instance"
properties: {
InstanceType: "t3.micro"
ImageId: "ami-0abcdef1234567890"
}
}
...
]Filter resources by type
Find all S3 bucket resources:
cnspec> cloudformation.template.resources.where(type == "AWS::S3::Bucket") { name properties }
cloudformation.template.resources.where: [
0: {
name: "DataBucket"
properties: {
BucketName: "my-data-bucket"
VersioningConfiguration: {
Status: "Enabled"
}
}
}
]List all resource types used in the template:
cnspec> cloudformation.template.types
cloudformation.template.types: [
0: "AWS::EC2::Instance"
1: "AWS::S3::Bucket"
2: "AWS::IAM::Role"
...
]Inspect template parameters
cnspec> cloudformation.template.parameters
cloudformation.template.parameters: {
InstanceType: {
Type: "String"
Default: "t3.micro"
AllowedValues: ["t3.micro", "t3.small", "t3.medium"]
}
Environment: {
Type: "String"
Default: "production"
}
...
}List template outputs
cnspec> cloudformation.template.outputs { name properties }
cloudformation.template.outputs: [
0: {
name: "InstanceId"
properties: {
Description: "The instance ID"
Value: {"Ref": "WebServer"}
}
}
...
]Retrieve conditions
cnspec> cloudformation.template.conditions
cloudformation.template.conditions: {
IsProduction: {
"Fn::Equals": [{"Ref": "Environment"}, "production"]
}
...
}Retrieve mappings
cnspec> cloudformation.template.mappings
cloudformation.template.mappings: {
RegionMap: {
us-east-1: {
AMI: "ami-0abcdef1234567890"
}
us-west-2: {
AMI: "ami-0fedcba9876543210"
}
}
...
}Get full template details
cnspec> cloudformation.template { * }Example security checks
Ensure EC2 instances don't use a hardcoded AMI
cloudformation.template.resources.where(type == "AWS::EC2::Instance").all(
properties["ImageId"] != /^ami-/
)Check that no security groups allow unrestricted SSH
cloudformation.template.resources.where(type == "AWS::EC2::SecurityGroup") {
name
properties["SecurityGroupIngress"]
}Learn more
-
For the full MQL resource reference, see the MQL CloudFormation provider documentation.
-
To learn more about how the MQL query language works, read Write Effective MQL.