2
votes

Overview

  1. Create a aws_secretsmanager_secret
  2. Create a aws_secretsmanager_secret_version
  3. Store a uniquely generated string as that above version
  4. Use local-exec provisioner to store the actual secured string using bash
  5. Reference that string using the secretsmanager resource in for example, an RDS instance deployment.

Objective

  1. Keep all plain text strings out of remote-state residing in a S3 bucket
  2. Use AWS Secrets Manager to store these strings
  3. Set once, retrieve by calling the resource in Terraform

Problem

Error: Secrets Manager Secret "arn:aws:secretsmanager:us-east-1:82374283744:secret:Example-rds-secret-fff42b69-30c1-df50-8e5c-f512464a4a11-pJvC5U" Version "AWSCURRENT" not found

when running terraform apply

Question

Why isn't it moving the AWSCURRENT version automatically? Am I missing something? Is my bash command wrong? The value does not write to the secret_version, but it does reference it correctly.

Look in main.tf code, which actually performs the command:

provisioner  "local-exec" {

command =  "bash -c 'RDSSECRET=$(openssl rand -base64 16); aws secretsmanager put-secret-value --secret-id ${data.aws_secretsmanager_secret.secretsmanager-name.arn} --secret-string $RDSSECRET --version-stages AWSCURRENT --region ${var.aws_region} --profile ${var.aws-profile}'"

}

Code

main.tf

data  "aws_secretsmanager_secret_version"  "rds-secret" {

secret_id =  aws_secretsmanager_secret.rds-secret.id

}

  

data  "aws_secretsmanager_secret"  "secretsmanager-name" {

arn =  aws_secretsmanager_secret.rds-secret.arn

}

  

resource  "random_password"  "db_password" {

length =  56

special =  true

min_special =  5

override_special =  "!#$%^&*()-_=+[]{}<>:?"

keepers =  {

pass_version = 1

}

}

  

resource  "random_uuid"  "secret-uuid" { }

  

resource  "aws_secretsmanager_secret"  "rds-secret" {

name =  "DAL-${var.environment}-rds-secret-${random_uuid.secret-uuid.result}"

}

  

resource  "aws_secretsmanager_secret_version"  "rds-secret-version" {

secret_id =  aws_secretsmanager_secret.rds-secret.id

secret_string =  random_password.db_password.result


  

provisioner  "local-exec" {

command =  "bash -c 'RDSSECRET=$(openssl rand -base64 16); aws secretsmanager put-secret-value --secret-id ${data.aws_secretsmanager_secret.secretsmanager-name.arn} --secret-string $RDSSECRET --region ${var.aws_region} --profile ${var.aws-profile}'"

}

}

variables.tf

variable  "aws-profile" {

description =  "Local AWS Profile Name "

type =  "string"

}

  

variable  "aws_region" {

description =  "aws region"

default="us-east-1"

type =  "string"

}

  

variable  "environment" {}

terraform.tfvars

aws_region="us-east-1"

aws-profile="Example-Environment"

environment="dev"
1

1 Answers

1
votes

The error likely isn't occuring in your provisioner execution per se, because if you remove the provisioner block the error still occurs on apply--but confusingly only the first time after a destroy. Removing the data "aws_secretsmanager_secret_version" "rds-secret" block as well "resolves" the error completely.

I'm guessing there is some sort of config delay issue here...but adding a 20 second delay provisioner to the aws_secretsmanager_secret.rds-secret resource block didn't help. And the value from the data block can be successfully output on subsequent apply runs, so maybe it's not just timing.

Even if you resolve the above more basic issue, it's likely your provisioner will still be confusing things by modifying a resource that Terraform is trying to manage in the same run. I'm not sure there's a way to get around that except perhaps by splitting into two separate operations.

Update:

It turns out that on the first run the data sources are read before the aws_secretsmanager_secret_version resource is created. Just adding depends_on = [aws_secretsmanager_secret_version.rds-secret-version] to the data "aws_secretsmanager_secret_version" block resolves this fully and makes the interpolation for your provisioner work as well. I haven't tested the actual provisioner.

Also you may need to consider this (which I take to not always apply to 0.13):

NOTE: In Terraform 0.12 and earlier, due to the data resource behavior of deferring the read until the apply phase when depending on values that are not yet known, using depends_on with data resources will force the read to always be deferred to the apply phase, and therefore a configuration that uses depends_on with a data resource can never converge. Due to this behavior, we do not recommend using depends_on with data resources.