Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Runtime Service Account running a Cloud Function

Is there a way to get the email of the Runtime Service Account programmatically from a Cloud Function?

Runtime Service Account option

I know I can "guess" the default App Engine account (since it is always <project-id>@appspot.gserviceaccount.com), but this is not what I want.

I was expecting to have some Environment Variable or something with this information, but I was not able to find any.

like image 888
Diego Queiroz Avatar asked Nov 16 '25 07:11

Diego Queiroz


2 Answers

For older runtimes (Node.js 8, Python 3.7 and Go 1.11), you can use FUNCTION_IDENTITY environment variable, as described here.

Example in Python:

import os
service_account_email = os.environ.get('FUNCTION_IDENTITY')

For newer runtimes, you need to query the Metadata Server, as in this example:

import requests
def query_metadata(entry):
    response = requests.get('http://metadata.google.internal/computeMetadata/v1/' + entry, headers={'Metadata-Flavor': 'Google'})
    return response.content.decode("utf-8")

service_account_email = query_metadata('instance/service-accounts/default/email')

You can also write a function that supports both runtimes (older and newer) using:

service_account_email = os.environ.get('FUNCTION_IDENTITY') or query_metadata('instance/service-accounts/default/email')

For a list of metadata endpoints that you can use to query for information, check here.

like image 74
Diego Queiroz Avatar answered Nov 17 '25 21:11

Diego Queiroz


If you're using the newer runtimes, you can get the runtime service account of your Cloud Function programmatically using REST API. Here's an example based from this answer:

import requests
import json

def get_sa():
  FUNCTION_NAME = 'func_name'
  PROJECT_ID = 'proj_id'
  REGION = 'us-central1'

  # Get the access token from the metadata server
  metadata_server_token_url = 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token?scopes=https://www.googleapis.com/auth/cloud-platform'
  token_request_headers = {'Metadata-Flavor': 'Google'}
  token_response = requests.get(metadata_server_token_url, headers=token_request_headers)
  token_response_decoded = token_response.content.decode("utf-8")
  access_token = json.loads(token_response_decoded)['access_token']

  # Call functions.get() to retrieve Cloud Functions information
  response = requests.get('https://cloudfunctions.googleapis.com/v1/projects/{}/locations/{}/functions/{}'.format(PROJECT_ID, REGION, FUNCTION_NAME),
    headers={
      'Accept': 'application/json', 
      'Content-Type': 'application/json',
      'Authorization': 'Bearer {}'.format(access_token)
      })   
  print(response.json()['serviceAccountEmail'])

get_sa()

Note that you can only get an access token from the metadata server if your app is deployed in GCP (Compute Engine, Cloud Functions, etc.). If your app is on your local machine, you need to use a service account and an auth library to generate the access token. Here's the auth library reference if you're using Python.

To learn more about the given REST API method, see projects.locations.functions.get().

like image 41
Donnald Cucharo Avatar answered Nov 17 '25 19:11

Donnald Cucharo