This is the multi-page printable view of this section.
Click here to print.
Return to the regular view of this page.
Single Sign-On with Keycloak
Learn how to configure Keycloak for Single Sign-On, securely expose it using Kubernetes Ingress and TLS, and integrate it with kubeops and other Kubernetes applications.
In this guide, you will learn how to implement Single Sign-On (SSO) using Keycloak. We will walk through the complete flow—from understanding SSO for platforms and services such as Rook Ceph, Harbor, OpenSearch, and other Kubernetes applications, to configuring Keycloak, exposing it securely, and integrating it with kubeops.
By the end of this guide, you will be able to:
- Understand how Keycloak enables centralized authentication
- Configure Keycloak for SSO
- Securely expose Keycloak using Kubernetes Ingress and TLS
- Integrate Keycloak with kubeops for authentication and authorization
- Validate and troubleshoot the SSO login flow
Let’s get started on enabling secure and seamless authentication with Keycloak.
1 - Single Sign-On (SSO) with Keycloak for Harbor
Learn how to configure Single Sign-On (SSO) for Harbor using Keycloak with OIDC in a Kubernetes environment.
This guide describes how to configure Harbor authentication using Keycloak (OIDC) in a kubeops-managed Kubernetes environment.
Prerequisites
Before proceeding, ensure the following requirements are met:
- A running Kubernetes cluster
- kubectl installed and configured.
- Keycloak is already installed and running
- Keycloak is exposed using Kubernetes Ingress
- A valid DNS record is configured for Keycloak and Harbor
- TLS is enabled with a trusted Certificate Authority (CA)
Step 1: Prepare Keycloak (Realm, User, and Client)
In this step, we configure Keycloak for Harbor SSO. Keycloak is assumed to be already installed, exposed via Ingress, and reachable over HTTPS.
Create Realm
Ensure a realm named kubeops-dashboards exists.
If it does not exist, create it in the Keycloak admin console.
- Realm name:
kubeops-dashboards
- Enabled: true
Create User
Ensure a user named kubeops exists in the kubeops-dashboards realm.
If the user does not exist, create it and set credentials.
- Username:
kubeops
- Enabled: true
- Set a permanent password
Create Client (Harbor)
Create a client for Harbor in the kubeops-dashboards realm.
- Client ID:
harbor
- Client type: OpenID Connect
- Client authentication: Enabled
- Standard flow: Enabled
- Direct access grants: Disabled
Valid Redirect URIs
Add the following redirect URI:
https://<your_DNS_name>/c/oidc/callback
Web Origins
<your_DNS_name>
Client Secret
After creating the client, copy the client secret.
This value will be used in the Harbor configuration:
oidc_client_id: harbor
oidc_client_secret: <CLIENT_SECRET>
Create Secret
⚠ Warning
You may use a different name for the oidc-harbor secret. If you do so, adapt secretKeyRef.name in the Harbor values accordingly.
kubectl create secret generic oidc-harbor \
--namespace <your_harbor_namespace> \
--from-literal=client_id=<your_oidc_client_id> \
--from-literal=client_secret=<your_oidc_client_secret>
Step 2: Prepare Harbor Values
The following kubeops package configuration enables Harbor and integrates it with Keycloak using OIDC authentication.
apiVersion: kubeops/kubeopsctl/enterprise/beta/v1
deleteNs: false
localRegistry: false
packages:
- name: harbor
enabled: true
values:
standard:
namespace: <you_harbor_namespace>
harborpass: "password"
databasePassword: "password"
redisPassword: "password"
externalURL: https://<your_DNS_name>
nodePort: 30002
hostname: <your_DNS_name>
harborPersistence:
persistentVolumeClaim:
registry:
size: 40Gi
storageClass: "rook-cephfs"
jobservice:
jobLog:
size: 1Gi
storageClass: "rook-cephfs"
database:
size: 1Gi
storageClass: "rook-cephfs"
redis:
size: 1Gi
storageClass: "rook-cephfs"
trivy:
size: 5Gi
storageClass: "rook-cephfs"
advanced:
core:
extraEnvVars:
- name: OIDC_CLIENT_ID
valueFrom:
secretKeyRef:
name: oidc-harbor
key: client_id
- name: OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: oidc-harbor
key: client_secret
- name: CONFIG_OVERWRITE_JSON
value: |
{
"auth_mode": "oidc_auth",
"oidc_name": "keycloak",
"oidc_endpoint": "https://<your_DNS_name>/keycloak/realms/kubeops-dashboards",
"oidc_client_id": "$(OIDC_CLIENT_ID)",
"oidc_client_secret": "$(OIDC_CLIENT_SECRET)",
"oidc_scope": "openid,profile,email",
"oidc_verify_cert": true,
"oidc_auto_onboard": true
}
Notes
- Ensure the OIDC client in Keycloak matches the
oidc_client_id and oidc_client_secret values.
- The
externalURL and hostname must match the Harbor DNS name exactly.
oidc_auto_onboard: true allows users to be created automatically in Harbor upon first login.
2 - Single Sign-On (SSO) with Keycloak for KubeOps Dashboard
Learn how to configure Single Sign-On (SSO) for KubeOps Dashboard using Keycloak with OIDC.
This guide describes how to configure KubeOps Dashboard using Keycloak (OIDC) in a kubeops-managed Kubernetes environment.
Prerequisites
Before proceeding, ensure the following requirements are met:
- A running Kubernetes cluster
- kubectl installed and configured.
- Keycloak is already installed and running
Important: Replace all <your_DNS_name> placeholders with your correct DNS name
- On your admin host, run the OpenSSL command (kept exactly as provided):
openssl s_client -showcerts -connect <your_DNS_name>:443 /dev/null | openssl x509 -outform PEM > keycloak-ca.crt
Step 2: Update kube-apiserver yaml
On every master, edit the yaml : /etc/kubernetes/manifests/kube-apiserver.yaml
Important: Replace all <your_DNS_name> placeholders with your correct DNS name
spec:
containers:
- command:
- --oidc-issuer-url=https://<your_DNS_name>/keycloak/realms/master
- --oidc-client-id=headlamp
- --oidc-username-claim=preferred_username
- --oidc-groups-claim=groups
- "--oidc-username-prefix=oidc:"
- "--oidc-groups-prefix=oidc:"
- --oidc-ca-file=/etc/kubernetes/pki/keycloak-ca.crt
Step 3: Create a Keycloak client for Headlamp
Important: Replace all <your_DNS_name> placeholders with your correct DNS name
-
Create a client for headlamp
- Client ID:
headlamp
- Client type: OpenID Connect
- Access type: Confidential
- Client authentication: Enabled
- Standard flow: Enabled
- Direct access grants: Disabled
-
Valid Redirect URIs
Add the following redirect URI:
https://headlamp/<your_DNS_name>/*
-
Web Origins
<your_DNS_name>
Step 4: Create a client scope for Headlamp
Step 5: Create a user Group and user in Keycloak
Create a group named headlamp (if doesn’t exist already) and user under the group.
Step 6: Create ClusterRoleBinding for Headlamp group
1.Use following yaml to create ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: headlamp-admin-user
subjects:
- kind: Group
name: "oidc:headlamp" # Der 'sub' oder 'preferred_username' from the Keycloak-Token
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
The name “oidc:headlamp” needs to be the same as the group name.
- Apply the ClusterRoleBinding file
kubectl apply -f headlamp-clusterrolebinding.yaml
Step 7: Get client secret
After creating the client, copy the client secret.
This value will be used in the next step.
Step 8: Prepare Headlamp values (enterprise.yaml)
configure enterprise-yaml
Important: Replace all <your_DNS_name> placeholders with your correct DNS name
packages:
- name: kubeops-dashboard
enabled: true
values:
standard:
namespace: monitoring
service:
nodePort: 30007
hostname: "<your_DNS_name>"
path: "/"
advanced:
config:
extraArgs:
- "--in-cluster"
- "--plugins-dir=/headlamp/plugins"
- "--oidc-client-id=headlamp"
- "--oidc-idp-issuer-url=https://<your_DNS_name>/keycloak/realms/master"
- "--oidc-scopes=openid,profile,email"
- "--insecure-ssl"
- "--oidc-client-secret=<client-secret>"
Replace with the secret retrieved in Step 7.
-oidc-client-id must match the Keycloak client name (headlamp).
Step 9: Install Headlamp
Deploy Headlamp with the updated enterprise.yaml.
3 - Single Sign-On (SSO) with Keycloak for OpenSearch
Learn how to log in to OpenSearch and OpenSearch Dashboards with Single Sign-On (SSO) using Keycloak (OIDC).
This guide describes how to log in to OpenSearch Dashboards using Keycloak (OIDC)
in a kubeops-managed Kubernetes environment.
Unlike some other integrations, you do not have to create the Keycloak realm,
client, roles or mapper by hand — the opensearch-dashboards package provisions
them automatically during install/update. Username/password login remains available
as a fallback.
Prerequisites
- A running Kubernetes cluster with
kubectl configured
- Keycloak is installed and running (the
keycloak package), exposed via Ingress and reachable over HTTPS
- A valid DNS record and a trusted TLS certificate (e.g. Let’s Encrypt) for the ingress hostname
- The OpenSearch
hostname is set to that public host and is identical for the opensearch-os and opensearch-dashboards packages
Note
If the hostname is a *.local name (not reachable), SSO is skipped automatically
and only username/password login is configured.
Set the shared hostname and (optionally) the adminPassword for both OpenSearch
packages in your enterprise-values.yaml:
apiVersion: kubeops/kubeopsctl/enterprise/beta/v1
deleteNs: false
localRegistry: false
packages:
- name: opensearch-os
enabled: true
values:
standard:
namespace: logging
hostname: <your_DNS_name> # must match opensearch-dashboards and Keycloak host
adminPassword: "<admin-password>" # optional, default Password@@123456
- name: opensearch-dashboards
enabled: true
values:
standard:
namespace: logging
nodePort: 30050
hostname: <your_DNS_name> # must match opensearch-os
adminPassword: "<admin-password>" # must match opensearch-os
Apply the configuration:
kubeopsctl apply -f enterprise-values.yaml
Step 2: What the package provisions automatically
During install/update the package configures Keycloak and OpenSearch for you:
- Realm:
kubeops-dashboards
- Client:
opensearch-dashboards (OpenID Connect, confidential, standard flow)
- User:
kubeops (default password password)
- Realm roles:
all_access, opensearch_dashboards_user
- Protocol mapper: exposes the realm roles as a
roles claim so OpenSearch can map them
- OpenSearch backend security config: an
openid authentication domain (Keycloak) plus a basic domain (username/password fallback), and a role mapping from the Keycloak realm roles to OpenSearch roles
The Keycloak admin credentials used for this are read from the keycloak-kubeops secret.
Step 3: Grant a user access
To let a Keycloak user log in to OpenSearch, assign them one of the realm roles in
the kubeops-dashboards realm:
all_access — full access (maps to the OpenSearch all_access role)
opensearch_dashboards_user — dashboards access (maps to the kibana_user role)
You can use the pre-created kubeops user, or assign the role to your own Keycloak users.
Step 4: Log in
Open the OpenSearch Dashboards URL:
https://<your_DNS_name>/opensearch/
- SSO: choose Log in with single sign-on → authenticate in Keycloak.
- Fallback: use username
admin and the adminPassword value (default Password@@123456).
Notes / Troubleshooting
-
hostname mismatch: the opensearch-os and opensearch-dashboards hostnames must be identical and must be the public Keycloak host, otherwise the OpenSearch backend cannot validate the token.
-
401 Unauthorized on SSO login: the OpenSearch backend could not validate the Keycloak token. Check that hostname is set and reachable from the OpenSearch pods, and that Keycloak’s TLS certificate is trusted (e.g. Let’s Encrypt). Verify the backend security config contains the openid domain:
curl -k -u admin:<adminPassword> \
https://opensearch-cluster-master:9200/_plugins/_security/api/securityconfig
-
*.local hostname: SSO is intentionally skipped; only username/password login is available.
-
Changing the admin password: see Changing the OpenSearch password.