Configuring Active Directory authentication with OpenShift 4
Understand AD LDAP structure and naming. Read the docs on the components
Create the OAuth config
# create a secret for the bindDN user password oc create secret generic ldap-bind-secret \ --from-literal=bindPassword=<secret> \ -n openshift-config # create the OAuth config file, you may want to update your existing or use # the GUI if you have more than one auth provider cat << EOF > ad-oauth.yaml apiVersion: config.openshift.io/v1 kind: OAuth name: cluster spec: identityProviders: - ldap: attributes: email: - mail id: - sAMAccountName name: - cn preferredUsername: - sAMAccountName bindDN: openshift-sa bindPassword: name: ldap-bind-secret insecure: false url: ldap://lab.lan/OU=Domain Users,DC=lab,DC=lan?sAMAccountName?sub?(&(objectClass=user)(|(memberOf:1.2.840.1135184.108.40.2061:=CN=OpenShift Admins,OU=Groups,OU=Domain Users,DC=lab,DC=lan)(memberOf:1.2.840.1135220.127.116.111:=CN=OpenShift Users,OU=Groups,OU=Domain Users,DC=lab,DC=lan))) mappingMethod: claim name: lab.lan type: LDAP EOF
memberOf:1.2.840.113518.104.22.1681:bit is important because we're wanting to allow only users of the specified group - and nested groups - to be allowed to authenticate. The
basednis very broad,
OU=Domain Users,DC=lab,DC=lan, so that all users are accounted for, even if they're spread across many OUs.
Also, I'm not using LDAPS here because it's a lab and I don't have it configured. You'll probably want to use it.
Apply the config,
oc apply -f ad-oauth.yaml, wait for the authentication cluster operator to update (
oc get co).
At this point, we can log into the cluster using Active Directory credentials. Users will be assinged the default
authenticatedrole and whatever permissions are associated with it.
OpenShift isn't aware of the user(s) until they log in for the first time, so if you were to check
oc get userimmediately, it would not reflect any AD users. Once you log in with the user account, it will show in the list.
With the above authentication configuration in place, we also want to configure authorization so that users are allowed - or not, as the case may be - to access resources.
Configure group syncing
OpenShift caches the groups and group membership, which means that we need to configure group syncing and pruning to ensure that users are able to (or not, as the case may be) connect as their group memebership in Active Directory is updated.
Importantly, we're using nested groups for membership, which means that we need to create an allow list and configure the sync config's
augmentedActiveDirectory.groupsQuerywith some specific options, see the docs here for more info.
# create the group sync config file # the groupUIDNameMapping is added to avoid spaces in the group names cat << EOF > ldap-sync.yaml kind: LDAPSyncConfig apiVersion: v1 url: ldap://lab.lan bindDN: openshift-sa bindPassword: '************' insecure: false groupUIDNameMapping: "CN=OpenShift Users,OU=Groups,OU=Domain Users,DC=lab,DC=lan": openshift-users "CN=OpenShift Admins,OU=Groups,OU=Domain Users,DC=lab,DC=lan": openshift-admins augmentedActiveDirectory: groupsQuery: derefAliases: never pageSize: 0 groupUIDAttribute: dn groupNameAttributes: [ cn ] usersQuery: baseDN: "OU=Domain Users,DC=lab,DC=lan" scope: sub derefAliases: never filter: (objectclass=person) pageSize: 0 userNameAttributes: [ sAMAccountName ] groupMembershipAttributes: [ "memberOf:1.2.840.113522.214.171.1241:" ] EOF # since we're using nested groups, we'll need an allow list as well cat << EOF > group-allowlist.txt CN=OpenShift Users,OU=Groups,OU=Domain Users,DC=lab,DC=lan CN=OpenShift Admins,OU=Groups,OU=Domain Users,DC=lab,DC=lan EOF # do a manual sync, leave off the --confirm if you want to check the result # without creating the groups in OpenShift oc adm groups sync \ --whitelist=group-allowlist.txt \ --sync-config=ldap-sync.yaml \ --confirm # check the groups are as expected oc get group
Groups, and their membership, need to be kept in sync with Active Directory. Arguably the easiest way to do this is via the Group Sync Operator, or you can use a
CronJob, see below for an example. Creating a
CronJobfor pruning is also recommended.
The default roles are explained here.
ClusterRolesto users and groups appropriately
For a namespace scoped
Role, use the format
oc adm policy add-role-to-user <role> <user> -n <project>, substituting
add-role-to-groupwhen using a group.
For a clsuter scoped
ClusterRole, use the format
oc adm policy add-cluster-role-to-user <role> <username>, substituting
add-cluster-role-to-groupwhen using a group.
To assign a group with cluster admin privileges, you would use the command
oc adm policy add-cluster-role-to-group cluster-admin openshift-admins
Group Sync CronJob
Thanks to examples.openshift.pub for this example.
Secretwith the relevant files
oc create secret generic ldap-sync \ --from-file=ldap-sync.yaml=ldap-sync.yaml \ --from-file=group-allowlist.txt=group-allowlist.txt
oc create clusterrole ldap-group-sync \ --verb=create,update,patch,delete,get,list \ --resource=groups.user.openshift.io
oc adm new-project ldap-sync oc create sa ldap-sync oc adm policy add-cluster-role-to-user ldap-group-sync \ -z ldap-sync \ -n ldap-sync
cat << EOF | oc apply -n ldap-sync -f - apiVersion: batch/v1beta1 kind: CronJob metadata: name: ldap-group-sync spec: schedule: '@hourly' suspend: false jobTemplate: spec: template: spec: serviceAccountName: ldap-sync restartPolicy: Never containers: - name: oc-cli command: - /bin/oc - adm - groups - sync - --whitelist=/ldap-sync/whitelist.txt - --sync-config=/ldap-sync/ldap-sync.yaml - --confirm image: registry.redhat.io/openshift4/ose-cli imagePullPolicy: Always volumeMounts: - mountPath: /ldap-sync/ name: config readOnly: true volumes: - name: config secret: defaultMode: 420 secretName: ldap-sync EOF