DEV Community

Felipe Arcaro
Felipe Arcaro

Posted on

Creating an AWS IAM user with Terraform

TL;DR

Here's the Terraform code to create an IAM user with access to EC2 and RDS instances:

data "aws_iam_policy_document" "my_project_policy" {
    statement {
        resources = [aws_instance.my_project_ec2.arn]
        actions = ["ec2:*"]
        effect = "Allow" # Default is Allow
    }

    statement {
        resources = ["aws_db_instance.my_project_db.arn"]
        actions = ["rds:DescribeDBInstances",
                   "rds:DescribeDBClusters",
                   "rds:DescribeGlobalClusters"]
    }             
}

# Provides an IAM user
resource "aws_iam_user" "my_project_user" {
  name = "my-project-user"
}

Enter fullscreen mode Exit fullscreen mode

Now that we already created an IAM role so the EC2 instance can access the RDS instance, it's time to create an IAM user with specific (and restricted) access to use/manage the infrastructure we just created.

Here's a quick recap on IAM:

  • 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
  • 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

Creating an IAM user

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

  • A policy defining permissions
  • An IAM user
  • Combine the two above

Let's start creating the policy:


data "aws_iam_policy_document" "my_project_policy" {
    statement {
        resources = [aws_instance.my_project_ec2.arn]
        actions = ["ec2:*"]
        effect = "Allow" # Default is Allow
    }

    statement {
        resources = ["aws_db_instance.my_project_db.arn"]
        actions = ["rds:DescribeDBInstances",
                   "rds:DescribeDBClusters",
                   "rds:DescribeGlobalClusters"]
    }             
}

# Provides an IAM user
resource "aws_iam_user" "my_project_user" {
  name = "my-project-user"
}

# Provides an IAM policy attached to a user
resource "aws_iam_user_policy" "my_project_user_policy" {
    name = "my-project-policy"
    user = aws_iam_user.my_project_user.name
    policy = data.aws_iam_policy_document.my_project_user_policy.json
}
Enter fullscreen mode Exit fullscreen mode

You probably noticed this is the first time we're using a data block instead of a resource block. The key difference here is that resource blocks are used to create/manage infrastructure resources, while data blocks are used to fetch and reference information from external services.

Now we create the user:

# Provides an IAM user
resource "aws_iam_user" "my_project_user" {
  name = "my-project-user"
}
Enter fullscreen mode Exit fullscreen mode

And attach the policy to the user:

# Provides an IAM policy attached to a user
resource "aws_iam_user_policy" "my_project_user_policy" {
    name = "my-project-policy"
    user = aws_iam_user.my_project_user.name
    policy = data.aws_iam_policy_document.my_project_user_policy.json
}
Enter fullscreen mode Exit fullscreen mode

Wrapping up

That's it, now we're really done with our little project. After going through all those steps, here's what we've got:

  • An EC2 instance where we can deploy our Python project
  • An RDS Postgres instance where that Python project can persist data
  • An IAM role that allows the EC2 instance to connect to the RDS Postgres instance
  • An IAM user with proper permissions to interact with the EC2 and RDS instances

Top comments (0)