Site icon UnixArena

Terraform – Source credentials from AWS secret Manager

Terraform plain text credentials

Terraform plain text credentials

How to avoid plain text credentials in terraform code? Terraform is an open-source infrastructure as a code tool that supports multi-cloud platforms. Many organizations have taken the multi-cloud strategy to manage the cost and eliminate the single vendor dependency. If you have multiple cloud environments, terraform becomes the default choice for provisioning. Communicating to multi-cloud in a single language is easier than using the respective cloud tools like cloud formation.

When it comes to credentials in terraform code, you have to rely on an external vault to encrypt it. Codes will be stored in a git repository and keeping plain text passwords in the code will lead to security breaches. This article will walk through how to source the encrypted credentials from AWS secret manager.

Sample Terraform code with plain text password:

1. The following sample terraform code consists plain text password. The secret will be written in a text file on the successful execution.

resource "null_resource" "test" {
  provisioner "local-exec" {
    when    = create
    command = "echo GooDay@123 > secret.txt"
  }
}

2. Let’s run the terraform apply.

lingesh@unixarena:~/test$ terraform apply --auto-approve

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # null_resource.test will be created
  + resource "null_resource" "test" {
      + id = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.
null_resource.test: Creating...
null_resource.test: Provisioning with 'local-exec'...
null_resource.test (local-exec): Executing: ["/bin/sh" "-c" "echo GooDay@123 > secret.txt"]
null_resource.test: Creation complete after 0s [id=3284626307449570859]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

3. Let’s look at the secret file which should be created.

lingesh@unixarena:~/test$ cat secret.txt
GooDay@123
lingesh@unixarena:~/test$

Let’s now simulate the same using AWS secret manager by encrypting the credentials.

Store the credentials in AWS Secret Manager

1. Login to AWS console and navigate to secret manager.

AWS Secrets Manager

2. Select the credentials type as “other type of secret” and select plain text. Enter the credentials in JSON format.

Store credentials – AWS secret Manager

3. Enter the secret name to store the credentials.

Enter the secret name – AWS secret manager

We have successfully stored the new credentials in AWS secret manager. In the next section, we will see how to call the stored credentials using terraform.

Update the terraform code to use encrypted credentials

1. Update the terraform code like the following to call the newly stored secret using terraform data module.

data "aws_secretsmanager_secret_version" "creds" {
  # Fill in the name you gave to your secret
  secret_id = "prod/app/ec2"
}

2. Source the data to terraform local to read the JSON code.

locals {
  ec2_creds = jsondecode(data.aws_secretsmanager_secret_version.creds.secret_string)
}

3. Let’s write the credentials to the text file using the following block of code. Here we haven’t used any plain text passwords in the code.

resource "null_resource" "test_user" {
  provisioner "local-exec" {
    when    = create
    command = "echo ${local.ec2_creds.user} >> secret.txt"
  }
}

resource "null_resource" "test_pass" {
  provisioner "local-exec" {
    when    = create
    command = "echo ${local.ec2_creds.password} >> secret.txt"
  }
}

4. You can also call the secret to any part of the terraform code like below. (Ex: local.ec2_creds.user & local.ec2_creds.password )

output "Username" {
  description = "ec2 username"
  value       = local.ec2_creds.user
  sensitive = true
}

output "Password" {
  description = "ec2 password"
  value       = local.ec2_creds.password
  sensitive = true
}

Putting all the codes together. Store the following content on “main.tf” file.

data "aws_secretsmanager_secret_version" "creds" {
  # Fill in the name you gave to your secret
  secret_id = "prod/app/ec2"
}

locals {
  ec2_creds = jsondecode(data.aws_secretsmanager_secret_version.creds.secret_string)
}

resource "null_resource" "test_user" {
  provisioner "local-exec" {
    when    = create
    command = "echo ${local.ec2_creds.user} >> secret.txt"
  }
}

resource "null_resource" "test_pass" {
  provisioner "local-exec" {
    when    = create
    command = "echo ${local.ec2_creds.password} >> secret.txt"
  }
}

output "Username" {
  description = "ec2 username"
  value       = local.ec2_creds.user
  sensitive = true
}

output "Password" {
  description = "ec2 password"
  value       = local.ec2_creds.password
  sensitive = true
}

5. Let’s execute the code and see the results.

lingesh@unixarena:~/test$ terraform apply --auto-approve

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # null_resource.test_pass will be created
  + resource "null_resource" "test_pass" {
      + id = (known after apply)
    }

  # null_resource.test_user will be created
  + resource "null_resource" "test_user" {
      + id = (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + Password = (sensitive value)
  + Username = (sensitive value)
null_resource.test_pass: Creating...
null_resource.test_user: Creating...
null_resource.test_user: Provisioning with 'local-exec'...
null_resource.test_user (local-exec): (output suppressed due to sensitive value in config)
null_resource.test_pass: Provisioning with 'local-exec'...
null_resource.test_pass (local-exec): (output suppressed due to sensitive value in config)
null_resource.test_user: Creation complete after 0s [id=5936974914414746230]
null_resource.test_pass: Creation complete after 0s [id=8908060725121377732]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Outputs:

Password = <sensitive>
Username = <sensitive>
lingesh@unixarena:~/test$ 

Here is the decrypted text file.

lingesh@unixarena:~/test$ cat secret.txt
admin
GooDay@123
lingesh@unixarena:~/test$

The following visual shows the mapping between the AWS secret manager key vs Terraform code.

AWS Secret Manager to Terraform Code mapping

Using the same method, you can encrypt the credentials in terraform code for any cloud resources deployment. Hope this article is informative to you.

Exit mobile version