aws

Authenticating to AWS with the Credentials File

This is Part 1 of the Comprehensive Guide to Authenticating to AWS on the Command Line. In the intro to the series, we went over the basics…
Authenticating to AWS with the Credentials File
YB
Yevgeniy Brikman
Co-Founder
Published August 4, 2018

This is Part 1 of the Comprehensive Guide to Authenticating to AWS on the Command Line. In the intro to the series, we went over the basics of AWS Authentication, including IAM Users, IAM Roles, and Access Keys. In this post, we’re going to present the first option for authenticating to AWS on the Command Line: the Credentials File.

Basic usage

You can store your AWS Access Keys in a Credentials File which lives in ~/.aws/credentials (or %UserProfile%\.aws\credentials on Windows). Normally, the way you create this file is by installing the AWS CLI and running the aws configure command:

$ aws configure
AWS Access Key ID: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: us-west-2
Default output format [None]: json

AWS prompts you to enter your Access Key ID and Secret Access Key and stores them in ~/.aws/credentials:

[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

It also stores the other settings you entered in ~/.aws/config:

[default]
region=us-west-2
output=json

Once these files exist, you can run any CLI or SDK tool that talks to AWS, and it will automatically find and use this credentials file and settings.

Working with multiple sets of Access Keys

If you have multiple sets of Access Keys (e.g., for multiple IAM Users in different AWS accounts), you can create a separate Named Profile for each one** in your Credentials File in ~/.aws/credentials:

[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[user2]
aws_access_key_id=AKIAI44QH8DHBEXAMPLE
aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY

And similarly, you can have multiple Named Profiles in your Config File in ~/.aws/config:

[default]
region=us-west-2
output=json
[profile user2]
region=us-east-1
output=text

Note that the Named Profile called default is used, as you might guess, by default. To tell your CLI tools to use something other than the default profile, you have to do one of the following:

  1. Set the AWS_PROFILE environment variable. For example, in Linux, you’d run export AWS_PROFILE=user2. After that, you can run any AWS CLI tool (e.g., terraform apply), and it should use your Named Profile.
  2. Some tools let you specify the profile as a command-line parameter or an argument in code. For example, the aws CLI lets you specify --profile: aws ec2 describe-instances --profile user2. In Terraform, you can set the profile parameter in a provider block:
provider "aws" {
profile = "user2"
}

Working with IAM Roles

If you want to assume IAM Roles — for example, you have an IAM User in the security account and want to assume an IAM Role in your dev account—you have two options. The first option depends on the CLI tool you’re using. Some CLI tools allow you to specify the IAM Role to assume via a command-line argument or in the code. For example, with Terraform, you can specify the assume_role setting in your provider configuration:

provider "aws" {
assume_role {
role_arn = "arn:aws:iam::123456789012:role/dev-full-access"
}
}

The second option is to specify the role_arn parameter in your Config File in ~/.aws/config:

[profile dev-full-access]
role_arn = arn:aws:iam::123456789012:role/dev-full-access

With either option, the value you specify for role_arn is the Amazon Resource Name (ARN) of the IAM Role in the dev account, which will have the format:

arn:aws:iam::<ACCOUNT_ID>:role/<ROLE_NAME>

Next time you run any CLI command that uses the dev-full-access Named Profile, the AWS SDK will automatically assume the IAM Role specified in role_arn.

Working with MFA

If you’re using the aws CLI, using MFA with a Credentials Profile is fairly straight forward. You just need to add the mfa_serial to your Config File in ~/.aws/config:

[profile with-mfa]
mfa_serial = arn:aws:iam::123456789012:mfa/jon-doe

The mfa_serial parameter should be set to the ARN of your MFA device, which you can get from the IAM User page of the AWS Web Console. It should be of the format:

arn:aws:iam::<ACCOUNT_ID>:mfa/<USERNAME>

Once you’ve added the mfa_serial parameter, the next time you run the aws CLI with that Named Profile, it will prompt you for an MFA token:

$ aws s3 ls --profile with-mfa
Enter MFA code:

But what if you’re running something that isn’t aws, such as terraform or packer? In that case, things get a bit hairy, as most other tools will not automatically prompt you for an MFA token. Instead, you have to do the MFA authentication process outside of that tool, which is a bit of a tedious process.

First, you configure your Credentials File with your normal (permanent) AWS Access Keys (e.g. by running aws configure). Next, you run the aws sts get-session-token command, passing it the ARN of your MFA device and an MFA token from the Google Authenticator App or your key fob:

aws sts get-session-token \
--serial-number arn:aws:iam::123456789012:mfa/jon-doe \
--token-code 123456 \
--duration-seconds 43200

This will return a blob of JSON that contains Temporary Access Keys (note the --duration-seconds argument in the earlier command, which specifies when these Temporary Access Keys will expire):

{
"Credentials": {
"SecretAccessKey": "secret-access-key",
"SessionToken": "temporary-session-token",
"Expiration": "expiration-date-time",
"AccessKeyId": "access-key-id"
}
}

You will need to take these Temporary Access Keys and copy them into a Named Profile in your Credentials File in ~/.aws/credentials:

[with-mfa]
aws_access_key_id = <Access-key-as-in-returned-output>
aws_secret_access_key = <Secret-access-key-as-in-returned-output>
aws_session_token = <Session-Token-as-in-returned-output>

Note that with Temporary Access Keys, you set not only aws_access_key_id and aws_secret_access_key in your Credentials File, but also aws_session_token.

Now you can run those other CLI tools with this Named Profile:

export AWS_PROFILE=with-mfa
terraform apply

Note that the Temporary Access Keys expire after a certain period of time (typically 12 hours), so you’ll have to do this over and over again. Not fun.

Pros and Cons

Pros

  • Basic authentication is easy.
  • Using IAM Roles is easy.
  • Named Profiles make it easy to manage multiple sets of credentials and settings.

Cons

  • Your Access Keys are stored in plaintext on disk. This is NOT secure.
  • You’re always using permanent Access Keys for auth rather than Temporary Access Keys that are rotated.
  • Using MFA is complicated and error prone.
  • Your credentials sit around on disk forever and the default Named Profile gets used for all commands if you forget to specify a different one, which is error prone.
  • It’s tempting to specify Named Profiles in your code (e.g., in your Terraform code) to ensure the proper credentials are used, but that requires all of your team members to use the same names for your Named Profiles, which can be hard to enforce.

Conclusion

Although many AWS tutorials use the Credentials File, we usually recommend against it, as storing your permanent AWS credentials on disk, in plaintext, is not safe. To make matters worse, MFA usage is so complicated with the Credentials File, that most users don’t bother with it.

To see a better alternative, head on to the next part of the series, Authenticating to AWS with Environment Variables.

Get your DevOps superpowers at Gruntwork.io.