Skip to content

Commit

Permalink
Oidc docs (#3075)
Browse files Browse the repository at this point in the history
* OIDC documentation split

Signed-off-by: Pepe Baena <ppbaena@gmail.com>
  • Loading branch information
ppbaena committed Jul 7, 2021
1 parent 9994977 commit 09161da
Show file tree
Hide file tree
Showing 8 changed files with 452 additions and 427 deletions.
57 changes: 57 additions & 0 deletions docs/user/OIDC/OAuth2OIDC-VMware-cloud-services.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Configuring VMware Cloud Services as an OIDC provider

This document explains how to configure VMware Cloud Services as an OIDC provider (check general information and pre-requisites for [using an OAuth2/OIDC Provider with Kubeapps](../using-an-OIDC-provider.md)).

> **_Note:_** there is a [more detailed guide on how to use VMware Cloud Services in this document](../../step-by-step/kubeapps-on-tkg/step-1.md#step-12-configure-an-oidc-provider).
Login to VMware Cloud Services and select the organization which you want to use.

1. Select View Organization (under Organization settings of the org menu),
![Copying the bearer token](../../img/csp-view-organization.png)
2. Click on the OAuth Apps tab,
3. Click Create App, select Web App and continue,
4. Enter a name and description for your OAuth app,
5. Add the callback URL where Kubeapps will be running (e.g. https://my.kubeapps.example.com/oauth2/callback),
6. Leave the rest of the options other than the OpenID checkbox, which must be checked,
7. Click Create

You will now see a dialog with the app id and secret. Click on the Download JSON option as there is other useful info in the JSON.

Your Kubernetes cluster's API server (or alternatively, your [Pinniped JWTAuthenticator](../using-an-OIDC-provider-with-pinniped.md)) will need to be configured with the following options (the production VMware cloud services issuer URL is used in the example below):

```yaml
kind: ClusterConfiguration
apiServer:
extraArgs:
oidc-issuer-url: https://gaz.csp-vidm-prod.com # the staging endpoint is 'https://gaz-preview.csp-vidm-prod.com'
oidc-client-id: <your client id from above>
oidc-username-claim: email
oidc-groups-claim: group_names
```

Once your cluster is running, you can then deploy Kubeapps with the following additional values:

```yaml
authProxy:
enabled: true
provider: oidc
clientID: <your app id>
clientSecret: <your app secret>
cookieSecret: <your random seed string for secure cookies>
scope: openid email group_names
additionalFlags:
# VMware Cloud Services has different endpoints for production and staging:
# To use the staging endpoints, replace:
# 'gaz.csp-vidm-prod.com' with 'gaz-preview.csp-vidm-prod.com'
# 'console.cloud.vmware.com' with 'console-stg.cloud.vmware.com/'
- --skip-oidc-discovery=true
- --oidc-issuer-url=https://gaz.csp-vidm-prod.com
- --login-url=https://console.cloud.vmware.com/csp/gateway/discovery
- --redeem-url=https://console.cloud.vmware.com/csp/gateway/am/api/auth/token
- --oidc-jwks-url=https://console.cloud.vmware.com/csp/gateway/am/api/auth/token-public-key?format=jwks
```

Note: VMware Cloud Services has an issuer URL specific to organizations which is required for the Kubeapps auth proxy configuration above, but if you check the [`.well-known/openid-configuration`](https://console-stg.cloud.vmware.com/csp/gateway/am/api/.well-known/openid-configuration) you will see that it identifies a different (parent) issuer, `https://gaz.csp-vidm-prod.com`.
It is for this reason that the `--skip-oidc-discovery=true` option is required above and we need to manually set each `oidc-issuer`, `login-url`, `redeem-url` and `oidc-jwks-url` instead of relying on the automatic discovery.

Once deployed, if you experience issues logging in, please refer to the [Debugging auth failures when using OIDC](./OAuth2OIDC-debugging.md) section below.
97 changes: 97 additions & 0 deletions docs/user/OIDC/OAuth2OIDC-azure-active-directory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Configuring Azure Active Directory as an OIDC provider

This document explains how to configure Azure Active Directory as an OIDC provider (check general information and pre-requisites for [using an OAuth2/OIDC Provider with Kubeapps](../using-an-OIDC-provider.md)).

## AKS-managed Azure Active Directory

This setup assumes that you are using the [AKS-managed Azure AD integration](https://docs.microsoft.com/en-us/azure/aks/managed-aad). Note that this is incompatible with the legacy AAD. We will use the `v2` token version instead of `v1`.

> If you really need to use `v1` tokens, please let drop us an issue and let us know your use case.
Please refer to the [official docs](https://docs.microsoft.com/en-us/azure/aks/managed-aad) in case of doubt, here we just highlight some important steps during the configuration that will be required in Kubeapps.

First, you need to verify that you have `AKS-managed Azure Active Directory: Enabled`.

![Enabled AKS-managed Azure Active Directory](../../img/azure-00.png)

Then, you have to register an Application. Go to `App registrations` and click on `Register an application`. Enter a `Name` (any name is ok) and a `Redirect URI` (it should be `https://<YOUR_KUBEAPPS_DOMAIN>/oauth2/callback` unless you have manually changed it).

> Replace `<YOUR_KUBEAPPS_DOMAIN>` with your actual Kubeapps domain. Note that you will need to use `https` instead of `http`.
![Registering an Application](../../img/azure-01.png)

Once you got your Application created, click `Overview` to see the `Application (client) ID` and the `Directory (tenant) ID`. You will need these values later.

![Application overview](../../img/azure-02.png)

The next step is to create a secret for the Application. Click on `Certificates & secrets` and then on `New client secret`.

![Creating secret screen](../../img/azure-03.png)

Fill the `Description` and `Expires` fields according to your preferences.

![Creating the secret](../../img/azure-04.png)

Next, the `Value` of the secret will appear and you will be able to copy it. You will need this value later.

![Retrieving the secret value](../../img/azure-05.png)

The following step is to define the permissions that the Application will need. To do so, go to `API permissions` and click `Add a permission`.

![Add permissions screen](../../img/azure-06.png)

Then, in the `APIs my organization uses` enter this value `6dae42f8-4368-4678-94ff-3960e28e3630`. This is a fixed Application ID corresponding to the _Azure Kubernetes Service AAD Server_ globally provided by Azure.

> You can also get this Application ID (`6dae42f8-4368-4678-94ff-3960e28e3630`) by executing `az ad sp list --display-name "Azure Kubernetes Service AAD Server"` and inspecting the `appId` value.
![Selecting the permissions](../../img/azure-07.png)

Next, select the `user.read` permission and click `Add permissions`.

![Selecting user.read permission](../../img/azure-08.png)

Then, go to `Manifest` and change `accessTokenAcceptedVersion` from `null` to `2`. It will make the Application generate `v2` tokens instead of `v1`.

![Editing the manifest](../../img/azure-09.png)

At the end of these steps, you will have created an application, generated a secret, granted it with `6dae42f8-4368-4678-94ff-3960e28e3630/user.read` permissions and changed the token version to `v2`. You also will have the following information:

- `Application (client) ID`, for instance, `<MY-APPLICATION-ID>`.
- `Application secret`, for instance, `<MY-SECRET>`.
- `Directory (tenant) ID`, for instance, `<MY-TENANT-ID>`.

The next step is just configuring Kubeapps to use all these values.

```yaml
frontend:
proxypassAccessTokenAsBearer: true # required to pass the access_token instead of the id_token
authProxy:
enabled: true
cookieSecret: <MY-COOKIE-SECRET> # See https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview/#generating-a-cookie-secret
provider: oidc
clientID: <MY-APPLICATION-ID>
clientSecret: <MY-SECRET>
additionalFlags:
- --oidc-issuer-url=https://login.microsoftonline.com/<MY-TENANT-ID>/v2.0 # required for azure
- --scope=openid email 6dae42f8-4368-4678-94ff-3960e28e3630/user.read # required for azure, exactly this string without modification
```

> Subsitute `<MY-COOKIE-SECRET>`, `<MY-APPLICATION-ID>`,`<MY-SECRET>` and `<MY-TENANT-ID>` with your values.
We highlight here:

- The issuer is `https://login.microsoftonline.com/<MY-TENANT-ID>/v2.0` (replacing `<MY-TENANT-ID>` with your own `Directory (tenant) ID`), since we are using v2 tokens.
- The scope is exactly `openid email 6dae42f8-4368-4678-94ff-3960e28e3630/user.read`.
- Besides using the `openid` and `email` scopes, we also need `6dae42f8-4368-4678-94ff-3960e28e3630/user.read`. This one corresponds to the Application ID of the global _Azure Kubernetes Service AAD Server_. This way, you will able to get the user's email to get access to the protected resource that is AKS.

> In `v1` tokens, you had to pass this value as part of the `--resource=6dae42f8-4368-4678-94ff-3960e28e3630` flag, but in `v2` tokens, this claim is performed just using the scope.
## Azure Active Directory integration (legacy)

For setting up an Azure Kubernetes cluster (aks) with Azure Active Directory (legacy) you can follow [this guide](https://docs.microsoft.com/en-us/azure/aks/azure-ad-integration-cli). At the end of the tutorial you should have an Active Directory Application (Server). That's the Application from which we will get the needed parameters.

- Client-ID: Azure Active Directory server Application ID.
- Client-secret: A "Password" Key of the server Application.
- OIDC Issuer URL: `https://sts.windows.net/<Tenant-ID>/`. The Tenant-ID can be found at `Home > Default Directory - Properties > Directory ID`.

**Note**: If you are using an nginx reverse proxy to get to kubeapps you might need to increase the `proxy_buffer_size` as [Azure's session store is too large for nginx](https://oauth2-proxy.github.io/oauth2-proxy/auth-configuration#azure-auth-provider). Similar changes might also be required for other reverse proxies.
75 changes: 75 additions & 0 deletions docs/user/OIDC/OAuth2OIDC-debugging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Debugging auth failures when using OIDC

## Viewing the JWT id token

The easiest way to check the credential that is being used is to temporarily set the `--set-authorization-header=true` option for the oauth2 proxy of the kubeapps deployment.

```bash
kubectl -n kubeapps patch deployments kubeapps --type=json \
-p '[{"op": "add", "path": "/spec/template/spec/containers/1/args/-", "value": "--set-authorization-header=true" }]'
```

Once the deployment runs a new container with the extra option, Kubeapps will then include the `id_token` that is being used to authenticate you with the Kubernetes api server in the response back to the browser.

To view the token, in your browser debugger's Network tab, watch for the request to `/api/clusters/default` or similar which will have a 40X status. Click on this request to view the headers and in the Response headers look for the `Authorization` header. The bearer token of the value will be the base64-encoded `id_token`. Copy the token as shown:

![Copying the bearer token](../../img/oidc-debug-copy-bearer-token.png)

## Testing the JWT Token directly with your Kubernetes cluster

If the credential is for a real environment, you can decode it on a command line with:

```bash
export TOKEN=<paste value here>
echo $TOKEN | base64 -d
```

to check that the user and groups associated with the credential are what you expect for your Kubernetes server. If the credential is for a test environment, you can instead just paste the value into a site like `https://jwt.io` to have it decoded and neatly formatted.

If the user and group values are what you expected you can then confirm that the appropriate `RoleBinding` or `ClusterRoleBinding` is specified on your cluster.

To use the token value with a query directly to your Kubernetes api server (ie. to verify that Kubeapps isn't actually involved), you can:

```bash
curl -H "Authorization: Bearer $TOKEN" https://my.k8s.cluster/
```

You should see the same status that you saw in the browser (as Kubeapps is using the token in exactly the same way).

## Checking your Kubernetes cluster OIDC options

Once you can reproduce the issue, there are a couple of possibilities for the cause which commonly trip people up.
One common issue is that the Kubernetes cluster's api server is not configured for oidc (some people don't realise this is necessary). This is easy to check by grepping for `oidc` in the api server pod output, for example, if your cluster _is_ configured for OpenID Connect, you should see something like:

```bash
$ kubectl -n kube-system get po -l component=kube-apiserver -o yaml | grep oidc
- --oidc-ca-file=/etc/kubernetes/pki/apiserver.crt
- --oidc-client-id=default
- --oidc-groups-claim=groups
- '--oidc-groups-prefix=oidc:'
- --oidc-issuer-url=https://172.18.0.2:32000
- --oidc-username-claim=email
- '--oidc-username-prefix=oidc:'
```

## Checking your OIDC prefix

Another common point of confusion is the `--oidc-username-prefix` option specified above. If it is set to a value such as `oidc:` (or using a [default value](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#configuring-the-api-server) without being set explicitly), then a JWT token identifying a user of `myname@example.com` will require the RBAC RoleBinding to specify the user as `oidc:myname@example.com` to match the OIDC user with the defined RBAC.

## Checking the logs of your Kubernetes API server

Finally, if none of the above are relevant to your issue, you can check the logs of the Kubernetes API server deployment for OIDC-related lines at the time of your login attempt. These may show a configuration issue with the API server itself.

## User automatically logged out from Kubeapps Console

When using the default auth proxy, some users may experience the behavior where they are automatically logged out from the console.
Prior to the Kubeapps chart version 7.1.0, the auth proxy configuration did not include a default `--cookie-refresh` value to refresh the access/openid token and so the console will logout once the token expires. In the case of Keycloak for example, this can happen quickly as the default access token expiration is 5m.

To avoid this issue, you can do one of the following:

- upgrade the Kubeapps chart to version 7.1.0+ which sets a default of `--cookie-refresh=2m` and exposes the value in the chart values as `authProxy.cookieRefresh`.
- update Kubeapps by adding the option `--cookie-refresh=2m` to `authProxy.additionalFlags`.

The duration for the refresh must be less than the access/openid expiration time configured in the OAuth2/OIDC provider.

**Note**: If you have configured a provider other than `oidc` for oauth2-proxy, the issue may still occur even after upgrading or updating Kubeapps as OAuth2 Proxy does not support cookie-refresh for all providers. See [OAuth2 Proxy Configuration Overview](https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview/#footnote1) for the list of supported providers.
9 changes: 9 additions & 0 deletions docs/user/OIDC/OAuth2OIDC-dex.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Configuring Dex as an OIDC provider

This document explains how to configure Dex as an OIDC provider (check general information and pre-requisites for [using an OAuth2/OIDC Provider with Kubeapps](../using-an-OIDC-provider.md)).

For Dex, you can find the parameters that you need to set in the configuration (a ConfigMap if Dex is deployed within the cluster) that the server reads the configuration from. Note that since Dex is only a connector you need to configure it with some third-party credentials that may be a client-id and client-secret as well. Don't confuse those credentials with the ones of the application that you can find under the `staticClients` section.

- **Client-ID**: Static client ID.
- **Client-secret**: Static client secret.
- **OIDC Issuer URL**: Dex URL (i.e. https://dex.example.com:32000).
9 changes: 9 additions & 0 deletions docs/user/OIDC/OAuth2OIDC-google-openid-connect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Configuring Google OIDC as an OIDC provider

This document explains how to configure Google OIDC as an OIDC provider (check general information and pre-requisites for [using an OAuth2/OIDC Provider with Kubeapps](../using-an-OIDC-provider.md)).

In the case of Google we can use an OAuth 2.0 client ID. You can find more information [here](https://developers.google.com/identity/protocols/OpenIDConnect). In particular we will use a "Web Application".

- **Client-ID**: `<abc>.apps.googleusercontent.com`.
- **Client-Secret**: Secret for the Web application.
- **OIDC Issuer URL**: https://accounts.google.com.
9 changes: 9 additions & 0 deletions docs/user/OIDC/OAuth2OIDC-keycloak.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Configuring Keycloak as an OIDC provider

This document explains how to configure Keycloak as an OIDC provider (check general information and pre-requisites for [using an OAuth2/OIDC Provider with Kubeapps](../using-an-OIDC-provider.md)).

In the case of Keycloak, you can find the parameters in the Keycloak admin console:

- **Client-ID**: Keycloak client ID.
- **Client-secret**: Secret associated to the client above.
- **OIDC Issuer URL**: `https://<keycloak.domain>/auth/realms/<realm>`.

0 comments on commit 09161da

Please sign in to comment.