multiple IDPs and identity transformations docs

This commit is contained in:
Ryan Richard 2023-09-13 14:33:53 -07:00
parent 06d456fc87
commit 54fb03153a
14 changed files with 492 additions and 23 deletions

View File

@ -17,7 +17,7 @@ environments with zero configuration.
Pinniped is composed of two parts.
1. The Pinniped Supervisor is an OIDC server which allows users to authenticate
with an external identity provider (IDP), and then issues its own federation ID tokens
with external identity providers (IDP), and then issues its own federation ID tokens
to be passed on to clusters based on the user information from the IDP.
1. The Pinniped Concierge is a credential exchange API which takes as input a
credential from an identity source (e.g., Pinniped Supervisor, proprietary IDP),

View File

@ -46,6 +46,11 @@ framework (e.g. Spring, Rails, Django, etc.) to implement authentication. The Su
- Clients must use `query` as the
[response_mode](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest) at the authorization endpoint,
or not specify the `response_mode` param, which defaults to `query`.
- If the Supervisor's FederationDomain was configured with explicit `identityProviders` in its spec, then the
client must send an extra parameter on the initial authorization request to indicate which identity provider
the user would like to use when authenticating. This parameter is called `pinniped_idp_name` and the value
of the parameter should be set to the `displayName` of the identity provider as it was configured on the
FederationDomain.
Most web application frameworks offer all these capabilities in their OAuth2/OIDC libraries.

View File

@ -76,6 +76,11 @@ One flag of note is `--upstream-identity-provider-flow browser_authcode` to choo
(the default for OIDCIdentityProviders), and `--upstream-identity-provider-flow cli_password` to choose end-user `kubectl`
login via CLI username/password prompts (the default for LDAPIdentityProviders and ActiveDirectoryIdentityProviders).
If the cluster is using a Pinniped Supervisor's FederationDomain to provide authentication services,
and if that FederationDomain allows multiple identity providers, then you will need to specify which identity provider
you would like to use in the resulting kubeconfig with the `--upstream-identity-provider-name` and/or `--upstream-identity-provider-type` flags.
You may call `pinniped get kubeconfig` multiple times to generate multiple kubeconfigs for the cluster.
## Use the generated kubeconfig with `kubectl` to access the cluster
A cluster user will typically be given a Pinniped-compatible kubeconfig by their cluster admin. They can use this kubeconfig

View File

@ -0,0 +1,414 @@
---
title: Configure Identity Providers (IDPs) on a FederationDomain
description: Learn how to use one or more identity providers, and identity transformations and policies, on a FederationDomain.
cascade:
layout: docs
menu:
docs:
name: IDPs on FederationDomains
weight: 20
parent: howto-configure-supervisor
---
This guide explains how to associate one or more external identity providers (IDPs) with a FederationDomain.
It also details how to configure identity transformations and identity policies for those identity
providers.
## Prerequisites
This how-to guide assumes that you have already [installed the Pinniped Supervisor]({{< ref "install-supervisor" >}})
and have already read the guide about how to [configure the Supervisor as an OIDC issuer]({{< ref "configure-supervisor" >}}).
This guide focuses on the use of the `spec.identityProviders` setting on the
[FederationDomain](https://github.com/vmware-tanzu/pinniped/blob/main/generated/{{< latestcodegenversion >}}/README.adoc#federationdomain)
CRD.
Note that the `spec.identityProviders` setting on the FederationDomain CRD was added in v0.26.0 of Pinniped.
This guide assumes that you are using at least that version.
## Summary
External identity providers may be configured in the Supervisor by creating OIDCIdentityProvider,
ActiveDirectoryIdentityProvider, or LDAPIdentityProvider resources in the same namespace as the Supervisor.
There are two ways to configure which of these external identity providers shall be used by a FederationDomain.
1. When there is no `spec.identityProviders` configured on a FederationDomain, then the FederationDomain will use
the one and only identity provider that is configured in the same namespace. This provides backwards compatibility
with older configurations of Supervisors from before the `spec.identityProviders` setting was added to the
FederationDomain CRD. There must be exactly one OIDCIdentityProvider,
ActiveDirectoryIdentityProvider, or LDAPIdentityProvider resource in the same namespace as the Supervisor.
If there are no identity provider resources, or if there are more than one, then the FederationDomain will
not allow any users to authenticate, and a error message will be shown in its `status`.
2. When `spec.identityProviders` is explicitly configured on a FederationDomain, then the FederationDomain will
allow clients to use any of those identity providers to authenticate. In this case, you may optionally also configure
identity transformations and policies that the FederationDomain should apply to each of these identity providers
(see below for details). When using the `pinniped get kubeconfig` CLI command, you will need to choose for
which identity provider you would like to generate a kubeconfig. A cluster may have multiple kubeconfigs,
e.g. one for each identity provider.
The remainder of this guide focuses on the second case, and describes the settings that may be used to explicitly
configure which identity providers are used, along with optional identity transformations and policies.
## Configuring a FederationDomain's identity providers
A user may authenticate to a FederationDomain using any of the IDPs configured in the FederationDomain's
`spec.identityProviders`. To add IDPs to this list, simply configure each as a reference to the type and name
of the resource. The identity provider resources must be in the same namespace where the Supervisor was
[installed]({{< ref "docs/howto/install-supervisor.md" >}}).
Here is an example FederationDomain with two IDPs configured.
```yaml
apiVersion: config.supervisor.pinniped.dev/v1alpha1
kind: FederationDomain
metadata:
name: my-provider
# Must be in the same namespace where the Supervisor is installed.
namespace: pinniped-supervisor
spec:
issuer: https://my-issuer.example.com/any/path
tls:
secretName: my-tls-cert-secret
# Available identity providers are selected here...
identityProviders:
- displayName: ActiveDirectory for Admins
objectRef:
apiGroup: idp.supervisor.pinniped.dev
kind: ActiveDirectoryIdentityProvider
name: ad-for-admins
- displayName: Okta for Developers
objectRef:
apiGroup: idp.supervisor.pinniped.dev
kind: OIDCIdentityProvider
name: okta-for-developers
```
Now users may use either of the above identity providers to authenticate. You can create
kubeconfigs for both IDPs for each cluster by using `pinniped get kubeconfig` twice for
each cluster.
## Important consideration when using multiple identity providers: conflicting usernames and group names
When multiple identity providers are configured onto a FederationDomain, then a user may use any of those
providers to authenticate to that FederationDomain. Since an identity in Kubernetes is simply a username string
and a list of group name strings, it is very important to consider what will happen if two users each authenticate
to a FederationDomain using different identity providers.
1. If two users are assigned the same username string as a result of authenticating, then those two users will be
considered the *same user* by Kubernetes, regardless of which IDP they came from.
2. If two users are assigned the same group name string as a result of authenticating, then those two users will be
considered to *both belong to same group* by Kubernetes, regardless of which IDP they came from.
This may or may not be desirable. If the two identity providers are intended to represent distinct, non-overlapping
sets of users, then it is not desirable for their usernames and group names to conflict by being identical.
On the other hand, if two identity providers contain the same sets of users, and when those users authenticate
then your intention is that they are the same identity, then it may be desirable.
Let's consider several example use cases.
- Imagine two IDPs in which usernames and group names are assigned to users by their administrators
separately, with no coordination between them. In this case, a user named "ryan" from one IDP is probably not
the same human as the user named "ryan" from the other IDP. The group named "admins" from one IDP may
have a totally different intended meaning then the group named "admins" from the other IDP.
In this case, it is not desirable for usernames and group names from one IDP to conflict with the usernames
and group names from the other IDP.
- Imagine two IDPs which both use corporate email addresses as usernames. These email addresses are
assigned by IT and are not adjustable by the individual users. In this case, it may be desirable for a human
user to be able to authenticate using either IDP and end up being assigned the same username in
Kubernetes clusters either way. However, it may or may not be the case that the user's group names from one IDP
are meant to represent the same Kubernetes groups as the same group names from the other IDP.
In this case, it is not a concern for usernames from one IDP to conflict with the usernames from the other IDP,
however it still might be a concern for group names from one IDP to conflict with the group names from the other IDP.
You can easily add configuration to the FederationDomain to handle username and group name conflicts.
1. When it is not desirable for usernames to conflict, then a simple solution is to use identity transformations
to change all usernames to have a prefix which is unique to each IDP within that FederationDomain. For example,
usernames `ldap:ryan` and `gitlab:ryan` will be considered two different users by Kubernetes.
2. Similarly, when it is not desirable for group names to conflict, then a simple solution is to use identity transformations
to change all group names to have a prefix which is unique to each IDP within that FederationDomain.
Refer to the next section to learn about how to configure identity transformations to add prefixes to usernames
and group names.
## Identity transformations and policies
When a user authenticates, the configuration of the OIDCIdentityProvider, ActiveDirectoryIdentityProvider, or
LDAPIdentityProvider resource determines how the user's username and group names will be extracted from the external
identity provider in a protocol-specific way (e.g. via OIDC ID token claims or LDAP record attributes).
Then, operating on the username and group names extracted from the external IDP:
- Identity **transformations** can change either the user's username or group names.
- Identity **policies** can reject the user's authentication based on their username and/or groups.
Identity transformations and policies are configured on the FederationDomain, so they are specific to that specific
FederationDomain's usage of the external identity provider.
Transformations and policies are configured using the Common Expression Language (CEL) programming language.
They are configured as a list, and they will be executed in the order specified. The output of each transformation
or policy expression may impact the input values for the next expression from the list.
Pinniped's implementation of CEL expressions includes the
[standard language features](https://github.com/google/cel-spec/blob/master/doc/langdef.md)
as well as [the string extensions](https://github.com/google/cel-go/tree/master/ext#strings).
### Pipelines of identity transformation and policy `expressions`
There are three types of transformation expressions:
- `username/v1` are expressions which may change the user's username. These expressions must return a string,
and the value of the string will be the user's username. Returning an empty string or a string that contains
only whitespace characters will cause an authentication error. Returning the value of the `username` variable
unmodified will leave the username unchanged.
- `groups/v1` are expressions which may change the group names of the groups to which the user belongs.
These expressions must return a list of strings. The returned list may be empty. The returned list will
be the names of the groups to which the user belongs. Returning the value of the `groups` variable
unmodified will leave the groups unchanged.
- `policy/v1` are expressions which may reject the user's authentication based on their username and/or groups.
These expressions must return a boolean. Returning true has no impact on the user's authentication
and will therefore allow the user's authentication to continue. Returning true also has no impact
on the username or group names. Returning false will the reject user's authentication
and the user will see the error message configured for that policy expression (or a default error message).
Rejecting a user's authentication prevents the user from authenticating into every cluster
which uses this FederationDomain for identity services. This happens before
Kubernetes RBAC policies are considered by the individual clusters. Therefore, this is a authentication-level
rejection, not an authorization check.
All three transformation expression types are written using CEL expressions. They are declared as a list of transformations and policies.
Each time a user attempts to authenticate, and each time a user's session is automatically refreshed periodically,
the list is evaluated in the order that it was declared.
`username/v1` expressions may change the username that is passed to the next expressions.
`groups/v1` expressions may change the group names that are passed to the next expressions.
`policy/v1` expressions may halt the processing of further expressions when they reject the authentication.
Because each expression in the list can pass information to the following expressions via its return values,
the list of expressions acts like a "pipeline".
Any unexpected runtime evaluation errors (e.g. division by zero) cause the authentication to fail.
The following variables are available to each expression, regardless of type:
- `username` is a string. The value will be the username of the user who is attempting to authenticate.
Its value will never be the empty string. The value of `username` may have been modified by the
previous `username/v1` transformations in the pipeline.
- `groups` is a list of strings. The value will be the list of group names to which
the user attempting to authenticate belongs. The list may be empty, meaning that the user does not belong to any groups.
The value of `groups` may have been modified by the previous `groups/v1` transformations in the pipeline.
- `strConst` contains the string constants declared for those transformations, and each string
constant can be referenced using its name e.g. a string constant called `x` can be referenced as `strConst.x`
- `strListConst` contains the list constants declared for those transformations, and each list
constant can be referenced using its name e.g. a list constant called `x` can be referenced as `strListConst.x`
Each identity provider selected for use in a FederationDomain may declare its own list of expressions.
The expressions will only be applied when that FederationDomain uses that identity provider.
### Transformation pipelines `constants`
Rather than repeating the same special strings across multiple expressions, you may optionally configure
string constants and string list constants for your transformation pipeline.
For example, if there is a special username or group name which will be used for comparisons in your expressions,
then you might like to declare it as a string constant. If there is a special list of usernames or group names
which will be used for comparisons then you might like to declare the list as a constant.
Constants are available in every expression of the pipeline.
### Transformation pipelines `examples`
Because the pipelines of expressions may behave differently based on their inputs, you may also optionally configure
`examples` to demonstrate how a pipeline is expected to behave for various possible input scenarios. These examples
act as living documentation for your fellow administrators, and also act as unit tests for your CEL expression code.
Each example declares inputs for the whole pipeline of expressions, and also declares the expected results of the
entire pipeline running on those inputs. The inputs are examples of the username and list of group names that might
be determined by the related OIDCIdentityProvider, ActiveDirectoryIdentityProvider, or LDAPIdentityProvider resource.
The expected outputs are the username and list of group names, or the authentication rejection, for which your pipeline
should result upon the given inputs.
If any example does not behave as expected, Pinniped will mark the whole FederationDomain with an error in
its `status` and users will not be allowed to use the FederationDomain to authenticate until the error is corrected.
### Putting it all together: an example of a transformation pipeline configuration
The following example is contrived to demonstrate every feature of the `transforms` configuration
(constants, expressions, and examples). It is likely more complex than a typical configuration.
Documentation for each of the fields shown below can be found in the API docs for the
[FederationDomain](https://github.com/vmware-tanzu/pinniped/blob/main/generated/{{< latestcodegenversion >}}/README.adoc#federationdomain)
CRD.
```yaml
kind: FederationDomain
apiVersion: config.supervisor.pinniped.dev/v1alpha1
metadata:
name: demo-federation-domain
namespace: pinniped-supervisor
spec:
issuer: https://issuer.example.com/demo-issuer
tls:
secretName: my-federation-domain-tls
identityProviders:
- displayName: ActiveDirectory for Admins
objectRef:
apiGroup: idp.supervisor.pinniped.dev
kind: ActiveDirectoryIdentityProvider
name: ad-for-admins
transforms:
constants:
- name: prefix
type: string
stringValue: "ad:"
- name: onlyIncludeGroupsWithThisPrefix
type: string
stringValue: "kube/"
- name: mustBelongToOneOfThese
type: stringList
stringListValue:
- "kube/admins"
- "kube/developers"
- "kube/auditors"
- name: additionalAdmins
type: stringList
stringListValue:
- "ryan@example.com"
- "ben@example.com"
- "josh@example.com"
expressions:
# This expression runs first, so it operates on the unmodified usernames
# and groups as extracted from AD by the ActiveDirectoryIdentityProvider.
# It rejects auth for any user who does not belong to certain groups.
# When it returns true, the pipeline continues. When it returns false,
# the pipeline stops and the auth is rejected.
- type: policy/v1
expression: 'groups.exists(g, g in strListConst.mustBelongToOneOfThese)'
message: "Only users in kube groups are allowed to authenticate"
# This expression runs second, and the previous expression was a policy
# (which cannot change username or groups), so this expression also
# operates on the unmodified usernames and groups as extracted from the
# IDP. For certain users, this adds a new group to their list of groups.
- type: groups/v1
expression: 'username in strListConst.additionalAdmins ? groups + ["kube/admins"] : groups'
# This expression runs next. Due to the expression above, this expression
# operates on the original username, and on a potentially changed list of
# groups. This drops all groups which do not start with a certain prefix.
- type: groups/v1
expression: 'groups.filter(group, group.startsWith(strConst.onlyIncludeGroupsWithThisPrefix))'
# Due to the expressions above, this expression operates on the original
# username, and on a potentially changed list of groups. This
# unconditionally prefixes the username.
- type: username/v1
expression: 'strConst.prefix + username'
# The expressions above have already changed the username and might have
# changed the groups before this expression runs. This unconditionally
# prefixes all group names.
- type: groups/v1
expression: 'groups.map(group, strConst.prefix + group)'
examples:
- username: "ryan@example.com"
groups: [ "kube/developers", "kube/auditors", "non-kube-group" ]
expects:
username: "ad:ryan@example.com"
groups: [ "ad:kube/developers", "ad:kube/auditors", "ad:kube/admins" ]
- username: "someone_else@example.com"
groups: [ "kube/developers", "kube/other", "non-kube-group" ]
expects:
username: "ad:someone_else@example.com"
groups: [ "ad:kube/developers", "ad:kube/other" ]
- username: "paul@example.com"
groups: [ "kube/other", "non-kube-group" ]
expects:
rejected: true
message: "Only users in kube groups are allowed to authenticate"
```
### Some useful features of CEL
Pinniped uses the cel-go library to implement CEL expressions.
It includes the CEL [standard language features](https://github.com/google/cel-spec/blob/master/doc/langdef.md)
as well as the [string extensions](https://github.com/google/cel-go/tree/master/ext#strings).
This section will attempt to highlight some of the useful features of CEL, but is not intended to
be a comprehensive overview of everything that you can use in CEL expressions.
- CEL has several [built-in functions](https://github.com/google/cel-spec/blob/master/doc/langdef.md) which may be called on strings:
`contains`, `startsWith`, `endsWith`, and `matches` (for regex matching), e.g. `x.contains("some-substring")` for a string `x`
- The [string extensions](https://github.com/google/cel-go/tree/master/ext#strings)
include several additional functions which may be called on strings:
`charAt`, `indexOf`, `join`, `lastIndexOf`, `lowerAscii`, `quote`, `replace`, `split`, `substring`,
`trim`, `upperAscii`, and `reverse`
- CEL has [several useful functions which can be called on lists](https://github.com/google/cel-spec/blob/master/doc/langdef.md#macros):
- `map` and `filter` can be used to return a modified copy of a list
- `exists`, `exists_one`, and `all` can be used to perform boolean checks on the contents of a list
- Equality of strings and lists can be compared with the `==` and `!=` operators
- Lexicographic ordering of strings can be compared with `<`, `<=`, `>`, and `>=` operators
- Concatenation of two strings or two lists can be performed with the `+` operator
- List membership may be tested using the `in` operator, e.g. `"foo" in x` for a list `x`
- CEL does not have an `if` statement, but it does include a ternary operator to achieve the same result:
`boolean_expression ? when_true_expression : when_false_expression`. These may be nested,
e.g. the `when_true_expression` may itself be another ternary expression.
- Boolean operators include `&&` (and), `||` (or), `!` (not), `in` (inclusion in a list), and the ternary `?:`
- String literals can be quoted using single quotes `''` or double quotes `""` and [may contain quoted special characters](https://github.com/google/cel-spec/blob/master/doc/langdef.md#string-and-bytes-values)
- List literals can be written as a comma-seperated list of elements within enclosing `[]`
- `[]` may be used to index into a list, e.g. `x[4]` for a list `x`
- `size(x)` returns the length of a string `x` or the length of a list `x`
### Example expressions
Below are some examples of using expressions for identity transformations and policies.
Note that any of the string literals in these examples could be replaced by string
constants, i.e. `"prefix"` could instead refer to a constant like `strConst.prefix`.
Any literal list of strings could be replaced by a string list constant, e.g.
`["allowed1", "allowed2"]` could instead refer to a constant like `strListConst.allowedGroups`.
#### Example `username/v1` expressions
- Prefix the username:
- `"prefix" + username`
- Suffix the username:
- `username + "suffix"`
- Down-case the username (be careful that this will cause "Ryan" and "ryan" to become the same user in Kubernetes):
- `username.lowerAscii()`
#### Example `groups/v1` expressions
- Prefix all group names:
- `groups.map(g, "prefix" + g)`
- Suffix all group names:
- `groups.map(g, g + "suffix")`
- Filter groups to remove any group names that start with `system:` which is a prefix that has a special meaning to Kubernetes:
- `groups.filter(group, !group.startsWith("system:"))`
- Filter groups to keep only groups with a certain prefix:
- `groups.filter(group, group.startsWith("kube/"))`
- Down-case all group names (be careful that this will cause "Admins" and "admins" to become the same group in Kubernetes):
- `groups.map(g, g.lowerAscii())`
- Filter groups based on an allow list, dropping any group names except those included in the allow list:
- `groups.filter(g, g in ["allowed1", "allowed2"])`
- Filter groups based on a disallow list, dropping any group names included in the disallow list:
- `groups.filter(g, !(g in ["dropped1", "dropped2"]))`
- Filter groups based on a list of disallowed prefixes, dropping any groups which have one of the disallowed prefixes:
- `groups.filter(group, !(["disallowed-prefix1:", "disallowed-prefix2:"].exists(prefix, group.startsWith(prefix))))`
- Unconditionally add a group:
- `groups + ["new-group"]`
- Add a group, but only if the user already belongs to another specific group:
- `"other" in groups ? groups + ["new-group"] : groups`
- Rename a particular group if the user belongs to that group:
- `groups.map(g, g == "other" ? "other-renamed" : g)`
- Unconditionally drop all groups:
- `[]`
#### Example `policy/v1` expressions
- User must belong to a particular group:
- `"required-group" in groups`
- User must belong to at least one of the groups in a list:
- `groups.exists(g, g in ["foobar", "foobaz", "foobat"])`
- User must belong to all the groups in a list:
- `["foobar", "foobaz", "foobat"].all(g, g in groups)`
- User must not belong to any of the groups in a list:
- `!groups.exists(g, g in ["foobar", "foobaz"])`
- Certain users are allowed to authenticate and everyone else is rejected:
- `username in ["foobar", "foobaz"]`
- Certain users are not allowed to authenticate:
- `!(username in ["foobar", "foobaz"])`
## Next steps
Next,
[configure the Concierge to use the Supervisor for authentication]({{< ref "configure-concierge-supervisor-jwt" >}})
on each cluster.

View File

@ -11,8 +11,8 @@ menu:
aliases:
- /docs/howto/configure-supervisor-with-activedirectory/
---
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting a single
"upstream" identity provider to many "downstream" cluster clients.
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting
"upstream" identity providers to many "downstream" cluster clients.
This guide shows you how to configure the Supervisor so that users can authenticate to their Kubernetes
cluster using their identity from Active Directory.

View File

@ -11,8 +11,8 @@ menu:
aliases:
- /docs/howto/configure-supervisor-with-auth0/
---
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting a single
"upstream" identity provider to many "downstream" cluster clients.
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting
"upstream" identity providers to many "downstream" cluster clients.
This guide shows you how to configure the Supervisor so that users can authenticate to their Kubernetes
cluster using their Auth0 credentials.

View File

@ -12,8 +12,8 @@ aliases:
- /docs/howto/configure-supervisor-with-dex/
---
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting a single
"upstream" identity provider to many "downstream" cluster clients.
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting
"upstream" identity providers to many "downstream" cluster clients.
This guide shows you how to configure the Supervisor so that users can authenticate to their Kubernetes
cluster using Dex and Github.

View File

@ -11,8 +11,8 @@ menu:
aliases:
- /docs/howto/configure-supervisor-with-gitlab/
---
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting a single
"upstream" identity provider to many "downstream" cluster clients.
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting
"upstream" identity providers to many "downstream" cluster clients.
This guide shows you how to configure the Supervisor so that users can authenticate to their Kubernetes
cluster using their GitLab credentials.

View File

@ -11,8 +11,8 @@ menu:
aliases:
- /docs/howto/configure-supervisor-with-jumpcloudldap/
---
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting a single
"upstream" identity provider to many "downstream" cluster clients.
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting
"upstream" identity providers to many "downstream" cluster clients.
[JumpCloud](https://jumpcloud.com) is a cloud-based service which bills itself as
"a comprehensive and flexible cloud directory platform". It includes the capability to act as an LDAP identity provider.

View File

@ -11,8 +11,8 @@ menu:
aliases:
- /docs/howto/configure-supervisor-with-okta/
---
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting a single
"upstream" identity provider to many "downstream" cluster clients.
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting
"upstream" identity providers to many "downstream" cluster clients.
This guide shows you how to configure the Supervisor so that users can authenticate to their Kubernetes
cluster using their Okta credentials.

View File

@ -11,8 +11,8 @@ menu:
aliases:
- /docs/howto/configure-supervisor-with-openldap/
---
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting a single
"upstream" identity provider to many "downstream" cluster clients.
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting
"upstream" identity providers to many "downstream" cluster clients.
[OpenLDAP](https://www.openldap.org) is a popular open source LDAP server for Linux/UNIX.

View File

@ -11,8 +11,8 @@ menu:
aliases:
- /docs/howto/configure-supervisor-with-workspace_one_access/
---
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting a single
"upstream" identity provider to many "downstream" cluster clients.
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting
"upstream" identity providers to many "downstream" cluster clients.
This guide shows you how to configure the Supervisor so that users can authenticate to their Kubernetes
cluster using their [Workspace ONE Access](https://www.vmware.com/products/workspace-one/access.html) credentials.

View File

@ -12,8 +12,8 @@ aliases:
- /docs/howto/configure-supervisor/
---
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting a single
"upstream" identity provider to many "downstream" cluster clients. When a user authenticates, the Supervisor can issue
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting
"upstream" identity providers to many "downstream" cluster clients. When a user authenticates, the Supervisor can issue
[JSON Web Tokens (JWTs)](https://tools.ietf.org/html/rfc7519) that can be [validated by the Pinniped Concierge]({{< ref "configure-concierge-jwt" >}}).
This guide explains how to expose the Supervisor's REST endpoints to clients.
@ -246,10 +246,54 @@ spec:
# for the HTTPS endpoints served by this OIDC Provider.
tls:
secretName: my-tls-cert-secret
# Configure which identity providers (OIDCIdentityProvider,
# ActiveDirectoryIdentityProvider, or LDAPIdentityProvider)
# shall be used by this FederationDomain.
identityProviders:
# See the "IDPs on FederationDomains" Supervisor configuration guide
# for details on how to configure this section of the FederationDomain's
# spec.
```
You can create multiple FederationDomains as long as each has a unique issuer string.
### How FederationDomains Work
Each FederationDomain can be used to provide access to a set of Kubernetes clusters for a set of user identities.
A FederationDomain will allow the same set of users to authenticate into all Kubernetes clusters
which choose to trust that FederationDomain to provide authentication services. Authenticating to a FederationDomain
will only provide access to those clusters which choose to trust that FederationDomain, and will not provide access
to any clusters that are trusting other FederationDomains. Therefore, FederationDomains are a means of providing
authentication isolation.
You can create multiple FederationDomains in a single Pinniped Supervisor, as long as each has a unique issuer string.
When a user authenticates into any cluster that chooses to trust the FederationDomain for authentication,
then the user has started a single sign-on session with that FederationDomain which will last approximately 9 hours.
The user will not need to manually authenticate again into any cluster any cluster that chooses to trust the
FederationDomain for authentication until the session expires. Behind the scenes, the user's client (e.g. `kubectl`)
will only be given short-lived access to each cluster (approximately 5 minutes), but will automatically refresh those
credentials without the need for user interaction. During each refresh, the Supervisor will perform checks against
the external identity provider to determine if the user's session should be allowed to continue.
A user may have active sessions with multiple FederationDomains at the same time, but each will require authenticating
separately to start the single sign-on session with that FederationDomain.
Technically, each FederationDomain is a separate OIDC issuer which serves multiple REST endpoints to clients, such
as the Pinniped CLI. The tokens issued by each FederationDomain are signed by that FederationDomain and cannot
be used by any other FederationDomain, which provides the isolation properties of the FederationDomain concept.
Any Kubernetes cluster can choose to trust a FederationDomain to provide user authentication
for that cluster by using the FederationDomain its OIDC issuer for JSON Web Token (JWT) formatted ID tokens.
This can be done by installing the Pinniped Concierge on each cluster and
[configuring the Concierge to use the Supervisor for authentication]({{< ref "configure-concierge-supervisor-jwt" >}})
on each cluster. Alternatively, it can be done by [configuring the Kubernetes API server on each cluster to use
the FederationDomain as its OIDC issuer]({{< ref "../../tutorials/supervisor-without-concierge-demo" >}}).
When two FederationDomains use the same hostname in the `spec.issuer`, then:
1. They must use different paths in their `spec.issuer` URLs to differentiate them from each other.
2. They must use the same `tls.secretName` if they both configure a `tls.secretName` (see below for details of TLS configuration).
The Supervisor uses the hostname on the each incoming request to determine which TLS certificate to serve for that
request, and then it uses the path to determine which FederationDomain should serve the request if there are multiple
FederationDomains with the same hostname.
### Configuring TLS for the Supervisor OIDC endpoints
@ -295,6 +339,7 @@ should be signed by a certificate authority that is trusted by their browsers.
## Next steps
Next, configure an OIDCIdentityProvider, ActiveDirectoryIdentityProvider, or an LDAPIdentityProvider for the Supervisor
(several examples are available in these guides). Then
(several examples are available in these guides). Then learn [how to configure a FederationDomain to use one or more
identity providers]({{< ref "configure-supervisor-federationdomain-idps" >}}). And finally,
[configure the Concierge to use the Supervisor for authentication]({{< ref "configure-concierge-supervisor-jwt" >}})
on each cluster!
on each cluster.

File diff suppressed because one or more lines are too long