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

Optimize authentication for base image #2789

Merged
merged 4 commits into from
Sep 30, 2020

Conversation

chanseokoh
Copy link
Member

Fixes #2784. Fixes #2134.

After we try to pull a base image manifest without sending credentials, we either attempt bearer auth or basic auth based on the WWW-Authenticate HTTP header value in a 401 unauthorized response. I have been thinking for a very long time even before filing #2134 this is the most ideal and optimized flow. I believe every sane registry implementation that throws 401 on a manifest request will send WWW-Authenticate.

However, since auth is the most frictional part, I didn't want to make a drastic change. So when the server doesn't return WWW-Authenticate (I don't expect this to happen), we do some fallback operations. First, we just blindly send credentials via basic auth, and if that fails again with 401, we attempt bearer auth for the last moment. This fallback is basically identical to the current auth flow.

@chanseokoh
Copy link
Member Author

FTR: the earlier PR #2202 to fix #2134 is basically same as this.

Copy link
Member

@loosebazooka loosebazooka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is fine, just some things I don't understand

// server and fail. However, to keep some old behavior, try a few things as a last resort.
// TODO: consider removing this fallback branch.
if (credential != null && !credential.isOAuth2RefreshToken()) {
eventHandlers.dispatch(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we actually do LogEvent.warn here with some guidance on reporting this, so that we may identify misbehaving servers by user reports?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think this is a good idea to identify registries that are acting strange. But up to you.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I missed this comment. I thought about that, and I agree logging a warning will be very valuable to us. But I think a warning should be something actionable and fixable on the user side, so that's my hesitation. I've seen some people regard a warning seriously (probably because of a 0-warning policy auto-enforced by some system). Gathering information is really useful to us, but I feel we should be careful for dual-purposing a warning.

@@ -140,40 +143,43 @@ public ImagesAndRegistryClient call()
LogEvent.lifecycle(
"The base image requires auth. Trying again for " + imageReference + "..."));

Credential registryCredential =
Credential credential =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems a little strange that we have so much auth code in PullBaseImage step and not somewhere else like RegistryAuthenticator?

Copy link
Member Author

@chanseokoh chanseokoh Sep 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(First of all, I don't know the initial intention of RegistryAuthenticator, but in reality it has always been "BearerAuthenticator" that's only about bearer auth.)

As discussed offline, we could have introduced an overarching RegistryClient.doRightAuth() that perhaps does

if (!doPull/PushBearerAuth()) {
 ... 
 configureBasicAuth();
}

I expect this flow should work for both pull and push auth with any registries, and this is exactly the flow we do for target registry auth. However, we were taking a different flow for base image registries (as can be seen in the PR), and what is one of the reasons we don't have doRightAuth().

Given this and that RegistryClient is a low-level API, it also seemed reasonable to have separate nobs for configuring basic auth and completing bearer auth. Another factor to this is the difference between configuring basic auth and completing the whole bearer auth leg: configuring basic auth means that you'll just send the credentials going forward no matter what, while completing bearer auth means interacting with a registry server and an auth server with two round-trips to get another form of credentials to send going forward.

if (authenticator.isPresent()) {
doBearerAuth(true, authenticator.get());
} else if (credential != null && !credential.isOAuth2RefreshToken()) {
configureBasicAuth();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this flow a little confusing. Should we just have multiple types of credentials instead of checking the state of the Credential everywhere?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like defining subclasses of Credentials?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I don't know, I've haven't done much in this section of the code base, so it's all a little strange.

@chanseokoh chanseokoh merged commit 093c8e3 into master Sep 30, 2020
@chanseokoh chanseokoh deleted the i2784-azure-www-authenticate-bearer branch September 30, 2020 15:23
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.

Azure Container Registry token works for push but not pull Optimize registry authentication
3 participants