Skip to content

Instantly share code, notes, and snippets.

@chrisfalter
Last active January 6, 2023 06:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chrisfalter/f9def6c0eb43fd5b7fe0d9cfc3977d44 to your computer and use it in GitHub Desktop.
Save chrisfalter/f9def6c0eb43fd5b7fe0d9cfc3977d44 to your computer and use it in GitHub Desktop.
Securely use a service account token in Google Cloud
# Let's assume you want to authenticate to a service API using a service account private key stored in Google.
# Secret Manager. You have followed these steps:
# 1. Created a service account with permissions to the API.
# 2. Stored the service account private key in Google Secret Manager.
# 3. Provided a separate service account (the one that's running a batch process) with the Secret Manager Secret Accessor
# role on the secret.
# Now you want to authenticate with the key without writing it to disk. Why bother to store the key in Secret Manager if
# you are just going to write it to disk? But you have a problem: All of the code snippets you find on cloud.google.com/docs
# and developers.google.com show how to use an authentication token that has been stored on disk in a file. Literally all of them!
#
# Here's a recipe for using the key without writing it to disk. Hat tip to my colleague Imee Cuison who helped develop this code.
import json
from google.oauth2.service_account import Credentials
from google.cloud import secretmanager
def access_secret(project_id:str, secret_id:str, version_id:str="latest")->str:
"""Return the secret in string format"""
# Create the Secret Manager client.
client = secretmanager.SecretManagerServiceClient()
# Build the resource name of the secret version.
name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"
# Access the secret version.
response = client.access_secret_version(name=name)
# Return the decoded payload.
return response.payload.data.decode('UTF-8')
def get_credentials_from_token(token:str)->Credentials:
"""Given an authentication token, return a Credentials object"""
credential_dict = json.loads(secret_payload)
return Credentials.from_service_account_info(credential_dict)
credentials_secret = access_secret("my_project", "my_secret")
creds = get_credentials_from_token(credentials_secret)
# And now you can use the `creds` Credentials object to authenticate to an API
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment