Sometimes we want to give users the ability to create pretty much anything with CloudFormation but at the same time prevent them from doing the same through the console or aws-cli. Perhaps it’s a company policy that everything must be managed using CloudFormation. Or on the other hand you may have Admin privileges but want to CloudFormation can do on your behalf.


CloudFormation Service Role

CFN Service Role can achieve exactly that – users can have a separate set of credentials for work outside of  CloudFormation and a completely different set of credentials for creating, updating and deleting CloudFormation stacks.

For example grant CloudFormation all the privileges it needs to create the stack but in the console limited the users to ReadOnly access.

Here is how…

1. Create CloudFormation Service Role

In this case we’ll give it Administrative privileges but in reality you should only give it as little privileges as it needs.

Of course we’ll use CloudFormation to create it 🙂

    Type: AWS::IAM::Role
      RoleName: svcCloudFormation
      Path: /service/
        Version: 2012-10-17
        - Action: sts:AssumeRole
          Effect: Allow
        - arn:aws:iam::aws:policy/AdministratorAccess

This role can only be used by CloudFormation, you can’t assume it as a user e.g. with aws sts assume-role or use it as EC2 instance role.

2. Create an IAM Policy that can use the role

The most important permission it needs is iam:PassRole that gives it the ability to instruct CloudFormation to use the above IAM Role to create resources in CFN stacks.

The policy also needs some basic CloudFormation permissions to upload the template file to S3 and to actually create the stack. However it does not need permissions to create any of the resources in the stack. That will be done through the role.

     Type: AWS::IAM::ManagedPolicy
       ManagedPolicyName: svcCloudFormation
       Path: /
         Version: 2012-10-17
         - Action:
           - iam:PassRole
           Effect: Allow
           - !GetAtt CfnServiceRole.Arn
         - Action:
           - cloudformation:CreateStack
           - cloudformation:CreateUploadBucket
           Effect: Allow
           Resource: "*"
         - Action:
           - s3:PutObject
           - s3:GetObject
           - s3:ListBucket
           Effect: Allow
           - arn:aws:s3:::cf-templates-*
           - arn:aws:s3:::cf-templates-*/*

The complete CloudFormation template to create the role and the policy is can be downloaded here: cfn-service-role-and-policy.yml

3. Create CFN User

We’ll create a new IAM User called e.g. cfn-user. We will restrict it to Read Only access but will also attach the above cfnCloudFormation managed policy to give it the ability to create CFN stacks.

CFN User Summary

4. Create a stack using the service role

Login in a new window as the just-created cfn-user account and try to create a new CloudFormation stack. Without the role the stack creation will fail because cfn-user doesn’t have a permission to create any resources:

However if you select the role in the drop-down list and proceed as usual your stack will get successfully created:

Updating and deleting stacks

Notice the warning above when you selected the role:


AWS CloudFormation will use this role for all stack operations. Other
users that have permissions to operate on this stack will be able to
use this role, even if they don’t have permission to pass it.

What does that mean? Once the IAM Role is attached to the CFN stack it is used for all subsequent operations on the stack! That means the users who can manipulate the stack can update, delete and add new resources even if they don’t have the appropriate iam:PassRole permission. The IAM role is attached to the stack when created and stays attached – keep this in mind!

Use only with permission boundaries!

Giving otherwise-restricted users the ability to create any resources through CloudFormation means that they can create new IAM users and even use CloudFormation to extend their own permissions for example through custom resources! Where possible use IAM Permission Boundary to mitigate this.