If you're on AWS, then have a look at "The Right Way to Manage Secrets" by Segment.io on the AWS Blog. We advocate using chamber
to all of our customers for managing secrets. It works by leveraging the AWS Systems Manager Parameter Store (SSM) together with KMS keys. This ensures secrets are encrypted at rest (and in transit), secured with IAM, auditable with CloudTrails, and only exposed as environment variables at run-time.
After configuring chamber and setting up the KMS key, we write the secrets to the parameter store.
chamber write db TF_VAR_DB_USER foobar
chamber write db TF_VAR_DB_PASS secret
Then use those secrets when you call terraform.
chamber exec db -- terraform plan
This assumes you've defined a variable called DB_USER
and DB_PASS
in your HCL code.
For example, you could add this to variables.tf
variable "DB_USER" { }
variable "DB_PASS" { }
NOTE: chamber
will always export environment variables in uppercase
We provide a terraform module called terraform-aws-kms-key
to make provisioning the KMS key easy. Check out our detailed documentation with examples of how to use chamber
with multiple namespaces as well as how to use chamber with terraform to manage secrets. See our complete reference example for provisioning chamber dependencies.
As for .tfstate
, you bring up a really good point about the existence of plain-text secrets in the state file. There's really no way around this. In order for terraform to calculate changes to build a plan, it needs to know the "before" and "after" state. For this reason, we recommend using an encrypted S3 bucket with mandatory versioning. Use the terraform-aws-tfstate-backend
module to provision a bucket and DynamoDB locking table according to best practices.