Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Mastering AWS CloudFormation

You're reading from   Mastering AWS CloudFormation Plan, develop, and deploy your cloud infrastructure effectively using AWS CloudFormation

Arrow left icon
Product type Paperback
Published in May 2020
Publisher Packt
ISBN-13 9781789130935
Length 300 pages
Edition 1st Edition
Tools
Arrow right icon
Author (1):
Arrow left icon
Karen Tovmasyan Karen Tovmasyan
Author Profile Icon Karen Tovmasyan
Karen Tovmasyan
Arrow right icon
View More author details
Toc

Table of Contents (17) Chapters Close

Preface 1. Section 1: CloudFormation Internals
2. CloudFormation Refresher FREE CHAPTER 3. Advanced Template Development 4. Section 2: Provisioning and Deployment at Scale
5. Validation, Linting, and Deployment of the Stack 6. Continuous Integration and Deployment 7. Deploying to Multiple Regions and Accounts Using StackSets 8. Configuration Management of the EC2 Instances Using cfn-init 9. Section 3: Extending CloudFormation
10. Creating Resources outside AWS Using Custom Resources 11. Dynamically Rendering the Template Using Template Macros 12. Generating CloudFormation Templates Using AWS CDK 13. Deploying Serverless Applications Using AWS SAM 14. What's Next? 15. Assessments 16. Other Books You May Enjoy

Understanding CloudFormation IAM permissions

We already know that CloudFormation performs API calls when we create or update the stack. Now the question is, does CloudFormation have the same powers as a root user?

When you work with production-grade AWS accounts, you need to control access to your environment for both humans (yourself and your coworkers) and machines (build systems, AWS resources, and so on). That is why controlling access for CloudFormation is important.

By default, when the user runs stack creation, they invoke the API method cloudformation:CreateStack. CloudFormation will use that user's access to invoke other API methods during the stack creation.

This means that if our user has an IAM policy with an allowed action ec2:*, but attempts to create an RDS instance with CloudFormation, the stack will fail to create with an error, User is unauthorized to perform this action.

Let's try this. We will create an IAM role with ec2:*, assume that role, and try to create the same bucket stack:

Important note

We already have an IAM user Admin in our AWS account and we will add that user as a principal.

MyIamRole.yaml

AWSTemplateFormatVersion: "2010-09-09"
Description: "This is a dummy role"
Resources:
  IamRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: AllowAssumeRole
            Effect: Allow
            Principal:
              AWS:
                - !Join
                  - ""
                  - - "arn:aws:iam::"
                    - !Ref "AWS::AccountId"
                    - ":user/Admin"
            Action: "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/AmazonEC2FullAccess"
        - "arn:aws:iam::aws:policy/AWSCloudformationFullAccess"
Outputs:
  IamRole:
    Value: !GetAtt IamRole.Arn

If we create this stack, assume that role, and try to create the previous mybucket stack, it will fail to create with an error. Let's take a look:

$ aws cloudformation create-stack \
                     --stack-name iamrole \
                     --capabilities CAPABILITY_IAM \
                     --template-body file://IamRole.yaml
$ IAM_ROLE_ARN=$(aws cloudformation describe-stacks \
                                    --stack-name iamrole \
--query "Stacks[0].Outputs[?OutputKey=='IamRole'].OutputValue" \
--output text)
$ aws sts assume-role --role-arn $IAM_ROLE_ARN \
                      --role-session-name tmp
# Here goes the output of the command. I will store the access credentials in the env vars
$ export AWS_ACCESS_KEY_ID=… 
$ export AWS_SECRET_ACCESS_KEY=…
$ export AWS_SESSION_TOKEN=…
$ aws cloudformation create-stack \
                     --stack-name mybucket \
                     --template-body file://MyBucket.yaml

We will see the following error on the AWS console:

Figure 1.1 – CloudFormation console – stack events

Figure 1.1 – CloudFormation console – stack events

On the other hand, we cannot provide everyone with an AdminAccess policy, so we need to find a way to use CloudFormation with the necessary permissions while only letting CloudFormation use those permissions.

CloudFormation supports service roles. Service roles are the IAM roles that are used by different AWS services (such as EC2, ECS, Lambda, and so on). CloudFormation service roles are used by CloudFormation during stacks and StackSets operations—creation, update, and deletion:

  1. Let's create a specific role for CloudFormation:

    CfnIamRole.yaml

    AWSTemplateFormatVersion: "2010-09-09"
    Description: "This is a CFN role"
    Resources:
      IamRole:
        Type: AWS::IAM::Role
        Properties:
          AssumeRolePolicyDocument:
            Version: 2012-10-17
            Statement:
              - Sid: AllowAssumeRole
                Effect: Allow
                Principal:
                  Service: "cloudformation.amazonaws.com"
                Action: "sts:AssumeRole"
          ManagedPolicyArns:
            - "arn:aws:iam::aws:policy/AdministratorAccess"
    Outputs:
      IamRole:
        Value: !GetAtt IamRole.Arn
  2. We create this stack for the service role and obtain the CloudFormation role ARN:
    $ aws cloudformation create-stack \
                         --stack-name cfniamrole \
                         --capabilities CAPABILITY_IAM \
                         --template-body file://CfnIamRole.yaml
    $ IAM_ROLE_ARN=$(aws cloudformation describe-stacks \
                                        --stack-name cfniamrole \
    --query "Stacks[0].Outputs[?OutputKey=='IamRole'].OutputValue" \
    --output text)
  3. Now we run the creation of the stack, which will use our role, specifying the Role ARN:
    $ aws cloudformation create-stack \
                         --stack-name mybucket \
                         --template-body file://MyBucket.yaml \
                         --role-arn $IAM_ROLE_ARN
  4. After a while, we can verify that our stack has been created, and we see our bucket!
    $ aws s3 ls
    # Output
    2019-10-16 14:14:24 mybucket-mybucket-jqjpr6wmz19q

    Before we continue, don't forget to clean your account:

    $ for i in mybucket iamrole cfniamrole; do aws cloudformation delete-stack --stack-name $i ; done

    Important note

    Note that in the preceding example, we provide the CloudFormation role with an AdminPolicy (the one that is provided by AWS by default).

In production-grade systems, we want to allow CloudFormation only those privileges that are required for the stack.

There are two permission schemas that are being applied for CloudFormation roles:

  • We have a certain list of services that we can use (for example, EC2, RDS, VPC, DynamoDB, S3, and so on).
  • Each template/stack combination will use only those services it needs—for example, if we declare Lambda functions with Simple Notification Service (SNS), then we should create the role with policies only for Lambda and SNS.
You have been reading a chapter from
Mastering AWS CloudFormation
Published in: May 2020
Publisher: Packt
ISBN-13: 9781789130935
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime