Writing January 5, 2022 · 3 min read

Protecting resources managed by CloudFormation with a Stack Policy


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.

Interested in learning CloudFormation?

Check out our self-directed, project-based CloudFormation course.

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.

All writing Start a conversation