Using Multiple AWS IAM Roles
Tags: terraform, aws, devops, github
Published: 2023-02-17 14:48:42

### Access Control with IAM

One of the most important, and oftentimes most confusing, aspects of cloud infrastructure is access control. AWS IAM provides a way to secure access to AWS resources.

IAM roles are a key concept in AWS IAM that allow users to delegate access to AWS resources to other AWS accounts, AWS services, and external identities.

Using multiple AWS IAM roles in combination with Terraform allows you to manage access to resources in a more secure and scalable manner.

### IAM Roles

AWS IAM roles that allow you to grant permissions to one or more AWS resources to a specific entity. An entity is just a way to reference another AWS account, AWS service, or third-party.

It's important to understand that IAM roles are not associated with specific users or groups. IAM roles are only associated with specific policies that grant access to AWS resources.

When an entity assumes an IAM role, it receives the permissions that are defined in the policy attached to that IAM role.

### Benefits of IAM Roles

There are many advantages when using IAM roles vs. other access controls.

- Static credentials are not required
- Ability to grant permissions to third-parties without the need of a dedicated IAM user
- Granular permissions for a specific use case
- Leverage ephemeral resources like EC2 instances and Lambda functions

### Using Multiple IAM Roles with Terraform

There are a few different ways to leverage AWS IAM roles with the Terraform AWS provider.

One common way is to use the `assume_role` parameter to specify which IAM role should be assumed
when running the Terraform CLI. This can be defined on the `provider` or `resource` level.

A real-world example is to use separate IAM roles for a `production` and `qa` environment.

```hcl
provider "aws" {
  assume_role {
    role_arn = "arn:aws:iam::123456789012:role/production-role"
  }
}

provider "aws" {
  assume_role {
    role_arn = "arn:aws:iam::123456789012:role/qa-role"
  }
}
```

Once defined, you can specify which provider block to use for each resource.

```hcl
resource "aws_instance" "example" {
  ami           = "ami-4c55b159cbfafe1fe"
  instance_type = "t2.micro"
  provider      = aws.qa
}
```

Another common way to leverage AWS IAM roles with the Terraform AWS provider is by using the AWS CLI to assume a role before executing Terraform commands. The `aws sts assume-role` command provides a very easy way to return a set of temporary security credentials for a specific IAM role.

```
aws sts assume-role \
--role-arn "arn:aws:iam::123456789012:role/qa-role" \
--role-session-name qa-role
```

AWS will return a set of temporary credentials that can then be used to create `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables which the Terraform AWS provider consumes. This is how
the Terrateam GitHub Action assumes a user-defined IAM role. This method doesn't require you to specify `role_arn` in your Terraform code.

By using separate IAM roles in each environment, you have the ability to define each role with its own set of permissions. The `qa` environment IAM role would not need access to the `production` environment
and vice versa.

### Benefits of Using Multiple IAM Roles with Terraform

As you can already start to see, there are many benefits of using multiple IAM roles with Terraform.

- Security: Separate IAM roles improves your security posture by limiting access to your AWS resources only to entities that require access.

- Simplicity: It's easier to understand which entities have access to AWS resources by using separate IAM roles for different environments. Having the ability to easily manage access to resources based on
internal needs helps keep you more organized and secure.

- Compliance: Industry standards, best practices, and various other regulations like HIPAA and GDPR often require having the ability to enforce least privilege access to infrastructure. Separate IAM roles
give you the building blocks to satisfy these requirements.

- Flexibility: Having the ability to create granular access rules based on the needs of an organization creates flexibility and scalability for engineering teams.

- Auditing: Monitoring account activity by separate IAM roles for each environment, entity, and third-party gives you the ability to easily audit access to resources.

### Using Multiple IAM Roles with Terrateam

Using multiple IAM roles in a Terraform repository with Terrateam is easy to accomplish by creating simple configuration in your `.terrateam/config.yml`.

Take the following directory structure as an example:

```bash
josh@elmer:~/terraform $ tree
.
├── modules
│   └── ec2
│       └── v1
│           └── main.tf
├── production
│   └── main.tf
└── qa
    └── main.tf

5 directories, 3 files
josh@elmer:~/terraform $ 
```

In this Terraform repository, we have three directories:

- `modules`: Custom-written Terraform modules that's referenced throughout the repository
- `production`: Defined Terraform resources for the Production environment
- `qa`: Defined Terraform resources for the QA environment

An ideal workflow for this repository layout is to use separate IAM roles for each environment. By creating a `.terrateam/config.yml` at the root of the repository, one can safely assume separate IAM roles
before any Terraform CLI commands are issued.

```yaml
workflows:
  - tag_query: dir:production
    plan:
      - type: oidc
        provider: aws
        role_arn: "arn:aws:iam::123456789012:role/terrateam-production-role"
      - type: init
      - type: plan
    apply:
      - type: oidc
        provider: aws
        role_arn: "arn:aws:iam::123456789012:role/terrateam-production-role"
      - type: init
      - type: apply
  - tag_query: dir:qa
    plan:
      - type: oidc
        provider: aws
        role_arn: "arn:aws:iam::123456789012:role/terrateam-qa-role"
      - type: init
      - type: plan
    apply:
      - type: oidc
        provider: aws
        role_arn: "arn:aws:iam::123456789012:role/terrateam-qa-role"
      - type: init
      - type: apply
```

The above configuration will execute the following steps in your isolated Terrateam GitHub Actions runtime environment

1. Issue a secure token using the official GitHub OIDC Identity Provider. This token is used to authenticate against your AWS account. After a successful authentication, the Terrateam action will
automatically assume the IAM role defined in the `role_arn` configuration.

2. After successful authentication to AWS, Terrateam will execute an `aws sts` command in the GitHub Actions runtime environment to generate short-lived credentials for the IAM role defined
in the `role_arn` depending on which directory contains Terraform-related changes in the pull request.

3. Execute the necessary Terraform CLI commands in the directory where the Terraform-code change lies
   - `terraform init`
   - `terraform plan` or `terraform apply` depending on the operation

Separate IAM roles are defined and used by leveraging Terrateam [workflows](https://terrateam.io/docs/features/workflows). With custom workflows, the user can define many customizations to the steps
Terrateam will take depending on what file, directory, or workspace is modified in a pull request.

### Conclusion

Multiple AWS IAM roles with Terraform allows your team to properly manage access to your AWS resources in many environments. This is instrumental in achieving a proper security posture and creates a strong
foundation for scalable IAM. With the help of Terrateam, you can create and enforce specific IAM roles to be used against resources laid out in your Terraform repository.

Give [Terrateam](https://terrateam.io) a try and start leveraging multiple IAM roles with [OIDC](https://terrateam.io/docs/features/oidc) today.