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

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

Step 1: Extract Keycloak CA certificate

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
  • Copy the CA certificate to each master

    scp @:/etc/kubernetes/pki/

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

  • Create a client scope

    • Assigned Client Scope : headlamp-dedicated
  • For groups, use the Group Mapper in Keycloak:

    • Mapper Type: groups
    • Name: groups
    • Token Claim Name: groups
    • Add to ID token: ON
    • Add to access token: ON
    • Add to user info: ON
    • Add to token introspection: ON

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.

  1. 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

Step 1: Configure the packages

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.