Smg is a SuperFetch plugin to access the Google Cloud Secrets API. SuperFetch is a proxy for UrlFetchApp with additional features – see SuperFetch – a proxy enhancement to Apps Script UrlFetch for how it works and what it does.
This is another in my series on SuperFetch plugins.
Motivation
Normally Apps Script developers use the Property service to store the secrets they need to run their scripts, and for most cases this is fine. However, Google cloud platform does have a Cloud Secret Manager you can use to store and manage secrets.
When to use the secret manager instead of Property Service
The main motivation would be if you need to share secrets across multiple Apps Script projects. There are a couple of workarounds to enable this with vanilla Apps Script services, but they are prone to potential security and management fails. A couple of examples would be.
- Store secrets in some shared Drive file
- Expose a script containing secrets as a library so that co-operating scripts can get the secrets from that library’s property store
Using the secret manager instead means sharing a Google Cloud Project across multiple Apps Script projects each of which will have access to the Project’s secret manager, with different levels of access to them controlled by IAM. You could also share across multiple cloud projects, but let’s leave that for another day.
If you already use Kubernetes, you’ve probably used its secret manager and will be familiar with this whole concept.
Note that the use of the Secret Manager is potentially not free, but it does have a free tier.
Secret versions
The secret manager has many features unavailable in the property store – in particular versioning, version aliases and labeling, which will allow you to use different versions of a secret in differetn modes – eg test/dev/prod etc.
Cloud console
Secrets are manageable via the cloud console and look like this
Secret manager also keeps a log so you can keep track of changes.
Smg plugin for SuperFetch
The smg plugin uses the Secrets Manager JSON API to provide a simple to use SuperFetch plugin to access and manager Secrets directly from Apps Script.
Secrets format
Secrets created via the console are held in base64 format in the secret manager. The Smg plugin can read and write these base64 content, but it also allows you to commit strings, objects, numbers, booleans and blobs, which it will automatically restore to their original state when you access them. More of that when we get into some examples.
Script Preparation
You’ll need the bmSuperFetch library and if you want to run some tests, the bmUnitTest library – details at the end of the article.
You need to use a regular cloud project rather than the Apps Script managed one (you can change it in Project settings), and you’ll need at least these scopes enabled in your manifest file (appsscript.json), as well as the Secret Manager API enabled
You’ll also may need to assign IAM roles to access secrets – See this configuration instructions for how, to those that need to access the secrets. Things get a little more complex if you are writing a script for someone else to use, but the secrets belong to you. I’ll deal with that scenario in a future article.
Instantiation
First you need a SuperFetch instance. If you don’t need caching, then just omit the cacheService property.
Smg instance
This will be the handle for accessing Smg
There are various other standard SuperFetch Plugin parameters that I’ll deal with later, but the one shown is of special interest to this article. The project id you can get from the cloud console dashboard.
noCache property (optional)
You can turn off caching by setting this to true, or by omitting the CacheService poperty in the SuperFetch instantiation.
Usage
There are 2 kinds of secrets that Smg can handle
- Those created in the Cloud console
- Those created and managed by Smg
Smg will automatically figure out which is which, and if it’s a secret that it created, it will be able to restore the data to the original state. If it’s one created in the console or by some other means, you’ll get back a standard base64 value, as well as decoded string version.
Creating a secret
A secret has an id of your choice. When you create a secret, you are not yet adding any value to it – just setting it up. The response is a standard SuperFetch response (see SuperFetch – a proxy enhancement to Apps Script UrlFetch for what those responses look like). The secret metadata will be found in the .data property.
Add version
Secrets can have multiple versions. To assign data to secret you simply add a version. These version numbers will be incremented automatically. In this example, we’re just adding a string.
Get a secret
Getting a secret also returns the data for a version you select (or the latest by default)
Getting a specific version
Dealing with native secrets
You’ll notice that the response from smg includes .value and .valueType properties. This is syntactic sugar added by smg. If you retrieve a secret that wasn’t created by smg, you’ll just get a value64 and value response – which is how the secrets are stored natively. As a help, smg attempts to return a decoded string in the .value property, but also returns the .value64 property in case you need to decode some non- string value.
Adding labels to secrets
You can add labels to secrets when you create them. Labels are useful for filtering queries when listing secrets. Notice I’ll adding the .throw() method in most of the following examples – like all SuperFetch plugins, this method will throw an error if one is detected.
Setting aliases for versions
Instead of juggling version numbers, you can create aliases for secret versions then use those aliases to get the values.
Listing Secrets
You can list all secrets like this
Listing versions
Here’s how to list all the versions of a given
Filter queries
You can add filters to the .list() method – there is a filter language described here.
Paging
Smg supports paging, but it’s quite unlikely you’ll have enough secrets to make this required. Without a page closure with a max parameter specified, it will return all matching secrets. It also supports a pageToken parameter if you have interupted a list with a max parameter. It works the same as described in SuperFetch plugin: Google Drive client for Apps Script : Part 1 where the mechanism is fully described.
Ref
You can create a new instance of smg base on an existing instance. To change some of the characteristics of the instance (eg switch off caching).
Error handling
All Superfetch plugins use the same method of signalling or optionally, reacting to an error.
You can detect an error by checking the result.error property or you can force an automatic throw if an error is detected. Here’s examples of each of these.
Unit testing
I’ll use Simple but powerful Apps Script Unit Test library to demonstrate calls and responses. It should be straightforward to see how this works and the responsese to expect from calls. These tests demonstrate each of the topics mentioned in this article, as well as some I’ll be covering in a later article, and could serve as a useful crib sheet for the plugin – it’s a long read so you may want to just come back and refer to this.
Next
This example shows how to use the Apps Script Oauth token to get secrets, which is fine if the script owner is accessing the secret. We’ll need to do something special for token processing if you are writing a script that will be run in the context of someone else who normally wouldn’t have the IAM rights to access secrets.
Links
bmSuperFetch: 1B2scq2fYEcfoGyt9aXxUdoUPuLy-qbUC2_8lboUEdnNlzpGGWldoVYg2
bmUnitTester: 1zOlHMOpO89vqLPe5XpC-wzA9r5yaBkWt_qFjKqFNsIZtNJ-iUjBYDt-x