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
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 CloudFormation : JSON
{
"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.
- Grab the YAML or JSON template from above as per your convenience.
- Save the template with .yml or .json as per the choice of template and follow the below steps.
- Login to AWS Management Console, navigate to CloudFormation and click on Create stack
- Click on “Upload a template file”, upload your saved .yml or .json file and click Next
- Enter the stack name and click on Next. In the configuration, keep everything as default and click on Next.
- In the events tab of the stack, you can view the status.
- Once the stack is successfully created, navigate to the resources tab of your stack, click on it and verify in the IAM console
- 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