Seamless Local Development with MFA-Enabled Roles on AWS
Tags: aws, localdev
Published: 2024-06-03 15:10:23

---
title: "Seamless Local Development with MFA-Enabled Roles on AWS"
published: true
tags:
  - AWS
  - localdev
---

This article is a translation of https://zenn.dev/tilfin/articles/ab53ae77a8378f.

## The Challenge

Many of us have an AWS account for our main login portal and separate AWS accounts for each project. We often need to assume roles to obtain temporary credentials and access resources like S3 and DynamoDB on AWS from our local development environment.

The challenge lies in the short-lived nature of these credentials. In a development environment where the server automatically reloads upon code changes, manually renewing credentials and restarting the server every hour becomes a tedious task. This becomes even more cumbersome with MFA (Multi-Factor Authentication), requiring manual one-time password entry.

This article outlines the steps I took to streamline this process and enable seamless development without interruptions.

## Temporary Credential Issuance

While `aws sts assume-role` is the standard AWS CLI command for this purpose, I've developed a tool called `swrole` to simplify this process.

https://github.com/tilfin/homebrew-aws/tree/master?tab=readme-ov-file#swrole

## swrole 1.1 Release

This latest update introduces multiple ways to handle one-time passwords (OTP). While version 1.0 only supported interactive input, version 1.1 allows you to pass the OTP directly as a command argument using `-t 123456`. Additionally, you can now define `generate_token` within the target profile section of your `~/.aws/config` file. This enables automatic OTP retrieval from services like 1Password.

### ~/.aws/credentials

```ini
[my-company]
aws_access_key_id = XXXXXXXXXX
aws_secret_access_key = XXXXXXXXXX
```

### ~/.aws/config

```ini
[profile my-company]
region = ap-northeast-1

[profile project-dev]
role_arn = arn:aws:iam::111111111111:role/developer
mfa_serial = arn:aws:iam::000000000000:mfa/member
source_profile = my-company
region = ap-northeast-1
generate_token = op item get "AWS Account" --otp
```

In this example, **generate_token** is configured to fetch the OTP for "AWS Account" using the [1Password CLI](https://developer.1password.com/docs/cli/).

## Leveraging Process Credential Provider in AWS SDKs

During my research, I discovered the `credential_process` configuration option in `~/.aws/config`. This allows AWS SDKs to execute a specified command and utilize the resulting JSON output (from standard output) as credentials.

https://docs.aws.amazon.com/sdkref/latest/guide/feature-process-credentials.html

Recognizing its potential, I've incorporated this functionality into **swrole** version 1.1. Using the `-j` option now outputs the credential JSON in the format expected by the Process credential provider.

However, directly using **credential_process** with the `project-dev` profile won't work seamlessly due to the SDK's credential prioritization. We need to define a separate profile specifically for application development.

### ~/.aws/config

```ini
[profile app-dev]
credential_process = swrole -j project-dev
```

### ~/.aws/credentials

```ini
[app-dev]
region = ap-northeast-1
```

While other SDKs are untested, using `~/.aws/credentials` for `credential_process` works with AWS SDK JavaScript v3.

Now, you can run your development server with this AWS profile, triggering the seamless credential fetching process:

```
$ AWS_PROFILE=app-dev pnpm dev
```

**Important:** Ensure your AWS SDK utilizes proper credential caching to avoid issues with concurrent requests using the same one-time password.

## Additional Notes

I encountered some challenges with AWS SDK JavaScript v3's credential caching behavior related to this approach. You can find a detailed explanation in this article:

[Optimizing Credential Configuration in AWS SDK for JavaScript v3: Understanding Cache Mechanisms and Best Practices](https://dev.to/tilfin/optimizing-credential-configuration-in-aws-sdk-for-javascript-v3-understanding-cache-mechanisms-and-best-practices-oka)

Furthermore, this method eliminates the need for manual OTP input even with the AWS CLI itself.