-
Notifications
You must be signed in to change notification settings - Fork 39
Description
REPRO CASE
- Create a Service account in GCP (if you don't have one)
- Create a user account in GCP (you probably have one)
- Allow the user account to run as (impersonate) the service account
- Run
gcloud auth application-default login --impersonate-service-account=SERVICE-ACCOUNT-NAME - Login as your user account
- Start R and run
gargle::credentials_app_default()(or something that calls it, likegargle::token_fetchorbigrquery::bq_auth())
Expected behavior: Successfully authenticates and acquires a token that authenticates as the service account, OR, fails in some explicit way (at least when debugging is enabled via options(gargle_quiet = FALSE))
Actual behavior: Prints that it found an ADC file, but then returns NULL instead of a token:
> print(gargle::credentials_app_default())
trying `credentials_app_default()`
file exists at ADC path:
/root/credentials.json
NULLEXPLANATION
Impersonation credentials are a relatively new and relatively obscure but very useful and increasingly supported type of credentials for GCP, see:
- the docs on service account impersonation
- the docs for
--impersonate-service-accountandgcloud auth application-default login - the
google.auth.impersonated_credentialsmodule in the Python google auth library - a blog post about doing this in Node
- a thread about adding this feature to the golang oauth2 library
Here is what these "impersonation credentials" look like:
{
"delegates": [],
"service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/<SERVICE ACCOUNT NAME>",
"source_credentials": {
"client_id": "<USER CLIENT ID>",
"client_secret": "<USER CLIENT SECRET>",
"refresh_token": "<USER REFRESH TOKEN>",
"type": "authorized_user"
},
"type": "impersonated_service_account"
}As you can see, they include a nested set of user credentials, plus instructions for how to use an API to get a token that impersonates the service account (without directly having the service account's credentials). The idea is that when fetching a token for these credentials, first you fetch a token for the nested user credentials, then you use that token to fetch a token to impersonate the service account, then you use that token.
At the very least, credentials_app_default.R should issue some sort of message if it falls of the end of the recognized info$type conditions, so that we'd see something like unknown ADC cred type: "impersonated_service_account" and have a clue about what's going wrong. Better yet, of course, would be to in fact support this type of credential properly...!