Regulated workloads must control, rotate and be able to revoke the keys that protect their data.
Google encrypts all data at rest by default with Google-managed keys. Cloud KMS lets you hold the keys yourself.
Structure: a key ring (in a location, cannot be deleted) contains keys; each key has versions. A key has a purpose: symmetric encryption, asymmetric encryption or signing, or MAC. Encryption uses the primary version; decryption works with any enabled version, so automatic rotation (e.g. every 90 days) is painless. Destroying a version is scheduled, by default 30 days later, giving time to undo a mistake.
Protection levels: software, HSM (Cloud HSM, FIPS 140-2 Level 3), or external (Cloud EKM, the key stays in a partner key manager outside Google).
Two ways to use KMS:
- Envelope encryption in your code: generate a data key locally, encrypt data with it, and encrypt (wrap) the data key with KMS. Direct
encryptcalls are limited to 64 KiB of plaintext. - CMEK (customer-managed encryption keys): configure Cloud Storage, BigQuery, Cloud SQL, Pub/Sub, GKE and others to protect data with your key. Grant the service's service agent
roles/cloudkms.cryptoKeyEncrypterDecrypteron the key. Disabling the key makes the data unreadable: a powerful kill switch and an outage risk.
Separate duties: key administrators (cloudkms.admin) should not also be the ones who can decrypt.
Example
gcloud kms keyrings create shop-ring --location=europe-west1
gcloud kms keys create storage-key --keyring=shop-ring --location=europe-west1 \
--purpose=encryption --rotation-period=90d --next-rotation-time=2026-12-01T00:00:00Z
# Direct encrypt/decrypt (small payloads only)
echo -n "card-token-123" > plain.txt
gcloud kms encrypt --key=storage-key --keyring=shop-ring --location=europe-west1 \
--plaintext-file=plain.txt --ciphertext-file=secret.enc
gcloud kms decrypt --key=storage-key --keyring=shop-ring --location=europe-west1 \
--ciphertext-file=secret.enc --plaintext-file=- # card-token-123
# CMEK: let Cloud Storage's service agent use the key, then set it as bucket default
gcloud storage service-agent --project=shop-dev-4821 --authorize-cmek=\
projects/shop-dev-4821/locations/europe-west1/keyRings/shop-ring/cryptoKeys/storage-key
gcloud storage buckets update gs://shop-dev-4821-uploads --default-encryption-key=\
projects/shop-dev-4821/locations/europe-west1/keyRings/shop-ring/cryptoKeys/storage-keyRemember
- Key ring > key > versions; rotation keeps old versions for decryption
- Use envelope encryption for data; KMS wraps the data key
- CMEK needs the service agent to have encrypter/decrypter on the key
Watch out for
- Disabling or destroying a CMEK key without realising every dataset using it becomes unreadable.