Creating an AWS IAM role with Terraform
Tags: terraform, dataops, devops, cloud
Published: 2023-10-03 19:44:04

## TL;DR

Here's the Terraform code to create an IAM role so an EC2 instance has proper access to an RDS instance:

```terraform
# IAM role for EC2 instance
resource "aws_iam_role" "my_project_role" {
  name = "my-project-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Sid    = ""
        Principal = {
          Service = "ec2.amazonaws.com"
        }
      }
    ]
  })
}

# IAM policy to be attached to the EC2 role
resource "aws_iam_role_policy" "my_project_role_policy" {
  name = "my-project-role-policy"
  role = aws_iam_role.my_project_role.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "rds:*",
        ]
        Effect   = "Allow"
        Resource = aws_db_instance.my_project_db.arn
      },
    ]
  })
}

# Update EC2 resource created earlier
resource "aws_instance" "my_project_ec2" {
  instance_type = "t2.micro"
  ami = "ami-06e46074ae430fba6"
  tags = {
    Name = "my-python-project"
  }

  iam_instance_profile = aws_iam_role.my_project_role.arn
}
```

---

Nice, we're done with the goals we defined at the beginning of this article but we want more – actually, we need more. Now it's time to create an IAM user with specific (and restricted) access to use/manage the infrastructure we just created and an IAM role so the EC2 instance can access the RDS instance.

> Identity and Access Management (IAM) is a service that allows you to manage access to AWS resources securely. IAM enables you to create and manage AWS users and groups and control their level of access to AWS resources.

As per IAM standards:

- We create groups with permissions and then add users to these groups 
- We create roles and assign them to AWS services so they communicate with each other 

For this example, we won't create any IAM groups but it is important to remember that we cannot assign a role to a user.

## Creating an IAM role

Here are the things we'll need to add to our Terraform code:

- A policy defining permissions
- An IAM role
- Update the EC2 code to use that role

Let's start creating an IAM role for our EC2 service:

```terraform
# IAM role for EC2 instance
resource "aws_iam_role" "my_project_role" {
  name = "my-project-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Sid    = ""
        Principal = {
          Service = "ec2.amazonaws.com"
        }
      }
    ]
  })
}
```

And now we create a policy with all permissions to our RDS instance and reference the role we just created.

```terraform
# IAM policy to be attached to the EC2 role
resource "aws_iam_role_policy" "my_project_role_policy" {
  name = "my-project-role-policy"
  role = aws_iam_role.my_project_role.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "rds:*",
        ]
        Effect   = "Allow"
        Resource = aws_db_instance.my_project_db.arn
      },
    ]
  })
}
```

Now we have to update our EC2 instance code to make sure it uses the role and permissions we just defined. For that, we just add `iam_instance_profile = aws_iam_role.my_project_role.arn` to it:

```terraform
resource "aws_instance" "my_project_ec2" {
  instance_type = "t2.micro"
  ami = "ami-06e46074ae430fba6"
  tags = {
    Name = "my-python-project"
  }

  iam_instance_profile = aws_iam_role.my_project_role.arn
}

```