-
Notifications
You must be signed in to change notification settings - Fork 58
CloudFormation Best Practices
- Validate your templates
- Use parameter constraints
- Use AWS-specific parameter types
- Use NoEcho to hide sensitive data
- Include an Outputs section
- Use CloudFormation::Init to install packages and customize the OS
- Use stack policies to protect critical resources
- Control stack access with IAM
- Verify service limits
- Log CloudFormation API calls with CloudTrail
Validate your templates
Validating your templates will help catch syntax and dependency issues before using them.
aws cloudformation validate-template \ --template-body file://myCFN.template.json
Use parameter constraints
Parameter constraints can help catch invalid values before launching a stack.
"OwnerService" : {
"Type" : "String",
"Default" : "eng",
"Description" : "Owner or service name.",
"AllowedPattern" : "[-a-z0-9]*",
"ConstraintDescription" : "Must be lowercase, no spaces, dashes ok."
}
"BastionCount" : {
"Type" : "Number",
"Default" : "1",
"MinValue" : "0",
"MaxValue" : "1",
"Description" : "Enter '1' to launch a bastion host, or '0' to terminate."
}
Use AWS-specific parameter types
This example will list all the existing key pair names that are available to choose from in the region where you're launching the stack.
UserKeys" : {
"Type" : "AWS::EC2::KeyPair::KeyName",
"Description" : "Your instance key pair name."
}
This example allows you to choose one or more existing Subnet Ids.
"PubSubnets" : {
"Type" : "List<AWS::EC2::Subnet::Id>,"
"Description" : "Public Subnet IDs."
}
Use NoEcho to hide sensitive data
Sensitive information such as usernames and passwords will not be displayed.
Note: NoEcho is set to false by default.
"DBPassword" : {
"NoEcho" : "true",
"Description" : "Master password",
"Type" : "String",
"MinLength" : "8",
"MaxLength" : "16"
}
Include an Outputs section
Organize and easily find important information. The Outputs section, when used with the Fn::GetAtt intrinsic function, returns the value of one or more attributes. This code snippet will return the public IP address of our NAT instance.
"Outputs" : {
"NatId" : {
"Description" : "NAT Id",
"Value" : { "Ref" : "ec2NATInstance" }
},
"NatIP" : {
"Description" : "NAT Public IP",
"Value" : { "Fn::GetAtt" : [ "ec2NATInstance", "PublicIp" ] }
}
}
Use CloudFormation::Init to install packages and customize the OS
This example configures iptables and ensures that it's running after a restart. It disables the sendmail service. cfn-init is called from the UserData section. Also see, cfn-hup.
"asBastionlaunch" : {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"Metadata" : {
"Comment" : "Setup iptables and disable unwanted services",
"AWS::CloudFormation::Init" : {
"config" : {
"commands" : {
"iptables.sh" : {
"command" : {
"Fn::Join" : [ "",
[ "/sbin/iptables -F\n",
"/sbin/iptables -P INPUT DROP\n",
"/sbin/iptables -P FORWARD DROP\n",
"/sbin/iptables -P OUTPUT ACCEPT\n",
"/sbin/iptables -A INPUT -p tcp --dport 22 -j ACCEPT\n",
"/sbin/iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT\n",
"/sbin/iptables -A INPUT -i lo -j ACCEPT\n",
"/sbin/service iptables save\n" ]
]
} } },
"services" : {
"sysvinit" : {
"sendmail" : {
"enabled" : "false",
"ensureRunning" : "false"
},
"iptables" : {
"enabled" : "true",
"ensureRunning" : "true"
} } }
}
}
},
"Properties" : {
...
"UserData" : {
"Fn::Base64" : {
"Fn::Join" : [ "",
[ "#!/bin/bash -ex\n",
"yum update -y aws-cfn-bootstrap\n",
"yum update -y\n",
"# Work on Metadata.\n",
"/opt/aws/bin/cfn-init -v",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource asBastionlaunch\n" ]
]
}
}
}
Use stack policies to protect critical resources
The policy below prevents the replacement of our NAT server instances during a stack update.
{
"Statement" : [
{
"Effect" : "Deny",
"Action" : "Update:Replace",
"Principal" : "*",
"Resource" : "LogicalResourceId/*NATServer*"
},
{
"Effect" : "Allow",
"Action" : "Update:*",
"Principal" : "*",
"Resource" : "*"
}
]
}
Control stack access with IAM
The following prevents an IAM user assigned the policy from updating or deleting stacks with "VPC" in the stack name.
{
"Version" : "2012-10-17",
"Statement" : [
{
"Action" : [
"cloudformation:*"
],
"Effect" : "Allow",
"Resource" : "*"
},
{
"Action" : [
"cloudformation:DeleteStack",
"cloudformation:UpdateStack"
],
"Effect" : "Deny",
"Resource" : "arn:aws:cloudformation:us-west-2:XXXXXXXX2745:stack/*VPC*"
}
]
}
Verify service limits
Check resource quotas via Trusted Advisor >> Performance >> Service Limits
Log CloudFormation API calls with CloudTrail
Enable CloudTrail in all regions. CloudTrail is a service that captures API calls. Using the information collected in CloudTrail, you can determine what requests were made to CloudFormation.