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

Implement OIDC Auth Provider #396

Merged
merged 5 commits into from
Feb 28, 2019
Merged

Implement OIDC Auth Provider #396

merged 5 commits into from
Feb 28, 2019

Conversation

rhysm
Copy link
Contributor

@rhysm rhysm commented Feb 25, 2019

Adds ability for Kubeclient to utilize the oidc auth-provider both by
re-using the id-token that is inside the kubeconfig if it is not expired
and refreshing it if the token has passed expiry.

Adds ability for Kubeclient to utilize the oidc auth-provider both by
re-using the id-token that is inside the kubeconfig if it is not expired
and refreshing it if the token has passed expiry.
@cben
Copy link
Collaborator

cben commented Feb 26, 2019

Sorry for delay, reviewing...
This is cool!
k8s docs: https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens

Copy link
Collaborator

@cben cben left a comment

Choose a reason for hiding this comment

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

Excellent 💯, very minor comments

README.md Outdated
If the id-token specified in your `$KUBECONFIG` file has not expired the OIDC Auth Provider will simply use that token.
If it has expired then the provider will refresh the token and use that.

Currently tokens are only valid for one hour and the provider will not automatically refresh them. Fresh id-tokens are also
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it always 1 hour? Isn't expiration up to the oidc server?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated for clarity.

README.md Outdated
#### OIDC Auth Provider

If the cluster you are using has OIDC authentication enabed you can use the `openid_connect` gem to refresh
id-tokens when they have expired.
Copy link
Collaborator

Choose a reason for hiding this comment

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

See next comment about the wording "refresh".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated for clarity.


def expired?(id_token)
# If token expired or expiring within 60 seconds
Time.now.to_i + 60 > id_token.exp.to_i
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this timezone independent? 👍 looks good, Time.now knows its timezone and Time.now.to_i is same either way:

~ $ env TZ= ruby -e 'p Time.now'
2019-02-27 10:47:22 +0000
~ $ ruby -e 'p Time.now'
2019-02-27 12:47:26 +0200
~ $ env TZ= ruby -e 'p Time.now.to_i'
1551264454
~ $ env ruby -e 'p Time.now.to_i'
1551264463

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The openid_connect gem performs the same check except for the 60 second grace so I believe it will be fine.

end

class << self
def token(auth_provider)
Copy link
Collaborator

Choose a reason for hiding this comment

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

[optional nit, your call] The name auth_provider sounds like this would contain the ['auth-provider'] part of the config, but it contains the ['auth-provider']['config'] sub-part. Maybe config? auth_provider_config (ouch)? provider_config?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, I've gone with provider_config.

issuer_url = auth_provider['idp-issuer-url']
discovery = OpenIDConnect::Discovery::Provider::Config.discover! issuer_url

id_token = OpenIDConnect::ResponseObject::IdToken.decode auth_provider['id-token'],
Copy link
Collaborator

Choose a reason for hiding this comment

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

What if the config doesn't contain id-token at all? (Is that possible?)
As we can always obtain a new one, let's allow this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure how you'd get into that state but kubectl supports it so I've implemented it too.

README.md Outdated
like [`dexter`](https://github.com/gini/dexter) in order to configure the auth-provider in your `$KUBECONFIG` file.

If the id-token specified in your `$KUBECONFIG` file has not expired the OIDC Auth Provider will simply use that token.
If it has expired then the provider will refresh the token and use that.
Copy link
Collaborator

@cben cben Feb 27, 2019

Choose a reason for hiding this comment

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

The wordings "will refresh" ... "will not automatically refresh" sounds confusing on a quick read.
I propose here saying:

If you use Config.context(...).auth_options and the kubeconfig file has user: {auth-provider: {name: gcp}}, kubeclient will automatically obtain a token (or use id-token if still valid)

to me "obtain" is one-time action, doesn't imply ability to keep refreshing it, nor sounds as action done to the token so less expectation it'll write it back to the config file (the disclaimer below is still good).

The other change is because this section talks abstractly about "the OIDC Auth Provider" but I wanted to say specifically how to invoke this (Client doesn't do this, Config does)

Copy link
Collaborator

Choose a reason for hiding this comment

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

(one day if we implement #393, we can reword these sections in terms of "refresh" or "renewal")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated README for more clarity, let me know what you think.

Copy link
Collaborator

@cben cben left a comment

Choose a reason for hiding this comment

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

perfect!

@cben cben merged commit c335035 into ManageIQ:master Feb 28, 2019
@cben
Copy link
Collaborator

cben commented Feb 28, 2019

BTW, a security question:
Kubeclient supports opt-out from some "dangerous" config handling — reading local files, and exec:.
(For scenarios where you take config from untrusted source, which I warn against anyway, and I haven't seen anyone doing, but on general principles...)
Do you think this opt-out should also disable OIDC (and GCP #394) auth-providers?

On one hand, making a network request is not risky to your machine(?).
On the other, that's still "acting on data" vs passively reading it. However the goal of Config is to feed it to Client which will act on a lot of it by network requests anyway so that's hardly a criterion...

cben added a commit to cben/kubeclient that referenced this pull request Mar 3, 2019
added changelog for ManageIQ#396
@cben cben mentioned this pull request Mar 3, 2019
@cben
Copy link
Collaborator

cben commented Mar 3, 2019

released in gem 4.3.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants