Terraform and AWS credentials handling?


If you are new to terraform or maybe you have been using the terraform for quite some time then might have felt the need to manage your AWS Credentials inside your terraform file.

In this blog we will go through the different ways to set up your AWS Credentials so that you do not have to re-configure the AWS Credentials every time, also we will pay attention what are the most secure way to handle your AWS Credentials

Here are three different ways of handling AWS Credentials -

  1. Hard coding AWS Credentials(ACCESS_KEY, SECRET_KEY) inside terraform file (*Not recommended)
  2. Using /.aws/credentials file along with terraform's shared_credentials_file settings
  3. Configure AWS Credentials as environment variables

AWS Credentials always consists of aws_access_key_id, aws_secret_access_key and same credentials are used by Terraform to communicate with Amazon Cloud.

If you do not store those credentials securely then you might compromise the security of your infrastructure by exposing AWS Root Account credentials. So it is always recommended to follow good security practices for handling the credentials. In this guide, we will go through all the possible ways to handle your AWS Credentials but also what are the recommended ways to handle it.

The easiest way to use the AWS credentials is to hard code the AWS's access_key and secret_key inside your terraform file.

(It is not recommended to hard code the credentials inside terraform file)

Here is an Example-

1provider "aws" {
2   profile    = "test"
3   region     = "eu-central-1"
4   access_key = "A0LPA99DFKJ74HW0CPAGH0FNM3"
5   secret_key = "a1toUHEBHSU49348JjdssNicCwcT61DfzHtHtkWJYhgnN"
6}

Problem with the above approach

  1. Your AWS Credentials are stored in plain text format
  2. If you are using version control(GitHub, BitBucket, etc..) then your AWS credentials might end up in a public code repository where anyone can use those credentials and can impose a great risk to your cloud infrastructure.
  3. Hard-coding credentials in one place make it hard to re-use those credentials in other terraform projects or other terraform modules. So if you are planning to create another terraform project using the same credentials then you can not re-use the same piece of code.

When to Hard Code AWS Credentials

  1. If you are doing some development work and your terraform code is only accessible within your local development environment.
  2. Doing some POC(Proof of Concept) tasks with terraform limiting it only to the local development environment.

2. Using /.aws/credentials file along with terraform's shared_credentials_file settings

The second approach would be to store your AWS Credentials inside /.aws/credentials file. You need to install aws cli before you start storing those credentials inside /.aws/credentials. Refer to this aws cli installation guide so that you have /.aws/credentials created onto your machine.

After installing the aws cli you will have file credentials present at /.aws/credetials

Here is screenshot of /.aws/credetials-

AWS Credentials file present at /.aws/credetials

Use terraform's shared_credentials_file settings

Now "How to make terraform to read AWS Credentials file?" - For that, we are going to use terraform setting shared_credentials_file. This setting allows you to refer /.aws/credentials present in your machine after installing the AWS CLI.

Example-

1provider "aws" {
2   profile    = "test"
3   region     = "eu-central-1"
4   shared_credentials_file = "/home/vagrant/.aws/credentials"
5}

Now you can compare both the screenshot of /.aws/credentials and the example code snippet where it is referring to the same /.aws/credentials file.

Pros of using /.aws/credentials and shared_credentials_file

  1. You can re-use the AWS Credentials with other terraform projects or terraform modules
  2. You do not need to repeat or hard code AWS Credentials everywhere
  3. AWS credentials are stored at the machine level, so they will not end up in the public code repository
  4. If you limit the access of /.aws/credentials to root user then you have improved the security over the credentials sharing

Cons

  1. If you do not set permission over the /.aws/credentials file then anyone with access to the machine can view the AWS credentials.

3. Configure AWS Credentials as environment variables

The third option to handle the AWS Credentials is to export the variables as environment variables.

How to Export? -

1export AWS_ACCESS_KEY_ID="A0LPA509NDFKJ74HW0CPAGH0FNM3" 
1export AWS_SECRET_ACCESS_KEY="a1toUHEBHSU404823JjdssNicCwcT61DfzHtHtkWJYhgnN"

Run the above command to export AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY variables into the environment variables. After exporting the above variables you do not need to hard code or refer to /.aws/credentials file.

You can simply write you are terraforming configuration and terraform will fetch the AWS Credentials from the environment variables

Here is a sample Terraform code for EC2 using environment variables-

 1terraform {
 2  required_providers {
 3    aws = {
 4      source  = "hashicorp/aws"
 5      version = "3.74.0"
 6    }
 7  }
 8}
 9
10provider "aws" {
11   region     = "eu-central-1"
12}
13
14resource "aws_instance" "ec2_example" {
15
16   ami           = "ami-0767046d1677be5a0"
17   instance_type =  "t2.micro"
18
19   tags = {
20           Name = "Terraform EC2"
21   }
22}

If you look carefully in the provider block then we have only defined region while the credentials are being fetched from environment variables.

Benefits-

  1. The AWS Credentials are separate from the code.
  2. Development team can change or update the AWS Credentials externally without the need to change the code
  3. The credentials are stored locally at the machine level, so they will not end up in a public code repository with broader access.
  4. Reducing the risk of messing up environment variables in production, stage, or test

Cons

  1. Anyone with access to the machine can update those environment variables.
  2. If the machine needs re-installation then you have to maintain the backup of environment variables otherwise you might end up losing those environment variables.

4.Conclusion

Handling the AWS Credentials should be on the top of the list for improving infrastructure security. Although /.aws/credentials file as well as environment variables will improve the security of AWS Credentials but still it is not sufficient from the production's point of view. The most preferred and secure way would be to dynamically generate short-lived AWS credentials and store them inside the credentials vault for better management. I will write a detailed post on generating AWS credentials dynamically using the Hashicorp vault soon.

Update - Here is the detailed blog post on - Securing AWS secrets using HashiCorp Vault with Terraform


Read More -

  1. Install terraform on Ubuntu 20.04, CentOS 8, MacOS, Windows 10, Fedora 33, Red hat 8 and Solaris 11
  2. How to setup Virtual machine on Google Cloud Platform using terraform
  3. Create EC2 Instance on AWS using terraform
  4. How to use Terraform Input Variables
  5. What is variable.tf and terraform.tfvars?
  6. How to use Terraform locals?
  7. How to use Terraform output values?
  8. Understanding terraform count, for_each and for loop?
  9. Cloud-nuke : How to nuke AWS resources and save additional AWS infrastructure cost?
  10. How to use Terraform Dynamic blocks?
  11. How to use Terraform resource meta arguments?
  12. How to use Terraform Data sources?
  13. What is terraform provisioner?
  14. Terraform how to do SSH in AWS EC2 instance?
  15. How Terraform modules works?
  16. How to run specific terraform resource?
  17. How to use Workspaces in Terraform?
  18. Securing AWS secrets using HashiCorp Vault with Terraform?
  19. Managing Terraform states?
  20. Terraform state locking using DynamoDB (aws_dynamodb_table)
  21. Terraform and AWS credentials handling?
  22. Terraform and AWS Multi account Setup?

Terragrunt -

  1. How to use Terragrunt?

Posts in this Series