Protecting resources managed by CloudFormation with a Stack Policy


Brett Gillett

A CloudFormation stack policy is a JSON document that allows you to control who can update resources deployed via CloudFormation.

In combination with a deletion policy, it provides you with a simple way to protect from accidentally updating a resource during a CloudFormation stack update.

Introduction

Before looking at a simple stack policy, knowing a few key concepts is essential.

First, a CloudFormation stack does not have an associated policy document by default. Therefore, you need to create a stack policy to protect resources in a CloudFormation stack.

It’s also important to remember that a stack policy applies only to CloudFormation update actions. It does not protect resources from updates made outside of CloudFormation. For example, someone - with the proper access - using the AWS Management Console or making an API call can still update a resource initially deployed via CloudFormation regardless of a stack policy being in place.

Also, a stack policy is an example of an inline (or embedded) policy, which means a one-to-one relationship exists between a CloudFormation stack and a stack policy. It also means that the associated policy document is deleted if you delete a CloudFormation stack.

A stack policy denies all activity by default. Therefore, you’ll need to decide what update actions (if any) you want to allow. Also, once a stack policy is associated, you cannot remove it - you can only ‘allow all’ update actions.

Here’s a super simple policy that allows updates on all resources but denies any updates to both EC2 and RDS instances defined in our CloudFormation Stack:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  "Statement" : [
    {
      "Sid": "AllowAllUpdates",
      "Effect": "Allow",
      "Action": "Update:*",
      "Principal": "*",
      "Resource": "*"
    },
    {
      "Sid": "DenyEC2RDSUpdates",
      "Effect": "Deny",
      "Action": "Update:*",
      "Principal": "*",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "ResourceType": ["AWS::EC2::Instance", "AWS::RDS::DBInstance"]
        }
      }
    }
  ]
}

What if you try to update an EC2 instance via the CloudFormation console? You’ll get an error - see the example below.

CloudFormation update failed due to stack policy

What happens in a scenario where you want to allow updates on resources? No problem - set a temporary policy that will enable updates. Then, when you’ve made the updates, reinstate the original policy document.

You might have a prebuilt ‘allow all’ policy document ready to go. Here’s an example,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  "Statement" : [
    {
      "Sid": "AllowAllUpdates",
      "Effect": "Allow",
      "Action": "Update:*",
      "Principal": "*",
      "Resource": "*"
    }
  ]
}

Adding a Stack Policy

You can add a stack policy when creating a new stack or add a policy to an existing stack. Creating or updating stack policies can be done via the AWS Management Console or programmatically using the AWS CLI or SDK.

If you already have a stack deployed and want to add a stack policy, you can do it easily using the AWS CLI. Here’s an example of using a local JSON file as your policy document:

1
 aws cloudformation set-stack-policy --stack-name <stack name> --stack-policy-body file://<path to local file>

You could also have the JSON policy document in S3 and reference it by adjusting the above command by changing: –stack-policy-body to –stack-policy-url and pointing to the JSON file in an S3 bucket using an S3 URL.


Brett Gillett


Orbit

Like what you read? Why not subscribe to the weekly Orbit newsletter and get content before everyone else?