Use Terraform to manage AWS IAM Policies, Roles and Users

This blog post is going to be a comprehensive guide on managing the AWS IAM User, IAM Roles and IAM Policies using Terraform.

Managing IAM Users, Roles and Policies are always crucial from a security perspective. Proper management of the IAM User, IAM Roles and IAM Policies can really improve the operational burden as well as the security of the AWS environment.

In this blog post, we are going to use Terraform to manage the IAM User, IAM Roles and IAM Policies. There are a couple of examples we are going to take a look -

  1. Managing one IAM User, one IAM Roles and one IAM policies with terraform
  2. Managing one IAM user, two IAM Roles and two IAM policies with terraform

Table of Content

  1. Prerequisites
  2. Understanding IAM Roles and Policies
  3. Create an IAM User(aws_iam_user) - Alice
  4. Create an IAM Role(aws_iam_role) - alice_role
  5. Create IAM Policy(aws_iam_policy) - AllowS3Access
  6. Create IAM Role and Policy attachment
  7. Create an aws_s3_bucket
  8. Create AWS IAM Instance Profile (aws_iam_instance_profile) - AliceProfile
  9. Create IAM user(aws_iam_user) and IAM Policy(aws_iam_policy) attachment
  10. Attaching IAM Instance profile to EC2 instance
  11. Conclusion

1. Prerequisites

1. An active AWS account and a basic understanding of AWS services - Before you begin and start following the steps mentioned in this blog post, you must have an active AWS account.

If you are using AWS for the first time, then you can use their initial trial period credit, and you should be able to perform all the steps mentioned in this blog post.

2. Terraform is installed on your machine - This complete blog post is focused around setting up the IAM User, IAM Roles and IAM Policies using Terraform, so you must install Terraform CLI onto your working machine.

Please refer to this guide on - How to install Terraform

3. Familiarity with Terraform syntax (HCL) - This particular blog requires you to be familiar with Terraform. If this is the first time you are trying to learn the Terraform, then I would highly recommend building your understanding by following this tutorial series: - On getting started with Terraform


2. Understanding IAM Roles and Policies

Before we start writing Terraform code, it is really important to understand the concept of IAM roles and IAM policies.

1. IAM Roles - It is a set of permissions that can be performed on AWS resources such as EC2, S3 Bucket, etc. With the help of IAM Roles you can grant permission to -

  • User
  • AWS Services

Here are some benefits that you get with the IAM roles -

  • Flexibility - The IAM roles can be assigned to any IAM user or AWS resource, and you can customize the granularity of the IAM roles based on your needs.
  • Security - IAM roles are very granular in nature, and hence, they always add an extra layer of security to your cloud infrastructure.
  • Scalability - When you use Terraform to manage IAM roles, it becomes really scalable, and any developer can manage the roles from the code.

2. IAM Policies - It is a JSON formatted document that defines the permissions for IAM users as well as IAM roles. With the help of IAM policies, you can control what kinds of actions you can perform on specific AWS resources.

Here are two types of policies that exist:

  • Managed Policies - IAM policies are managed policies that are administered by the account administrator.
  • Inline Policies - These policies are directly embedded in the IAM user, IAM group, and IAM roles.

3. Create an IAM User(aws_iam_user) - Alice

Let's start by creating an User which we call an IAM user. To keep our Terraform project code clean, I am going to create a file called iam-user.tf and put the following code inside the file.

1# Step 1 : Create an IAM user named Alice
2
3resource "aws_iam_user" "alice" {
4name = "Alice"
5}
  1. The above code will create an IAM user named Alice.
  2. To run the above code, simply run terraform plan and terraform apply commands.
  3. After running the terraform code, you can verify the user by going into the AWS console -> IAM -> Access Management -> User create-iam-user.webp

Terraform create IAM user


4. Create an IAM Role(aws_iam_role) - alice_role

After creating the IAM user in the [Step-3][3], let's create an IAM Role. Here is the Terraform code for creating the IAM role -

 1resource "aws_iam_role" "alice_role" {
 2name = "AliceRole"
 3assume_role_policy = jsonencode({
 4Version = "2012-10-17"
 5Statement = [
 6{
 7Action = "sts:AssumeRole"
 8Effect = "Allow"
 9Principal = {
10Service = "ec2.amazonaws.com"
11}
12}
13]
14})
15}
  1. The above code will create an IAM role named AliceRole.
  2. To run the above code, simply run terraform plan and terraform apply commands.
  3. After running the Terraform code, you can verify the user by going into the AWS console -> IAM -> Access Management -> Roles

Create IAM role by the name AliceRole

  1. Click on the AliceRole to view the details about the roles .e.g., Creation Date, ARN, Instance Profile ARN etc..

IAM Role description for AliceRole

  1. To view Permission Policy of the role click on the Permission and then click on the + icon to expand the policy permission.

IA role permission policy description for ALiceRole

Here is a detailed explanation of each policy:

  • AliceRole - The name of the IAM role
  • assume_role_policy - This is an attribute that sets the trust policy for the IAM role, which defines who can assume the role.
  • Version = "2012-10-17": This line indicates the policy language version. In this case, it is the 2012-10-17 version.
  • Statement = [...]: This is an array of policy statements. In this example, there's only one statement that is defined as follows:
  • Action = "sts:AssumeRole": This specifies the action to be allowed, which is to assume the IAM role.
  • Effect = "Allow": This indicates that the action is allowed.
  • Principal = { ... }: This defines the principal (the entity that is allowed to assume the role). In this example, it is set to an AWS service.
  • Service = "ec2.amazonaws.com": The service that is allowed to assume the role. In this case, it is the Amazon EC2 service.

5. Create IAM Policy(aws_iam_policy) - AllowS3Access

An AWS IAM policy is like a set of rules that decide who can do what in the digital world of AWS.

These rules help make sure that people or programs can only get to the things they need and can't touch anything they shouldn't.

Here is the IAM Policy for AllowS3Access -

 1resource "aws_iam_policy" "allow_s3_access" {
 2name = "AllowS3Access"
 3description = "Allow Alice to access specific S3 resources"
 4policy = jsonencode({
 5Version = "2012-10-17"
 6Statement = [
 7{
 8Action = [
 9"s3:ListBucket",
10"s3:GetObject",
11"s3:PutObject"
12]
13Effect = "Allow"
14Resource = [
15"arn:aws:s3:::test-bucket-for-alice",
16"arn:aws:s3:::test-bucket-for-alice/*"
17]
18}
19]
20})
21}

Here is a detailed explanation of the above policy -

  • AllowS3Access - It is the name of the policy.

  • description - A meaningful description to tell more about the policy

  • policy - A Json string containing all the Actions and Resources

  • Version = "2012-10-17": This line indicates the policy language version. In this case, it is the 2012-10-17 version.

  • Statement = [...]: This is an array of policy statements. In this example, there's only one statement that is defined as follows:

  • Action = [...]: This lists the actions that are allowed by the policy. In this case, it includes:

  • "s3:ListBucket": Listing the contents of a bucket.

  • "s3:GetObject": Retrieving an object from the bucket.

  • "s3:PutObject": Uploading an object to the bucket.

  • Effect = "Allow": This indicates that the actions listed above are allowed by the policy.

  • Resource = [...]: This specifies the resources the policy applies to. In this example, there are two resources:

  • "arn:aws:s3:::test-bucket-for-alice": The Amazon Resource Name (ARN) of the S3 bucket is "test-bucket-for-alice". This allows the policy to apply to the bucket itself.

  • "arn:aws:s3:::test-bucket-for-alice/*": This allows the policy to apply to all objects within the "test-bucket-for-alice" bucket.

How to Create the Policy?

  1. To create the policy, run the above code: simply run terraform plan and terraform apply command
  2. After running the Terraform code, you can verify the user by going into the AWS console -> IAM -> Access Management -> Policies

AWS IAM Policy AllowS3Access

  1. Click on the AllowS3Access Policy and you will find all the details related to that policy.

AWS IAM S3 Policy with Read, List and Write permission


6. Create IAM Role and Policy attachment

Before we create the IAM Role and Policy attachment, let's try to understand Why it is important to attach the IAM Role and Policy in AWS?

IAM jobs and policy attachments are important in AWS because they help keep track of who can do what in a safe and controlled way. Here are some additional benefits that you will get with the IAM role and policy attachment:

1. Only necessary access: Only those who need to get in. It's like a school where only teachers have the keys to certain rooms. IAM roles and rules make sure that people or programs can only do what they are meant to do and nothing else. This makes sure that everything stays safe and sound.

2. One place to manage: Instead of writing down on a bunch of sticky notes who can do what, IAM jobs and policies let you keep track of everything in one place. This makes it easy to deal with rights and keep track of them.

3. Rules that can be used more than once: Imagine if you could make a rule like "All teachers can open classroom doors" and use it for every teacher in the school. You can make rules like this using IAM jobs and policies, so you don't have to say the same thing over and over again.

4. Easier to change: If the rules change, like letting some students into certain places, IAM roles and policies make it easy to change these rights. You don't have to go to each door and change the lock. Instead, you just have to change the rule in one place.

5. Safer sharing: Sometimes you have to let a friend take your video game or toy. IAM jobs and rules are like giving your friend the key to your locker so they can get your toy but not anything else. So, you can share access without thinking about someone going through your stuff.

Here is the IAM Role and Policy Attachment for the AliceRole and AllowS3Access policies:

1# IAM Role and IAM Policy Attachment
2
3resource "aws_iam_role_policy_attachment" "attach_s3_access" {
4policy_arn = aws_iam_policy.allow_s3_access.arn
5role = aws_iam_role.alice_role.name
6}

7. Create an aws_s3_bucket

In the previous 6 steps, we have created IAM User, IAM Role, IAM Policy and IAM RolePolicy Attachment but we haven't yet created an S3 Bucket.

Here is the Terraform code to create an S3 bucket:

 1# S3 Bucket creation by the name - test-bucket-for-alice
 2
 3resource "aws_s3_bucket" "example" {
 4bucket = "test-bucket-for-alice"
 5
 6tags = {
 7Name = "test-bucket-for-alice"
 8Environment = "Dev"
 9}
10}

Apply the change by running the Terraform command-

  1. To create the S3 bucket, run the terraform plan and terraform apply commands.
  2. Here is the screenshot from my AWS Console after creating an S3 Bucket by the name - test-bucket-for-alice

S3 Bucket Creation


8. Create AWS IAM Instance Profile (aws_iam_instance_profile) - AliceProfile

aws_iam_instance_profile is a Terraform resource used to create and manage an AWS IAM Instance Profile.

In the context of the current blog post, aws_iam_instance_profile is used to create an IAM Instance Profile that allows an Amazon EC2 instance to access the S3 bucket using the permissions defined in an IAM role.

Here is the Terraform code to create an AWS IAM instance profile:

1# AWS IAM Instance Profile - AliceProfile
2
3resource "aws_iam_instance_profile" "alice_profile" {
4name = "AliceProfile"
5role = aws_iam_role.alice_role.name
6}

To create an AWS IAM instance profile, run the above code: simply run terraform plan and terraform apply commands.


9. Create IAM user(aws_iam_user) and IAM Policy(aws_iam_policy) attachment

We have setup everything that is needed: IAM User, IAM Role and IAM Policy but we did not attach IAM User with IAM Policy yet.

Let's write the Terraform resource to attach the IAM User(aws_iam_user) with the IAM Policy(aws_iam_policy) -

1# Attaching the IAM user(aws_iam_user) to IAM Policy(aws_iam_policy)
2
3resource "aws_iam_user_policy_attachment" "alice_s3_access" {
4user = aws_iam_user.alice.name
5policy_arn = aws_iam_policy.allow_s3_access.arn
6}

Attach IAM User(aws_iam_user) to IAM Policy(aws_iam_policy)

Here is the screenshot I have taken from the AWS console, which shows all the permissions associated with the IAM User - Alice

IAM user permissions for S3 bucket


10. Attaching IAM Instance profile to EC2 instance

Alright, so far we have covered a lot of topics and been able to create the following:

  • IAM User : Alice
  • IAM Role : AliceRole
  • IAM Policy : AllowS3Access
  • IAM Role Policy Attachment : AliceRole + AllowS3Access
  • IAM Instance Profile : AliceProfile -> AliceRole
  • IAM User Policy Attachment : Alice + AllowS3Access

Next Task - Let's bind the IAM Instance Profile to an EC2 instance, and we will do it the Terraform way, but let's take a peek into the AWS Console so that we know where to find these settings to attach the IAM Instance Profile option.

IAM Instance Profile to Attach Role to EC2 Instance

Here is the Terraform code to provision the EC2 instance as well as attach IAM Instance Profile -

(Note - Here is my GitHub Repository where you can find the complete project. If you are new to Terraform and want to learn more about it, then follow this post - How to Setup EC2 instance with Terraform)

 1# Setup EC2 instance with iam_instance_profile
 2
 3resource "aws_instance" "ec2_example" {
 4
 5ami = "ami-0767046d1677be5a0"
 6instance_type = "t2.micro"
 7tags = {
 8Name = "test-t2-micro"
 9}
10key_name= "aws_key"
11vpc_security_group_ids = [aws_security_group.main.id]
12
13# Attach IAM instance profile with EC2 instance
14iam_instance_profile = aws_iam_instance_profile.alice_profile.name
15}

Here is the screenshot I have taken from my AWS console after provisioning the EC2 instance with aws_iam_instance_profile

Attach IAM instance profile to EC2 instance


11. Conclusion

I hope this blog post will help you get started with on How to manage the IAM Roles, IAM Policies and IAM User Permission with Terraform. All the steps mentioned in this blog are really necessary for setting up the correct IAM roles, IAM policies, and IAM permissions.

But the same steps can be customized to setup other IAM roles, IAM policies, and IAM User permissions as well.

If you have any questions or suggestions, then please put them in the comment section.

Posts in this series