How to setup & use CloudFormation Hooks
Introduction
AWS CloudFormation hooks allows you to invoke custom logic to automate validation of resources. Customers have can select a pre-existing Hook from AWS’ Public Registry. It is also possible to create your own hook and publish them to your own Private Registry.
In this article, we will take a look at how to use one of the sample Hooks to prevent creation of an EC2 instance with an open ingress security group.
How to activate a CloudFormation Hook?
First, go to the CloudFormation console, and click on Public Extensions from the left menu.
Next, choose the following filters: Hooks
for Extension Type and Third Party
for Publisher
. We will be activating the following hook:
Before, we can activate this hook, we need to create an Execution IAM role for this hook.
The Trust policy
for the IAM role should be the following (replace your AWS region and Account number)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"resources.cloudformation.amazonaws.com",
"hooks.cloudformation.amazonaws.com"
]
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "account"
},
"StringLike": {
"aws:SourceArn": "arn:aws:cloudformation:us-west-2:account:type/hook/AWSSamples-SecurityGroupOpenIngress-Hook/*"
}
}
}
]
}
Also, give this IAM role permission to describe the security groups so that it can verify the security group during the stack invocation.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "ec2:DescribeSecurityGroup*",
"Resource": "*"
}
]
}
Now that you have created the IAM role, we will activate the CloudFormation Hook. In the activation screen enter the ARN for the Execution role that you just created and click on Activate Extension
. You can leave the other settings as default.
We also need to configure the Hook before we can start using it. In the next screen, add the following as the Configuration JSON and click on Configure extension
. Since the hook we are using doesn’t require any additional properties, our configuration is pretty straightforward. We want to apply this hook to ALL
stacks and we want the stack to FAIL
if there is a violation.
{
"CloudFormationConfiguration": {
"HookConfiguration": {
"TargetStacks":"ALL",
"FailureMode":"FAIL"
}
}
}
How to test the hook?
We have enabled our hook that should ensure we don’t have any EC2 instances with open security groups. Let’s test if the hook is working as expected.
Lets create a CloudFormation stack that is not compliant with our hook as follows:
AWSTemplateFormatVersion: "2010-09-09"
Resources:
EC2InstanceNonCompliant:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
SecurityGroups: [!Ref 'InstanceSecurityGroup']
ImageId: ami-0341aeea105412b57
Tags:
- Key: Name
Value: EC2InstanceNonCompliant
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "wide open group"
SecurityGroupIngress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
We can use the AWS CLI to create the stack as follows:
aws cloudformation create-stack --stack-name sg-group-hook-non-compliant --template-body file://ec2-non-compliant.yaml
As expected, we see the CloudFormation stack that we just created failed because it was non-compliant with our hook.
We will also create an EC2 instance that is valid to ensure that the hook won’t fail a stack that is compliant.
AWSTemplateFormatVersion: "2010-09-09"
Resources:
EC2InstanceCompliant:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
SecurityGroups: [!Ref 'InstanceSecurityGroup']
ImageId: ami-0341aeea105412b57
Tags:
- Key: Name
Value: EC2InstanceCompliant
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "less wide open group"
SecurityGroupIngress:
- IpProtocol: -1
CidrIp: 10.0.0.0/16
As expected, this stack succeeded and the EC2 instance was created.