-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Adds google_kms_secret data source #741
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly looks good - a few comments/questions.
```hcl | ||
data "google_kms_secret" "sql_user_password" { | ||
crypto_key = "${google_kms_crypto_key.my_crypto_key.id}" | ||
ciphertext = "CiQAqD+xX4SXOSziF4a8JYvq4spfAuWhhYSNul33H85HnVtNQW4SOgDu2UZ46dQCRFl5MF6ekabviN8xq+F+2035ZJ85B+xTYXqNf4mZs0RJitnWWuXlYQh6axnnJYu3kDU=" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: maybe this base64 text should be truncated? It's going to spill out of the <code></code>
container on the doc site ...
ciphertext = "C1QAqD+x ... "
would probably do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that you'd probably have to scroll right a bunch to see the whole thing, but I think that a complete example without truncated strings is worth that cost.
The docs for aws_kms_secret
also displays the entire encrypted string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could, however, encrypt a shorter string. That might make it easier to read.
}) | ||
} | ||
|
||
func testAccEncryptSecretDataWithCryptoKey(s *terraform.State, resourceName, plaintext string) (string, *kmsCryptoKeyId, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we rename resourceName
to refer to the fact that it's a CryptoKey? Given that something else is actually under test I think it would clarify things.
return fmt.Errorf("Error decrypting ciphertext: %s", err) | ||
} | ||
|
||
plaintext, err := base64.StdEncoding.DecodeString(decryptResponse.Plaintext) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't these two calls be the other way around - ie, base64 decode the ciphertext first, and then send the ciphertext to KMS?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope. decrypt
expects the encrypted data that was originally returned from encrypt
, which is already in base64, and it returns some plaintext that is base64 encoded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks on closer inspection like I got confused by a difference between how the gcloud CLI handles this (ie, it spits raw bytes out to the terminal) and how the REST API does (ie, it base64 encodes everything). Sorry about that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries!
LGTM functionality wise |
Hi Michael, Coding wise, your solution is ready to be merged. However, we are reluctant to accept this change because we think it encourages a bad practice security wise. As you wrote in the documentation for this data source, the plaintext password is saved in the Terraform state (on operators and potentially CI server machines). This defeats the whole purpose of using KMS in the first place. It gives the user a false sense of security... I can see that this is better than putting the plaintext password in the configuration file itself. At least, the code repository doesn't store the plaintext password. Have you considered using Vault to dynamically provision your db users/passwords? I am happy to discuss this further :) |
Hi @rosbo, thank you for the response. One of the reasons I decided to add this was because the AWS provider has a similar data source. I didn't have an immediate need for this data source when I started working on it, but after working with terraform a bit more, I've started to see how a data source like this could be useful. Perhaps I have a misunderstanding of Terraform state, but I've always treated it as sensitive and encrypted it using Google Cloud KMS before storing it in version control. This is because all of my projects have GKE clusters, and the Terraform state file includes the master's username and password. There are probably other examples of this, but as soon as I saw this, I started encrypting my state files. The problem this data source solves for me is that it removes the need for me to encrypt my terraform variables file. I have a specific variables file reserved for secrets that could store things like database passwords or pre-shared keys for Cloud VPN, and those are also encrypted with KMS before storing them in version control. I understand that moving towards a solution like Vault is probably the best way to go. Unfortunately, I just haven't had the time at my company to set this up, especially when our applications are already using KMS and it's extremely easy to use it for this purpose as well. I definitely understand your concerns, and I'm not opposed to having this PR closed because of them. The workflow I'm using now (encrypting terraform variable files) works until I move to something more permanent like Vault. |
I personally also find this very useful (though didn't realize the limitation about it being in the state in cleartext). If there's the issue with this, why does the AWS provider have a kms data source? I would love to see some other suggestions for lighter weight solutions (short of using something like Vault) to avoid having cleartext secrets stored along with the code. As far as the potential security issue, maybe there should be a docs fix, and / or the kms data source for AWS should be dropped? (unrelated, also looks like there's a merge conflict now). |
I agree that the tfstate already contains a lot of sensitive information and should be handled accordingly (until Hashicorp release a better solution for tfstate secrets). I don't see any other security problems with this approach. |
FWIW, the equivalent AWS one has this at the top of the docs now:
maybe a warning like that? It would be nice if resources could be marked sensitive so they're not printed and / or encrypted somehow within the state. |
I think they can be marked sensitive (there are quite a few resources that don't display secrets in plans). But there is no way currently to encrypt secrets in the tfstate. |
@wyardley I included a similar warning in the documentation: https://github.com/terraform-providers/terraform-provider-google/pull/741/files#diff-c558c1ef972405ca1d0adcc58f6487b9R17 I think I copy/pasted it from the aws resource. |
@rosbo it would seem like using Vault as a backend currently may have some of the same limitations anyway? |
Additionally Google cloud storage encrypts at rest as standard, so using the GCS backend would offer some protection. Then you're left with keeping it out of logs etc. I no longer have a use case for this, but it seems to me possible to mitigate the security risks on the model of the equivalent aws resource. |
@danawillow I am on the fence about this one. What do you think? |
I think that given there's precedent for a similar resource in the AWS provider, a way to encrypt state files using remote state, and a prominent warning message on the documentation page, I'm a cautious yes. |
I can fix the merge conflicts here if there's a desire to get this merged. I've been holding off since I wasn't sure. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will accept it. Please fix the merge conflict and I also suggested one small change below. Thank you
}..., | ||
) | ||
|
||
projectOrg := os.Getenv("GOOGLE_ORG") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use these instead and delete the skipIfEnvNotSet block above:
projectOrg := getTestOrgFromEnv(t)
projectBillingAccount := getTestBillingAccountFromEnv(t)
9a15cad
to
b3e509f
Compare
@rosbo I rebased to fix the conflicts and included your suggestion. |
Failing build: |
858719d
to
2c601f3
Compare
Yup, my bad. I fixed it. |
|
Would you accept a PR on a data source for encrypting the plaintext using Google KMS as well? It's quite a logical flow that you would want to create the KMS keyring and crypto key and then encrypt some secret with that. Like how they are doing in the GCP Terraform Vault template now. |
Storing the plaintext secret in your code repo is a bad idea but if the secret is the output of some other resource like in the example for the GCP Terraform Vault template you linked above, I see some value and would accept it. Again, we would need to add a big warning sings in the docs about the terraform state not being encrypted by default. |
* Create google_kms_secret datasource * Create google_kms_secret datasource documentation * Remove duplicated code * Create acceptance test * Fix indentation * Add documentation to sidebar * Update Cloud SDK link in docs * Oxford comma * Rename variable to make it clear which resource is under test * Update test to use utils from provider_test
How to fetch encrypted certificates file from Google cloud storage to deploy vault instead of using self sign certificate with terraform code? |
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 hashibot-feedback@hashicorp.com. Thanks! |
Discussion in #495
cc @rochdev and @tragiclifestories who asked for this.
Example:
Acceptance test: