Secure Secret Storage using Google Cloud Platform

Rhys working at his desk in the Brightec office

A simple solution to securely storing client and application secrets when using Google Cloud Platform

Recently, we have been developing a Slack app that imports data to Google Sheets and uses Google Cloud Platform as the backend. In order for this to happen there are several secrets involved. We have made a distinction between the two types of secrets we deal with. User-level secrets are those that are unique to the user, whereas application-level secrets are those that are specific to the app that we are writing. We classify the following secrets into the different aforementioned categories:

  • GSuite OAuth Access Token (user-level)
  • GSuite OAuth Refresh Token (user-level)
  • Slack Bot User OAuth Access Token (user-level)
  • GSuite API Client Secret (app-level)
  • Slack App Client Secret (app-level)
  • Slack App Signing Secret (app-level)

The user-level secrets are used to allow the app to act on behalf of the authorised user; The GSuite OAuth tokens are required to read and write to the Google Sheets reporting spreadsheet. The Slack OAuth token is required to allow the app to send Slack messages to users.

The app-level secrets are used to verify the app has the rights to access the required APIs; The GSuite API secrets are required to make calls to the Google Sheets API. The Slack Client Id and Client Secret are used to validate the authenticity of the Slack app when requesting a Slack OAuth token. The Slack App Signing Secret is used to verify messages received by the app from Slack are valid.

Handling user-level secrets

Once the user completes the OAuth flow we store their secret in a Firestore Database, however the secret is encrypted using GoogleKMS. In order to do this, we first need to create an encryption key. Before we can do this we need to create keyring. You can do this in the Google Cloud Console (by search KMS) or using the following code:

Then we can create a key (in this example we will be creating a symmetric key), again in the Google Cloud Console or using the following code:

Once you receive the token from the OAuth you can encrypt it as follows:

Then you can decrypt when needed:

The above examples are receiving Google OAuth tokens, so the fields might not match exactly but the principle is the same.

In order to ensure security you should rotate the keys used. You probably should do this automatically following this guide. Although you can also do this manually to rotate a suspected compromised key. Reasons for rotating a key include:

  • To Limit the number of encrypted messages available to cryptanalysis for a specific key version.
  • To limit the total number of enciphered bytes available to cryptanalysis for a specific key version
  • To reduce the volume of ciphertext that would be unprotected if a key version is compromised
  • To prevent use of a key version that is compromised or suspected of being compromised. The old key is not destroyed in order to prevent data loss. Multiple versions of a symmetric key can be active at any time for decryption, with only one primary key version used for encrypting new data.

Handling app-level secrets

The handling of app-level secrets is far less complex. We use Secret Manager. To store a secret use this code:

Then to use that secret:

Voila you are set to store secrets securely using GCP.

Looking for something else?

Search over 400 blog posts from our team

Want to hear more?

Subscribe to our monthly digest of blogs to stay in the loop and come with us on our journey to make things better!