Dex: Kubernetes cli tokens

Created on 27 Sep 2017  路  10Comments  路  Source: dexidp/dex

Please document how to setup dex such that you can get a token via the web browser that you can use with the kubectl cli.

help wanted kindocumentation

Most helpful comment

I have a working implementation of the setup described above, with a commandline tool that uses a Public Client and a localhost http server to go through the login flow. It needs a bit of cleanup before I can share it but I should be able to get it posted in the next few days.

All 10 comments

@kfox1111 DEX itself does not actually provide you with this feature afaik.

What I did was i took the example-app from the DEX repo as foundation and created a login service that i run and expose via ingress, that login service in turn will talk to DEX allowing you to authenticate against your defined user backends, the user is then returned to the login app which presents user with the token.

I'm currently running a devel cluster with this setup and users login via their LDAP credentials and gets a token they use to talk to the API

RBAC roles is out of this scope and has to be manually provisioned to allow the users to actually have rights to do things after authing.

I followed the getting started guide and using-dex to piece the puzzle together.

Imho there is a little catch 22 here as DEX is the backend service and users are suposed to write the actual login frontend themselves ( please correct me if i'm wrong here )

Thanks for the info.

I did some further digging, and ran into dex's support for public clients and a document describing how kubeconf can be configured with refresh tokens. I think this is probably part of the solution but haven't pieced it all together yet.

I think we probably want to have a different client secret for the kube-dashboard since its a web service then from the kubeconf case, where it has to be public? This implies separate clients, but k8s only supports one.

Dex also mentions in docs, but I havent found a concrete example yet, of one client trusting another. I think this might be a part of the solution too?

So, here's what I'm thinking currently. If someone could validate the idea, that would be great.

  1. create 2 clients. one for dashboard, one for cli.
  2. setup the kube apiserver with the dashboard one
  3. make a trust between the dashboard one and the cli one.
  4. throw a json document describing all the config needed by a local client on a web server somewhere
  5. make a go binary that gets the config from step 4, goes through the local auth flow and builds the user a kubeconfig file with a refresh token?

What does everyone think?

Has anyone built that kind of client before?

I have a working implementation of the setup described above, with a commandline tool that uses a Public Client and a localhost http server to go through the login flow. It needs a bit of cleanup before I can share it but I should be able to get it posted in the next few days.

Cool. looking forward to seeing it. :)

I was pondering something yesterday... I dug through the docs and noticed: urn:ietf:wg:oauth:2.0:oob
A RedirectURI that displays a web page with a copy/paste'able token.

That is 90% of what we would need I think. Would the dex devs be against someone adding templating functionality using gotl for that page? If that was acceptable, we could let the operator add a kubectl compatable .conf file template that renders out something that looks like this (Option 1 - OIDC Authenticator):
https://kubernetes.io/docs/admin/authentication/#using-kubectl

The user could then download a kubeconf file prepopulated with a refresh token, and kubectl itself could refresh them.

It would be something we could easily add a link to for the kube-dashboard too, to let you download one.

I could see this being used for other use cases as well. maybe an openstack oidc based config file.

What do you folks think?

Just dug through the code base a little. Looks like it already is gotl templated. There just can only be one for the entire server.
All we would need is a way to allow it to be overridden on a client by client basis in the config file?

hmm.... two other changes are needed.
https://github.com/coreos/dex/blob/master/server/handlers.go#L522

Currently, it looks like it only passes the id token, and not the refresh token. We should pass all the info and allow the template to display the pieces it things are needed. Like in this case, the refresh token.

Does anyone have any objection to just passing 'code' instead of 'code.ID' through?

The second thing, is a way to pass a mime type through to so that it can force the browser to enter download mode instead of trying to render the kubeconf.

another wrinkle. It doesn't look like the /auth endpoint ever deals with refresh tokens....

I was able to get this mostly working by writing a basic web client to generate id and refresh tokens. However, i've been having a hard time getting cross-client trust working for a public kubectl client. It would appear that dex creates a refreshtokens.dex.coreos.com custom resource object with clientID: web-client, rather than clientID: kubectl. Therefore, I can use the initial token just fine, but dex throws the following error when a token needs to be refreshed:

time="2017-11-30T17:17:41Z" level=error msg="client kubectl trying to claim token for client web-client"

This results in the following error from kubectl:

Unable to connect to the server: failed to refresh token: oauth2: cannot fetch token: 400 Bad Request
Response: {"error":"invalid_request","error_description":"Refresh token is invalid or has already been claimed by another client."}

see https://github.com/coreos/dex/blob/master/server/handlers.go#L829-L833

tectonic-identity seems to successfully generate tokens that can be refreshed for a public tectonic-kubectl client. And when I check the refresh-token.oidc.coreos.com third party resources in tectonic, they appear to properly configure clientID: tectonic-kubectl. Perhaps someone familiar with tectonic-identity can give us some pointers.

The way to set this up properly I think requires two different accounts. one for the web service, and one for the cli. but you can't get a refresh token for the cli from the web service account. The server doesn't support the use case.

Plus it has the added drawback of a web service having access to a token that can refresh a users creds forever. a fairly important piece of data that maybe it shouldn't have.

I implemented a pr here:
https://github.com/coreos/dex/pull/1105

That lets you use the oob process to allow you to generate a prepopulated kubeconf. It is working well for me. Dex itself then is the only entity seeing the refresh token outside of the user downloading the config file who already has access. So I think its one of the more secure solutions. I have a prototype helm chart that can use this mechanism to allow you to login via dex to the dashboard and also download a cli config.

FYI, kubelogin automates the fetching of an id-token, and integrates nicely into kubectl.

Was this page helpful?
0 / 5 - 0 ratings