OpenShift offers the capability to leverage a Directory Service as an authentication source for user lookup. However, it lacks native functionality for automatic group synchronization into its Identity Management system. To achieve group syncing, we will implement a workaround solution. This involves deploying a cronjob that synchronizes groups from the source LDAP (FreeIPA in this instance) to OpenShift's OAuth service.
Start by creating a dedicated namespace to encapsulate all the resources required for the automated synchronization of LDAP groups with OpenShift.
$ cat << EOF > 0-namespace.yml
---
apiVersion: v1
kind: Namespace
metadata:
name: ldap-group-sync
...
EOF
$ oc apply -f 0-namespace.yml
Given the use of LDAPS with certificates signed by a custom Certificate Authority (CA), it is necessary to create:
- A ConfigMap to store the CA certificate.
- A Secret to securely store the password for the service account used for LDAP lookups."
$ oc -n ldap-group-sync create configmap ldap-cacert --from-file ca.crt=/etc/ipa/ca.crt
$ oc -n ldap-group-sync create secret generic ldap-bindpw --from-literal bindPassword='super-secure-password-for-ldap-bind-user'
The jobs executed by the CronJob will require elevated privileges to manage group configurations and memberships. To address this requirement, we will create:
- A ServiceAccount
- A ClusterRole to define the necessary permissions
- A RoleBinding to associate the ClusterRole with the ServiceAccount.
$ cat << EOF > 1-serviceaccount.yml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: ldap-group-syncer
namespace: ldap-group-sync
...
EOF
$ oc apply -f 1-serviceaccount.yml
The Clusterrole adds privileges to manage group objects:
$ cat << EOF > 2-clusterrole.yml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
namespace: ldap-group-sync
name: ldap-group-syncer
rules:
- apiGroups:
- user.openshift.io
resources:
- groups
verbs:
- get
- list
- create
- update
...
EOF
$ oc apply -f 2-clusterrole.yml
Definition for the Clusterrolebinding tying it all together:
$ cat << EOF > 3-clusterrolebinding.yml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ldap-group-syncer
subjects:
- kind: ServiceAccount
name: ldap-group-syncer
namespace: ldap-group-sync
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ldap-group-syncer
...
EOF
$ oc apply -f 3-clusterrolebinding.yml
The subsequent step involves creating a ConfigMap. This ConfigMap will encapsulate the LDAP Sync Configuration. This configuration encompasses details such as attribute mappings, base search parameters, filters, and the bind account credential references:
$ cat << EOF > 4-configmap.yml
---
apiVersion: v1
kind: ConfigMap
metadata:
namespace: ldap-group-sync
name: ldap-group-syncer
data:
sync.yaml: |
---
apiVersion: v1
kind: LDAPSyncConfig
url: ldaps://ipa03.archyslife.lan:636
insecure: false
ca: /etc/ldap-ca/ca.crt
bindDN: uid=openshift-bind,cn=users,cn=accounts,dc=archyslife,dc=lan
bindPassword:
file: /etc/secrets/bindPassword
rfc2307:
groupsQuery:
baseDN: 'cn=groups,cn=accounts,dc=archyslife,dc=lan'
scope: sub
derefAliases: never
pageSize: 0
filter: (cn=ocpadmins)
groupUIDAttribute: dn
groupNameAttributes: [ cn ]
groupMembershipAttributes: [ member ]
usersQuery:
baseDN: 'cn=users,cn=accounts,dc=archyslife,dc=lan'
scope: sub
derefAliases: never
pageSize: 0
userUIDAttribute: dn
userNameAttributes: [ uid ]
tolerateMemberNotFoundErrors: false
tolerateMemberOutOfScopeErrors: false
...
...
EOF
$ oc apply -f 4-configmap.yml
The last piece of the puzzle is the CronJob configuration:
$ cat << EOF > 5-cronjob.yml
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: ldap-group-syncer
namespace: ldap-group-sync
spec:
timeZone: "Europe/Prague"
schedule: "*/30 * * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
backoffLimit: 0
ttlSecondsAfterFinished: 1800
template:
spec:
restartPolicy: Never
terminationGracePeriodSeconds: 30
activeDeadlineSeconds: 500
dnsPolicy: ClusterFirst
serviceAccountName: ldap-group-syncer
containers:
- name: ldap-group-sync
image: registry.redhat.io/openshift4/ose-cli@sha256:a0fc3e52059468c0176d917e026310d91230f276913086ba678635179373a11a
command:
- "/bin/bash"
- "-c"
- "oc adm groups sync --sync-config=/etc/config/sync.yaml --confirm"
volumeMounts:
- mountPath: /etc/config
name: ldap-sync-volume
- mountPath: /etc/secrets
name: ldap-bind-password
- mountPath: /etc/ldap-ca
name: ldap-ca-cert
volumes:
- name: ldap-sync-volume
configMap:
name: ldap-group-syncer
- name: ldap-bind-password
secret:
secretName: ldap-bindpw
- name: ldap-ca-cert
configMap:
name: ldap-cacert
...
EOF
$ oc apply -f 5-cronjob.yml
This CronJob will trigger the execution of jobs. These jobs will subsequently spawn pods. These pods will then facilitate the synchronization of groups from the source LDAP directory, as defined within the ConfigMap, into the OpenShift environment.
While technically optional, this next step is highly recommended. It involves binding ClusterRoles to groups, which will be automatically synchronized from the CronJob previously configured.
$ cat << EOF > 6-clusterrolebinding.yml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ocpadmins-cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: ocpadmins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
...
EOF
$ oc apply -f 6-clusterrolebinding.yml
This Clusterrolebinding will automatically provide all members of the 'ocpadmins' with the 'cluster-admin' clusterrole.
Comments
Post a Comment