10
votes

Google API clients typically recognise the GOOGLE_APPLICATION_CREDENTIALS environment variable. If found, it's expected to point to a JSON file with credentials for either a service account or a user.

Service account credentials can be downloaded from the GCP web console and look like this:

{
  "type": "service_account",
  "project_id": "...",
  "private_key_id": "...",
  "private_key": "...",
  "client_email": "...",
  "client_id": "...",
  "auth_uri": "...",
  "token_uri": "...",
  "auth_provider_x509_cert_url": "...",
  "client_x509_cert_url": "..."
}

User credentials are often available in ~/.config/gcloud/application_default_credentials.json and look something like:

{
  "client_id": "...",
  "client_secret": "...",
  "refresh_token": "...",
  "type": "authorized_user"
}

Here's an example of the official google rubygem detecting the type of credentials provided via the environment var.

I'd like to authenticate an unconfigured gcloud install with both types of credential. In our case we happen to be passing the GOOGLE_APPLICATION_CREDENTIALS variable and path into a docker container, but I think this is a valid question for clean installs outside docker too.

If the credentials file is a service account type, I can do this:

gcloud auth activate-service-account --key-file=${GOOGLE_APPLICATION_CREDENTIALS}

However I can't see any way to handle the case where the credentials belong to a real user.

Questions:

  1. Why doesn't the official gcloud tool follow the conventions that other google API clients use and use GOOGLE_APPLICATION_CREDENTIALS when available?
  2. Is there a hidden method that will activate the user credentials case?
2

2 Answers

4
votes

As you point out gcloud command line tool (CLI) does not use application default credentials. It has separate system for managing its own credentials.

GOOGLE_APPLICATION_CREDENTIALS are designed for client libraries to simplify wiring in credentials, and gcloud CLI is not a library. Even in the client code best practice is not to depend on this environment variable but instead explicitly provide credentials.

To answer your second question, user credentials can be obtained via

gcloud auth login

command. (NOTE this is different from gcloud auth application-default login) This besides saving actual credentials will also set account property in current configuration:

 gcloud config list

gcloud can have many configurations, each with different credentials. See

gcloud config configurations list

You can create multiple configurations, one with user account another with service account and use it simultaneously by providing --configuration parameter, for example

gcloud compute instances list --configuration MY_USER_ACCOUNT_CONFIG

Similarly you can also switch which credentials are used by using --account flag, in which case it will use same configuration and will only swap out the account.

0
votes

I've found a way to authenticate a fresh gcloud when GOOGLE_APPLICATION_CREDENTIALS points to a file with user credentials rather than service account credentials.

cat ${GOOGLE_APPLICATION_CREDENTIALS}
{
 "client_id": "aaa",
 "client_secret": "bbb",
 "refresh_token": "ccc",
 "type": "authorized_user"
}

gcloud config set auth/client_id aaa                                                                                             
gcloud config set auth/client_secret bbb                                                                                     
gcloud auth activate-refresh-token user ccc

This uses the undocumented auth activate-refresh-token subcommand - which isn't ideal - but it does work.

Paired with gcloud auth activate-service-account --key-file=credentials.json, this makes it possible to initialize gcloud regardless of the credential type available at $GOOGLE_APPLICATION_CREDENTIALS