Using Secrets in Google Cloud Functions
Tags: python, cloudfunctions, serverless, secretmanager
Published: 2019-04-25 20:41:46

---
title: Using Secrets in Google Cloud Functions
published: true
description: How to use secret values in your serverless Python programs
tags: python, cloudfunctions, serverless, secretmanager
---

Google Cloud Functions makes it easy to build serverless Python programs. This post will show you how you can use the [Google Secret Manager](https://cloud.google.com/secret-manager) to safely and securely use secrets in your function.

Hard-coding or using environment variables to store plain-text strings that should be "secret", like API keys, secret tokens for cookies, etc. generally isn't recommended. Any third-party dependency or library you use has access to these same environment variables.

However, it's very convenient to store secrets along side your function. You can still do it, as long as you store these secrets safely and securely. 

We'll do this by storing our secret with the [Google Secret Manager](https://cloud.google.com/secret-manager), and accessing our secrets at the application layer. Doing so will limit access to the secret to just members of your team who have access to the secret (and, of course, the function when it's running on Google Cloud).

# Setup
I'll assume that you've already created a Google Cloud project with a name (mine is `my_cloud_project`). If you haven't, go ahead and do that now.

# Storing your secret
Now that you've created a project, the next step is to create a secret in it. We can do this on the command line with the `gcloud` tool! Also, we'll do it via Cloud Shell, so no credentials ever have to leave the cloud.

First, [launch Cloud Shell](https://console.cloud.google.com/home/dashboard?cloudshell=true) for your project.

You should see a prompt that looks like this:

```
Welcome to Cloud Shell! Type "help" to get started.
Your Cloud Platform project in this session is set to my_cloud_project.
Use “gcloud config set project [PROJECT_ID]” to change to a different project.
di@cloudshell:~ (my_cloud_project)$
```

Next, we'll enable the [Secret Manager API](https://console.developers.google.com/apis/api/secretmanager.googleapis.com/overview) (and the [Cloud Functions API](https://console.developers.google.com/apis/api/cloudfunctions.googleapis.com/overview), while we're at it):

```
$ gcloud services enable secretmanager.googleapis.com cloudfunctions.googleapis.com
```

Next, we'll create a new secret with the `gcloud` command line tool:

```
$ echo -n "The chickens are in the hayloft." | \
    gcloud secrets create my-secret \
      --data-file=- \
      --replication-policy automatic
```

The `--data-file=-` flag allows us to pipe the secret to the `gcloud` command from the output of the previous command, which just `echo`s the secret (with no newline).  

Our secret is now securely stored. If we want to verify this, we can use the following command to access our secret on the command line:

```
$ gcloud secrets versions access 1 --secret="my-secret"
The chickens are in the hayloft.
```

# Using your secret
Now we'll write our function. Here's our whole function that we'll deploy, that will live in a file called `main.py`:

```python
import os
from google.cloud import secretmanager

client = secretmanager.SecretManagerServiceClient()
secret_name = "my-secret"
project_id = "my-gcp-project"
request = {"name": f"projects/{project_id}/secrets/{secret_name}/versions/latest"}
response = client.access_secret_version(request)
secret_string = response.payload.data.decode("UTF-8")


def secret_hello(request):
    return secret_string
```

This function is determining the resource name for the secret based on the function's environment, accessing the latest version of our secret, and then decoding the response, and finally returning the original string.

Also note how the function is doing this work _outside_ of the Python function itself. This will speed up our function by only accessing the secret once when the Cloud Function is instantiated, and not once for every single request.

We'll also need to tell our function to install the `google-cloud-secret-manager` library, so we can access the secret from Python. In a file called `requirements.txt`, add the line:

```
google-cloud-secret-manager==2.0.0
```

At this point, your directory structure should look like this:

```
.
├── main.py
└── requirements.txt
```

# Applying Permissions
We'll also need to give our function permission to access the secret:

```
$ gcloud secrets add-iam-policy-binding my-secret \
    --role roles/secretmanager.secretAccessor \
    --member serviceAccount:my-cloud-project@appspot.gserviceaccount.com
```

The `serviceAccount` here is the default service account for Cloud Functions.

# Deploying your app
The last step is to deploy our function with the `gcloud` tool:

```
$ gcloud functions deploy secret_hello \
    --runtime python38 \
    --trigger-http
```

Now we can test our function once it's deployed:

```
$ gcloud functions call secret_hello
executionId: 4856xc8an4fa
result: The chickens are in the hayloft.
```

# Next steps
There's lots more you can do with Cloud Functions! Follow the links below to learn how to:

* [Write "background" trigger functions that respond to events](https://cloud.google.com/functions/docs/writing/background)
* [Monitor functions at a high level with Stackdriver](https://cloud.google.com/functions/docs/monitoring/)
* [See additional tips & tricks for writing Cloud Functions](https://cloud.google.com/functions/docs/bestpractices/tips)

_All code © Google w/ Apache 2 license_