I am using a Google Cloud Function (GCF) with a Pubsub trigger which sends a HTTP request to a third party API.
The GCF receives notifications from a Pubsub topic used by a service which should not be aware of the third party API.
The third party API requires an authentication using Basic HTTP Authentication.
In order to not to have to hardcode the password in my source code I am using Google KMS to generate a new encrypted key each time I deploy my function. I am using Google Cloud KMS to decrypt the secret each time the function is instantiated.
For decrypting using KMS I have to provide a private key for a service account to the NodeJS Google API.
My main problem today is that I have to push my private key to the GCloud Bucket if I want my GCF to work properly.
Is it possible by using either the Runtime Configurator or the Deployment Manager to configure secrets for a Google Cloud Function?
Thanks you.
Cloud KMS is a REST API that can use a key to encrypt, decrypt, or sign data such as secrets for storage. Cloud KMS is available in several global locations and across multi-regions, allowing you to place your service where you want for low latency and high availability.
Even though KMS is a global service but keys are regional that means you can't send keys outside the region in which they are created.
100,000 key use operations for symmetric encryption and decryption, or signing and verification. (Key admin operations are free.)
As of December 2019, the preferred way to store and manage secrets on Google Cloud is Secret Manager:
$ echo -n "user:pass" | gcloud beta secrets create "my-basic-auth" \
--data-file=- \
--replication-policy "automatic"
You can also create and manage secrets from API:
// Import the library
const {SecretManagerServiceClient} = require('@google-cloud/secret-manager');
// Create the client
const client = new SecretManagerServiceClient();
// Create the secret
const [secret] = await client.createSecret({
parent: "projects/<YOUR-PROJECT-ID>",
secretId:"my-basic-auth",
secret: {
replication: {
automatic: {},
},
},
});
// Add the version with your data
const [version] = await client.addSecretVersion({
parent: secret.name,
payload: {
data: Buffer.from("user:pass", "utf8"),
},
});
Then, in your Cloud Function:
const [version] = await client.accessSecretVersion({
name:"projects/<YOUR-PROJECT-ID>/secrets/<MY-SECRET>/versions/1",
});
const auth = version.payload.data.toString('utf-8');
// auth is user:pass
The service account with which you deploy your Cloud Function will need roles/secretmanager.secretAccessor
permissions.
The other solution to this which came out only in the last few months, is to use Google Cloud Runtime Configuration with Firebase for Functions: https://firebase.google.com/docs/functions/config-env
Firebase for Functions seems to provide access to several features that are not yet available via other means.
Runtime Configurator does not charge for use, but enforces the following API limits and quotas:
- 1200 Queries Per Minute (QPM) for delete, create, and update requests
- 600 QPM for watch requests.
- 6000 QPM for get and list requests.
- 4MB of data per user, which consists of all data written to the Runtime Configurator service and accompanying metadata.
https://cloud.google.com/deployment-manager/pricing-and-quotas#runtime_configurator
As an aside, I find this conflict in the Firebase for Functions comical:
The Firebase SDK for Cloud Functions offers built-in environment configuration to make it easy to store and retrieve this type of data for your project without having to redeploy your functions.
Then a moment later:
After running
functions:config:set
, you must redeploy functions to make the new configuration available.
The KMS solution is a viable alternative, however it seems costly for functions. KMS is billed at $0.06 per month per active key, as well as $0.03 per 10,000 operations.
This would then change the cost of your Cloud Function from $0.40 per million invocations, to $3.40 per million invocations. That is quite the jump.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With