Using Google Cloud Platform’s Cloud Key Management Service (KMS) to Encrypt / Decrypt Secrets
I am trying to get rid of all plain text GCP Service Account JSON credential files from my source code such that no developer has access to these at any stage in the dev lifecycle (development, testing, staging and production).
While I still haven’t figured out the best practices for implementing this at an enterprise level, one easy way of achieving this is by encrypting these files at rest and decrypting them via an additional build step via my favorite CI / CD tool upon every code deployment.
That’s where GCP’s Cloud Key Management Service (KMS) can be used beautifully and it’s surprisingly easy to implement. This blog post is restricted to using KMS for encrypting / decrypting secrets, i.e., GCP Service Account JSON credential files in this case.
Another blog post which builds upon this one and explains the best practices for achieving enterprise level security including separation of developer duties, GCP Projects, GCP Users and / or GCP Service Accounts, etc soon once I have figured all of it out.
Time for some code! Key rings group keys together to keep them organized. Create a new key ring by the name “development-key-ring” in location “global”:
gcloud kms keyrings create development-key-ring --location global
Create a new key by the name “datastore-key” in location “global” in key ring “development-key-ring” for a default “90” days rotation period:
gcloud kms keys create datastore-key --location global --keyring development-key-ring --purpose encryption
Encrypt the GCP Service Account JSON credential file using above created key ring and key:
gcloud kms encrypt \
You can safely delete the plain text GCP Service Account JSON credential file at C:\datastore.json now.
Decrypt the encrypted GCP Service Account JSON credential file using above created key ring and key:
gcloud kms decrypt \
All that’s pending is to include a build step in your favorite CI / CD tool to replace the encrypted datastore.json.enc file with the decrypted one by calling the above decrypt command upon every code deployment.
To wrap up, it might be a good idea to:
- Maintain a different GCP project for all things KMS.
- Maintain different key rings for different dev lifecycles: development, testing, staging and production.
- Maintain different keys for different secrets, or at least different keys for a group of secrets which serve a common purpose. Having a single key for all your secrets is probably a bad idea.
Having said that, fine tune your strategy to your unique environment. There is no one size fits all approach here.
You can apply above concept to any secret that requires encryption / decryption, not just GCP Service Account JSON credential files. But you do have to factor in performance and costs in your architecture.
NB this post only scratches the surface of what KMS can do as far as encryption / decryption of secrets are concerned. Also, key rings and keys once created cannot be deleted in GCP and active key versions as well as encryption / decryption operations are chargeable although minimal. Therefore, it is recommended that you spend about half a day reading about KMS extensively before implementing it in production. Check the links in the Resources section at the end of this post for more info.