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

Switch to use oauth2_proxy for oidc/oauth2 authentication #1199

Merged
merged 14 commits into from
Oct 21, 2019

Conversation

absoludity
Copy link
Contributor

This supports authenticating with Kubeapps on vanilla Kubernetes and also managed GKE kubernetes (which uses the OAuth2 access_token as a bearer instead of the id_token).

I've done a gazillion deployments today verifying the combinations of GKE + oidc, GKE + oauth2, local Kind cluster + oidc, kind + oauth2. Hopefully the updated docs explain the cases - let me know.

I'm not sure if we should land this - it will be a breaking change to someone who currently expects the chart options for gatekeeper, but not difficult to update. WDYT?

Also, note that I've removed the whitelist that we were using with gatekeeper - this actually secures the k8s API, as Kubeapps never needs to see the actual credential necessarily (for example, with the GKE setup, kubeapps never sees the access_key at all - it never leaves the cluster... we could update to do the same for the oidc use-case - the frontend would never need to see the id_token, but just has the cookie (which has both the id and access token encrypted)).

@absoludity absoludity self-assigned this Oct 2, 2019
Copy link
Contributor

@andresmgot andresmgot left a comment

Choose a reason for hiding this comment

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

Thank you for all the investigation and testing!

I am okay with this change but we would need to bump the major version of the chart. My suggestion is to hold this PR until we release a new version of Kubeapps so if we need to release a new minor change of the chart we can do that without the breaking change.

Apart from that I have a couple of questions:

  • Have you tried this with an IdP different than Google? Maybe if we try dex or Keycloak we find issues with the default flags.
  • We coudn't use oauth2_proxy at the beginning because it didn't have support for websockets. AFAIK that should not be a problem now but can you confirm that? Visiting any AppView, you should see some websocket connections like:

Screenshot from 2019-10-02 10-36-01


**Note**: Depending on the configuration of the Identity Provider more parameters may be needed.

In the next sections we will explain how you can find the parameters above for some of the identity providers tested. If you have configured your cluster to use an Identity Provider you will already know some of these parameters.
Kubeapps uses [OAuth2 Proxy](https://github.com/pusher/oauth2_proxy) to handle the OAuth2/OpenIDConnect authentication. The following sections explain how you can find the parameters above for some of the identity providers tested. If you have configured your cluster to use an Identity Provider you will already know some of these parameters. More detailed information can be found on the [OAuth2 Proxy Auth configuration page](https://pusher.github.io/oauth2_proxy/auth-configuration).

### Keycloak
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these sections still relevant? AFAIK the OIDC Issuer URL is not a needed parameter 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.

Yep, the -oidc-issuer-url is needed if the oicd provider is used - see the example I added below (it's in the additional flags, because it's not mandatory unless you're using the oidc provider).

Copy link
Contributor Author

@absoludity absoludity left a comment

Choose a reason for hiding this comment

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

Thank you for all the investigation and testing!

I am okay with this change but we would need to bump the major version of the chart. My suggestion is to hold this PR until we release a new version of Kubeapps so if we need to release a new minor change of the chart we can do that without the breaking change.

+1, it's a breaking change to the chart (if someone has Kubeapps setup with the auth-proxy then certain parameters will be new).

Apart from that I have a couple of questions:

* Have you tried this with an IdP different than Google? Maybe if we try dex or Keycloak we find issues with the default flags.

I haven't, but will tomorrow. I don't see that it would be different, but definitely good to verify - thanks.

* We coudn't use `oauth2_proxy` at the beginning because it didn't have support for websockets. AFAIK that should not be a problem now but can you confirm that? Visiting any AppView, you should see some websocket connections like:

I did verify that I could deploy a chart, but didn't explicitly check the websocket connections. oauth2_proxy defaults to proxying them (and the creds will be set in the same way), but I'll double check tomorrow two.

Thanks


**Note**: Depending on the configuration of the Identity Provider more parameters may be needed.

In the next sections we will explain how you can find the parameters above for some of the identity providers tested. If you have configured your cluster to use an Identity Provider you will already know some of these parameters.
Kubeapps uses [OAuth2 Proxy](https://github.com/pusher/oauth2_proxy) to handle the OAuth2/OpenIDConnect authentication. The following sections explain how you can find the parameters above for some of the identity providers tested. If you have configured your cluster to use an Identity Provider you will already know some of these parameters. More detailed information can be found on the [OAuth2 Proxy Auth configuration page](https://pusher.github.io/oauth2_proxy/auth-configuration).

### Keycloak
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, the -oidc-issuer-url is needed if the oicd provider is used - see the example I added below (it's in the additional flags, because it's not mandatory unless you're using the oidc provider).

@migmartri
Copy link
Contributor

I thought that oauth2-proxy did not work well with websockets?

--set authProxy.additionalFlags="{-cookie-secure=false,-oidc-issuer-url=https://accounts.google.com}" \
```

**Example 2: Using Google OAuth2**
Copy link
Contributor

Choose a reason for hiding this comment

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

I find this example confusing, I mean, why would I use Google Oauth2 in the general sense? I know that for GKE it makes sense to do it like that but just in that case isn't it?

I'd have just the generic OIDC example + the new GKE one using oauth2.

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 find this example confusing, I mean, why would I use Google Oauth2 in the general sense? I know that for GKE it makes sense to do it like that but just in that case isn't it?

Yes it's confusing, but no it makes sense to use the 'google' provider generally, it's the heading I've given that is incorrect - it's really using oauth2-proxy's custom Google OIDC provider. The benefit of using the google provider is that it provides a richer UI experience to users (as I tried to explain below in the GKE example). One aspect of that only affects you when you're requesting extra scopes (which generally would only be on GKE)[1], another is the default button shown by oauth2-proxy ("Login with Google" rather than "Login with OpenID Connect") - but that is configurable too.

A few of the oauth2-proxy supported providers are actually using OpenID Connect and setting the IDToken in the session state. These are: gitlab, google and logingov.

Let me re-word these examples to see if I can make it much clearer.

Thanks!

[1] This might change in the future - I don't see why Google wouldn't want the same UI experience for generic OIDC logins, or it could even be a quirk of oauth2_proxy's generic oidc implementation - not sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please take another look :)

Copy link
Contributor

Choose a reason for hiding this comment

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

"Login with Google"

I thought that we were redirecting by default to the IdP?

@absoludity
Copy link
Contributor Author

absoludity commented Oct 3, 2019

I thought that oauth2-proxy did not work well with websockets?

AFAIK, it didn't work at all prior to March this year, when it was fixed by merging the websockets support from the openshift fork: oauth2-proxy/oauth2-proxy#92

I've just tested and there is one small issue on our end (in dashboard), in that even though we're logged in via oauth2-proxy (so we send the auth cookie), we're additionally setting the wsProtocol (effectively the Sec-WebSocket-Protocol header) in the client which means oauth2-proxy appends to these, which results in a 400. If I remove these from the upgrade request from the client, then oauth2-proxy adds them and the request is upgraded as expected.

@absoludity
Copy link
Contributor Author

I did verify that I could deploy a chart, but didn't explicitly check the websocket connections. oauth2_proxy defaults to proxying them (and the creds will be set in the same way), but I'll double check tomorrow two [sic].

As above, when I checked them they are 400ing because the frontend adds the wsProtocol for the authentication first, then oauth2-proxy does the same (appending, I guess?) resulting in a bad request. If I remove the Sec-WebSocket-Protocol header from the request client request, it succeeds. I have not tested this yet in the frontend, just via cURL, so will need to do that before considering landing this..

@migmartri
Copy link
Contributor

I thought that oauth2-proxy did not work well with websockets?

AFAIK, it didn't work at all prior to March this year, when it was fixed by merging the websockets support from the openshift fork: pusher/oauth2_proxy#92

Nice, great to hear :)

Copy link
Contributor

@migmartri migmartri left a comment

Choose a reason for hiding this comment

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

Nice, thanks for the changes.

docs/user/using-an-OIDC-provider.md Outdated Show resolved Hide resolved
--set authProxy.additionalFlags="{-cookie-secure=false,-oidc-issuer-url=https://accounts.google.com}" \
```

**Example 2: Using a custom provider**
Copy link
Contributor

Choose a reason for hiding this comment

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

I do not understand what a custom provider is nor why I should care about them. Are these pre-configured OIDC Idp and that's why you do not need scopes or the oidc-issuer-urls? Where can I find more information about them?

When you say "Example 2: Using a custom provider in the section header, are we still talking about complaint OIDC Id provider?

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 do not understand what a custom provider is nor why I should care about them.

I've updated the example title to make it clear that they are oauth2-proxy providers (it is also mentioned in the next sentence), and I had already tried to highlight below why you should care in the following para?

Are these pre-configured OIDC Idp and that's why you do not need scopes or the oidc-issuer-urls?

Yes. That is, oauth2-proxy provides a bunch of oauth2 providers, a few of which are actually using openid connect so can be used here if they provide better integration (eg., example 3).

Where can I find more information about them?

About the providers themselves? I've updated with a link to the oauth2 providers, but it doesn't include details about which providers are using openid connect.

* The scopes required by the user to interact with cloud platform are included, and
* The Kubeapps frontend uses the OAuth2 `access_key` as the bearer token when communicating with the managed Kubernetes API

Note that using the custom `google` provider here enables google to prompt the user for consent for the specific permissions requested in the scopes below, in a user-friendly way. You can also use the `oidc` provider but in this case the user is not prompted for the extra contsent:
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: contsent

You can also use the oidc provider but in this case the user is not prompted for the extra contsent:

I couldn't follow.

Copy link
Contributor Author

@absoludity absoludity Oct 8, 2019

Choose a reason for hiding this comment

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

Thanks, fixed the typo. The extra consent is:

google-signin-oauth2

If you use the oidc provider, you don't get this (which is odd, but verified multiple times). I initially thought it was just depending on the scopes requested, but it's not. For example, if I deploy with the oidc provider and request the extra scopes:

helm install $HOME/dev/kubeapps/chart/kubeapps \
  --namespace kubeapps --name kubeapps \
  --set authProxy.enabled=true \
  --set authProxy.provider=oidc \
  --set authProxy.clientID=<myclient-id>.apps.googleusercontent.com \
  --set authProxy.clientSecret=<myclient-secret> \
  --set authProxy.cookieSecret=$(echo "not-good-secret" | base64) \
  --set authProxy.additionalFlags="{-cookie-secure=false,-oidc-issuer-url=https://accounts.google.com,-scope=https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/cloud-platform}" 

I do not see the above consent, but if I deploy with the google-specific oidc provider:

helm install $HOME/dev/kubeapps/chart/kubeapps \
  --namespace kubeapps --name kubeapps \
  --set authProxy.enabled=true \
  --set authProxy.provider=google \
  --set authProxy.clientID=<myclient-id>.apps.googleusercontent.com \
  --set authProxy.clientSecret=<myclient-secret> \
  --set authProxy.cookieSecret=$(echo "not-good-secret" | base64) \
  --set authProxy.additionalFlags="{-cookie-secure=false,-scope=https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/cloud-platform}" \

then I do see the consent acceptance.

Copy link
Contributor

@migmartri migmartri left a comment

Choose a reason for hiding this comment

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

Nice! Thanks for applying the changes

Just one tibdit

For this guide we assume that you have a Kubernetes cluster that is properly configured to use an Identity Provider (IdP) to handle the authorization of your cluster

" to handle the authorization of your cluster" > to handle the authentication of your cluster?

@absoludity
Copy link
Contributor Author

Nice! Thanks for applying the changes

Just one tibdit

For this guide we assume that you have a Kubernetes cluster that is properly configured to use an Identity Provider (IdP) to handle the authorization of your cluster

" to handle the authorization of your cluster" > to handle the authentication of your cluster?

Updated. I was actually wondering if it's safe for me to create a rando google account and setup a provider authorising lvh.me only, and actually include that in the README (so the README can then clearly document how to run a kind cluster with kubeapps installed using that IdPn).

@absoludity absoludity merged commit 2985f4d into vmware-tanzu:master Oct 21, 2019
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.

3 participants