How to Create IAM Role using CloudFormation

How to Create IAM Role using CloudFormation

Dear Reader, hope you are doing great today :). In this post, I will help you create IAM role using CloudFormation. While creating the role using CloudFormation we will learn various ways a policy can be attached to an IAM Role.

In case you have just started with AWS, below is a small section on IAM roles which will help you understand this tutorial better.

But Hey, Before we get into the details, join our Facebook group, follow us on Facebook, Twitter, LinkedIn, Instagram or Subscribe to our newsletter below to not miss any updates from us.

What is IAM Role?

IAM role is an IAM entity that specifies a set of permissions to interact with AWS services.

Unlike other entities like users, a role can’t do anything on its own. However, other trusted entities such as the user, an application running on EC2, a lambda function or an AWS service such as CloudFormation can assume the role to perform actions specified in the role policy.

  • Roles are not associated with users or groups
  • You create a role by proving a name and then attaching a policy to it
  • You can attach inline as well as managed policy to a role
  • A maximum 10 managed policies can be attached to a role

In the next section, let’s learn to create an IAM role using CloudFormation.

Related: 5 Ways to Create and Manage Resources in AWS

Steps to Create IAM Role using CloudFormation

  • Provide proper permission
  • Prepare a template
  • Create a Stack using the prepared template

Step 1: Provide proper permission

While creating resources via CloudFormation, it’s good to have administrator access so that you don’t have to fix the permission of executing users one by one.

However, if your user/role can’t have an admin policy, below mentioned policy is close enough for this tutorial.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1633520091694",
      "Action": [
        "iam:AttachRolePolicy",

        "iam:CreateRole",
        "iam:CreatePolicy",
        "iam:CreatePolicyVersion",
        "iam:DeletePolicy",
        "iam:DeletePolicyVersion",
        "iam:DeleteRole",
        "iam:DeleteRolePolicy",
        "iam:DetachRolePolicy",
        "iam:GetPolicy",
        "iam:GetPolicyVersion",
        "iam:GetRole",
        "iam:GetRolePolicy",
        "iam:ListAttachedRolePolicies",
        "iam:ListPolicies",
        "iam:ListPolicyVersions",
        "iam:ListRolePolicies",
        "iam:PutRolePolicy"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

Note: Additionally, you will also need cloudformation:* as well to be able to do CloudFormation stack creation, updation etc.

Step 2: Prepare a template

You can use YAML or JSON for your template. I prefer YAML for writing my templates. But don’t worry, If you want it in JSON, I will provide JSON template as well.

To create an IAM role, all you need is a AWS::IAM::Role resource like below.

  MyRole: 
    Type: AWS::IAM::Role
    Properties: 
      AssumeRolePolicyDocument: PolicyDocuent
      .....
      .....

Few things to note there –

  • AssumeRolePolicyDocument is the only mandatory parameter of a role resource.
  • It specifies the trust policy or in simple terms who can assume this role.

For example-

The below policy creates a role which can be assumed by the AWS lambda service. This role will have no permission yet because no policy is attached to this role.

Resources:
  MyTestRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'

Template to Create IAM Role using CloudFormation : YAML

In this template we are-

  • Declaring one IAM role with an embedded inline policy and an AWS-managed policy.
  • Creating a customer-managed IAM policy and attaching it to this role.
  • Creating and attaching an external inline policy to this role.
  • Outputting Role name and Role ARN for later uses
role
AWSTemplateFormatVersion: '2010-09-09'
Description: Template to Create an IAM Role

Resources:
  MyTestRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Description: Role to provide access to S3
      Policies:
        - PolicyName: EmbeddedInlinePolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action: 'cloudformation:*'
                Resource: '*'
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
      RoleName: LambdaS3Access
      
  DynamoDBMangedPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties: 
      Description: Managed Policy to attach to MyTestRole Role
      ManagedPolicyName: DynamoDBAccessPolicyForLambda
      Path: /
      PolicyDocument: 
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - 'dynamodb:Query'
              - 'dynamodb:Scan'
            Resource: '*'
      Roles: 
        - !Ref MyTestRole
        
  ExternalInlinePolicy:
    Type: AWS::IAM::Policy
    Properties: 
      PolicyDocument: 
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - 'sqs:*'
            Resource: '*'
      PolicyName: InlinePolicy
      Roles: 
        - !Ref MyTestRole
Outputs: 
  RoleName: 
    Description: Name of Created IAM Role
    Value: !Ref MyTestRole  
  RoleArn: 
    Description: Arn of Created Role
    Value: !GetAtt MyTestRole.Arn      

Template to Create IAM Role using CloudFormationJSON

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Template to Create an IAM Role",
    "Resources": {
        "MyTestRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "lambda.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                },
                "Description": "Role to provide access to S3",
                "Policies": [
                    {
                        "PolicyName": "EmbeddedInlinePolicy",
                        "PolicyDocument": {
                            "Version": "2012-10-17",
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": "cloudformation:*",
                                    "Resource": "*"
                                }
                            ]
                        }
                    }
                ],
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/AmazonS3FullAccess"
                ],
                "RoleName": "LambdaS3Access"
            }
        },
        "DynamoDBMangedPolicy": {
            "Type": "AWS::IAM::ManagedPolicy",
            "Properties": {
                "Description": "Managed Policy to attach to MyTestRole Role",
                "ManagedPolicyName": "DynamoDBAccessPolicyForLambda",
                "Path": "/",
                "PolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Action": [
                                "dynamodb:Query",
                                "dynamodb:Scan"
                            ],
                            "Resource": "*"
                        }
                    ]
                },
                "Roles": [
                    {
                        "Ref": "MyTestRole"
                    }
                ]
            }
        },
        "ExternalInlinePolicy": {
            "Type": "AWS::IAM::Policy",
            "Properties": {
                "PolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Action": [
                                "sqs:*"
                            ],
                            "Resource": "*"
                        }
                    ]
                },
                "PolicyName": "InlinePolicy",
                "Roles": [
                    {
                        "Ref": "MyTestRole"
                    }
                ]
            }
        }
    },
    "Outputs": {
        "RoleName": {
            "Description": "Name of Created IAM Role",
            "Value": {
                "Ref": "MyTestRole"
            }
        },
        "RoleArn": {
            "Description": "Arn of Created Role",
            "Value": {
                "Fn::GetAtt": [
                    "MyTestRole",
                    "Arn"
                ]
            }
        }
    }
}

Few Common Use-cases:

Add Inline Policy to IAM Role using CloudFormation



Resources:
  MyTestRole:
    Type: AWS::IAM::Role
    Properties:
      .................................
      .................................
      Policies:
        - PolicyName: EmbeddedInlinePolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action: 'cloudformation:*'
                Resource: '*'
      .................................
      .................................

Attach Managed Policy to IAM Role using CloudFormation

Resources:
  MyTestRole:
    Type: AWS::IAM::Role
    Properties:
      .................................
      .................................

      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/AmazonS3FullAccess

Attach a customer-managed policy to an existing role using CloudFormation

Resources:
  DynamoDBMangedPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties: 
      Description: Managed Policy to attach to MyTestRole Role
      ManagedPolicyName: DynamoDBAccessPolicyForLambda
      Path: /
      PolicyDocument: 
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - 'dynamodb:Query'
              - 'dynamodb:Scan'
            Resource: '*'
      Roles: 
        - !Ref MyTestRole

Please note that reference to the role is being made using the role name here.

Roles: 
  - !Ref MyTestRole

If you have a role name handy, you can simply specify that in the Roles parameter. If not you can use !Ref as above to get the role name. Also notice that Roles is actually an array and you can attach this policy to as many roles as you want

Step 3: Create a Stack using a prepared template

Now, we know the basics and we have the template so let’s go and create the stack.

  1. Grab the YAML or JSON template from above as per your convenience.
  2. Save the template with .yml or .json as per the choice of template and follow the below steps.
  3. Login to AWS Management Console, navigate to CloudFormation and click on Create stack
  4. Click on “Upload a template file”, upload your saved .yml  or .json file and click Next
  5. Enter the stack name and click on Next. In the configuration, keep everything as default and click on Next.
  6. In the events tab of the stack, you can view the status.
  7. Once the stack is successfully created, navigate to the resources tab of your stack, click on it and verify in the IAM console
  8. Also, you can check the output tab of your CloudFormation stack to view the role name and Arn.

Clean Up

If you are creating this IAM role for learning purposes, you can go ahead and delete the stack to delete all the created resources.

Happy Learning !!!

Conclusion:

In this post, we learnt how to create IAM role using CloudFormation

  • We learn about mandatory parameters while creating a role
  • We also learnt how we can add various types of policies such as inline or managed policies
  • The managed policy can be an AWS-managed or customer-managed as per the requirement
  • You can have a maximum of 10 managed policies per role

I hope you found this post helpful.

Enjoyed the content?

Subscribe to our newsletter below to get awesome AWS learning materials delivered straight to your inbox.

Don’t forget to motivate me by-

  • Adding a comment below on what you liked and what can be improved.
  • Follow us on
  • Subscribe to our newsletter to get notified each time we post new content
  • Share this post with your friends

Suggested Read:

Leave a Reply

Your email address will not be published. Required fields are marked *