Keycloak (Identity Provider / SSO)
Keycloak provides OIDC authentication for kubectl and Single Sign-On (SSO) for Grafana. It runs inside the Kubernetes cluster with a PostgreSQL backend and is exposed via Istio at https://keycloak.local.
Access
# Via Istio Gateway (requires /etc/hosts — see Quick Start step 5)
open https://keycloak.local
# Via NodePort (no /etc/hosts needed)
open http://192.168.56.10:30080
Admin credentials
All Keycloak credentials are stored in Vault at secret/k8s-provisioner/api-keys:
| Vault key | Description |
|---|---|
keycloak_admin_username | Admin console username (admin) |
keycloak_admin_password | Admin console password |
keycloak_postgres_username | PostgreSQL username (keycloak) |
keycloak_postgres_password | PostgreSQL password |
keycloak_grafana_client_secret | Grafana OIDC client secret |
keycloak_k8sadmin_password | Realm user k8sadmin password |
keycloak_developer_password | Realm user developer password |
To customize passwords before provisioning:
export VAULT_ADDR=http://192.168.56.20:8200
export VAULT_TOKEN=$(cat /etc/k8s-provisioner/vault-init.json | jq -r .root_token)
vault kv patch secret/k8s-provisioner/api-keys \
keycloak_k8sadmin_password="MinhaSenh@Forte" \
keycloak_developer_password="OutraSenha@123"
Note: Run this after Vault is initialized but before Keycloak is installed (or recreate the cluster).
Pre-configured realm: k8s
| Resource | Details |
|---|---|
| Realm | k8s |
| kubectl client | kubectl (public, PKCE enabled) |
| Grafana client | grafana (confidential) |
| Admin group | k8s-admins → cluster-admin RBAC |
| Developer group | k8s-developers → view RBAC |
| Test user (admin) | k8sadmin / (Vault: keycloak_k8sadmin_password) |
| Test user (dev) | developer / (Vault: keycloak_developer_password) |
kubectl access
Quick access (admin)
# 1. Copy kubeconfig and fix the API server address
vagrant ssh controlplane -c "cat /etc/kubernetes/admin.conf" \
| sed 's|https://.*:6443|https://192.168.56.10:6443|' \
> ~/.kube/k8s-lab.conf
# 2. Use it
export KUBECONFIG=~/.kube/k8s-lab.conf
kubectl get nodes
This uses cluster-admin credentials. Suitable for day-to-day lab usage.
OIDC login via Keycloak (kubelogin)
Use this for role-based access — each user logs in with their own Keycloak credentials and gets the permissions of their group.
| Keycloak group | Kubernetes access | Grafana role |
|---|---|---|
k8s-admins | cluster-admin | Admin |
k8s-developers | view (read-only) | Viewer |
The kubeconfig-oidc file contains no credentials — it is safe to distribute. It is stored in Vault automatically during provisioning.
How authentication works
The API server uses AuthenticationConfiguration (/etc/kubernetes/pki/auth-config.yaml) to validate tokens:
apiVersion: apiserver.config.k8s.io/v1beta1
kind: AuthenticationConfiguration
jwt:
- issuer:
url: https://keycloak.local/realms/k8s
audiences:
- kubectl
- account
audienceMatchPolicy: MatchAny
claimMappings:
username:
claim: preferred_username
prefix: "oidc:"
groups:
claim: groups
prefix: "oidc:"
Group-based ClusterRoleBindings are applied automatically during provisioning:
# k8s-admins → cluster-admin
kind: ClusterRoleBinding
metadata:
name: oidc-k8s-admins
subjects:
- kind: Group
name: "oidc:k8s-admins"
---
# k8s-developers → view
kind: ClusterRoleBinding
metadata:
name: oidc-k8s-developers
subjects:
- kind: Group
name: "oidc:k8s-developers"
Admin: adding a new user
Access is group-based — no Kubernetes changes needed. Just create the user in Keycloak and assign the group.
Option A — Keycloak Admin Console:
- Open
https://keycloak.local/admin→ realmk8s→ Users → Add user - Set username, email, enable the user, save
- Go to Credentials tab → Set password
- Go to Groups tab → Join
k8s-adminsork8s-developers
Option B — CLI (from controlplane):
KCADM="kubectl exec -n keycloak deploy/keycloak -- /opt/keycloak/bin/kcadm.sh"
$KCADM config credentials --server http://localhost:8080 --realm master \
--user "$KEYCLOAK_ADMIN" --password "$KEYCLOAK_ADMIN_PASSWORD"
NEW_UID=$($KCADM create users -r k8s \
-s username=alice \
-s email=alice@example.com \
-s firstName=Alice \
-s lastName=Smith \
-s enabled=true -i)
$KCADM set-password -r k8s --username alice --new-password 'Alice@K8s123'
GID=$($KCADM get groups -r k8s | grep -A1 k8s-developers | grep id | cut -d'"' -f4)
$KCADM update users/$NEW_UID/groups/$GID -r k8s -s realm=k8s -s userId=$NEW_UID -s groupId=$GID -n
New user: first-time setup (once)
# 1. Install kubelogin
brew install int128/kubelogin/kubelogin # macOS
# 2. Add keycloak.local to /etc/hosts (required to reach the OIDC issuer)
INGRESS_IP=$(vagrant ssh controlplane -c "kubectl get svc -n istio-system istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}'" 2>/dev/null | tr -d '\r')
echo "$INGRESS_IP keycloak.local" | sudo tee -a /etc/hosts
# 3. Save the kubeconfig received from admin
mkdir -p ~/.kube
cp kubeconfig-oidc ~/.kube/k8s-lab.conf
export KUBECONFIG=~/.kube/k8s-lab.conf # add to ~/.zshrc to persist
# 4. First login — opens browser at Keycloak
kubectl get nodes
Log in with your Keycloak credentials. The token is cached locally; the browser will not open again until it expires (24h).
Verify who you are authenticated as:
kubectl auth whoami
# ATTRIBUTE VALUE
# Username oidc:alice
# Groups [oidc:k8s-developers system:authenticated]
Retrieving the kubeconfig-oidc from Vault
vagrant ssh storage
export VAULT_ADDR=http://127.0.0.1:8200
export VAULT_TOKEN=$(sudo cat /etc/vault.d/vault-init.json | grep root_token | cut -d'"' -f4)
vault kv get -field=config secret/k8s-provisioner/kubeconfig-oidc > /tmp/kubeconfig-oidc
exit
Copy to your Mac:
vagrant scp storage:/tmp/kubeconfig-oidc ./kubeconfig-oidc
Grafana SSO
Grafana is configured to use Keycloak for SSO. Click “Sign in with Keycloak” on the Grafana login page.
| User | Grafana Role |
|---|---|
Users in k8s-admins group | Admin |
| All other OIDC users | Viewer |
Local admin login still works: admin / (password from Vault).
Registering a new application in Keycloak
To protect a new application with Keycloak SSO, create a client in the k8s realm:
Via Admin Console:
- Open
https://keycloak.local/admin→ realmk8s→ Clients → Create client - Set
clientId, chooseOpenID Connect - Enable
Client authenticationfor confidential clients (backend apps) - Set
Valid redirect URIsto your app’s callback URL - Copy the client secret from the Credentials tab
Via CLI:
KCADM="kubectl exec -n keycloak deploy/keycloak -- /opt/keycloak/bin/kcadm.sh"
CLIENT_ID=$($KCADM create clients -r k8s \
-s clientId=my-app \
-s publicClient=false \
-s 'redirectUris=["https://my-app.local/*"]' \
-i)
$KCADM get clients/$CLIENT_ID/client-secret -r k8s