The following command allows you to set your default credentials:
gcloud auth application-default login
It opens up a window (unless you use --no-launch-browser) and allows you to connect your account. It creates a local json file that contains your credentials, which will be picked up when an application uses the Google Cloud SDK.
However, if I'd like to set my application credentials to a service account as follows:
gcloud auth application-default login \
--impersonate-service-account=saname#project.iam.gserviceaccount.com
This still allows me to authenticate in the browser, but it seems to load the credentials for my user account, not for the service account.
Is there anyway to achieve this? I.e., service account set as application default, without the need for a service account file.
Note: I do have the rights to impersonate the Service Account
gcloud auth application-default login uses the active|specified user account to create a local JSON file that behaves like a service account.
I assume -- correct? -- that, even though your user account is permitted to impersonate the ServiceAccount, using your user account as ADC does not work. I don't know why that is.
The alternative is to use gcloud auth activate-service-account but, as you know, you will need to have the service account's credentials as these will be used instead of the credentials created by application-default login.
Related
How do I enable API services specifically for a service account and not a user account?
Context: I'm using a Python script to locally test a cloud function (query BQ, convert results to json, drop in GCS bucket). I can do this fine with my own test account where I'm able to enable services, but not sure how I would do it (or how a client would go about doing it) for a client's service account. This is how I do it for my own service account:
Get service account credentials as json
Follow installations for gcloud cloud sdk
Issue: gcloud auth activate-service-account --key-file="/path/to/json-todd-credentials.json" --project="json-todd"
Enable API services like so: gcloud enable --account="json-todd#json-todd.iam.gserviceaccount.com" cloudfunctions.googleapis.com pubsub.googleapis.com etc.
I have the client's service account json and I can auth activate-service-account the service account but I can't enable because I don't have permissions - but how would the client enable APIs it specifically for a service account on GCP without having to install/initialise/auth the service account in the way above?
There is a misunderstanding I think. The API are enabled for a project, not for a service account (or a user account). Then, you have permissions to access to the API that you have activated.
If you have a service account, on a new project, without the API enable, there is no issue to grant this service account with the roles/serviceusage.serviceUsageAdmin. Like this, the service account will be able to activate the API on the project, possibly, ALL the API. BUT if the service account has only the permission to access to BigQuery (for example) and the service account activate the compute engine API, it won't be able to access to VM, even if, the API is enabled.
At the opposite, if the API are already enabled on the project, the service account doesn't need to have the roles/serviceusage.serviceUsageAdmin role granted, only the permission to use the activated API.
I'm trying to understand how gcloud manages to work with APIs that require service account to access them, e.g. accessing Speech API using your user (not svcacc) credentials will result in "403 Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the speech.googleapis.com".
However when I run gcloud ml speech recognize gs://cloud-samples-tests/speech/brooklyn.flac --language-code=en-US it works just fine even-though I didn't set any dedidcated svcacc keys as described in the quick start [1], and even disabled all service accounts in the project just to be sure.
So again,
gcloud ml speech recognize gs://cloud-samples-tests/speech/brooklyn.flac --language-code=en-US - works
curl -s -H "Content-Type: application/json" -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) https://speech.googleapis.com/v1/speech:recognize -d #sync-request.json as per [2] fails with 403 error above
Question: how gcloud manages to work without me providing it with a dedicated service account?
[1] https://cloud.google.com/speech-to-text/docs/quickstart-gcloud
Google credentials are provided by two types of account: service accounts and regular (human?) accounts (e.g. #gmail.com, #your.email). The types of tokens issued for these accounts differ but they both authenticate to services.
When you use gcloud you're often using human accounts that you have previously authenticated using gcloud auth login and may be shown with gcloud auth list.
In this case, you're also using these gcloud human credentials with curl because you acquire an access token using gcloud auth print-access-token. Your two examples effectively authenticated using the same (probably human) account.
When you want to have one service authenticate to another, it is recommended that you use service accounts. There's no human in the process to support OAuth's three-legged auth and so service accounts use two-legged auth (see link).
Generally with Cloud Platform services, credentials must also have IAM roles that describe permissions that authorize their use, but some Cloud Platform services (IIRC ML) do not (yet) implement IAM and so authorization is achieved solely using OAuth scopes and you can use vanilla service accounts that have no specific IAM bindings assigned.
NOTE it is possible to authenticate gcloud with service accounts too gcloud auth activate-service-account but IIRC this approach is being discouraged.
What is the difference between gcloud auth application-default login vs gcloud auth login?
Despite the definitions below, it is still hard to differentiate them.
gcloud auth application-default login :
acquire new user credentials to use for Application Default Credentials
gcloud auth login :
authorize gcloud to access the Cloud Platform with Google user credentials
When should I use one over the other?
The difference is the use cases:
As a developer, I want to interact with GCP via gcloud.
gcloud auth login
This obtains your credentials and stores them in ~/.config/gcloud/. Now you can run gcloud commands from your terminal and it will find your credentials automatically. Any code/SDK will not automatically pick up your creds in this case.
Reference: https://cloud.google.com/sdk/gcloud/reference/auth/login
As a developer, I want my code to interact with GCP via SDK.
gcloud auth application-default login
This obtains your credentials via a web flow and stores them in 'the well-known location for Application Default Credentials'. Now any code/SDK you run will be able to find the credentials automatically. This is a good stand-in when you want to locally test code which would normally run on a server and use a server-side credentials file.
Reference: https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login
Edit (09/19/2019):
As Kent contributed in his comment below, 'the well-known location for Application Default Credentials' is a file named application_default_credentials.json located in your local ~/.config/gcloud/ directory. I've added an additional link below to an article by Theodore Sui and Daniel De Leo which goes into greater detail about the different authentication methods.
Article:
https://medium.com/google-cloud/local-remote-authentication-with-google-cloud-platform-afe3aa017b95
I'm adding this as an answer because I don't have the reputation to comment. I think #Himal's answer is spot on but I'd like to clarify that when it says code/SDK, we should think code or Language (Java/Ruby/Python) SDK v/s the gcloud SDK (which is also referred to as Cloud SDK). This confused me a bit because I had the same doubts
So,
gcloud auth login -> Login to gcloud SDK
gcloud auth application-default login -> Login to any code running on the computer (language SDK's within an application)
There is also a give-away in the OAuth authentication screen in the browser windows that open up:
gcloud auth login asks you to choose an account to continue to give access to 'google cloud sdk'.
gcloud auth application-default login asks you to give access to google auth library instead.
Here is the error:
Your application has authenticated using end user credentials from the
Google Cloud SDK or Google Cloud Shell which are not supported by the
dialogflow.googleapis.com. We recommend that most server applications
use service accounts instead. For more information about service
accounts and how to use them in your application, see
https://cloud.google.com/docs/authentication/.
Many of the Client Libraries pull from the Application Default Credentials, a summary of how they're checked is provided on that link. Essentially it will check environmental variables for a path and pull credentials from that location. This error message means you're using a User account, and not a service account.
Most commonly you logged in once using gcloud auth login, and even though you provided your service account it's still pulling from the Application Default location.
As you did, the method to associate a specific service account is gcloud auth activate-service-account --key-file <path>
Alternatively to use the true application default you can use gcloud auth application-default login
I have a service running in GCE with default service account A. This service uses gcloud to talk to various GCP services. Currently, it uses service account B to talk to some of the GCP services (using private key). However, we want to get rid of using private key and use account impersonation. To do that, I have added account A to the service account B's role and given token creator role.
I wrote a test program in go and was able to verify the impersonation works. However, our service is in PHP, and uses gcloud SDK. I couldn't find a way to configure gcloud to impersonate a service account or provide custom token.
One option is that I rewrite all the gcloud code to use google SDK, but that is lots of work, and I'd rather avoid that. My question is, how do I invoke gcloud using service account B in this scenario?. Is there a way to pass access token to gcloud or specify impersonation user?
gcloud has a --impersonate-service-account flag for this.
Run gcloud auth login and login using your gcp email address.
Run export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token --impersonate-service-account=<sa-name>.iam.gserviceaccount.com) command to generate temporary credentials from the service account and store as the current OAUTH token. (this OAUTH token only lasts for 1 hour so make sure the operation using this token can complete within that time frame.