Skip to main content

GCP Cloud KMS Key Wrapping

Use Google Cloud KMS to protect the Trust Domain Server's signing key material at rest. Signing keys are encrypted before being written to the Kubernetes CRD, with a Cloud KMS-held key acting as the Key Encrypting Key (KEK). The KEK never leaves Google infrastructure.

info

This page covers key wrapping — encrypting stored signing keys at rest. If you want signing keys to live entirely inside Cloud KMS so they never enter server memory, see GCP Cloud KMS Key Manager instead.

How it works

The Trust Domain Server uses envelope encryption. When it needs to persist a signing key, the server generates a fresh AES-256-GCM data-encryption key (DEK) and uses it to encrypt the signing key locally. It then asks Cloud KMS to wrap the DEK with the KEK. The CRD stores the encrypted signing key alongside the wrapped DEK. To decrypt, the server asks Cloud KMS to unwrap the DEK, then decrypts the signing key locally with it.

The Cloud KMS key acts as the KEK and never leaves Google infrastructure. Cloud KMS only ever sees DEKs, and the signing-key plaintext never leaves the Trust Domain Server.

How to Deploy

Step 1 — Create a key ring and symmetric key

Create a key ring and a symmetric encrypt/decrypt key. The key must have the ENCRYPT_DECRYPT purpose (the default for symmetric keys):

gcloud kms keyrings create my-key-ring \
--location us-central1 \
--project my-project

gcloud kms keys create defakto-wrapping-key \
--keyring my-key-ring \
--location us-central1 \
--project my-project \
--purpose encryption

Step 2 — Set up IAM permissions

Grant the Trust Domain Server's GCP service account the cloudkms.cryptoKeyEncrypterDecrypter role on the key:

gcloud kms keys add-iam-policy-binding defakto-wrapping-key \
--keyring my-key-ring \
--location us-central1 \
--project my-project \
--member "serviceAccount:SA_EMAIL" \
--role roles/cloudkms.cryptoKeyEncrypterDecrypter

For GKE deployments, use Workload Identity Federation to bind the Trust Domain Server's Kubernetes service account to the GCP service account:

gcloud iam service-accounts add-iam-policy-binding SA_EMAIL \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]"

Then annotate the Kubernetes service account:

kubectl annotate serviceaccount KSA_NAME \
--namespace NAMESPACE \
iam.gke.io/gcp-service-account=SA_EMAIL

Step 3 — Update Helm values

Set the GCP project, location, key ring, and key name in your spirl-system Helm values:

gcp:
projectID: "my-project"
location: "us-central1"
kms:
keyRing: "my-key-ring"
keyName: "defakto-wrapping-key"

Apply the Helm release:

helm upgrade spirl-system spirl/spirl-system \
-f values.yaml \
--namespace <namespace>

Step 4 — Verify

On successful startup, the Trust Domain Server logs the following:

Key wrapping via GCP KMS projectID=my-project location=us-central1 keyRing=my-key-ring keyName=defakto-wrapping-key

The server validates on startup that the key exists, is a symmetric encryption key, and is in the ENABLED state. If any of these checks fail, startup is aborted with an error describing the issue.

Helm Values Reference

ValueRequiredDefaultDescription
gcp.projectIDYes""GCP project ID where the key ring resides.
gcp.locationYes""GCP region or multi-region for the key ring (e.g., us-central1, global).
gcp.kms.keyRingYes""Name of the Cloud KMS key ring. The key ring must already exist.
gcp.kms.keyNameYes""Name of the symmetric encryption key within the key ring.

All four values must be set together. If any are missing, the chart falls back to the default Kubernetes Secret–based key wrapping.

When to configure

Key wrapping must be configured before the Trust Domain Server stores any signing key material. Configure it as part of your initial Helm installation.

Switching key wrapping providers on an existing deployment is not supported. Data the Trust Domain Server has already persisted is encrypted with the current KEK, and the server cannot decrypt it with a different provider's key. If you need to change providers, contact Defakto support for guidance on your specific deployment.

Security Considerations

  • Symmetric key required. The wrapping key must have the ENCRYPT_DECRYPT purpose. Asymmetric signing keys are not supported for key wrapping.
  • Key state validation. The server checks at startup that the key's primary version is in the ENABLED state. Disabled or destroyed key versions cause startup failure.
  • Cloud KMS availability. The Trust Domain Server calls Cloud KMS at startup and during key rotation. In steady state, SVID issuance does not require Cloud KMS calls; the decrypted signing key is held in server memory.
  • Workload Identity. Use GKE Workload Identity Federation rather than a static service account key file so credentials rotate automatically.
  • Cloud Audit Logs. Encrypt and Decrypt calls appear in Cloud Audit Logs under the cloudkms.googleapis.com service with the caller identity and key resource name.
  • Key ring must pre-exist. The Trust Domain Server does not create the key ring. Create it before deploying.