I decided to play around with keycloak and use OpenLDAP as the backend to store the user details. That sounds like a pretty simple thing to set up, and actually it was - that is until I noticed that when I modify a password in keycloak then it gets stored in plain text in the ldap database. Google told me it's easy to fix, you just need to use the ppolicy overlay and set the olcPPolicyHashCleartext option to true. The first problem I found out is that recent versions of OpenLDAP use a slapd.d configuration directory rather than a slapd.conf file, so most of the helpful advice I had found didn't work. The second problem was that I was always getting the error message

modifying entry "olcDatabase={0}config,cn=config"
ldap_modify: Insufficient access (50)

This was even after using the ldapmodify -Y EXTERNAL -H ldapi:/// trick which seemed to work for everyone else. In the end my only solution was to edit the files in /etc/openldap/slapd.d which say AUTO-GENERATED FILE - DO NOT EDIT!! along the top. I know it says do not edit, and it seems to have a checksum in there to make sure you don't edit it, but it seemed to be my only option. This is obviously not the recommended way to fix the Insufficient access message, but if you have tried everything else then this works.

So, the first thing to do was give myself access to the cn=config database. That could be done by editing the olcRootDN and olcRootPW in slapd.d. First create a password for the admin user

# slappasswd 
New password: 
Re-enter new password: 

Then stop your openldap server (on slackware that is /etc/rc.d/rc.openldap stop) and edit the file slapd.d/cn=config/olcDatabase={0}config.ldif (which is /etc/openldap/slapd.d/cn=config/olcDatabase={0}config.ldif on slackware). Look for the line saying olcRootDN: cn=config and modify it to add cn=admin to it, also add the new line olcRootPW with the password generated earlier. It should end up something like this

# CRC32 4a06bf20
dn: olcDatabase={0}config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcAccess: {0}to *  by * none
olcAddContentAcl: TRUE
olcLastMod: TRUE
olcLastBind: FALSE
olcLastBindPrecision: 0
olcMaxDerefDepth: 15
olcReadOnly: FALSE
olcRootDN: cn=admin,cn=config
olcRootPW: {SSHA}iNZc7Yk4i2AldPEBFwe+nv+E+jZxRnGh
olcSyncUseSubentry: FALSE
olcMonitoring: FALSE
structuralObjectClass: olcDatabaseConfig
entryUUID: 06791820-97ee-4c5f-9381-8339eca954ca
creatorsName: cn=config
createTimestamp: 20230225185452Z
entryCSN: 20230225185452.280134Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20230225185452Z

Save the file and start your openldap server again.

You should now be able to use ldapmodify and ldapadd using your new password and the bind DN cn=admin,cn=config

ldapadd -x -D cn=admin,cn=config -W -f ./ppolicy_mod.ldif
ldapadd -x -D cn=admin,cn=config -W -f ./ppolicy.ldif

The first ldif file loads the ppolicy overlay module, and the second one enables olcPPolicyHashCleartext. Their contents are:

dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: ppolicy.la


dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcPPolicyConfig
olcOverlay: ppolicy
olcPPolicyDefault: cn=passwordDefault,ou=Policies,dc=example,dc=com
olcPPolicyHashCleartext: TRUE

Change example.com to whatever your domain is.

Previous Post Next Post