2

I'm developing a Cloud Run Service that accesses different Google APIs using a service account's secrets file with the following python 3 code:

from google.oauth2 import service_account
credentials = service_account.Credentials.from_service_account_file(SECRETS_FILE_PATH, scopes=SCOPES)

In order to deploy it, I upload the secrets file during the build/deploy process (via gcloud builds submit and gcloud run deploy commands).

How can I avoid uploading the secrets file like this?

Edit 1:

I think it is important to note that I need to impersonate user accounts from GSuite/Workspace (with domain wide delegation). The way I deal with this is by using the above credentials followed by:

delegated_credentials = credentials.with_subject(USER_EMAIL)

3 Answers3

1

I've found one way to solve the problem.

First, as suggested by guillaume blaquiere answer, I used google.auth ADC mechanism:

import google.auth
credentials, project_id = google.auth.default(scopes=SCOPES)

However, as I need to impersonate GSuite's (now Workspace) accounts, this method is not enough, as the credentials object generated from this method does not have the with_subject property. This led me to this similar post and specific answer which works a way to convert google.auth.credentials into the Credential object returned by service_account.Credentials.from_service_account_file. There was one problem with his solution, as it seemed that an authentication scope was missing.

All I had to do is add the https://www.googleapis.com/auth/cloud-platform scope to the following places:

  1. The SCOPES variable in the code
  2. Google Admin > Security > API Controls > Set client ID and scope for the service account I am deploying with
  3. At the OAuth Consent Screen of my project

After that, my Cloud Run had access to credentials that were able to impersonate user's accounts without using key files.

0

Using the Secret Manager might help you, as you can manage the multiple secrets you have and not have them stored as files, as you are doing right now. I would recommend you to take a look at this article here, so you can get more information on how to use it with Cloud Run, to improve the way you manage your secrets.

In addition to that, as clarified in this similar case here, you have two options: use default service account that comes with it or deploy another one with the Service Admin role. This way, you won't need to specify keys with variables - as clarified by a Google developer in this specific answer.

gso_gabriel
  • 4,199
  • 1
  • 10
  • 22
  • If I understand correctly, this flow would mean that I need to give the service account permission to access Secret Manager API, and then, with just the default credentials given by the environment I can access the secrets that I set, which might be the keys to other APIs or Cloud services that I need? – TheChouzanOne Nov 04 '20 at 01:56
0

To improve the security, the best way is to never use service account key file, locally or on GCP (I wrote an article on this). To achieve this, Google Cloud service have an automatically loaded service account, either this one by default or, when possible, a custom one.

On Cloud Run, the default service account is the Compute Engine default service account (I recommend you to never use it, it has editor role on the project, it's too wide!), or you can specify the service account to use (--service-account= parameter)

Then, in your code, simply use the ADC mechanism (Application Default Credential) to get your credentials, like this in Python

import google.auth
credentials, project_id = google.auth.default(scopes=SCOPES)
guillaume blaquiere
  • 66,369
  • 2
  • 47
  • 76
  • Thanks for the info! I've got a question about this approach: in my use case, I need to impersonate GSuite's email addresses in order to read and modify Gmail messages. I do this via Domain Wide Delegation and the python method `creds.with_subject(TARGET_EMAIL)`. Is there an equivalent approach using the google.auth package and its ADC mechanism? – TheChouzanOne Nov 03 '20 at 18:14
  • There is no difference between a service account key file and the ADC mechanism on Cloud Run. Instead of having a file, you have the metadata server that serves you endpoint to get the credentials. However, if you test locally, with your user credential, you could have some issue (that you can fix, but it's not so trivial!) – guillaume blaquiere Nov 03 '20 at 20:15
  • It seems that the credential objects from your post do not have the property `with_subject`, so the credentials are different (I got an attribute error). However, that error led me to this [answer](https://stackoverflow.com/a/57092533/14532932). It was missing an authentication scope but after it, the issue was resolved. I will add an answer with that – TheChouzanOne Nov 04 '20 at 01:51