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

oidc client plugin: reduce round trips and fix scopes requested #45317

Merged
merged 1 commit into from
May 25, 2017

Conversation

ericchiang
Copy link
Contributor

@ericchiang ericchiang commented May 3, 2017

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.

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

NONE

Updates #42654
Closes #37875
Closes #37874

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label May 3, 2017
@k8s-github-robot k8s-github-robot added approved Indicates a PR has been approved by an approver from all required OWNERS files. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. release-note Denotes a PR that will be considered when it comes time to generate release notes. labels May 3, 2017
@k8s-reviewable
Copy link

This change is Reviewable

@ericchiang
Copy link
Contributor Author

@k8s-bot unit test this

@gmarek gmarek assigned caesarxuchao and unassigned gmarek and piosz May 4, 2017
@ericchiang ericchiang changed the title oidc client plugin: reduce round trips and switch to golang.org/x/oauth2 oidc client plugin: reduce round trips and fix scopes requested May 9, 2017
@ericchiang ericchiang force-pushed the oidc-client-update branch from c21fe5b to 1bc434c Compare May 10, 2017 17:50
@ericchiang
Copy link
Contributor Author

rebased with #45529

@ericchiang
Copy link
Contributor Author

@k8s-bot kops aws e2e test this

@caesarxuchao
Copy link
Member

Reassign to @liggitt to triage.

@caesarxuchao caesarxuchao assigned liggitt and unassigned caesarxuchao May 10, 2017
@caesarxuchao caesarxuchao added the sig/auth Categorizes an issue or PR as relevant to SIG Auth. label May 10, 2017
@liggitt
Copy link
Member

liggitt commented May 11, 2017

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?

@liggitt
Copy link
Member

liggitt commented May 11, 2017

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

@liggitt
Copy link
Member

liggitt commented May 11, 2017

I don't think this is release-note-worthy

Copy link
Contributor

@lpabon lpabon left a 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 .

@ericchiang
Copy link
Contributor Author

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?

@liggitt yeah, this PR stopped validating the following things on the kubectl side that the API server does check.

  • JWT signatures
  • Sub claim (which holds the client id)

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:

  • Malformed JWT (loosely checked client side)
  • Malformed or missing username or group claim (same as client ID, hard to check client side because claim names are dynamic)

cfgIDToken = "id-token"
cfgRefreshToken = "refresh-token"

// Unused. Scopes aren't sent during refreshing.
cfgExtraScopes = "extra-scopes"
Copy link
Member

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?

Copy link
Contributor Author

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.
Copy link
Member

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

Copy link
Contributor Author

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.

Copy link
Contributor Author

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
Copy link
Member

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
Copy link
Member

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.

Copy link
Contributor Author

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].

[1] https://github.com/golang/oauth2/blob/ad516a297a9f2a74ecc244861b298c94bdd28b9d/internal/token.go#L62-L63

@liggitt
Copy link
Member

liggitt commented May 15, 2017

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.

I can buy that. A few questions, LGTM overall

@ericchiang ericchiang force-pushed the oidc-client-update branch from 1bc434c to 96edba2 Compare May 16, 2017 00:23
@ericchiang
Copy link
Contributor Author

@k8s-bot kops aws e2e test this

@ericchiang
Copy link
Contributor Author

bump @liggitt

@liggitt
Copy link
Member

liggitt commented May 19, 2017

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 19, 2017
@curtisallen
Copy link
Contributor

@k8s-bot pull-kubernetes-federation-e2e-gce test this

@curtisallen
Copy link
Contributor

@k8s-bot kops aws e2e test this

@ericchiang
Copy link
Contributor Author

Federation test (https://k8s-gubernator.appspot.com/build/kubernetes-jenkins/pr-logs/pull/45317/pull-kubernetes-federation-e2e-gce/5836/)

I0519 22:03:12.461] Extracting kubernetes-test.tar.gz into /workspace/kubernetes
W0519 22:03:19.063] 2017/05/19 22:03:19 util.go:131: Step './get-kube.sh' finished in 12.426052885s
W0519 22:03:19.063] 2017/05/19 22:03:19 util.go:129: Running: ./federation/cluster/federation-down.sh
W0519 22:03:19.115] Project: k8s-jkns-pr-bldr-e2e-gce-fdrtn
W0519 22:03:19.116] Zone: us-central1-f
W0519 22:03:19.318] error: context "e2e-f8n-agent-pr-93-0" does not exist
I0519 22:03:19.419] Cleaning Federation control plane objects
W0519 22:03:49.518] Unable to connect to the server: dial tcp 35.188.69.68:443: i/o timeout
W0519 22:04:19.720] Unable to connect to the server: dial tcp 35.188.69.68:443: i/o timeout
W0519 22:04:49.902] Unable to connect to the server: dial tcp 35.188.69.68:443: i/o timeout

Kops test (https://k8s-gubernator.appspot.com/build/kubernetes-jenkins/pr-logs/pull/45317/pull-kubernetes-e2e-kops-aws/26025/)

<testsuite failures="1" tests="4" time="1324.691737505">
<testcase classname="e2e.go" name="TearDown Previous" time="8.444205226"/>
<testcase classname="e2e.go" name="Up" time="1226.128770805">
<failure>waiting for nodes timed out</failure>
</testcase>
<testcase classname="e2e.go" name="DumpClusterLogs" time="17.527676872"/>
<testcase classname="e2e.go" name="Deferred TearDown" time="72.590966347"/>
</testsuite>

@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.
@ericchiang ericchiang force-pushed the oidc-client-update branch from 96edba2 to 6915f85 Compare May 22, 2017 17:31
@k8s-github-robot k8s-github-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 22, 2017
@ericchiang
Copy link
Contributor Author

Federation test flake is #45978 Everything else is green.

@liggitt
Copy link
Member

liggitt commented May 24, 2017

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 24, 2017
@k8s-github-robot
Copy link

[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 /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-ci-robot
Copy link
Contributor

k8s-ci-robot commented May 25, 2017

@ericchiang: The following test(s) failed:

Test name Commit Details Rerun command
Jenkins kops AWS e2e 96edba25700e08e6215a4bc260eaa5ff042e0781 link @k8s-bot kops aws e2e test this
pull-kubernetes-federation-e2e-gce 6915f85 link @k8s-bot pull-kubernetes-federation-e2e-gce test this

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.

@k8s-github-robot
Copy link

Automatic merge from submit-queue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/auth Categorizes an issue or PR as relevant to SIG Auth. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants