Konfiguration der OIDC-Authentifizierung für Browserless Clients
5 Minuten Lesezeit
Diese Anleitung beschreibt, wie Sie die OpenID-Connect-Authentifizierung (OIDC) für einen Shoot-Cluster einrichten. Sie umfasst das Erstellen der API-Server-Authentifizierungskonfiguration, die Installation des OIDC-Login-Plugins sowie das Berechtigen von OIDC-Nutzern bzw. Clients im Cluster.
Voraussetzungen
Stellen Sie sicher, dass Ihnen folgende Zugänge und Informationen vorliegen:
- Project Kubeconfig: Im PSKE-Dashboard unter Members > Service Accounts verfügbar.
- Shoot Kubeconfig: Im Shoot-Overview des PSKE-Dashboards herunterladbar.
- OIDC-Zugangsdaten: Issuer-URL, Client-ID und Client-Secret Ihres OIDC-Identity-Providers.
1. Authentifizierungs-ConfigMap erstellen
Erstellen Sie eine Datei kube-apiserver-auth-config.yaml und fügen Sie den folgenden Inhalt ein. Ersetzen Sie dabei die Platzhalter für Issuer-URL und Client-ID. Weitere Informationen finden Sie in der Dokumentation zur OIDC-Konfiguration: OIDC / Structured Authentication.
# kube-apiserver-auth-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-apiserver-auth-config
data:
config.yaml: |-
apiVersion: apiserver.config.k8s.io/v1beta1
kind: AuthenticationConfiguration
jwt:
- issuer:
url: https://example.com
audiences:
- example-client-id
claimMappings:
username:
claim: sub
prefix: https://example.com#
Danach wird die ConfigMap mit der Project-Kubeconfig angewendet:
export KUBECONFIG=kubeconfig-project.yaml
kubectl apply --filename=kube-apiserver-auth-config.yaml
Hinweis: Wenn Sie diese ConfigMap später ändern, kann es erforderlich sein, den Shoot-Cluster manuell neu zu reconcilieren. (s. Punkt 2).
2. ConfigMap am Shoot-Cluster hinterlegen
Bearbeiten Sie die Shoot-Ressource entweder über das PSKE-Dashboard (Ansicht von Overview auf YAML wechseln) oder per kubectl edit mit der Project-Kubeconfig.
Fügen Sie die folgende Konfiguration unter spec.kubernetes.kubeAPIServer.structuredAuthentication hinzu:
apiVersion: core.gardener.cloud/v1beta1
kind: Shoot
spec:
kubernetes:
kubeAPIServer:
structuredAuthentication:
configMapName: kube-apiserver-auth-config
Hinweis: Änderungen an der structuredAuthentication des Shoots lösen automatisch ein Rollout der Authentifizierungskonfiguration aus.
Wird lediglich der Inhalt der ConfigMap geändert (ohne Namensänderung), erfolgt keine automatische Reconcilierung.
3. OIDC-Login-Plugin installieren
Installieren Sie das kubectl OIDC-Login-Plugin. Die offizielle Anleitung finden Sie hier:
https://github.com/int128/kubelogin#setup
4. OIDC-Token mit Client-Credentials abrufen
Überprüfen Sie die OIDC-Konfiguration mit folgendem Befehl:
kubectl oidc-login setup --oidc-issuer-url=https://example.com --oidc-client-id=example-client-id --oidc-client-secret=example-client-secret --grant-type=client-credentials
Bei erfolgreicher Ausführung erhalten Sie eine Ausgabe mit den Token-Claims, beispielsweise:
Authentication in progress...
## Authenticated with the OpenID Connect Provider
You got the token with the following claims:
```
{
"iss": "https://example.com",
"sub": "example-sub",
"aud": "example-client-id",
"exp": 1767312000,
"iat": 1767225600,
"jti": "3e9a0664-fa50-46de-85a2-d2b0c060b19c",
"at_hash": "uav9UWBowQlxgbIzgsvCpE",
}
```
Merken Sie sich insbesondere den Wert des Feldes sub, da dieser im nächsten Schritt benötigt wird.
5. Zugriff auf den Shoot freigeben
Erstellen Sie ein ClusterRoleBinding, das den OIDC-User anhand des sub-Claims an die Rolle view im Cluster bindet:
# oidc-user.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: oidc-cluster-viewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: view
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: https://example.com#example-sub
Anwenden:
export KUBECONFIG=kubeconfig-shoot.yaml
kubectl apply --filename=oidc-user.yaml
6. OIDC-User im kubeconfig hinterlegen
Tragen Sie den OIDC-Login als Benutzer in die kubeconfig ein, damit kubectl automatisch Tokens abrufen kann:
export KUBECONFIG=kubeconfig-shoot.yaml
kubectl config set-credentials oidc \
--exec-api-version=client.authentication.k8s.io/v1 \
--exec-interactive-mode=Never \
--exec-command=kubectl \
--exec-arg=oidc-login \
--exec-arg=get-token \
--exec-arg="--oidc-issuer-url=https://example.com" \
--exec-arg="--oidc-client-id=example-client-id" \
--exec-arg="--oidc-client-secret=example-client-secret" \
--exec-arg="--grant-type=client-credentials"
7. Zugriff testen
Nun können Sie den OIDC-Benutzer verwenden, um kubectl-Befehle auszuführen, zum Beispiel:
kubectl --kubeconfig=kubeconfig-shoot.yaml --user=oidc get nodes
Dex als OIDC Identity Provider für browserlose Clients einrichten
Diese Anleitung ist für Entwicklungs- und Testumgebungen vorgesehen:
- nip.io: Wird für dynamische DNS-Namen verwendet und ist nicht für produktive Umgebungen geeignet.
- Secrets: Client-Secrets dürfen niemals direkt in Konfigurationsdateien gespeichert werden.
Voraussetzungen
- Tools: Helm, kubectl, kubelogin, openssl sowie eine Shell (z. B. bash)
- Shoot Kubeconfig: Shoot-Kubeconfig aus dem PSKE-Dashboard
1. Traefik installieren
helm repo add traefik https://traefik.github.io/charts
helm repo update traefik
helm upgrade traefik traefik/traefik --create-namespace --install --namespace=traefik
2. cert-manager installieren
helm repo add jetstack https://charts.jetstack.io
helm repo update jetstack
helm upgrade cert-manager jetstack/cert-manager --create-namespace --install --namespace=cert-manager \
--set=crds.enabled=true
Erstellen Sie eine cluster-issuers.yaml Datei mit dem folgenden Inhalt:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-http01
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-http01
solvers:
- http01:
ingress:
ingressClassName: traefik
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-http01-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-http01-staging
solvers:
- http01:
ingress:
ingressClassName: traefik
Anwenden:
kubectl --namespace=cert-manager apply --filename=cluster-issuers.yaml
3. Dex installieren
Erstellen Sie eine Datei dex-values.yaml:
config:
enablePasswordDB: true
issuer: https://localhost # placeholder, overridden by helm --set
oauth2:
passwordConnector: local
staticClients:
- id: example-client-id
secret: example-client-secret
name: example-client-name
staticPasswords:
- username: admin
email: admin@example.com
# password: admin (echo admin | htpasswd -Bin admin | cut -d: -f2)
hash: $2y$05$T0abwx/OUS0EZNkDZgznd.rTsUJZrH1QSlRDHirCGQEMYko7LJbgK
storage:
type: memory
env:
DEX_CLIENT_CREDENTIAL_GRANT_ENABLED_BY_DEFAULT: true
image:
# using "latest" because even the most recent release v2.45.1 does not support the required grant type "client credentials"
tag: latest@sha256:bb4835dd1e71986cae4f6b8565e7d79c48f77460098b9e40ad5c117b4ad11465
ingress:
enabled: true
annotations:
cert-manager.io/cluster-issuer: letsencrypt-http01-staging # use staging initially
traefik.ingress.kubernetes.io/router.entrypoints: websecure
hosts:
- host: localhost # placeholder, overridden by helm --set
paths:
- path: /
pathType: Prefix
tls:
- hosts:
- localhost # placeholder, overridden by helm --set
secretName: dex-tls
Ermitteln Sie die LoadBalancer-IP und erzeugen Sie eine nip.io-Domain:
IP=$(kubectl --namespace=traefik get service/traefik --output=jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "IP=${IP:?}"
# "${IP//./-}" replaces dots with dashes (e.g. 1.2.3.4 -> 1-2-3-4)
HOST=${IP//./-}.nip.io
echo "HOST=${HOST:?}"
Installation von Dex:
helm repo add dex https://charts.dexidp.io
helm repo update dex
helm upgrade dex dex/dex --create-namespace --install --namespace=dex \
--values=dex-values.yaml \
--set="config.issuer=https://${HOST:?}" \
--set="ingress.hosts[0].host=${HOST:?}" \
--set="ingress.tls[0].hosts[0]=${HOST:?}"
4. Zertifikate prüfen
Dex verwendet zunächst das Staging-Zertifikat, um Rate-Limits zu vermeiden. Prüfen Sie, ob es vom Staging-Provider ausgestellt wurde:
openssl s_client -showcerts -connect "${HOST:?}:443" </dev/null 2>/dev/null |
openssl x509 -noout -issuer -nameopt lname | tee -a /dev/stderr |
grep -F "organizationName=(STAGING) Let's Encrypt,"
Sobald dies verifiziert ist, aktualisieren Sie den Ingress von Dex, sodass er den Produktions-Let’s-Encrypt-Issuer verwendet:
helm upgrade dex dex/dex --create-namespace --install --namespace=dex --reuse-values \
--set="ingress.annotations.\"cert-manager.io/cluster-issuer\"=letsencrypt-http01"
Zertifikat überprüfen:
openssl s_client -showcerts -connect "${HOST:?}:443" </dev/null 2>/dev/null |
openssl x509 -noout -issuer -nameopt lname | tee -a /dev/stderr |
grep -F "organizationName=Let's Encrypt,"
5. Test OIDC Authentication
kubectl oidc-login setup \
--oidc-issuer-url="https://${HOST:?}" \
--oidc-client-id=example-client-id \
--oidc-client-secret=example-client-secret \
--grant-type=client-credentials
Alternativ steht auch das Tutorial PSKE - Einrichten von OIDC/2FA auf PSKE zur Verfügung.