Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix caching of default credentials #84

Closed
wants to merge 1 commit into from
Closed

Fix caching of default credentials #84

wants to merge 1 commit into from

Conversation

kerneis
Copy link
Contributor

@kerneis kerneis commented Dec 9, 2019

Two independent changes, please let me know if you'd rather have two separate pull requests:

  • Make caching work with GOOGLE_APPLICATION_CREDENTIALS
  • Fix oauth2l test

If the user uses GOOGLE_APPLICATION_CREDENTIALS (or another default
mechanism provided by sgauth instead of an explicit --credential),
caching is broken when the environment variable changes.

This commit reads the JSON file from its default location through sgauth
to ensure more robust caching.
@shinfan
Copy link
Collaborator

shinfan commented Dec 9, 2019

Could you please provide more details, like a repro example, about the caching issue of the default location?

@andyrzhao
Copy link
Collaborator

I think we should separate the 2 changes. The first change to use exit code for "oauth2l test" is good in theory, but it would not be backwards compatible with older scripts that relied on "stdout" for the test function right? I'll let shinfan comment on whether this is acceptable.

As for the second change to support robust caching for GOOGLE_APPLICATION_CREDENTIALS: If my understanding is correct, the existing behavior used an "empty json" as part of the cache key when caching for GOOGLE_APPLICATION_CREDENTIALS (via util/cache.go), so only 1 version of the cached token is possible. And your proposed change allows us to cache multiple tokens obtained through different GOOGLE_APPLICATION_CREDENTIALS. I think in this particular scenario, it would probably be better to either not use caching or "reset" the cache beforehand - both of which are already supported. If the default credentials get changed, I doubt that it will ever be changed back to the previous state, which would make the cache on the old key useless. What do you think?

@kerneis kerneis changed the title Fix caching and test Fix caching of default credentials Dec 10, 2019
@kerneis
Copy link
Contributor Author

kerneis commented Dec 10, 2019

I've split the test change in #85 and updated this pull request to focus on the caching change alone.

@andyrzhao has correctly described the change. Here is our use case:

  • we have several environments (eg. prod and test)
  • we have a playbook to debug or investigate issues, with a number of command-line snippets to copy-paste (those are not full-fledged scripts because remember the debugging, interactive nature of this task—which is also specifically what oauth2l is about, according to oauth2l is unnecessarily interactive, which gets in the way of automation #61 for instance),
  • instructions in this playbook typically ask the user to set set GOOGLE_APPLICATION_CREDENTIALS to a json file they download from the web (to a location of your choice) for the appropriate environment (test or prod), and then use oauth2l --scope openid curl ... or something equivalent.

It is only natural for a user want to test in multiple environments to compare results, either by redefining the global variable or by switching between different terminal sessions. Having the cache unaware of those environment changes is surprising, which is harmful especially while debugging and violates the POLA. Having the cache disabled for such cases would break very legitimate use cases. In particular, any usage of the form $(oauth2l fetch --scope openid) would silently stall.

A work-around for us would be to explicitly maintain separate caches (which is more tedious), or use a separate shell variable and pass it explicitly with --credentials. But that wouldn't solve the similar violation of POLA for other users in the field (this PR originated from me being very puzzled for about 20 minutes until I figured out what the issue was).

The only downside I can see with the propose PR is that I was afraid to break existing workflows I may not envision or understand, and didn't go as far as failing the whole command if the JSON resolution fails. That means we could still corrupt the cache with empty json keys, eg. in the case of subtle race conditions where the environment changes between the two resolutions. I'm open to making that change if you think it's better to ensure we have exactly one default resolution for any command call.

@sethvargo
Copy link
Member

Could you use oauth2l ... --cache=/dev/null to disable the cache?

@kerneis
Copy link
Contributor Author

kerneis commented Dec 10, 2019 via email

@andyrzhao
Copy link
Collaborator

andyrzhao commented Dec 10, 2019

Understood. I agree that the current caching behavior for default credentials is "broken" and should be fixed. I'd like to make 2 recommendations however:

  1. For your particular use-case of toggling between credentials, using the explicit "--credentials" parameter is preferable and more predictable than updating default credentials env variable, which is intended to be static. Unless you are using GOOGLE_APPLICATION_CREDENTIALS for other tools besides OAuth2l at the same time, it is probably better to update your playbook to use the explicit parameter.
  2. The caching logic in util/cache.go probably has other subtle issues that need to be fixed, such as how we construct the cache key in general. With this in mind, it is probably better to put your resolution logic inside util/cache.go instead of main.go to keep everything in one place. What do you think?

@kerneis
Copy link
Contributor Author

kerneis commented Dec 12, 2019 via email

@andyrzhao
Copy link
Collaborator

I see your concern regarding consistency. Here is one more alternative to consider: Updating sgauth/default.go to store the application default credentials back into the settings object, after it has been retrieved. This should give us the correct cache key and avoid the problem of trying to resolve the default credentials twice.

If the above alternative is not feasible, then I'd still prefer you add the logic to the caching util. Practically speaking, corruption due to concurrency etc. should not be a concern the way this tool is intended to be used. Thanks!

@kerneis
Copy link
Contributor Author

kerneis commented Dec 13, 2019 via email

@shinfan shinfan closed this Aug 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants