❗ Important note: using this method, the plaintext value of the secret will be persisted into your Terraform state file. This ideally shouldn't pose a problem as long as your Terraform state files are properly secured and encrypted too.
The Google Cloud Terraform provider provides a very clean and intuitive interface in order to store secrets in Git.
Before we can start committing our secrets in a Git repositoriy we first have to create a KMS key ring and a KMS crypto key.
# Create a KMS key ring in order to attach a KMS crypto key to.
resource "google_kms_key_ring" "default" {
name = "default-ring"
location = "global"
}
# Create a KMS crypto key that's being prevented from being destroyed.
resource "google_kms_crypto_key" "default" {
name = "default-crypto-key"
key_ring = google_kms_key_ring.default.id
rotation_period = "604800s"
lifecycle {
prevent_destroy = true
}
}
# Optionally we can grant Bob access to encrypt and decrypt.
resource "google_kms_crypto_key_iam_member" "bob_crypto_key_encrypter_decrypter" {
crypto_key_id = google_kms_crypto_key.default.id
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
member = "user:[email protected]"
}
Once these resources have been created we can encrypt our plaintext secret using our newly created KMS crypto key.
To do so we can use the gcloud kms encrypt command, see below:
$ echo -n my-super-secret-string | gcloud kms encrypt --plaintext-file=- \
--ciphertext-file=- --location=global --keyring=default-ring \
--key=default-crypto-key | base64
CiQAa2/tURAxviiz3qT4J3h4L4Vf759k65N4sSa+fhN/lZEbn08SNAAUPVwiGojZWfA7wAPr7xG4RbBUh+2GUAfYWScf+ZkHCsZAPMDUldaLvQ2DSzk99h1mY18=
We base64 encode the output as that's required by the Terraform Google provider data source we're going to use ⛓️.
Now that we have a base64 encrypted secret we can safely store this in Git, it's meaningless to attackers.
If we want to get the actual value of our secret, we can use a data source called google_kms_secret. This data source allows us to decrypt the secret and extract the value as plaintext.
# Here we decrypt a base64 encoded string using our newly created KMS crypto key.
data "google_kms_secret" "slack_oauth_token" {
crypto_key = google_kms_crypto_key.default.id
ciphertext = "CiQAa2/tURAxviiz3qT4J3h4L4Vf759k65N4sSa+fhN/lZEbn08SNAAUPVwiGojZWfA7wAPr7xG4RbBUh+2GUAfYWScf+ZkHCsZAPMDUldaLvQ2DSzk99h1mY18="
}
I personally like to hardcode the base64 encrypted secret together with the data source. This is useful because it shows me which KMS crypto key is associated with the encryption operation and I'm able to easily figure out who has access to that KMS crypto key.