In this tutorial, you will learn how to integrate OpenShift with Active Directory for authentication. This setup enables users to log in to OpenShift using their existing AD credentials, streamlining access and enhancing security through centralized identity management. By following this guide, you’ll configure OpenShift to leverage AD’s robust user and group management capabilities, ensuring a unified and efficient authentication process across your organization’s infrastructure.
Table of Contents
Integrate OpenShift with Active Directory for Authentication
By default, a fresh OpenShift installation provides a single administrative user, kubeadmin, which is intended for initial cluster setup and configuration. However, relying solely on kubeadmin or manually managing individual user accounts within OpenShift is impractical and insecure for enterprise environments. Integrating OpenShift with Active Directory (AD) for authentication addresses these limitations and offers several critical benefits:
- Centralized Identity Management: Use existing AD accounts hence no need to create separate OpenShift users.
- Enterprise-Grade Security: Leverage AD features like password policies, account lockouts…
- Scalability: Manage access based on AD group membership, simplifying role assignments in large environments.
- Improved User Experience: Enable single sign-on (SSO) with familiar AD credentials.
- Compliance & Auditing: Centralized authentication supports regulatory compliance (e.g., GDPR, HIPAA).
- Eliminates kubeadmin Dependency: Replace the insecure default user with a trusted identity provider.
- and many more…
Prerequisites
Before beginning the integration, ensuring the following are in place is a critical step to successfully integrate OpenShift with Active Directory for Authentication in your environment:
- A running OpenShift Container Platform (this guide uses OCP v4.19). You can check our guide on how to deploy OpenShift on User-provisioned infrastructure.
- Active Directory Domain Services running on Windows Server (we are running AD on Windows Server 2025).
- Network connectivity between OpenShift cluster and AD domain controllers.
- DNS resolution configured for both AD and OpenShift endpoints.
- SSL certificates for secure LDAP connections (recommended).
- Cluster administrator privileges on OpenShift.
- Domain administrator or delegated permissions in Active Directory.
- Service account in AD for LDAP bind operations (read-only permissions sufficient).
- User Mapping Strategy: Decide whether to use AD usernames or unique identifiers (UPN recommended).
- Group Structure: Plan which AD groups will map to OpenShift roles.
- Security Boundaries: Determine which OUs and groups should have access.
- Naming Conventions: Establish consistent naming for OpenShift users and groups.
Understanding OpenShift Authentication Architecture
OpenShift’s authentication system consists of several key components that work together to provide secure access control:
Core Components:
The following core components form the foundation of OpenShift’s authentication and authorization architecture.
- OAuth Server: This is the central authentication service in OpenShift that handles login requests and token generation. It validates credentials against configured identity providers and issues OAuth tokens for accessing the OpenShift API. It exposes two primary endpoints:
- /oauth/authorize which initiates the OAuth authorization flow. When a user or application requests access, they are redirected to this endpoint to authenticate and grant permission.
- /oauth/token which is used by clients to exchange authorization codes or credentials for access tokens, which are then used for authenticated API requests.
- Identity Providers: These are the pluggable authentication backends responsible for verifying user credentials. For Active Directory integration, the LDAP identity provider is typically used to connect OpenShift to the AD server. There are other providers such as keystone, basic authentication, htpasswd, OIDC…Read more on Red Hat OpenShift supported identity providers.
- User and Identity Objects: OpenShift creates internal user objects and links them to identity objects that represent external authentication sources (like AD). This separation enables multiple identity providers to map to the same OpenShift user if needed.
- Role-Based Access Control (RBAC): OpenShift handles authorization through Kubernetes-native RBAC. Permissions are assigned using Roles, ClusterRoles, and their respective RoleBindings and ClusterRoleBindings.
OpenShift Authentication Flow
OpenShift authentication follows the sequence below when using an external identity provider (e.g., Active Directory) for user login:
- User Initiates Access: The user attempts to access OpenShift via the web console (browser) or CLI (oc login), sending a request to the OAuth server’s /oauth/authorize endpoint.
- OAuth Server Redirects to Identity Provider: The OAuth server then redirects the user to the configured identity provider (e.g., LDAP for Active Directory) using the OAuth 2.0 authorization code flow over a TLS-secured connection.
- Identity Provider Validates Credentials: The LDAP provider authenticates the user against Active Directory, mapping attributes like sAMAccountName or userPrincipalName for user identity and memberOf for group membership. Invalid credentials result in an error, and the OAuth server denies access.
- User and Identity Object Management: Upon successful authentication, the OAuth server creates or updates an Identity object for the external identity and maps it to an internal User object. Existing User objects are updated to support single sign-on (SSO) across multiple identity providers.
- Token Issuance: The OAuth server issues an OAuth 2.0 access token (short-lived, for API access) and a refresh token (longer-lived, for session renewal) via the /oauth/token endpoint. These tokens are used as Bearer tokens in API request headers.
- RBAC Permission Evaluation: For each API request, OpenShift’s RBAC system evaluates permissions based on RoleBindings or ClusterRoleBindings, including group-based roles from Active Directory group mappings. Access is granted or denied as per defined Roles or ClusterRoles (e.g., admin, view).
Active Directory Integration Methods
OpenShift’s authentication system, built on OAuth 2.0 and Kubernetes, supports multiple methods for integrating with Active Directory via pluggable identity providers. Below are the primary methods for AD integration, along with their configurations, benefits, and considerations.
- LDAP Identity Provider: The LDAP identity provider offers the most direct and widely-supported method for Active Directory integration. It uses standard LDAP(S) protocols to authenticate users and can retrieve user attributes for profile information.
- OpenID Connect (OIDC) with AD Federation Services (ADFS): OpenShift can integrate with AD via OpenID Connect (OIDC) using Active Directory Federation Services (ADFS) as an OIDC provider. ADFS acts as a bridge, authenticating users against AD and issuing OIDC tokens.
- RequestHeader Identity Provider (Proxy-Based Integration): The RequestHeader identity provider allows OpenShift to trust authentication headers set by a reverse proxy or load balancer that integrates with AD. This is less common but useful in environments with existing proxy-based authentication.
- SAML 2.0 with ADFS: OpenShift supports SAML 2.0 integration with AD via ADFS as a SAML identity provider. SAML is an alternative to OIDC for SSO, commonly used in enterprise environments.
We will use LDAP identity provider for integrating with AD in this guide.
Step by Step Guide to AD for Authentication
This section provides a detailed process to integrate OpenShift with Active Directory for authentication.
Step 1: Configure Bind DN Account in Windows AD
To allow OpenShift to authenticate users against Active Directory via LDAP, it needs a service account, commonly referred to as a Bind DN, with permission to search the directory tree.
This account is used by OpenShift (via the LDAP identity provider) to:
- Connect to AD securely
- Perform user lookups
- Resolve group membership (if group-based access is configured)
We have created a BIND DN in our AD;
Get-ADUser -Identity read-only | Select-Object DistinguishedName
Replace read-only with the correct username (sAMAccountName) of your BIND DN account.
Sample output;
DistinguishedName
-----------------
CN=read-only,OU=ServiceAccounts,DC=kifarunix,DC=com
If you haven’t created your BIND DN, refer here; Create BIND DN User for Application Authentication.
Step 2: Verify AD Bind DN Connectivity from the Bastion Host
Before integrating Active Directory (AD) with OpenShift, it’s important to verify that your Bind DN account can successfully connect and authenticate to the AD server over LDAPS. In this setup, we’re performing the test from the Bastion Host, which has network access to the AD environment and is used to manage the OpenShift cluster.
To test the BIND DN connection, you need to ensure that the LDAP utilities are installed on your Bastion Host or any node from which you are performing the test.
On RHEL/CentOS/Fedora systems, you can install the required utilities using the following command:
sudo yum install openldap-clients
On Ubuntu/Debian systems, you can install the utilities using:
sudo apt install ldap-utils
Next, ensure that the CA certificate for your Active Directory server is imported onto the host where you’ll run the tests (e.g., Bastion Host). This is necessary to establish trust and prevent certificate validation errors during the LDAP connection.
Once the CA certificate is imported, you can perform a test query to verify connectivity and authentication for your Bind DN account:
ldapsearch -x -D "cn=read-only,ou=ServiceAccounts,dc=kifarunix,dc=com" \
-W -H ldaps://dc01.kifarunix.com:636 \
-b "ou=accessgroups,dc=kifarunix,dc=com" dn -LLL
Here is a break down of the command;
-x
: Use simple authentication instead of SASL.-D "cn=read-only,ou=ServiceAccounts,dc=kifarunix,dc=com"
: The Bind DN you created in AD (this is the account you’re testing).-W
: Prompts for the password for the Bind DN.-H ldaps://dc01.kifarunix.com:636
: The LDAP server (using LDAPS for secure communication over port 636).-b "ou=accessgroups,dc=kifarunix,dc=com"
: The Base DN of the AD domain (this specifies where to begin searching).dn
: Only retrieve the DN (Distinguished Name) for each object found.-LLL
: Format the output to remove extra metadata and show only the search results.
If the Bind DN is valid and the connection is successful, you should see a list of distinguished names (DNs) of the objects found in the search base. If there are issues with the Bind DN, you may encounter errors like “Invalid credentials” or “Unable to connect.”
Sample results in my case:
dn: OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=OCP-Admins,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=OCP-Infra,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=OCP-Developers,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=OCP-CyberSec,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=OCP-ViewOnly,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=ERP-Admins,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=DBA-Admins,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=OCP-All,OU=AccessGroups,DC=kifarunix,DC=com
This confirms that the BIND DN works fine.
OU=AccessGroups,DC=kifarunix,DC=com
organizational unit. This OU is primarily used to store access control groups, including those mapped to OpenShift roles. Within this OU, we use a parent group called OCP-All
, which contains all individual OpenShift-related groups such as OCP-Admins, OCP-Infra, OCP-Developers, OCP-CyberSec,
and others. This structure allows us to manage OpenShift access in a centralized and scalable manner such that new groups can be added in AD and included in OpenShift access simply by nesting them under the OCP-All
group, without needing to modify the OpenShift configuration. While directory structures may vary across organizations, administrators have the flexibility to design a group hierarchy that best fits their environment and use cases.Step 3: Configure AD Certificate Authority (CA) in OpenShift
If you’re using LDAPS (recommended for secure communication), OpenShift must trust the certificate authority (CA) used by your AD server.
This step is required because:
- OpenShift’s OAuth server has to connects over TLS to the AD LDAP endpoint (
ldaps://...
). - If the AD server uses a self-signed or internal CA, OpenShift needs that CA certificate to validate the connection.
To install the CA certificate:
- Export the root CA certificate from your AD server. Refer here for the process.
- Ensure the certificate file is available on your Bastion Host or wherever you are running the
oc
commands. I have exported the certificate already and it is on my bastion host current working directory as ad-cs-root-ca.crt.ls -alh ad-ldaps-ca.crt
-rw-rw-r-- 1 kifarunix kifarunix 1.3K Aug 19 13:08 ad-ldaps-ca.crt - Create a ConfigMap in OpenShift with the certificate. See below.
After exporting the certificate from the Active Directory server, create a ConfigMap in the openshift-config namespace using the certificate:
If you are working from the CLI or using the web console, ensure are logged in as a user with proper rights.
oc create configmap ad-ldaps-ca-cert \
--from-file=ca.crt=./ad-ldaps-ca.crt \
-n openshift-config
Replace the path and the name of the ca certificate accordingly.
We will reference this ConfigMap in the LDAP identity provider configuration later.
Step 4: Create LDAP Bind Secret in OpenShift
Next, you’ll need to store the Bind DN password as a Kubernetes secret in OpenShift. We’ll do this using the CLI. Hence:
read -s BIND_DN_PASS
oc create secret generic ad-binddn-secret \
--from-literal=bindPassword="$BIND_DN_PASS" \
-n openshift-config
unset BIND_DN_PASS
Step 5: Configure LDAP Identity Provider in OpenShift
To enable OpenShift to authenticate users against Active Directory via LDAP, you must configure an identity provider (IdP) in the OpenShift OAuth system.
This is done by modifying the default OAuth custom resource (CR) named cluster
, which already exists in every OpenShift cluster. In the Custom Resource, you define how OpenShift should:
- Connect to the LDAP server
- Authenticate users
- Optionally filter or map user group membership
oc get oauth cluster -o yaml > oauth-cluster-backup.yaml
Below is the sample updated Identity Provider (IdP) configuration we’ll apply to the OpenShift cluster:
cat ad-idp-cr.yaml
apiVersion: config.openshift.io/v1
kind: OAuth
metadata:
name: cluster
spec:
identityProviders:
- name: win-ad-idp
mappingMethod: claim
type: LDAP
ldap:
attributes:
id: [ sAMAccountName ]
email: [ mail ]
name: [ displayName ]
preferredUsername: [ sAMAccountName ]
bindDN: "cn=read-only,ou=ServiceAccounts,dc=kifarunix,dc=com"
bindPassword:
name: ad-binddn-secret
ca:
name: ad-ldaps-ca-cert
insecure: false
url: "ldaps://dc01.kifarunix.com:636/DC=kifarunix,DC=com?sAMAccountName?sub?(&(objectClass=person)(memberOf:1.2.840.113556.1.4.1941:=CN=OCP-All,OU=AccessGroups,DC=kifarunix,DC=com))"
This Custom Resource (CR) integrates OpenShift with an LDAP server (Active Directory) over LDAPS and maps user attributes to OpenShift identities.
- Resource Type:
OAuth
configuration for the OpenShift cluster. - Identity Provider Name:
win-ad-idp
- Mapping Method:
claim
– maps LDAP attributes (e.g., username, email) directly to OpenShift user identities. - LDAP Bind DN: The service account (
cn=read-only,ou=ServiceAccounts,...
) used to perform LDAP queries. - Bind Password: Stored securely in a Kubernetes secret named
ad-binddn-secret
. - CA Certificate: References a ConfigMap named
ad-ldaps-ca-cert
containing the trusted CA certificate for secure LDAPS communication. - LDAP URL: Uses secure LDAPS (
ldaps://
) to connect to the domain controller. The LDAP search filter includes:objectClass=person
: Ensures only user objects are queried.memberOf:1.2.840.113556.1.4.1941:=...
: Recursively checks group membership forCN=OCP-All
, which simplifies access control by allowing any nested group underOCP-All
to authenticate.- Note: The LDAP URL should be designed to strike a balance between security and flexibility, allowing authorized users to authenticate without requiring frequent changes to the IdP configuration.
Once you’re ready, apply the updated OAuth Custom Resource:
oc apply -f ad-idp-cr.yaml
oc apply
creates a new CR and might trigger the following warning:
Warning: resource oauths/cluster is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by oc apply. oc apply should only be used on resources created declaratively by either oc create --save-config or oc apply. The missing annotation will be patched automatically.
In this case, you can safely ignore this warning.
You can check that the IdP was applied correctly:
oc get oauth cluster -o yaml
apiVersion: config.openshift.io/v1
kind: OAuth
metadata:
annotations:
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"config.openshift.io/v1","kind":"OAuth","metadata":{"annotations":{},"name":"cluster"},"spec":{"identityProviders":[{"ldap":{"attributes":{"email":["mail"],"id":["sAMAccountName"],"name":["displayName"],"preferredUsername":["sAMAccountName"]},"bindDN":"cn=read-only,ou=ServiceAccounts,dc=kifarunix,dc=com","bindPassword":{"name":"ad-binddn-secret"},"ca":{"name":"ad-ldaps-ca-cert"},"insecure":false,"url":"ldaps://dc01.kifarunix.com:636/DC=kifarunix,DC=com?sAMAccountName?sub?(\u0026(objectClass=person)(memberOf:1.2.840.113556.1.4.1941:=CN=OCP-All,OU=AccessGroups,DC=kifarunix,DC=com))"},"mappingMethod":"claim","name":"win-ad-idp","type":"LDAP"}]}}
release.openshift.io/create-only: "true"
creationTimestamp: "2025-08-06T07:57:46Z"
generation: 10
name: cluster
ownerReferences:
- apiVersion: config.openshift.io/v1
kind: ClusterVersion
name: version
uid: 5d9a1e8a-ad5f-464b-9dbe-fa0149fd0417
resourceVersion: "4187155"
uid: 4a99f9d9-aa4e-4eec-b5f8-14b3f49155eb
spec:
identityProviders:
- ldap:
attributes:
email:
- mail
id:
- sAMAccountName
name:
- displayName
preferredUsername:
- sAMAccountName
bindDN: cn=read-only,ou=ServiceAccounts,dc=kifarunix,dc=com
bindPassword:
name: ad-binddn-secret
ca:
name: ad-ldaps-ca-cert
insecure: false
url: ldaps://dc01.kifarunix.com:636/DC=kifarunix,DC=com?sAMAccountName?sub?(&(objectClass=person)(memberOf:1.2.840.113556.1.4.1941:=CN=OCP-All,OU=AccessGroups,DC=kifarunix,DC=com))
mappingMethod: claim
name: win-ad-idp
type: LDAP
When you apply the changes, OpenShift will trigger a restart the OAuth server pods automatically in the openshift-authentication project/namespace:
oc get pod -n openshift-authentication
NAME READY STATUS RESTARTS AGE
oauth-openshift-9965df6cd-7j7mh 1/1 Running 0 36s
oauth-openshift-9965df6cd-8h7mq 1/1 Running 0 63s
oauth-openshift-9965df6cd-gvc7g 1/1 Running 0 82s
Configure IdP on OpenShift Web Console
You can also configure AD integration from the OpenShift web console.
Login as admin user and head over to:
- Administration > Cluster Settings > Configuration
- Scroll down and click OAuth configuration resource
- Under Identity Providers, you can add new IdP or remove existing ones:
- Click Add drop down and select your respect IdP from the list. For this specific case, select LDAP.
- Provide required details:
- Name: A unique name for the identity provider (e.g.,
win-ad-idp
). This value cannot be changed once the provider is created. - URL: An RFC 2255-compliant LDAP URL that defines how OpenShift should search for users in Active Directory. Check URL we used above.
- Bind DN: The distinguished name (DN) of the service account OpenShift will use to bind to LDAP for performing user lookups. Check our DN above.
- Bind Password: The password for the bind DN account. This will be stored securely in a Kubernetes secret.
- Attributes: Maps LDAP attributes to OpenShift user identity fields:
- ID: LDAP attribute(s) used as the unique user ID (e.g.,
sAMAccountName
) - Preferred Username: Attribute(s) used as the OpenShift username (commonly also
sAMAccountName
) - Name: Attribute(s) used to populate the user’s full display name (e.g.,
displayName
) - Email: Attribute(s) used for the user’s email address (e.g.,
mail
)
- ID: LDAP attribute(s) used as the unique user ID (e.g.,
- CA File (optional): If using
ldaps
, you must provide the root CA certificate of the AD/LDAP server to establish trust. From the command line, you can cat and paste the contents of your CA cert. - After entering all required values, click Add to create the identity provider, or Cancel to discard changes.
- Name: A unique name for the identity provider (e.g.,
Step 6: Validate AD Connectivity and Test AD User Login on OpenShift
After configuring the LDAP identity provider for AD in OpenShift, it’s critical to verify that the integration works correctly. This step confirms:
- The Active Directory connection (including certificates and bind credentials) is functional.
- AD users can successfully authenticate and log in.
Validating these early helps detect any issues with LDAP filters, credentials, or certificate trust before users start accessing production resources.
Verify Bind DN Connectivity to Active Directory from OAuth Server Pods
Before testing AD user logins on OpenShift, confirm that the OpenShift OAuth server pods can reach Active Directory over LDAPS using the configured Bind DN credentials. This step ensures that the OpenShift authentication components can successfully connect to the AD server.
oc get pods -n openshift-authentication
NAME READY STATUS RESTARTS AGE
oauth-openshift-9965df6cd-7j7mh 1/1 Running 0 11m
oauth-openshift-9965df6cd-8h7mq 1/1 Running 0 12m
oauth-openshift-9965df6cd-gvc7g 1/1 Running 0 12m
So, login to one of the pods:
oc rsh -n openshift-authentication oauth-openshift-9965df6cd-7j7mh
You will drop into the Pods shell. You can verify the OS and install required LDAP utilities as mentioned above.
sh-5.1# cat /etc/os-release | head -n2
NAME="Red Hat Enterprise Linux"
VERSION="9.4 (Plow)"
sh-5.1#
Since this is a RHEL 9, let’s install openldap-clients packages:
yum install openldap-clients -y
Next, use ldapsearch
command to test the connection and authentication to your AD server. Since we’re using LDAPS, and have created a ConfigMap containing the AD LDAPS CA root certificate in the previous step (Step 5), this certificate is stored inside the OAuth pod at the following path:
/var/config/user/idp/0/configMap/v4-0-config-user-idp-0-ca/ca.crt
Similarly, the bind password created via the secret in step 4 is stored at:
/var/config/user/idp/0/secret/v4-0-config-user-idp-0-bind-password/bindPassword
The 0
in both paths corresponds to the position of the identity provider in the OAuth configuration’s identityProviders
list. Since this is the only IdP configured in our setup, it is at index 0. If you have multiple identity providers (for example, an htpasswd
provider before the LDAP provider), the index will change accordingly and you should adjust the path to match.
You can then run the command below to test the connection. Let’s list the groups in our OU:
ldapsearch -x -H ldaps://dc01.kifarunix.com:636 \
-D "cn=read-only,ou=ServiceAccounts,dc=kifarunix,dc=com" \
-w `cat /var/config/user/idp/0/secret/v4-0-config-user-idp-0-bind-password/bindPassword` \
-b "ou=accessgroups,dc=kifarunix,dc=com" \
-o "TLS_CACERT=/var/config/user/idp/0/configMap/v4-0-config-user-idp-0-ca/ca.crt" \
dn \
-LLL
Sample output;
dn: OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=OCP-Admins,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=OCP-Infra,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=OCP-Developers,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=OCP-CyberSec,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=OCP-ViewOnly,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=ERP-Admins,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=DBA-Admins,OU=AccessGroups,DC=kifarunix,DC=com
dn: CN=OCP-All,OU=AccessGroups,DC=kifarunix,DC=com
This confirms that the AD LDAPS configuration is functional inside OpenShift.
Exit the pod when done.
exit
Test AD User Login via OpenShift Console and CLI
After validating the Bind DN connection, test user authentication to confirm the LDAP Identity Provider (IdP) is working as expected.
OpenShift Web Console:
- If you’re already logged into the OpenShift web console, log out first. Otherwise, open the console URL in a private/incognito browser window to avoid session interference.
- On the login screen, you should see a list of configured identity providers.
- Select your Active Directory / LDAP IdP (e.g.,
win-ad-idp
). - Enter your AD user credentials and try logging in.
If successful, you’ll be redirected to the OpenShift dashboard with the user session initialized.

To test login from the CLI obtain the API address:
oc whoami --show-server
Sample API:
https://api.ocp.kifarunix.com:6443
Then login as AD user:
oc login -u <your-ad-username> https://<your-cluster-api>:6443
For example:
oc login -u b.colly https://api.ocp.kifarunix.com:6443
When prompted, provide the AD user password.
Console URL: https://api.ocp.kifarunix.com:6443/console
Authentication required for https://api.ocp.kifarunix.com:6443 (openshift)
Username: b.colly
Password:
Login successful.
You don't have any projects. You can try to create a new project, by running
oc new-project
kifarunix@ocp-bastion:~/ocp-upi$ oc whoami
b.colly
Step 7: Synchronize AD Groups with OpenShift groups
After confirming that AD authentication is working, the next step is to configure authorization in order to be able to control what authenticated AD users can do in OpenShift.
Rather than assigning permissions individually, you can synchronize Active Directory (AD) groups into OpenShift groups using an LDAPSyncConfig
custom resource. This allows you to map AD group memberships to OpenShift roles (e.g., admin
, edit
, view
, or cluster-admin
, e.t.c), enabling centralized and scalable access control.
Synchronizing AD Groups with OpenShift groups brings about:
- Scalability: Managing permissions through AD groups is far more efficient than assigning roles to individual users.
- Centralized Management: Permissions are controlled through existing AD infrastructure, reducing OpenShift-specific administration.
- RBAC Integration: Synced groups become OpenShift
Group
objects, which can be directly bound to cluster or project roles.
OpenShift supports group synchronization from LDAP directories using three common schemas for defining group membership:
- Active Directory: Designed for environments where user entries list group membership via the
memberOf
attribute. OpenShift infers group associations by querying users, without querying group objects directly. This method is ideal when you only need to sync group membership, not group metadata. - RFC 2307: Based on traditional UNIX-style LDAP schemas like OpenLDAP, where group entries store user lists using attributes such as
member
ormemberUid
. User entries typically do not reference their groups. This schema is well-suited for POSIX-compliant directories and offers fine-grained filtering and control. - Augmented Active Directory: A hybrid approach for Active Directory environments that queries both user and group entries. Groups define their members using the
member
attribute, while users can also be queried for context. This schema supports syncing group metadata and allows more precise targeting of groups and users.
In this setup, we are using RFC 2307 schema because our AD setup uses standard member-based group relationships and supports direct querying of group members. It gives us precise control over group and user queries, making it better suited for our structured OU-based group model (OU=AccessGroups
)..
The process of synchronizing Active Directory (AD) groups into OpenShift follows these steps:
- Define an LDAPSyncConfig YAML file that describes your AD structure and group query logic.
- Perform an initial group synchronization using the
oc adm groups sync
command. - (Optional) Set up a CronJob to automate and schedule regular group syncs.
Create the LDAP Sync Configuration
Below is our sample configuration. Note that for a one-off sync using the oc adm groups sync
command:
- you must manually type the bind password (bindPassword: “yourbindPassword”) on the YAML
- specify the path to the CA certificate file (ca: ./ad-ldaps-ca.crt) on the local host where the command is run.
However, for automated syncs (e.g., via a CronJob), the bind password and CA certificate must be accessible within the pod, typically by mounting them from a Kubernetes Secret
and ConfigMap
.
cat ad-groups-sync-config.yaml
apiVersion: v1
kind: LDAPSyncConfig
url: ldaps://dc01.kifarunix.com:636
bindDN: "CN=read-only,OU=ServiceAccounts,DC=kifarunix,DC=com"
bindPassword: "yourbindPassword"
ca: ./ad-ldaps-ca.crt
insecure: false
groupUIDNameMapping: {}
rfc2307:
groupsQuery:
baseDN: OU=AccessGroups,DC=kifarunix,DC=com
scope: sub
derefAliases: never
filter: (&(objectClass=group)(cn=OCP-*)(!(cn=OCP-All)))
pageSize: 0
groupUIDAttribute: dn
groupNameAttributes: [ cn ]
groupMembershipAttributes: [ member ]
usersQuery:
baseDN: DC=kifarunix,DC=com
scope: sub
derefAliases: never
pageSize: 0
userUIDAttribute: dn
userNameAttributes: [ sAMAccountName ]
tolerateMemberNotFoundErrors: true
tolerateMemberOutOfScopeErrors: true
Before you can proceed, log back into OpenShift as an admin user.
oc login -u kubeadmin
Run Initial One-off AD Groups Sync to OpenShift
To perform a one-time LDAP group sync, you can run the following command from a machine with oc
access (e.g., a bastion host):
Dry run:
oc adm groups sync --sync-config=./ad-groups-sync-config.yaml
This command reads your LDAP configuration from the ad-sync-config.yaml
file and prints the specified AD groups into OpenShift to stdout.
To write the groups to OpenShift, confirm the task:
oc adm groups sync --sync-config=./ad-groups-sync-config.yaml --confirm
Sample command output for my setup:
group/OCP-Admins
group/OCP-CyberSec
group/OCP-Developers
group/OCP-Infra
group/OCP-ViewOnly
If you want some level of verbosity, add the option, –loglevel=8.
You can also utilize the whitelist or blacklist option to restrict which groups to sync. Refer to oc adm groups sync –help.
You can verify the imported groups with:
oc get groups
NAME USERS
OCP-Admins b.colly
OCP-CyberSec r.roe
OCP-Developers a.smith
OCP-Infra
OCP-ViewOnly
Get group details on OpenShift:
oc describe group OCP-Admins
See result:
Name: OCP-Admins
Created: 2 minutes ago
Labels: openshift.io/ldap.host=dc01.kifarunix.com
Annotations: openshift.io/ldap.sync-time=2025-08-22T15:30:03Z
openshift.io/ldap.uid=CN=OCP-Admins,OU=AccessGroups,DC=kifarunix,DC=com
openshift.io/ldap.url=dc01.kifarunix.com:636
Users: b.colly
Note, if for some reasons you need to desync AD groups from OpenShift, you can simply delete the synced groups using:
oc delete group <group-name>
This removes them from OpenShift without affecting the original groups in Active Directory.
Also check:
oc adm prune groups --help
Set Up Automatic AD Group Sync in OpenShift Using a CronJob
You can automate synchronization of AD groups into OpenShift by scheduling a periodic CronJob. This is useful for keeping your OpenShift RBAC in sync with changes in Active Directory.
To proceed, ensure:
- You are logged into the cluster as a cluster admin.
- An LDAP Identity Provider (IDP). This is already configured above.
- You have created:
- A secret containing the AD bind credentials.
- A ConfigMap containing the AD CA certificate.
Hence create a new project for the AD Groups sync CronJob. You can use any suitable name for your project:
oc new-project ad-group-sync
Remember the bind password secret and CA certificate ConfigMap we created before:
oc get secret,cm -n openshift-config
NAME TYPE DATA AGE
secret/ad-binddn-secret Opaque 1 45h
...
NAME DATA AGE
configmap/ad-ldaps-ca-cert 1 46h
...
Copy them from openshift-config
to your new project above.
oc get secret ad-binddn-secret -n openshift-config -o yaml | \
sed 's/namespace: openshift-config/namespace: ad-group-sync/' | oc apply -f -
oc get configmap ad-ldaps-ca-cert -n openshift-config -o yaml | \
sed 's/namespace: openshift-config/namespace: ad-group-sync/' | oc apply -f -
Confirm they there on your project:
oc get secret,cm
NAME TYPE DATA AGE
secret/ad-binddn-secret Opaque 1 65s
NAME DATA AGE
configmap/ad-ldaps-ca-cert 1 6s
configmap/kube-root-ca.crt 1 5m59s
configmap/openshift-service-ca.crt 1 5m59s
Next, create a service account that will be used to grant the CronJob pods the appropriate permissions to perform the group sync operation.
oc create sa ad-group-syncer
Next, create a ClusterRole that defines the permissions required for the CronJob pods to perform group synchronization operations. The required permissions include the ability to get, list, create, and update OpenShift group resources;
oc create clusterrole ad-group-syncer --verb=get,list,create,update --resource=groups.user.openshift.io
Create a ClusterRoleBinding that links the previously created ClusterRole to the ServiceAccount, granting the CronJob pods the necessary permissions.
oc create clusterrolebinding ad-group-syncer --clusterrole=ad-group-syncer --serviceaccount=ad-group-sync:ad-group-syncer
Now, you have to create the LDAPSyncConfig as a configmap. As such, edit the LDAPSyncConfig
configuration above and update the bindPassword
and ca
fields to point to the appropriate file paths where the bind password secret and CA certificate will be mounted. We will configure the sync CronJob to mount the corresponding Kubernetes Secret and ConfigMap into the container at the specified paths. This ensures that the LDAP bind credentials and TLS certificate are securely and consistently available during each sync operation.
Here is our updated LDAPSyncConfig file:
cat ad-groups-sync-config.yaml
apiVersion: v1
kind: LDAPSyncConfig
url: ldaps://dc01.kifarunix.com:636
bindDN: "CN=read-only,OU=ServiceAccounts,DC=kifarunix,DC=com"
bindPassword:
file: "/etc/secrets/bindPassword"
ca: /etc/ldap-ca/ca.crt
insecure: false
groupUIDNameMapping: {}
rfc2307:
groupsQuery:
baseDN: OU=AccessGroups,DC=kifarunix,DC=com
scope: sub
derefAliases: never
filter: (&(objectClass=group)(cn=OCP-*)(!(cn=OCP-All)))
pageSize: 0
groupUIDAttribute: dn
groupNameAttributes: [ cn ]
groupMembershipAttributes: [ member ]
usersQuery:
baseDN: DC=kifarunix,DC=com
scope: sub
derefAliases: never
pageSize: 0
userUIDAttribute: dn
userNameAttributes: [ sAMAccountName ]
tolerateMemberNotFoundErrors: true
tolerateMemberOutOfScopeErrors: true
Then create a configmap;
oc create cm ad-groups-sync-config --from-file=ad-groups-sync-config.yaml
And finally, create the CronJob. Below is a manifest file we will use to create our cronjob.
cat ad-group-sync-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: ad-group-syncer
namespace: ad-group-sync
spec:
schedule: "*/30 * * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
backoffLimit: 0
ttlSecondsAfterFinished: 1800
template:
spec:
serviceAccountName: ad-group-syncer
containers:
- name: ad-group-sync
image: registry.redhat.io/openshift4/ose-cli:latest
command:
- "/bin/bash"
- "-c"
- |
oc adm groups sync --sync-config=/etc/config/ad-groups-sync-config.yaml --confirm
volumeMounts:
- name: ad-sync-config
mountPath: /etc/config
- name: ad-bind-password
mountPath: /etc/secrets
- name: ad-ca-cert
mountPath: /etc/ldap-ca
volumes:
- name: ad-sync-config
configMap:
name: ad-groups-sync-config
- name: ad-ca-cert
configMap:
name: ad-ldaps-ca-cert
- name: ad-bind-password
secret:
secretName: ad-binddn-secret
restartPolicy: Never
terminationGracePeriodSeconds: 30
activeDeadlineSeconds: 500
dnsPolicy: "ClusterFirst"
This CronJob runs the oc adm groups sync
command every 30 minutes to synchronize AD groups into OpenShift. It mounts the LDAP sync config file, bind password secret, and CA certificate into the container, and uses a dedicated service account (ad-group-syncer
) with the required ClusterRole
permissions to manage OpenShift group objects.
The apply the cronjob yaml to create it.
oc apply -f ad-group-sync-cronjob.yaml
Confirm the job is created:
oc get cronjobs
NAME SCHEDULE TIMEZONE SUSPEND ACTIVE LAST SCHEDULE AGE
ad-group-syncer */30 * * * * False 0 41s
NB: We reduced the schedule time to every two minutes to allow us verify if all is working as expected without having to wait for 30 mins.
So, by now, the cronjob should have already ran.
oc get jobs
NAME STATUS COMPLETIONS DURATION AGE
ad-group-syncer-29264618 Complete 1/1 6s 4m49s
ad-group-syncer-29264620 Complete 1/1 6s 2m49s
ad-group-syncer-29264622 Complete 1/1 5s 49s
Check the status of the latest Job(s):
oc describe job ad-group-syncer-29264622
Name: ad-group-syncer-29264622
Namespace: ad-group-sync
Selector: batch.kubernetes.io/controller-uid=039ab3ce-50db-4407-8e98-cf7f5012ba5d
Labels: batch.kubernetes.io/controller-uid=039ab3ce-50db-4407-8e98-cf7f5012ba5d
batch.kubernetes.io/job-name=ad-group-syncer-29264622
controller-uid=039ab3ce-50db-4407-8e98-cf7f5012ba5d
job-name=ad-group-syncer-29264622
Annotations: batch.kubernetes.io/cronjob-scheduled-timestamp: 2025-08-22T15:42:00Z
Controlled By: CronJob/ad-group-syncer
Parallelism: 1
Completions: 1
Completion Mode: NonIndexed
Suspend: false
Backoff Limit: 0
TTL Seconds After Finished: 1800
Start Time: Fri, 22 Aug 2025 15:42:00 +0000
Completed At: Fri, 22 Aug 2025 15:42:05 +0000
Duration: 5s
Pods Statuses: 0 Active (0 Ready) / 1 Succeeded / 0 Failed
Pod Template:
Labels: batch.kubernetes.io/controller-uid=039ab3ce-50db-4407-8e98-cf7f5012ba5d
batch.kubernetes.io/job-name=ad-group-syncer-29264622
controller-uid=039ab3ce-50db-4407-8e98-cf7f5012ba5d
job-name=ad-group-syncer-29264622
Service Account: ad-group-syncer
Containers:
ad-group-sync:
Image: registry.redhat.io/openshift4/ose-cli:latest
Port:
Host Port:
Command:
/bin/bash
-c
oc adm groups sync --sync-config=/etc/config/ad-groups-sync-config.yaml --confirm
Environment:
Mounts:
/etc/config from ad-sync-config (rw)
/etc/ldap-ca from ad-ca-cert (rw)
/etc/secrets from ad-bind-password (rw)
Volumes:
ad-sync-config:
Type: ConfigMap (a volume populated by a ConfigMap)
Name: ad-groups-sync-config
Optional: false
ad-ca-cert:
Type: ConfigMap (a volume populated by a ConfigMap)
Name: ad-ldaps-ca-cert
Optional: false
ad-bind-password:
Type: Secret (a volume populated by a Secret)
SecretName: ad-binddn-secret
Optional: false
Node-Selectors:
Tolerations:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 3m19s job-controller Created pod: ad-group-syncer-29264622-jdrq8
Normal Completed 3m14s job-controller Job completed
The output shows the Job completed successfully:
- Pods Status:
1 Succeeded / 0 Failed
means the Pod ran and finished without errors. - Events:
Job completed
confirms the Job ran to completion. - The Pod named
ad-group-syncer-29264622-jdrq8
was created and completed.
Check the Pods created by the Job:
oc get pods -n ad-group-sync --selector=job-name=<job-name>
View the logs of the Pod to confirm the group sync operation:
oc logs <pod-name> -n ad-group-sync
Look for success messages or errors from the oc adm groups sync
command.
(Optional) Watch pod status in real-time:
oc get pods -n ad-group-sync -w
Step 8: Configure Authorization with RBAC
Once users and groups are synced, use RBAC to explicitly assign permissions.
OpenShift follows a default-deny model. For example, I am currently logged as AD user, Bob Colly (b.colly):
oc whoami
b.colly
If try to run some command, you may get a Forbidden message.
oc get groups
Error from server (Forbidden): groups.user.openshift.io is forbidden: User "b.colly" cannot list resource "groups" in API group "user.openshift.io" at the cluster scope
Hence, you must bind roles directly to users or groups to grant access. OpenShift uses the usual Kubernetes RBAC components:
- RoleBindings: Assign Roles to users/groups within projects.
- ClusterRoles: Define permissions across the entire cluster.
- Roles: Define permissions within specific projects/namespaces.
- ClusterRoleBindings: Assign ClusterRoles to users/groups cluster-wide
So, to begin, login as a cluster admin:
oc whoami
kube:admin
Then, you can now map groups to specific rols. For example, let’s assign the OCP-Admins group some admin rights on the cluster.
oc adm policy add-cluster-role-to-group cluster-admin OCP-Admins
And now, any user who is a member of the OCP-Admins
group will be granted cluster-admin
privileges across the OpenShift cluster.
As an admin user, you can now verify access for the members of the group. For example, b.colly is a member of OCP-Admins group. Let’s check their permissions:
oc auth can-i '*' '*' --all-namespaces --as="b.colly" --as-group=OCP-Admins
Since user via the OCP-Admins group is in cluster-admin
role, this should return yes
for all queries.
Step 9: Validate Active Directory User Permissions
After syncing your AD groups and assigning roles, it’s important to verify that users have the expected access in OpenShift. This can be done via the web console or CLI like we did above.
Using the OpenShift Web Console:
- Log out of the console if you’re currently logged in.
- Log in using the credentials of an AD user (e.g.,
b.colly
) who belongs to a synced group with permissions (e.g.,OCP-Admins
). - If the user has cluster-level permissions (e.g.,
cluster-admin
), they will see options like:- Cluster Settings
- Cluster Operators
- Custom Resource Definitions
- If the user does not have sufficient permissions, these options will be hidden.
Validate AD User Permissions via CLI:
- Log in to the CLI as the AD user:
oc login -u r.roe
- Run a command to check permissions, for example, list groups:
oc get groups
- If the user is an admin, the command will return the list of groups.
- If the user is not an admin, you will see a “forbidden” error message like:
Error from server (Forbidden): groups.user.openshift.io is forbidden: User "r.roe" cannot list resource "groups" in API group "user.openshift.io" at the cluster scope
Step 10: Create Custom Roles if Needed
If the default roles (such as admin
, edit
, or view
) don’t meet your requirements, you can create a custom role.
Example custom role YAML:
custom-role.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: custom-role
namespace: my-project
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
Apply the role:
oc apply -f custom-role.yaml
Bind the custom role to a group in the specific namespace:
oc adm policy add-role-to-group custom-role ocp-viewonly -n my-project
Read more on:
- Assign Roles to Users and Groups in Kubernetes Cluster
- Introduction to Role-Based Access Control (RBAC) in Kubernetes
As a best practice, ensure:
- Least Privilege: Start with view and escalate as needed.
- Group-Based: Prefer binding to groups over individual users for scalability.
- Auditing: Regularly review roles and cluster roles.
- Avoid Defaults: Don’t modify built-in roles; create new ones.
- Testing: After changes, log in as an AD user and test access (e.g., oc get pods).
Considerations for Removing the kubeadmin
Account
After integrating OpenShift with Active Directory (AD), you may want to remove the default kubeadmin
account for security reasons. However, be cautious:
- If AD becomes unreachable, and
kubeadmin
is removed, you could be locked out of the cluster. - Ensure AD is highly available before removing
kubeadmin
(e.g., multiple LDAP endpoints, DNS failover). - Consider adding a fallback identity provider (e.g., HTPasswd) with a local admin account for emergencies.
Do not delete the kubeadmin
credentials until you have tested HA for AD authentication and/or implemented a fallback identity provider.
Conclusion
By integrating OpenShift with Active Directory and properly configuring authentication, group synchronization, and RBAC, you enable centralized, secure access management for your cluster. Ensure high availability for AD services and retain a fallback admin method before removing the kubeadmin
account to avoid access disruption