OpenShift Operator

In this article, I demonstrate a systematic method to configure LDAP user and group synchronization in Red Hat OpenShift, as well as OpenShift role-based access control (RBAC) for these LDAP users and groups. Following these steps makes the management of your LDAP users and groups within OpenShift much easier. I achieve this goal by demonstrating:

  • How to validate your ldap parameters with ldaptool prior to installing OpenShift.
  • How to enable LDAP authentication in OpenShift for specific LDAP groups and organization units.
  • The scripts and commands that let you synchronize members of your LDAP groups to OpenShift, which in turn lets you apply custom OpenShift RBAC rules on specific users or groups.

My assumptions

For the purpose of this article, I assume the following:

  • You have a working LDAP service.
  • The only two LDAP groups allowed to authenticate to your OpenShift environment are ocp-cluster-admins and ocp-cluster-users and are associated with ou=OPENSHIFT in your ldap tree.
  • You have assigned ocp-cluster-admins to user ocpadminuser1, and ocp-cluster-users to user ocpuser1.

This article shows one of the many ways to configure LDAP for OpenShift. Because different users in ocp-cluster-users will have different roles within your Red Hat OpenShift environment, this task can be automated or centrally managed, but that process will not be discussed in detail here.

Note that this article deliberately uses mixed cases (upper- and lowercase) in various sections to demonstrate case sensitivity within OpenShift versus LDAP. However, if you wish to minimize problems with OpenShift's case sensitivity, stick to lowercase for everything.

LDAP details

Identify all of your LDAP details prior to commencing your OpenShift installation. For this article, I use the following details:

ldap hostname: myldap.mydomain
ldap bind dn: CN=OPENSHIFT-BU,ou=users,o=MyOrg
ldap bind password: mypassword
ldap ocp admins group DN: cn=ocp-cluster-admins,ou=OPENSHIFT,o=MyOrg
ldap ocp users group DN: cn=ocp-cluster-users,ou=OPENSHIFT,o=MyOrg

Ideally, all your secret credentials should be managed via Red Hat Ansible Vault.

LDAP parameter and credential testing

For your tests to provide reliable results, confirm you have users in both groups. Before defining the OpenShift inventory parameters and the scripts used to synchronize ldap groups, it is important to ensure all of your ldap settings are correct, independent of OpenShift.

I tested my ldap connection with the details mentioned in the previous section using ldapsearch, and I also wanted to make sure that I could see the users in my groups, as this is what OpenShift will be seeing:

$ ldapsearch -x -LLL -D "CN=OPENSHIFT-BU,ou=users,o=MyOrg" -w mypassword -H ldap://myldap.mydomain:389 -b ou=users,o=MyOrg -s sub "(|(memberof=cn=ocp-cluster-admins,ou=OPENSHIFT,o=MyOrg)(memberof=cn=ocp-cluster-users,ou=OPENSHIFT,o=MyOrg))" "CN"

dn: cn=ocp-cluster-admins,ou=OPENSHIFT,o=MyOrg
CN: adminuser1

dn: cn=ocp-cluster-users,ou=OPENSHIFT,o=MyOrg
CN: ocpuser1

After that, it is important to identify what ldap fields are listed when you perform an ldap search for one of your users (e.g., ocpuser1):

$ ldapsearch -x -LLL -h myldap.mydomain -D "CN=OPENSHIFT-BU,ou=users,o=MyOrg" -w mypassword -b "ou=users,o=MyOrg" -s sub "cn=ocpuser1"
dn: CN=ocpuser1,ou=users,o=MyOrg
groupMembership: cn=ocp-cluster-users,ou=OPENSHIFT,o=MyOrg
UID: myuid
DESCRIPTION: OpenShift Cluster User 1
SN: ocpuser1
OBJECTCLASS: top
OBJECTCLASS: person
cn: ocpuser1

Note that these values can be different based on your LDAP schema and design. In this case, the attributes of interest are DN, UID, and CN.

Red Hat OpenShift inventory parameters

Reference:

I personally find LDAP connection information in OpenShift inventories very confusing. Here, I deconstruct it for clarity (notice the "attributes" section below):

openshift_master_identity_providers=[

{
'name': 'myldap', 
'challenge': 'true', 
'login': 'true', 
'kind': 'LDAPPasswordIdentityProvider', 
'attributes': {'DN' : ['DN'], 'UID': ['UID'], 'CN': ['CN']}, 
'bindDN': 'CN=OPENSHIFT-BU,ou=users,o=MyOrg', 
'bindPassword': 'mypassword', 
'ca': '', 
'insecure': 'true', 
'url': 'ldap://myldap.mydomain:389/ou=users,o=MyOrg?CN??
(|
(memberof=cn=ocp-cluster-admins,ou=OPENSHIFT,o=MyOrg)
(memberof=cn=ocp-cluster-users,ou=OPENSHIFT,o=MyOrg)
)'
}

]

Then, once I have all my details clear, I remove all of the new lines and unnecessary spaces. The code becomes:

openshift_master_identity_providers=[{'name': 'myldap', 'challenge': 'true', 'login': 'true', 'kind': 'LDAPPasswordIdentityProvider', 'attributes': {'DN' : ['DN'], 'UID': ['UID'], 'CN': ['CN']}, 'bindDN': 'CN=OPENSHIFT-BU,ou=users,o=MyOrg', 'bindPassword': 'mypassword', 'ca': '', 'insecure': 'true', 'url': 'ldap://myldap.mydomain:389/ou=users,o=MyOrg?CN??(|(memberof=cn=ocp-cluster-admins,ou=OPENSHIFT,o=MyOrg)(memberof=cn=ocp-cluster-users,ou=OPENSHIFT,o=MyOrg))'}]

If you wish to add htpasswd authentication for contingency (for example, just to have a local admin user), include it as another identity provider. For example:

openshift_master_identity_providers=[{htpasswd fileds},{ldap fields}]

Red Hat OpenShift post-install configuration

Once installation completes, ldap users in the groups identified earlier can authenticate to the master API (with the oc login command) but will not have any access by default. If you want your users to have proper role based access, you will need to perform two steps. The first is synchronizing LDAP groups to OpenShift groups. This task needs to be done periodically, or every time a new user is added to ldap (either via crontab or a CI/CD pipeline). Doing so allows Red Hat OpenShift to see the LDAP groups and users as its own users.

Second, RBAC rules need to be granted to OpenShift groups or users, synchronized from ldap. I demonstrate this manually, but ideally, you should automate this process.

Step 1: Synchronize ldap groups

Reference:

Create the file /root/ldap_group_sync.yml on your master node with the following content (the comments are not part of the file, but instead are there for elaboration):

# LDAP is case insensitive, but OpenShift is not, so all LDAP parameters have been converted to lower case as per https://access.redhat.com/solutions/3232051 (under "Case Sensitivity")
kind: LDAPSyncConfig
apiVersion: v1
url: ldap://myldapserver:389
insecure: true
ca: ""
bindDN: "cn=openshift-bu,ou=users,o=MyOrg"
bindPassword: "mypassword"
rfc2307:
    groupsQuery:
        baseDN: "ou=openshift,o=MyOrg"
        scope: sub
        filter: (|(cn=ocp-cluster-admins)(cn=ocp-cluster-users))
        derefAliases: never
        timeout: 0
        pageSize: 0
    groupUIDAttribute: dn
    groupNameAttributes: [ cn ]
    groupMembershipAttributes: [ member ]
    usersQuery:
        basedn: "ou=users,o=MyOrg"
        scope: sub
        derefAliases: never
        pageSize: 0
    userUIDAttribute: dn
    userNameAttributes: [ cn ]
    tolerateMemberNotFoundErrors: true
    tolerateMemberOutOfScopeErrors: true

Run a test:

[root@master ~]# oc adm groups sync --sync-config=/root/ldap_groups.yml
apiVersion: v1
items:
- apiVersion: user.openshift.io/v1
  kind: Group
  metadata:
    annotations:
      openshift.io/ldap.sync-time: 2019-07-21T07:16:1101000
      openshift.io/ldap.uid: cn=ocp-cluster-admins,OU=OPENSHIFT,o=MyOrg
      openshift.io/ldap.url: myldapserver:389
    creationTimestamp: null
    labels:
      openshift.io/ldap.host: myldapserver
    name: ocp-cluster-admins
  users:
  - ocpadminuser1
- apiVersion: user.openshift.io/v1
  kind: Group
  metadata:
    annotations:
      openshift.io/ldap.sync-time: 2019-07-21T07:16:1101000
      openshift.io/ldap.uid: cn=ocp-cluster-users,OU=OPENSHIFT,o=MyOrg
      openshift.io/ldap.url: myldapserver:389
    creationTimestamp: null
    labels:
      openshift.io/ldap.host: myldapserver
    name: ocp-cluster-users
  users:
  - ocpuser1
kind: List
metadata: {}

If you get the following error, you can find the fix here:

For group ignoring member search for entry with dn would search outside of the base dn specified

If you run the command above, this will only be a dry run. To ensure it actually performs the user and group synchronization, add --confirm to the end:

[root@master ~]# oc adm groups sync --sync-config=/root/ldap_groups.yml --confirm
group/ocp-cluster-admins
group/ocp-cluster-users

Now, check to see your groups:

# oc get groups
NAME               USERS
ocp-cluster-admins ocpadminuser1
ocp-cluster-users  ocpuser1

Step 2: Create custom OpenShift RBAC rules for synchronized LDAP users and groups

Ideally, you should automate and centrally manage this process. One of the many ways to automate the assignment of roles for all your different users would be via Red Hat Ansible. However, because we have only two users, doing this manually is not too painful. I want my ocp-cluster-admins group to have the cluster-admin role, and my ocp-cluster-users to have the project edit role:

root@master ~]# oc adm policy add-cluster-role-to-group cluster-admin ocp-cluster-admins
role "cluster-admin" added: "ocp-cluster-admins"
[root@master ~]# oc adm policy add-role-to-group edit ocp-cluster-users
role "edit" added: "ocp-cluster-users"

Conclusion

To ensure you have a relatively smooth experience with OpenShift RBAC for your LDAP groups and users, validate all your LDAP details with ldaptool. Additionally, it is best to adopt the lower case for all your parameters (except passwords) to avoid future problems caused by differing case-sensitivity between systems (e.g., ldap vs. OpenShift). Finally, automation of roles for different users is the best way forward.

Last updated: March 28, 2023