11

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?
James Healy
  • 14,557
  • 4
  • 33
  • 43

2 Answers2

4

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.

cherba
  • 8,681
  • 3
  • 27
  • 34
  • Thanks for the details. My challenge is that I already have an environment (on my laptop) where gcloud is configured (with both gcloud auth login and gcloud auth application-default login) and I'd like to share that config with a fresh glcoud install without re-authenticating. – James Healy Jul 10 '18 at 00:44
  • `gcloud info --format="value(config.paths.global_config_dir)"` will tell you where gcloud config is located. On unix like systems it is `~/.config/gcloud`. Simply copying this config directory to new machine should allow new install to pick it up. Also you can set CLOUDSDK_CONFIG environment variable to new location for gcloud to use. (You will likely need to also set GOOGLE_APPLICATION_CREDENTIALS in this case.) – cherba Jul 10 '18 at 11:46
  • Thanks. So there's no way to get a fresh gcloud to install to load credentials that are are valid GOOGLE_APPLICATION_CREDENTIALS (ie. a user version of `auth activate-service-account --key-file=${GOOGLE_APPLICATION_CREDENTIALS}`)? – James Healy Jul 10 '18 at 11:49
  • That is right. They are obtained via two different methods. One via `gcloud auth login` and the other `gcloud auth application-default login`, and under the hood are different credentials. Even if you succeeded in "activating" application default credentials in gcloud you will find that a lot of gcloud cli commands will stop working, or some API calls will be capped at much lower quotas. User application default credentials are there only for testing/debugging/demo purposes, one would not use them in any serious prod environment. Use service account instead. – cherba Jul 11 '18 at 12:53
  • @cherba - Do you have a reference for you comment "stop working ...". I have been digging very deep into Google Cloud credentials and I do not find your comment correct. I have been writing articles for my personal blog with lots of details. Your comments may change my articles. www.jhanley.com – John Hanley Nov 06 '18 at 20:18
  • Regarding "stop working" comment. If you look what kind of application-default credentials are you will see that they are attached to shared/global project. APIs needs to be enabled in that global project, which google does for most APIs but also some have quotas. So if many people use ADC excessively, it might consume enough quota and then all of them will start failing. These credentials are only meant for development/debugging, initial on-boarding not production setup. Moreover gcloud is not validated against ADC, you might find that some gcloud commands simply do not work. – cherba Nov 07 '18 at 15:57
  • How did AWS get this so right but Google get it so wrong? – jbrown Aug 30 '21 at 09:08
0

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

James Healy
  • 14,557
  • 4
  • 33
  • 43
  • This is not good idea. For one undocumented command might go away, and two you will start getting strange API errors. – cherba Jul 11 '18 at 12:56
  • Thanks for the heads up. So far it's been working well for us, but I'll keep an eye out for unexplained issues that might be related. – James Healy Jul 21 '18 at 05:59