K8s-AD Integration using Keycloak

Q:

How to integrate keycloak on K8s on RHEL 8 with AD, given RHEL 8 is integrated with AD via Kerberos and password auth.

A:

Integrating Keycloak on Kubernetes (K8s) running on RHEL 8 with Active Directory (AD), especially when RHEL 8 is already integrated with AD via Kerberos and password authentication, involves several steps. Below is a high-level guide to achieve this integration:

Prerequisites

LDAP : Lightweight Directory Access Protocol

Successor to DAP (Directory Access Protocol) of switched-based telecoms era, and is origin of X.500 series standards.

Port(s):

Both schemes use TCP mostly, but for Connectionless LDAP (CLDAP) protocol, which is a lightweight version of LDAP that uses UDP for simple, stateless queries, such as when a client needs to locate a domain controller in a Microsoft Active Directory environment. This is commonly seen in the initial stages of authentication, such as during a "ping" to locate domain controllers.

Terminology

CN=ldap-reader,OU=Service Accounts,DC=example,DC=com

LDAP Security Objects

Step 1: Deploy Keycloak on Kubernetes

  1. Create a Namespace for Keycloak:

    kubectl create namespace keycloak
    
  2. Deploy Keycloak: You can deploy Keycloak using a Helm chart or a custom deployment. Here's an example using a Helm chart:

    helm repo add codecentric https://codecentric.github.io/helm-charts
    helm install keycloak codecentric/keycloak --namespace keycloak
    
  3. Expose Keycloak: Use an Ingress or a LoadBalancer service to expose Keycloak externally. Example:

    apiVersion: v1
    kind: Service
    metadata:
    name: keycloak
    namespace: keycloak
    spec:
    ports:
    - port: 80
    targetPort: 8080
    protocol: TCP
    selector:
    app: keycloak
    type: LoadBalancer
    

Step 2: Integrate Keycloak with Active Directory

  1. Access Keycloak Admin Console:
    • Access the Keycloak admin console using the external IP or DNS name provided by the LoadBalancer or Ingress.
    • Log in using the default admin credentials (which should be set during deployment).
  2. Create a New Realm:
    • In the Keycloak admin console, create a new realm that will be used for AD integration.
  3. Add LDAP/AD as a User Federation Provider: Allowing Keycloak to connect to, and synch with, other IdP/IdM such as Active Directory Domain Services (AD DS), and otherwise act as an intermediary IdP. Implementing such Federated Identity allows users to quickly move between systems securely.
    • Navigate to User Federation in the Keycloak admin console.
    • Click on Add provider and select LDAP.
    • Configure LDAP settings as follows:
      • Vendor: Active Directory
      • Connection URL: ldap://<AD_SERVER_IP>:389 or ldaps://<AD_SERVER_IP>:636 (for LDAPS)
      • Users DN: The base DN where your users are located, e.g., OU=Users,DC=example,DC=com
      • Bind DN: The DN of an AD service account that has read access to the user data, e.g., CN=ldap-reader,OU=Service Accounts,DC=example,DC=com
      • Bind Credential: The password for the Bind DN account.
      • Kerberos Integration: Set Allow Kerberos Authentication to ON if Keycloak is to delegate authentication to AD using Kerberos.
      • Sync Settings: Configure how and when to synchronize user data from AD to Keycloak.
    • Test the connection to ensure that Keycloak can communicate with the AD server.
  4. Configure Kerberos Authentication (Optional):
    • If you want Keycloak to use Kerberos for authentication, additional configuration is required:
      • Kerberos Realm: Set the Kerberos realm, which should match your AD domain.
      • Server Principal: The principal name Keycloak will use, usually something like HTTP/<keycloak-hostname>@EXAMPLE.COM.
      • Keytab File: Upload the keytab file for the Keycloak service principal, which should be generated and exported from AD.
  5. Sync Users:
    • After configuring the LDAP provider, trigger a full sync to import AD users into Keycloak.

Step 3: Integrate Kubernetes with Keycloak

UPDATE: OIDC v. SAML

  1. Enable OIDC Authentication on Kubernetes :
  2. Update your Kubernetes API server configuration (kube-apiserver.yaml) to use Keycloak as the OIDC provider. This involves adding flags to the API server configuration:

    --oidc-issuer-url=https://<keycloak-url>/auth/realms/<realm-name>
    --oidc-client-id=<client-id>
    --oidc-username-claim=preferred_username
    --oidc-groups-claim=groups
    
  3. Create a Keycloak Client for Kubernetes:

    • In the Keycloak admin console, create a new client for Kubernetes within your realm.
    • Set the Client ID to match the --oidc-client-id configured in Kubernetes.
    • Set the Access Type to confidential.
    • Configure the Valid Redirect URIs to include the Kubernetes API server URL.
    • See kubelogin
  4. Configure RBAC in Kubernetes:

    • Map the Keycloak roles/groups to Kubernetes RBAC roles. You can use a ClusterRoleBinding or RoleBinding to grant appropriate permissions to the users authenticating via Keycloak.

Step 4: Testing and Verification

  1. Login to Kubernetes using Keycloak:
    • Use a Kubernetes client (like kubectl) with an OIDC plugin or a custom script to obtain an OIDC token from Keycloak.
    • Test the login and ensure users can authenticate to Kubernetes via Keycloak using their AD credentials.
  2. Monitor Logs and Debug:
    • Check the Keycloak and Kubernetes logs to ensure that the integration is working correctly and troubleshoot any issues.

Step 5: Optionally Refactor Groups/Roles

In environment having AD DS as the domain-level IdP, both K8s and its workloads (application services) have the option of abiding AD groups exclusively or refactoring to better fit upstream services.

@ AD DS (Domain IdP)

AD's org-based groups (having users);
are all synchronized with RHEL clients,
providing realm-level (domain) Authn:

@ Keycloak (OIDC / User-Federation IdP)

Example @ Unchanged:

Example @ Refractored:

An authenticated subject (identity) is issued a bearer token (JWT) having claims including id: <UUID>, groups:[] and roles:[]. Such claims scope all upstream API access (Authz) regardless (K8s API, App-X API, Web UI SSO, …).

@ K8s API Authn modes for Authz

Role and RoleBinding are objects of K8s API, whereas group and user are merely concepts of K8s API, known only as token subjects. The latter map to Role only by RoleBinding.

ClusterRole and ClusterRoleBinding objects are ommitted here for clarity. Where Role and RoleBinding are scoped to a Namespace, the Cluster* versions apply cluster-wide.

So, the lone coupling is the map from domain IdP (AD DS) user/group to DevOps-controlled IdP (Keycloak) group/role.

User/Group (Authn) is otherwise decoupled from roles (Authz). Moreover, access to K8s API endpoints is entirely decoupled from that of applications. Though decoupled, these may be configured identically, entirely refactored, or any mix thereof, all at the discretion of cluster/application administrators, and that separation too (cluster admin vs teams/apps admin) is discretionary and maintains its flexibility.

Summary

This setup provides a secure and centralized authentication mechanism for Kubernetes users, leveraging existing AD infrastructure and using Keycloak as a flexible and powerful identity broker.