-
Notifications
You must be signed in to change notification settings - Fork 9.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Storing sensitive values in state files #516
Comments
See #874. I changed the RDS provider to store an SHA1 hash of the password. That said, I'm not sure I'd agree that it's Terraform's responsibility to protect data in the state file. Things other than passwords can be sensitive: for example if I had a security group restricting SSH access to a particular set of hosts, I wouldn't want the world to know which IP they need to spoof to gain access. The state file can be protected orthogonally: you can not put it on github, you can put it in a private repo, you can use git-crypt, etc. |
related #689 |
Just want to give my opinion on this topic. I do think Terraform should address this issue. I think it will increase the usefulness and ease of use of Terraform. Some examples from other projects: Ansible has vaults, and on Travis CI you can encrypt informaton in the |
Ansible vaults is a feature I often want in other devops tools. Protecting these details is not as easy as protecting the state file.. what about using consul or Atlas as a remote/backend store? +1 on this |
I just want to point out that, according to official documentation, storing the state file in version control is a best practice: https://www.terraform.io/intro/getting-started/build.html
(emphasis added) Which means we really shouldn't have to worry about secrets popping up in there... |
👍 on this idea -- it would be enough for our case to allow configuration of server-side encryption for S3 buckets. Any thoughts on implementing that? |
At the risk of adding scope to this discussion, I think another way to think of this is that Terraform's current architecture is based on a faulty assumption: Terraform assumes that all provider configuration is sensitive and that all resource configuration isn't sensitive. That is wrong in both directions:
So all of this is to say that I think overloading the provider/resource separation as a secret/non-secret separation is not the best design. Instead, it'd be nice to have a mechanism on both sides to distinguish between things that should live in the state and things that should not, so that e.g. generated secrets can be passed into provisioners but not retained in the state, and that the state can encode that a particular instance belongs to a particular AWS region and respond in a better way when the region changes. There are of course a number of tricky cases in making this situation, which I'd love to explore some more. Here are some to start:
|
Hi, any progress on that? Terraform 0.6.3 still stores raw passwords in the state file. Also, as a related issue, if you do not want to keep passwords in configuration, you can create variable without default value. But, this will force you to pass this variable every time you run I think, it would be nice to separate sensitive stuff from other attributes, so it will:
So, for configuration like:
terraform will require variable for the first run, when it doesn't have anything, but will not require on subsequent runs. To change such value one need to provide different value for password. |
Maybe there's a simple solution: store the state in Vault? |
A good solution for this would be useful for us as well - we're manually configuring certain things to keep them out of the |
So as I slowly cobble together another clean-sheet infra with Terraform I see this problem still exists, and this issue is almost exactly 1 year old. What is the thinking in regards to solving this? the ability to mark specific attributes within a resource as sensitive and storing SHA1 or SHA2 hashes of their values in the state for comparison? I see this comment on a related ticket, does that mean that using Vault will be the prescribed way? I get that it promotes product synergy but I'd really like a quick-n-dirty hashing solution as a fallback option if I'm honest. |
Moving secrets to vault, and using consul-template or integration with other custom solutions you have for CM certainly helps for a lot of cases, but completely avoiding secrets in TF or ending up in TF state is not always reasonable. |
Sure, in this particular case I don't want to manually manage RDS but I don't want the PW in the state in cleartext, regardless of where I keep it. I'm sure this is a somewhat common issue. Maybe an overarching ability to mark arbitrary attributes as sensitive is shooting for the moon but a good start would be anything that is obviously sensitive, such as passwords. |
Would it be feasible to open up state handling to plugins? That way this issue can be dealt with appropriately based on the use-case. |
I just got tripped up by this as well, as the docs explicitly tell you to store
|
One thing to consider around this is output. When you create a resource with secrets (key pair, access keys, db password, etc.), you likely want to show the secret in question at least once (possibly in the stdout of the first run, as Currently output are also stored in plain text in the One possible solution would be a mechanism to only show the secrets once, then not store them at all and not show them again (like AWS does), possibly using only-once output as I suggested in #4437 |
This comment was marked as duplicate.
This comment was marked as duplicate.
1 similar comment
This comment was marked as duplicate.
This comment was marked as duplicate.
Yes, this (plus Also:
See #33007 for alternative backend. |
I am of the opinion that the provider should never read the values of SecureStrings from This resource and data provider should never read the value. Even if using TFC - this allow anyone with access to TFC to add Managing the existence of a parameter in IaC makes sense - other resources can depend on the namespace and name w/o relying on magical strings; but managing the value should, IMHO, always be impossible. |
Sensitive secrets should be masked in the state file if it cannot be removed completely |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
Looks like the parallel open source project OpenTofu is working on this. Moving sensitive values to outside the state (e.g. key mgmt system) would require deep architectural changes. A more feasible, near-term fix is state encryption: opentofu/opentofu#874 I understand that this still doesn't solve the problem that teams setting infra would still have access to the state file with app level secrets. Saving secret hashes instead of the secrets themselves... seems to be difficult to implement (very likely because it requires architectural changes in code of all providers): opentofu/opentofu#801 (comment) |
@archvalmiki depending on your remote setup this is already possible today. E.g. when using s3 Backend, you can use KMS for encypting the s3 bucket containing your state. Or if you use kubernetes secret backend you can configure kubernetes to use a key management system to encrypt its secrets. Just to name a few options |
The RFC introduces encryption directly within Terraform for state files, allowing more granular control over encryption, such as partial encryption of sensitive values and full encryption of state and plan files. |
Got that :) just sharing this information for those that who are looking for a (somewhat) workable solution right now. It probably has been said somewhere in this thread before, but it's quite long by now so... 😅 |
Pls note that S3 bucket encryption (and anything similar) is only at-rest. If you authenticate yourself to S3 or to Terraform to view the state, you get the value. The only solution is if the value is not in state, and fetched at runtime temporarily from actual secret stores...for TF to compare it with reality and forget it afterwards. |
@Tbohunek - I don't think this is the only solution. The backend is well-placed to encrypt/decrypt sensitive values within the state at the point of serialization/deserialization (which is agnostic to the physical backend), so that providers can access the raw values as normal. If this were done with a key fetched at runtime from an actual secret store, then you have a statefile that is portable but doesn't leak sensitive values to those not authorised to see them. I tried a simple POC here - mr-miles@3e466c1 - which turns values marked as sensitive into "REDACTED" when storing in state. It doesn't look like the changes are even that extensive. |
@mr-miles can you explain what do you use for encryption? I mean, which "key/password" and where that is stored? By fetching secrets at runtime from AWS KMS or similar, you eliminate all possible ways of leaking the secret. You only give your TF identity access to the KMS, and TF applies it to where it should be and forgets it until next time.. No one else needs to have actual access to the secret value, and it never ever has to be known. If need be, IAM access to it can still be added in those rare cases, typically debug. |
Hi @Tbohunek - thanks for the questions. What I meant was, it is possible to store one encryption key/password in (say) AWS KMS for sensitive values, and permission the TF identity to retrieve it at runtime (as you describe), but store the encrypted sensitive values in the statefile. That way the actual values are still useless to anyone who hasn't got access to the key, but users don't have to coordinate the terraform and an independent secret store, or to encrypt the statefile in its entirety. I think there are two other advantages:
|
Right @mr-miles, so an explicit encryption key from KMS. This works too. |
Do you have an example? I'm just wondering if there are data-fetches where the field you'd request is not marked as sensitive already. For example, the aws_kms_secrets data source returns plaintext values but they are flagged as sensitive so would be spotted and encrypted automatically. There is a "sensitive" function to flag arbitrary values too, but AFAICS it looks like the need for the user to mark values as sensitive (and possibly forget, like you say) is vanishingly small. What do you think? |
Made a proposal that could remove many, if not all, secrets from the state: #34860. Current workarounds listed also. |
@mr-miles Indeed the field could be marked as sensitive, but it can only be encrypted if encryption is configured. There's no possible encryption by default as anyone can run their Terraform whenever and wherever they can. This is why I seek a way to not store the secrets at all in state. Value is stored in the Vault, and if any resource/provider needs secret input, Terraform could fetch it from the Vault on the fly, both |
It should be incorporated into vault by default, maybe one day. |
@omarismail are we getting close to an actionable design yet? It has been seven years since @sarneaud first proposed a lifecycle parameter along the lines of |
I'm not from Hashicorp so could be wrong, but I think this is expected to be resolved with "ephemeral values" which is currently in v1.10-alpha. However the example at the start of this issue (a password attribute in a resource) would need "write-only attributes" which the PR notes will not be ready for experimentation due changes needed in the provider protocol. |
#309 was the first change in Terraform that I could find that moved to store sensitive values in state files, in this case the
password
value for Amazon RDS. This was a bit of a surprise for me, as previously I've been sharing our state files publicly. I can't do that now, and feel pretty nervous about the idea of storing state files in version control at all (and definitely can't put them on github or anything).If Terraform is going to store secrets, then some sort of field-level encryption should be built in as well. In the meantime, I'm going to change things around to use https://github.com/AGWA/git-crypt on sensitive files in my repos.
The text was updated successfully, but these errors were encountered: