I'm trying to avoid having secrets in Terraform state.
Is there a better way of setting an RDS password from a secret in Secrets Manager that does this?
resource "null_resource" "master_password" {
triggers = {
db_host = module.myrdsdatabase.cluster_id
}
provisioner "local-exec" {
command = <<TOF
password=$(aws secretsmanager get-secret-value --secret-id myrdscreds | jq '.SecretString | fromjson | .password' | tr -d '"')
aws rds modify-db-cluster --db-cluster-identifier ${module.myrdsdatabase.cluster_id} --master-user-password $password --apply-immediately
TOF
interpreter = ["bash", "-c"]
}
}
There is no concrete solution to this issue. There is nearly 7 year old, still active, discussion on TF github issue about handling secrets in TF.
In your question you are already avoiding aws_secretsmanager_secret_version which is good practice. aws_secretsmanager_secret_version will not protect your secrets from being in plain text in TF state file!
Generally, there are two things people do to keep the secrets secret:
local-exec, other could be using remote lambda through aws_lambda_invocation.Other ways are possible, such as creating RDS databases through CloudFormation (CFN) from your TF. CFN has a proper way of accessing secret manager securely through dynamic references.
We have to accept that the secrets are in the state and manage access and encryption to the remote state accordingly.
You can get a value right out of secrets manager with the aws_secretsmanager_secret_version data source
your local-exec can be simplified a bit by using jq --raw-format or -r
password=$(aws secretsmanager get-secret-value --secret-id myrdscreds | jq -r .SecretString | jq -r .password)
I prefer to fetch and then pass in the secret in a variable from a build script, rather than local-exec. It seems cleaner, in some cases the trigger on the null resource may not fire when the secret value has been changed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With