How to Create IAM Role using CloudFormation

How to Create IAM Role using CloudFormation
Sharing is Caring:

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 in which a policy can be attached to an IAM Role.

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

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 by it’s own. However, other trusted entities such as 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 user 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
  • Maximum 10 managed policy can be attached to a role

Let’s learn to create an IAM role using CloudFormation in the next section.

Steps to Create IAM Role using CloudFormation

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 user one by one.

However, by some reason if your user/role can’t have 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-

Below policy creates a role which can be assumed by 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 role name here.

Roles: 
  - !Ref MyTestRole

If you have role name handy, you can simply specify that in 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 any roles as you want

Step 3: Create a Stack using 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 convinience.
  2. Save the template with .yml or .json as per the choice of template and follow 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 configuration, keep everything as default and click on Next.
  6. In the events tab of stack, you can view the status.
  7. Once stack is successfully created, navigate to resources tab of your stack, click on it and verify in IAM console
  8. Also, you can check output tab of your CloudFormation stack to view role name and Arn.

Clean Up

If you are creating this IAM role for learning purpose, 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 parameter while creating a role
  • We also learnt how we can add various types of policies such as inline or managed policies
  • Managed policy can be an AWS managed or customer managed as per requirement
  • You can have maximum of 10 managed policy 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:

Sharing is Caring:

Leave a Reply

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