Answers: <p>We avoid terraform handle our secrets. Even if you manage to inject secrets by a var file "secrtes.tfvars" as pointed out above, these secrets will be stored in your terraform (remote-)state.</p>
  
  <p>You can protect remote-state files by using e.g. S3 authorization, or you can gitignore local state files but we decided not to rely on this kind of protection.</p>
  
Answers: CC BY-SA 3.0
Answers: 2017-10-02T19:34:13.230Z
Answers: Also check https://github.com/hashicorp/terraform/issues/516 which is where they track the issue of tfstate leaking secrets
Answers: jottr
Answers: CC BY-SA 3.0
Answers: 2017-09-15T19:10:53.623Z
Answers: 2017-09-15T20:05:13.667Z
Answers: 2017-09-15T20:05:13.667Z
Answers: jerger
Answers: <p>To import secrets into .tf files, you can also use an <a href="https://www.terraform.io/docs/providers/external/data_source.html" rel="nofollow noreferrer">external data source</a>. This could be e.g. a script which decrypts your secrets.</p>
  
Answers: CC BY-SA 4.0
Answers: 2020-02-06T10:52:32.530Z
Answers: A downside to this is that any resource with an attribute relying on a value from the external data source will be "calculated" so likely be modified by terraform on every run even if the secret hasn't changed. That might be OK but in some cases might take a while or at worst break stuff.
Answers: Davos
Answers: CC BY-SA 3.0
Answers: 2018-02-15T07:31:16.887Z
Answers: 2018-02-15T07:31:16.887Z
Answers: jofel
Answers: <p>I looked at a few different ways but I particularly liked git-crypt for an adhoc thing to do before implementing something bigger like Vault.</p>
  
Answers: CC BY-SA 3.0
Answers: 2017-10-02T19:43:11.343Z
Answers: to thoe who downvoted, please explain why.
Answers: jottr
Answers: CC BY-SA 3.0
Answers: 2017-02-28T20:01:28.683Z
Answers: 2017-02-28T20:01:28.683Z
Answers: Naphta
Answers: <p>If you're on AWS, then have a look at <a href="https://aws.amazon.com/blogs/mt/the-right-way-to-store-secrets-using-parameter-store/" rel="noreferrer">"The Right Way to Manage Secrets"</a> by <a href="https://segment.io" rel="noreferrer">Segment.io</a> on the AWS Blog. We advocate using <a href="https://github.com/segmentio/chamber" rel="noreferrer"><code>chamber</code></a> 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. </p>
  
  <p>After <a href="https://docs.cloudposse.com/secrets-management/aws-kms-ssm/" rel="noreferrer">configuring chamber</a> and setting up the KMS key, we write the secrets to the parameter store. </p>
  
  <pre><code>chamber write db TF_VAR_DB_USER foobar
  chamber write db TF_VAR_DB_PASS secret
  </code></pre>
  
  <p>Then use those secrets when you call terraform.</p>
  
  <pre><code>chamber exec db -- terraform plan
  </code></pre>
  
  <p>This assumes you've defined a variable called <code>DB_USER</code> and <code>DB_PASS</code> in your HCL code. </p>
  
  <p>For example, you could add this to <code>variables.tf</code></p>
  
  <pre><code>variable "DB_USER" { }
  variable "DB_PASS" { }
  </code></pre>
  
  <p><strong>NOTE:</strong> <code>chamber</code> will always export environment variables in uppercase</p>
  
  <p>We provide a terraform module called <a href="https://github.com/cloudposse/terraform-aws-kms-key" rel="noreferrer"><code>terraform-aws-kms-key</code></a> to make provisioning the KMS key easy. Check out our detailed documentation with examples of how to use <a href="https://docs.cloudposse.com/tools/chamber/" rel="noreferrer"><code>chamber</code></a> with multiple namespaces as well as <a href="https://docs.cloudposse.com/secrets-management/aws-kms-ssm/" rel="noreferrer">how to use chamber with terraform</a> to manage secrets. See our <a href="https://github.com/cloudposse/terraform-root-modules/tree/master/aws/chamber" rel="noreferrer">complete reference example</a> for provisioning chamber dependencies. </p>
  
  <p>As for <code>.tfstate</code>, 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 <a href="https://github.com/cloudposse/terraform-aws-tfstate-backend" rel="noreferrer"><code>terraform-aws-tfstate-backend</code></a> module to provision a bucket and DynamoDB locking table according to best practices. </p>
  
Answers: CC BY-SA 4.0
Answers: 2018-07-27T08:21:27.143Z
Answers: This is highly tied to AWS services, which the question doesn't mention and sounds not really an answer for on premise infrastructures or any other cloud.
Answers: Tensibai
Answers: CC BY-SA 4.0
Answers: 2018-07-27T20:42:25.440Z
Answers: @tensibai, you are correct. The original question does not provide enough information to ascertain the operating platform in order to make the best recommendation. Every platform will be different depending on platform capabilities. On prem or baremetal users may want to consider using a combination of Vault and Terraform Enterprise. The scope of implementing that will be much, much greater. :)
Answers: Erik Osterman
Answers: CC BY-SA 4.0
Answers: 2019-01-21T16:19:06.620Z
Answers: I already use AWS Secrets Manager and dont want to use chamber and Parameter Store. Is it possible to do this same thing with Secrets Manager too?
Answers: red888
Answers: CC BY-SA 4.0
Answers: 2018-07-27T05:03:52.553Z
Answers: 2018-07-27T05:03:52.553Z
Answers: Erik Osterman
Answers: <p>you can store values in the parameter store and use them in terraform resources by fetching values using data resources.</p>
  <pre><code>data &quot;aws_ssm_parameter&quot; &quot;rds_password&quot; {
    name = &quot;/${var.project_name}/DB_PASSWORD&quot;
  }
  
  resource &quot;aws_db_instance&quot; &quot;rds&quot; {
    ...
    password = data.aws_ssm_parameter.rds_password.value
    ...
  }
  </code></pre>
  
Answers: CC BY-SA 4.0
Answers: 2020-09-29T14:48:06.227Z
Answers: 2020-09-29T14:48:06.227Z
Answers: Piyush Sonigra
Answers: <p>You can utilize the <a href="https://www.terraform.io/docs/providers/external/data_source.html" rel="nofollow noreferrer">external data source</a> to import secrets to Terraform and encrypt the secret files with <code>gpg</code>.</p>
  
  <p>For instance, this what a terraform file would like for creating an rds instance with password <code>foobarbaz</code></p>
  
  <pre><code>data "external" "rds" {
    program  = [ "cat", ".secrets/rds.json"]
  }
  
  
  resource "aws_db_instance" "default" {
    allocated_storage    = 20
    storage_type         = "gp2"
    engine               = "mysql"
    engine_version       = "5.7"
    instance_class       = "db.t2.micro"
    name                 = "mydb"
    username             = "foo"
    password             = "${data.external.rds.result.password}"
    parameter_group_name = "default.mysql5.7"
  }
  </code></pre>
  
  <p>You can check <a href="http://issamben.com/how-to-encrypt-terraform-secrets/" rel="nofollow noreferrer">this post</a> that explains in detail how to do this. </p>
  
  <p><strong><a href="http://issamben.com/how-to-encrypt-terraform-secrets/" rel="nofollow noreferrer">How to encrypt terraform secrets</a></strong></p>
  
Answers: CC BY-SA 4.0
Answers: 2022-04-27T12:39:37.070Z
Answers: `.tfstate` will still contain the secrets un-encrypted.
Answers: Valerij Dobler
Answers: CC BY-SA 4.0
Answers: 2020-02-22T19:42:05.477Z
Answers: 2020-02-22T19:42:05.477Z
Answers: sam ben
Answers: <p>Terraform <a href="https://www.terraform.io/intro/getting-started/variables.html" rel="noreferrer">supports</a> adding an additional file with variables during invocation.</p>
  
  <p><sup>documentation: <a href="https://www.terraform.io/intro/getting-started/variables.html#from-a-file" rel="noreferrer">https://www.terraform.io/intro/getting-started/variables.html#from-a-file</a></sup></p>
  
  <p>We are using that feature to provide a <code>secrets.tfvars</code> file on each invocation of Terraform. We also use a script to wrap the command so that its invocation is consistent, and all team members avoid having to make the same mistakes. The wrapper synchronizes <code>.tfstate</code> with S3 before an execution, and pushes <code>.tfstate</code> back to S3 at the end. I also hear of people doing the same thing with state stored in Consul, even adding a kind of semaphore in consul to prevent two people from starting Terraform at the same time.</p>
  
  <p>When you avoid setting a default value in a <code>variables.tf</code> file, it forces the user to input the value. It can be either entered manually or using the <code>-var-file</code> command option like described above. Not setting a default on your secrets is a good way to enforce changes that require a change in secrets.</p>
  
  <p>The <code>secrets.tfvars</code> file is a symbolic link to one of the files with secrets which are not stored in version control. We have several, one per environment, like so <code>secrets-prod.tfvars</code>, <code>secrets-dev.tfvars</code>, <code>secrets-stg.tfvars</code>, etc...</p>
  
  <p>An even better practice would be to generate these secrets files during the wrapper script based on data in Vault or some other way to <em>share</em> secrets. Since currently when the format of secrets changes, or secrets themselves, we need to communicate it to the team outside the version control channel - and this doesn't always work well, to be honest. But secrets do change infrequently.</p>
  
Answers: CC BY-SA 3.0
Answers: 2017-04-03T09:31:04.530Z
Answers: Link to code - https://gist.github.com/kesor/21f942be0350559b44f7ad1f9d846e7c
Answers: Evgeny Zislis
Answers: CC BY-SA 3.0
Answers: 2017-03-01T01:36:58.157Z
Answers: 2017-03-02T15:37:00.370Z
Answers: 2017-03-02T15:37:00.370Z
Answers: Evgeny Zislis
Body: <p>I would like to use the Terraform <a href="https://www.terraform.io/docs/providers/mysql/index.html" rel="noreferrer">MySQL Provider</a> to keep a list of mysql users and grants handy for creating new test environments. The <code>.tf</code> and <code>.tfstate</code> files both seem to want to store the MySQL passwords in plaintext.</p>
  
  <p><strong>Concerning .tf:</strong></p>
  
  <p>It is my understanding that <code>.tf</code> files live in revision control and are maintained by a team.  How does that practice differ when secrets are in the <code>.tf</code>? It is possible to encrypt these values at all?</p>
  
  <p><strong>Concerning .tfstate:</strong></p>
  
  <p>I can store the <code>.tfstate</code> securely somewhere after running Terraform apply, but it would be preferable for this use case to not store it at all?</p>
  
Tags: <terraform><security>
Title: How can I manage secrets in .tf and .tfstate?
UserDisplayName: Anthony Neace
ThreadText: # How can I manage secrets in .tf and .tfstate?
  
  (Asked by: username_0 on 2017-02-28)
  
  I would like to use the Terraform [MySQL Provider](https://www.terraform.io/docs/providers/mysql/index.html) to keep a list of mysql users and grants handy for creating new test environments. The `.tf` and `.tfstate` files both seem to want to store the MySQL passwords in plaintext.
  
  **Concerning .tf:**
  
  It is my understanding that `.tf` files live in revision control and are maintained by a team. How does that practice differ when secrets are in the `.tf`? It is possible to encrypt these values at all?
  
  **Concerning .tfstate:**
  
  I can store the `.tfstate` securely somewhere after running Terraform apply, but it would be preferable for this use case to not store it at all?
  
  **Tags:** terraform, security
  
  
  ---
  
  ## 7 answers
  
  ### Answer by username_12 on 2017-03-01. Score: 30 | Accepted answer
  
  Terraform [supports](https://www.terraform.io/intro/getting-started/variables.html) adding an additional file with variables during invocation.
  
  documentation: <https://www.terraform.io/intro/getting-started/variables.html#from-a-file>
  
  We are using that feature to provide a `secrets.tfvars` file on each invocation of Terraform. We also use a script to wrap the command so that its invocation is consistent, and all team members avoid having to make the same mistakes. The wrapper synchronizes `.tfstate` with S3 before an execution, and pushes `.tfstate` back to S3 at the end. I also hear of people doing the same thing with state stored in Consul, even adding a kind of semaphore in consul to prevent two people from starting Terraform at the same time.
  
  When you avoid setting a default value in a `variables.tf` file, it forces the user to input the value. It can be either entered manually or using the `-var-file` command option like described above. Not setting a default on your secrets is a good way to enforce changes that require a change in secrets.
  
  The `secrets.tfvars` file is a symbolic link to one of the files with secrets which are not stored in version control. We have several, one per environment, like so `secrets-prod.tfvars`, `secrets-dev.tfvars`, `secrets-stg.tfvars`, etc...
  
  An even better practice would be to generate these secrets files during the wrapper script based on data in Vault or some other way to *share* secrets. Since currently when the format of secrets changes, or secrets themselves, we need to communicate it to the team outside the version control channel - and this doesn't always work well, to be honest. But secrets do change infrequently.
  
  > **Comments:**
  > **username_12**: Link to code - https://gist.github.com/kesor/21f942be0350559b44f7ad1f9d846e7c  
  
  ---
  
  ### Answer by username_6 on 2018-07-27. Score: 11
  
  If you're on AWS, then have a look at ["The Right Way to Manage Secrets"](https://aws.amazon.com/blogs/mt/the-right-way-to-store-secrets-using-parameter-store/) by [Segment.io](https://segment.io) on the AWS Blog. We advocate using [`chamber`](https://github.com/segmentio/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](https://docs.cloudposse.com/secrets-management/aws-kms-ssm/) 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`](https://github.com/cloudposse/terraform-aws-kms-key) to make provisioning the KMS key easy. Check out our detailed documentation with examples of how to use [`chamber`](https://docs.cloudposse.com/tools/chamber/) with multiple namespaces as well as [how to use chamber with terraform](https://docs.cloudposse.com/secrets-management/aws-kms-ssm/) to manage secrets. See our [complete reference example](https://github.com/cloudposse/terraform-root-modules/tree/master/aws/chamber) 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`](https://github.com/cloudposse/terraform-aws-tfstate-backend) module to provision a bucket and DynamoDB locking table according to best practices.
  
  > **Comments:**
  > **username_7**: This is highly tied to AWS services, which the question doesn't mention and sounds not really an answer for on premise infrastructures or any other cloud.  
  > **username_6**: @username_7, you are correct. The original question does not provide enough information to ascertain the operating platform in order to make the best recommendation. Every platform will be different depending on platform capabilities. On prem or baremetal users may want to consider using a combination of Vault and Terraform Enterprise. The scope of implementing that will be much, much greater. :)  
  > **username_8**: I already use AWS Secrets Manager and dont want to use chamber and Parameter Store. Is it possible to do this same thing with Secrets Manager too?  
  
  ---
  
  ### Answer by username_1 on 2017-09-15. Score: 8
  
  We avoid terraform handle our secrets. Even if you manage to inject secrets by a var file "secrtes.tfvars" as pointed out above, these secrets will be stored in your terraform (remote-)state.
  
  You can protect remote-state files by using e.g. S3 authorization, or you can gitignore local state files but we decided not to rely on this kind of protection.
  
  > **Comments:**
  > **username_2**: Also check https://github.com/hashicorp/terraform/issues/516 which is where they track the issue of tfstate leaking secrets  
  
  ---
  
  ### Answer by username_3 on 2018-02-15. Score: 3
  
  To import secrets into .tf files, you can also use an [external data source](https://www.terraform.io/docs/providers/external/data_source.html). This could be e.g. a script which decrypts your secrets.
  
  > **Comments:**
  > **username_4**: A downside to this is that any resource with an attribute relying on a value from the external data source will be "calculated" so likely be modified by terraform on every run even if the secret hasn't changed. That might be OK but in some cases might take a while or at worst break stuff.  
  
  ---
  
  ### Answer by username_5 on 2017-02-28. Score: 2
  
  I looked at a few different ways but I particularly liked git-crypt for an adhoc thing to do before implementing something bigger like Vault.
  
  > **Comments:**
  > **username_2**: to thoe who downvoted, please explain why.  
  
  ---
  
  ### Answer by username_9 on 2020-09-29. Score: 0
  
  you can store values in the parameter store and use them in terraform resources by fetching values using data resources.
  
  ```
  data "aws_ssm_parameter" "rds_password" {
    name = "/${var.project_name}/DB_PASSWORD"
  }
  
  resource "aws_db_instance" "rds" {
    ...
    password = data.aws_ssm_parameter.rds_password.value
    ...
  }
  
  ```
  
  
  ---
  
  ### Answer by username_10 on 2020-02-22. Score: 0
  
  You can utilize the [external data source](https://www.terraform.io/docs/providers/external/data_source.html) to import secrets to Terraform and encrypt the secret files with `gpg`.
  
  For instance, this what a terraform file would like for creating an rds instance with password `foobarbaz`
  
  ```
  data "external" "rds" {
    program  = [ "cat", ".secrets/rds.json"]
  }
  
  resource "aws_db_instance" "default" {
    allocated_storage    = 20
    storage_type         = "gp2"
    engine               = "mysql"
    engine_version       = "5.7"
    instance_class       = "db.t2.micro"
    name                 = "mydb"
    username             = "foo"
    password             = "${data.external.rds.result.password}"
    parameter_group_name = "default.mysql5.7"
  }
  
  ```
  
  You can check [this post](http://issamben.com/how-to-encrypt-terraform-secrets/) that explains in detail how to do this.
  
  **[How to encrypt terraform secrets](http://issamben.com/how-to-encrypt-terraform-secrets/)**
  
  > **Comments:**
  > **username_11**: `.tfstate` will still contain the secrets un-encrypted.  
  
  ---
  
  