-
Notifications
You must be signed in to change notification settings - Fork 39.8k
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
oidc client plugin: reduce round trips and fix scopes requested #45317
oidc client plugin: reduce round trips and fix scopes requested #45317
Conversation
@k8s-bot unit test this |
c21fe5b
to
1bc434c
Compare
rebased with #45529 |
@k8s-bot kops aws e2e test this |
Reassign to @liggitt to triage. |
if they have an unexpired but invalid token, this change would make them go through more manual steps to obtain a valid token again, right? |
for example, if the keys used to sign id_tokens got rotated, so their current id_token was not valid, but they could have used the refresh token to obtain a new valid id_token |
I don't think this is release-note-worthy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not an auth expert, but the code looks sound and the tests look great. Nice job @ericchiang .
@liggitt yeah, this PR stopped validating the following things on the kubectl side that the API server does check.
When we've had problems with signature validation, it's usually because of provider incompatibilities, not something that changes with a new id_token. I don't know if refreshing will help this situation. Client ID claims are hard to validate because we don't know which client ID the API server has been configured with. The rest of the API server validations are:
|
cfgIDToken = "id-token" | ||
cfgRefreshToken = "refresh-token" | ||
|
||
// Unused. Scopes aren't sent during refreshing. | ||
cfgExtraScopes = "extra-scopes" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
worth a release note, and maybe worth outputting a low-verbosity info message, since they're ignored now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I can add a warning message.
mu sync.RWMutex | ||
mu sync.RWMutex | ||
// Each oidcAuthProvider holds a mutex to ensure a set of credentials only refresh | ||
// their token once. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this assume short-lived processes? refreshing a token multiple times could be valid
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It tries to ensure that concurrent calls to the round tripper, when the credentials expire, only trigger a single refresh. E.g. if I've configure a client and do something like:
go client.ListNodes()
go client.ListNodes()
Only one of those calls should trigger a refresh event.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed this comment because it's addressed where the actual mutex is defined on oidcAuthProvider
return false, fmt.Errorf("parsing claims: %v", err) | ||
} | ||
|
||
return time.Now().Add(expiryDelta).Before(time.Time(claims.Expiry)), nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pass in now() for testing?
// jsonTime is a json.Unmarshaler that parses a unix timestamp. | ||
// Because JSON numbers don't differentiate between ints and floats, | ||
// we want to ensure we can parse either. | ||
type jsonTime time.Time |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please tell me you haven't seen a floating point expiration time in the wild.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An old version of dex used to do this because of handling claims as map[string]interface{}
:( We've "fixed" it for all relevant but I've always done this defensively so if other providers do it I wouldn't know. golang.org/x/oauth2 does something similar for numeric values (expires_in)[1].
I can buy that. A few questions, LGTM overall |
1bc434c
to
96edba2
Compare
@k8s-bot kops aws e2e test this |
bump @liggitt |
/lgtm |
@k8s-bot pull-kubernetes-federation-e2e-gce test this |
@k8s-bot kops aws e2e test this |
Federation test (https://k8s-gubernator.appspot.com/build/kubernetes-jenkins/pr-logs/pull/45317/pull-kubernetes-federation-e2e-gce/5836/)
@k8s-bot pull-kubernetes-federation-e2e-gce test this @k8s-bot kops aws e2e test this If these don't pass will rebase and re-request LGTM. |
This PR attempts to simplify the OpenID Connect client plugin to reduce round trips. The steps taken by the client are now: * If ID Token isn't expired: * Do nothing. * If ID Token is expired: * Query /.well-known discovery URL to find token_endpoint. * Use an OAuth2 client and refresh token to request new ID token. This avoids the previous pattern of always initializing a client, which would hit the /.well-known endpoint several times. The client no longer does token validation since the server already does this. As a result, this code no longer imports github.com/coreos/go-oidc, instead just using golang.org/x/oauth2 for refreshing.
96edba2
to
6915f85
Compare
Federation test flake is #45978 Everything else is green. |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: ericchiang, liggitt
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
@ericchiang: The following test(s) failed:
Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
Automatic merge from submit-queue |
This PR attempts to simplify the OpenID Connect client plugin to
reduce round trips. The steps taken by the client are now:
This avoids the previous pattern of always initializing a client,
which would hit the /.well-known endpoint several times.
The client no longer does token validation since the server already
does this. As a result, this code no longer imports
github.com/coreos/go-oidc, instead just using golang.org/x/oauth2
for refreshing.
Overall reduction in tests because we're not verify as many things
on the client side. For example, we're no longer validating the
id_token signature (again, because it's being done on the server
side).
This has been manually tested against dex, and I hope to continue
to test this over the 1.7 release cycle.
cc @mlbiam @frodenas @curtisallen @jsloyer @rithujohn191 @philips @kubernetes/sig-auth-pr-reviews
Updates #42654
Closes #37875
Closes #37874