RFC: Make DefaultCredentialsProvider public.#1913
RFC: Make DefaultCredentialsProvider public.#1913tjgq wants to merge 1 commit intogoogleapis:mainfrom
Conversation
Motivation: Bazel uses GoogleCredentials.getApplicationDefault() to locate and load Application Default Credentials. Because this method calls through to a DefaultCredentialsProvider singleton instance which caches the credentials, they can never be reloaded; the only way to force a reload is to restart the Bazel server (see bazelbuild/bazel#23368). With this change, Bazel could instantiate a fresh DefaultCredentialsProvider and call getDefaultCredentials() on it directly. I'd also accept any alternative that has the effect of forcing a reload (e.g., a GoogleCredentials.getApplicationDefaultUncached() method; or a reload argument to the existing method; or a cache reset method). All I want is to avoid duplicating the DefaultCredentialsProvider logic in Bazel.
@tjgq Can you provide a bit more information about this regarding how Bazel uses this? From the logs on the other ticket, it seems like this is trying to call ADC multiple times (or a testing workflow that calls it multiple times?). Does the underlying credential change or do you need to just get a new access token? Happy to have a discussion here, but we are slowing migrating over to https://github.com/googleapis/google-cloud-java. Future PRs and Issues should be raised against the monorepo. Thanks! |
I'm not sure, but I think it's the former; this is about the contents of the file pointed to by the The main use case is the credentials expiring or getting revoked in between builds. However, looking at what DefaultCredentialsProvider does internally, I suppose the issue would also occur if one were to run a subsequent build with a different value for the (In case it's not clear, note that Bazel keeps a persistent server process running in the background between build commands; that's where the state is preserved. One can force a server restart to work around this problem, but that destroys build incrementality, and is a poor/confusing user experience.)
Sure, I'm happy to recreate the PR there once we have agreement on what to do (but let's please continue the discussion on this thread). |
If the credential is expiring, then the auth library has a method to refresh the access token ( I see from the other ticket that there is the call to
I think I'll need more information about this use case. Our client libraries don't support this behavior and we've never really considered this use case (e.g. swapping the ADC value without a restart).
I think I understand a use case where there may be an expiring cred (e.g. SA cred is valid for ~3 months and needs to be rotated). Even for this use case, I think it would fine to do a restart as it's not resetting every build. |
We already wrap all of our calls in a retry-after-refresh (see https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/remote/util/Utils.java;l=482-496) so I'm pretty sure that this is about a change to the credential file, not just an expired token. (Tne stack traces in the Bazel issue also corroborate this.) I think the explicit
Yes, you may assume that this is is the only use case I care about; the other scenarios I described are of marginal importance.
It might be infrequent, but when it does happen, it's still annoying and confusing. I'd rather not expose my users to it. I'm curious - why do you feel it's important for the auth library to impose a requirement that the only way to reload the credentials from disk is to restart the process? Is there a subtle security implication that I'm missing here? Outside of possible security concerns, I'd argue that persistent un-resettable global state is just a bad implementation choice for a general-purpose library. |
Motivation: Bazel uses GoogleCredentials.getApplicationDefault() to locate and load Application Default Credentials. Because this method calls through to a DefaultCredentialsProvider singleton instance which caches the credentials, they can never be reloaded; the only way to force a reload is to restart the Bazel server (see bazelbuild/bazel#23368). With this change, Bazel could instantiate a fresh DefaultCredentialsProvider and call getDefaultCredentials() on it directly.
I'd also accept any alternative that has the effect of forcing a reload (e.g., a GoogleCredentials.getApplicationDefaultUncached() method; or a reload argument to the existing method; or a cache reset method). All I want is to avoid duplicating the DefaultCredentialsProvider logic in Bazel.