The OpenID Connect Webhook Authenticator allows Kubernetes cluster administrators to dynamically register new OpenID Connect providers in their clusters to use for kube-apiserver authentication.
Note: This repository still in
alpha
stage and in active development. It should not be used in production. The API can change without any backwards compatibility.
In Kubernetes, only a single OpenID Connect authenticator can be used for end-users to authenticate.
To workaround this limitations, a Webhook Token Authentication can be configured. The Kube APIServer then sends the Bearer Tokens (id_token) to an external webhook for validation:
{
"apiVersion": "authentication.k8s.io/v1beta1",
"kind": "TokenReview",
"spec": {
"token": "(BEARERTOKEN)"
}
}
Where upon verification, the remote webhook returns the identity of the user (if authentication succeeds):
{
"apiVersion": "authentication.k8s.io/v1beta1",
"kind": "TokenReview",
"status": {
"authenticated": true,
"user": {
"username": "[email protected]",
"uid": "42",
"groups": [
"developers",
"qa"
],
"extra": {
"extrafield1": [
"extravalue1",
"extravalue2"
]
}
}
}
}
This repository is the out-of tree implementation of Dynamic Authentication KEP.
- Establish trust relationship between different Kubernetes clusters using Service Account Token Volume Projection and Service Account Issuer Discovery.
- Offer cluster admins the option to dynamically allow users from other OIDC IDPs to authenticate against their
kube-apiserver
.
This webhook is a Kubernetes controller that acts on OpenIDConnect
resources e.g:
apiVersion: authentication.gardener.cloud/v1alpha1
kind: OpenIDConnect
metadata:
name: foo
spec:
issuerURL: https://foo.bar
clientID: some-client-id
usernameClaim: email
usernamePrefix: "test-"
groupsClaim: groups
groupsPrefix: "baz-"
supportedSigningAlgs:
- RS256
requiredClaims:
baz: bar
caBundle: LS0tLS1CRUdJTiBDRVJU...base64-encoded CA certs for issuerURL.
Note: The fields in the specification corresponds to the kube-apiserver OIDC flags.
The flow is following:
- Admin adds a new
OpenIDConnect
to the cluster. - The webhook controller watches for changes on this resource and does OIDC discovery. The OIDC provider's configuration has to be accessible under the
spec.issuerURL
with a well-known path (.well-known/openid-configuration). - The webhook controller uses the
jwks_uri
obtained from the OIDC providers configuration, to fetch the OIDC provider's public keys from that endpoint. - The webhook controller uses those keys, issuer, client_id and other settings to add OIDC authenticator to a in-memory list of Token Authenticators.
An overview of the controller:
When a user wants to authenticate to the kube-apiserver
via this new Custom OpenIDConnect IDP:
-
The user authenticates in Custom IDP.
-
id_token
is obtained from Custom IDP (e.g.ddeewfwef...
). -
The user uses
id_token
to perform an API call to Kube APIServer. -
As the
id_token
is not matched by any build-in or configured authenticators in the Kube APIServer, it is send to OpenID Connect Webhook Authenticator for validation.{ "TokenReview": { "kind": "TokenReview", "apiVersion": "authentication.k8s.io/v1", "spec": { "token": "ddeewfwef..." } } }
-
The webhook then iterates over all registered
OpenIDConnect
Token authenticators and tries to validate the token. -
Upon a successful validation it returns the
TokenReview
with user, groups and extra parameters:{ "TokenReview": { "kind": "TokenReview", "apiVersion": "authentication.k8s.io/v1", "spec": { "token": "ddeewfwef..." }, "status": { "authenticated": true, "user": { "username": "[email protected]", "groups": [ "test-some-group" ], "extra": { "gardener.cloud/authenticator/name": [ "gardener" ], "gardener.cloud/authenticator/uid": [ "e5062528-e5a4-4b97-ad83-614d015b0979" ] } } } } }
It adds the following extra information, that can be used by custom authorizers later on:
gardener.cloud/authenticator/name
contains the name of theOpenIDConnect
authenticator which was used.gardener.cloud/authenticator/uid
contains the UID of theOpenIDConnect
authenticator which was used.
Docker images are available here or you can choose to pull the latest pre-release version with the following command:
docker pull europe-docker.pkg.dev/gardener-project/public/gardener/oidc-webhook-authenticator:latest
For this setup the following components are needed:
The API server is started with --authentication-token-webhook-config-file
with kubeconfig
file pointing to the Webhook.
mkdir -p ~/.minikube/files/var/lib/minikube/certs
cp config/samples/minikube-webhook-kubeconfig.yaml ~/.minikube/files/var/lib/minikube/certs/minikube-webhook-kubeconfig.yaml
minikube start \
--extra-config=apiserver.authentication-token-webhook-config-file=/var/lib/minikube/certs/minikube-webhook-kubeconfig.yaml \
--extra-config=apiserver.authentication-token-webhook-cache-ttl=10s
To allow easy communication between the kube-apiserver
and the oidc-webhook-authenticator
minikube IP is added as control-plane.minikube.internal
in /etc/hosts
sudo sed -ie '/control-plane.minikube.internal/d' /etc/hosts
echo "$(minikube ip) control-plane.minikube.internal" | sudo tee -a /etc/hosts
Add the CRD:
kubectl apply -f config/crd/bases/authentication.gardener.cloud_openidconnects.yaml
Build the image, so it's accessible by minikube
:
minikube image build -t oidc-webhook-authenticator .
Deploy the oidc webhook authenticator.
kubectl apply -f config/samples/deployment.yaml
Create an OpenIDConnect
resource configured with your identity provider's settings (see an example here). Get a token from your identity provider. You can now authenticate against the minikube cluster.
curl -k -H "Authorization: Bearer $MY_TOKEN" $(k config view -o=jsonpath="{.clusters[?(@.name=='minikube')].cluster.server}")
Alternatively you can also use a token kubeconfig or the kubelogin plugin and configure an OIDC kubeconfig.