Skip to content

Instantly share code, notes, and snippets.

@bschaatsbergen
Last active October 30, 2022 15:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bschaatsbergen/2cafe913ed050322abae8f8d7d29665e to your computer and use it in GitHub Desktop.
Save bschaatsbergen/2cafe913ed050322abae8f8d7d29665e to your computer and use it in GitHub Desktop.
Secrets in your Terraform code (GCP)

Managing secrets in your Terraform code (the GCP way).

❗ 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:bob@example.com"
}

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment