In this article, we will look at what an IAM (Identity and Access Management) role in AWS (Amazon Web Services) is, and show a step-by-step example of how to create one using Terraform. Buckle up!
We will cover:
An IAM role is an IAM identity that you can create in your account that has specific permissions. This security principal enables you to delegate permissions to AWS resources to entities within your AWS account. It is a way to manage access to AWS services and resources without the need to share long-term credentials, such as access keys or passwords.
IAM roles are typically used to grant permissions to AWS services, applications, or other AWS accounts. By assuming an IAM role, an entity can temporarily acquire the permissions associated with that role.
For example, IAM roles are commonly used in scenarios like EC2 instances accessing other AWS services, allowing AWS Lambda functions to access specific resources, or granting cross-account access.
When creating an IAM role, you can define the set of permissions and policies that specify what actions are allowed or denied. These policies can be based on AWS-managed policies, customer-managed policies, or inline policies. IAM roles can be assigned to entities such as IAM users, AWS services, or even external identities federated through identity providers like Active Directory or SAML. Note that when you first create your AWS account, no roles are created by default.
Check out our detailed guide to AWS IAM Roles and AWS IAM best practices.
Let’s see what we need before we start:
- An Amazon Web Service (AWS) account. You can get a free-tier account if you don’t have one. The free tier includes 750 hours of Linux and Windows t2.micro instances (t3.micro for the regions in which t2.micro is unavailable) each month for one year. To stay within the Free Tier, use only EC2 Micro instances. The example in the article uses t2.micro.
- Terraform — the step-by-step guide below will use the latest Terraform version available, (v1.52 at the time of writing).
- A code editor such as VSCode.
In this example, we will use the Amazon Web Services (AWS) Terraform provider to interact with the many resources supported by AWS. We will create an IAM role and assign it to a newly created EC2 instance that will allow it read-only access to a newly created S3 storage bucket.
Step 1: Configure the AWS provider
You must configure the provider with the proper credentials before you can use it. To authenticate with AWS, you can use one of several methods.
- Credentials can be provided by adding an access_key, secret_key, and optionally token, to the AWS provider block. Hard-coded credentials are not recommended in any Terraform configuration and risk secret leakage should this file ever be committed to a public version control system.
provider "aws" {
region = "us-east-1"
access_key = "my-access-key"
secret_key = "my-secret-key"
}
- Arguably a better way to authenticate when testing locally is to use environment variables.
$ export AWS_ACCESS_KEY_ID="my-access-key"
$ export AWS_SECRET_ACCESS_KEY="my-secret-key"
$ export AWS_REGION="us-east-1"
- If you have the AWS Command Line Interface (CLI) installed, you can run
aws configure
and enter the access key ID, secret access key, and default region. Terraform will automatically use these credentials. I will use this method in my example.
Step 2: Obtain your Access key ID and secret access key for your AWS user
Next, obtain your Access key ID and secret access key for your AWS user.
If you don’t have one, follow the steps below to retrieve one:
- Sign in to the AWS Management Console using your AWS account credentials.
- Open the IAM (Identity and Access Management) service from the console.
- In the IAM dashboard, navigate to “Users” in the left-hand navigation pane.
- Select the IAM user for which you want to generate or retrieve the Access Key ID and Secret Access Key.
- Under the “Security credentials” tab for the selected user, you will find a section labeled “Access keys.”
- If the user doesn’t have any access keys, you can click on the “Create access key” button to generate a new pair of access keys.
- After creating or selecting an existing access key, you will be able to view the Access Key ID. To view the Secret Access Key, click on the “Show” button in the “Secret access key” column.
Make sure to record the Secret Access Key immediately, as AWS will only show it once. If you lose the Secret Access Key, you will need to generate a new one.
Note: Your user will need permission to put the S3 access policy on the bucket — to check those in place, check the link here.
Step 3: Run aws configure
Run aws configure
in the console to authenticate. Enter your AWS Access key ID and secret access key when prompted.
Step 4: Create a new main.tf file
Open your code editor and create a new file called main.tf
.
Step 5: Set the IAM role
Copy and paste the following code into the file and save it.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_iam_role" "example_role" {
name = "examplerole"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "example_attachment" {
role = aws_iam_role.example_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
}
resource "aws_iam_instance_profile" "example_profile" {
name = "example_profile"
role = aws_iam_role.example_role.name
}
resource "aws_instance" "example_instance" {
ami = "ami-06ca3ca175f37dd66"
instance_type = "t2.micro"
iam_instance_profile = aws_iam_instance_profile.example_profile.name
tags = {
Name = "exampleinstance"
}
}
resource "aws_s3_bucket_policy" "example_bucket_policy" {
bucket = "example-bucket"
policy = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${aws_iam_role.example_role.name}"
},
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::example-bucket",
"arn:aws:s3:::example-bucket/*"
]
}
]
})
}
data "aws_caller_identity" "current" {}
What this will do:
- Add the provider block to declare we will use the AWS provider and set the region (us-east-1 in the example is North Virginia).
- Create an IAM role named “example-role” using the
aws_iam_role
resource. Theassume_role_policy
attribute specifies the trust policy, allowing EC2 instances to assume this role. - Attach an AWS-managed policy, “AmazonS3ReadOnlyAccess,” to the role using the
aws_iam_role_policy_attachment
resource. - Create the EC2 instance using the
aws_instance
resource. Theami
attribute is set to the desired Amazon Machine Image (AMI) ID. The AMI used in the example is an Amazon Linux 2023 AMI eligible for the free tier at the time of writing.To check available AMIs, log into the console at https://console.aws.amazon.com/ec2/ and click on ‘AMI Catlog’ under the Instances section.
- To associate the IAM role with the EC2 instance, we use the
iam_instance_profile
attribute and provide the name of the IAM role created earlier,aws_iam_role.example_role.name
.
Step 6: Run terraform init
With the configuration files created, open a console and type terraform init
to initialize the Terraform code.
Step 7: Run terraform validate
Run terraform validate
to check the syntax of your configuration is valid.
Step 8: Run terraform plan
In the console type terraform plan
to generate the plan. Review it and check you are happy the plan matches what you expect to happen.
Step 9: Run terraform apply
Run terraform apply
to apply the configuration to AWS.
Step 10: See the new resources in AWS
Check the AWS for the newly created resources. You should see the IAM role, S3 bucket, and EC2 instance.
Under the EC2 instance security tab, you can see the role has been assigned.
Step 11: Clean up
To clean up, run terraform destroy
to remove all the resources in your Terraform configuration.
Check out also how to create AWS IAM policy using Terraform.
An IAM role is a secure way to manage and delegate permissions in AWS, allowing you to control access to resources without sharing long-term credentials and providing a mechanism for temporary permissions for trusted entities.
IAM roles can be created using Terraform and assigned to resources as shown in the step-by-step tutorial.
We encourage you also to explore how Spacelift makes it easy to work with Terraform. If you need any help managing your Terraform infrastructure, building more complex workflows based on Terraform, and managing AWS credentials per run, instead of using a static pair on your local machine, Spacelift is a fantastic tool for this. It supports Git workflows, policy as code, programmatic configuration, context sharing, drift detection, and many more great features right out of the box.
Note: New versions of Terraform are placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that expands on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6.
Manage Terraform Better with Spacelift
Build more complex workflows based on Terraform using policy as code, programmatic configuration, context sharing, drift detection, resource visualization and many more.