OpenLDAP for Testing Locally
Motivation
Enterprise middleware components usually requires integration with enterprise identity providers - such as Windows Active Directory. There are many vendors in this space, but luckily there is a common protocol that can talk to most of these in a standard way. We have LDAP - Lightweight Directory Access Protocol and the opensource tool, OpenLDAP.
If you’ve ever had to integrate with these components in the past, you’d understand that everyone sets up their directory trees differently. There’s probably best practices on how to organize the tree, and where/how to store certain attributes, but everyone customizes it for their specific organization. That can cause quite a headache when it comes time for integration, such as for Authentication and Authorization.
Standing up your own containerized OpenLDAP server is quick and painless way to test integration points, especially working in a disconnected environment.
Lastly, I’m a big Simpsons fan, hence why you’ll see the Simpsons-based test data!
Image
The image being used is https://hub.docker.com/r/openshift/openldap-2441-centos7/
. Even though this may not be the latest version of OpenLDAP, and it has a bold disclaimer that this is only meant to be used internally for testing their Openshift project, it still provides enough functionality for local testing.
One thing to note is the certificate it uses is expired, so the ldaps://
protocol won’t be able to establish a trusted secure connection. It probably doesn’t matter for testing purposes though. If you really want to use this though, just turn off the certificate check by passing an environment variable to your ldap commands.
Configuration
An example LDIF
is provided here for convenience. Customize this for your specific use-case, or use your own LDIF
file.
sh-4.2$ cat sample.ldif
## DEFINE DIT ROOT/BASE/SUFFIX ####
## uses RFC 2377 format
## replace example and com as necessary below
## or for experimentation leave as is
## dcObject is an AUXILLIARY objectclass and MUST
## have a STRUCTURAL objectclass (organization in this case)
# this is an ENTRY sequence and is preceded by a BLANK line
## FIRST Level hierarchy - people
## uses mixed upper and lower case for objectclass
# this is an ENTRY sequence and is preceded by a BLANK line
dn: ou=intranet,dc=example,dc=com
ou: intranet
objectclass: organizationalunit
dn: ou=people,ou=intranet,dc=example,dc=com
ou: people
description: All people in organisation
objectclass: organizationalunit
dn: ou=groups,ou=intranet,dc=example,dc=com
ou: groups
description: generic groups branch
objectclass: organizationalunit
## SECOND Level hierarchy
## ADD a single entry under FIRST (people) level
# this is an ENTRY sequence and is preceded by a BLANK line
# the ou: Human Resources is the department name
dn: cn=Homer Simpson,ou=people,ou=intranet,dc=example,dc=com
objectclass: inetOrgPerson
cn: Homer Simpson
sn: Simpson
uid: hsimpson
userpassword: 123456
homephone: 555-555-5555
mail: homer@simpson.com
description: test account
dn: cn=Marge Simpson,ou=people,ou=intranet,dc=example,dc=com
objectclass: inetOrgPerson
cn: Marge Simpson
sn: Simpson
uid: mbsimpson
userpassword: 123456
homephone: 555-555-5555
mail: marge@simpson.com
description: test account
dn: cn=Lisa Simpson,ou=people,ou=intranet,dc=example,dc=com
objectclass: inetOrgPerson
cn: Lisa Simpson
sn: Simpson
uid: lsimpson
userpassword: 123456
homephone: 555-555-5555
mail: lisa@simpson.com
description: test account
dn: cn=Bart Simpson,ou=people,ou=intranet,dc=example,dc=com
objectclass: inetOrgPerson
cn: Bart Simpson
sn: Simpson
uid: bsimpson
userpassword: 123456
homephone: 555-555-5555
mail: bart@simpson.com
description: test account
dn: cn=Maggie Simpson,ou=people,ou=intranet,dc=example,dc=com
objectclass: inetOrgPerson
cn: Maggie Simpson
sn: Simpson
uid: msimpson
userpassword: 123456
homephone: 555-555-5555
mail: maggie@simpson.com
description: test account
dn: cn=Kirk Van Houten,ou=people,ou=intranet,dc=example,dc=com
objectclass: inetOrgPerson
cn: Kirk Van Houten
sn: Van Houten
uid: kvanhouten
userpassword: 123456
homephone: 555-555-5555
mail: kirk@vanhouten.com
description: test account
dn: cn=Luann Van Houten,ou=people,ou=intranet,dc=example,dc=com
objectclass: inetOrgPerson
cn: Luann Van Houten
sn: Van Houten
uid: lvanhouten
userpassword: 123456
homephone: 555-555-5555
mail: luann@vanhouten.com
description: test account
dn: cn=Milhouse Van Houten,ou=people,ou=intranet,dc=example,dc=com
objectclass: inetOrgPerson
cn: Milhouse Van Houten
sn: Van Houten
uid: mvanhouten
userpassword: 123456
homephone: 555-555-5555
mail: milhouse@vanhouten.com
description: test account
dn: cn=Clancy Wiggum,ou=people,ou=intranet,dc=example,dc=com
objectclass: inetOrgPerson
cn: Clancy Wiggum
sn: Wiggum
uid: cwiggum
userpassword: 123456
homephone: 555-555-5555
mail: clancy@wiggum.com
description: test account
dn: cn=Sarah Wiggum,ou=people,ou=intranet,dc=example,dc=com
objectclass: inetOrgPerson
cn: Sarah Wiggum
sn: Wiggum
uid: swiggum
userpassword: 123456
homephone: 555-555-5555
mail: sarah@wiggum.com
description: test account
dn: cn=Ralph Wiggum,ou=people,ou=intranet,dc=example,dc=com
objectclass: inetOrgPerson
cn: Ralph Wiggum
sn: Wiggum
uid: rwiggum
userpassword: 123456
homephone: 555-555-5555
mail: ralph@wiggum.com
description: test account
dn: cn=Simpsons,ou=groups,ou=intranet,dc=example,dc=com
cn: Simpsons
description: The Simpsons group
objectclass: groupOfNames
member: cn=Homer Simpson,ou=people,ou=intranet,dc=example,dc=com
member: cn=Marge Simpson,ou=people,ou=intranet,dc=example,dc=com
member: cn=Bart Simpson,ou=people,ou=intranet,dc=example,dc=com
member: cn=Lisa Simpson,ou=people,ou=intranet,dc=example,dc=com
member: cn=Maggie Simpson,ou=people,ou=intranet,dc=example,dc=com
dn: cn=Van Houtens,ou=groups,ou=intranet,dc=example,dc=com
cn: Van Houtens
description: The Van Houtens group
objectclass: groupOfNames
member: cn=Kirk Van Houten,ou=people,ou=intranet,dc=example,dc=com
member: cn=Luann Van Houten,ou=people,ou=intranet,dc=example,dc=com
member: cn=Milhouse Van Houten,ou=people,ou=intranet,dc=example,dc=com
dn: cn=Wiggums,ou=groups,ou=intranet,dc=example,dc=com
cn: Wiggums
description: The Wiggums group
objectclass: groupOfNames
member: cn=Clancy Wiggum,ou=people,ou=intranet,dc=example,dc=com
member: cn=Sarah Wiggum,ou=people,ou=intranet,dc=example,dc=com
member: cn=Ralph Wiggum,ou=people,ou=intranet,dc=example,dc=com
Note that the image honors some environment variables to change the default values, such as changing the administrative bind account name. See the Github page https://github.com/openshift/openldap for a full list of all the variables.
Deployment
OCP
It’s fairly easy to just click on the deploy image button within the Openshift UI. Even the most underpowered systems will deploy this in less than a minute. The real bottleneck is network bandwidth though, as the image weighs in at 355MB.
Docker
Running this locally also works, assuming you have Docker installed.
docker run -it --rm openshift/openldap-2441-centos7
Podman
This container image unfortunately runs as root, so there is a little bit of work to get it to run correctly. I never got around to actually figuring this out, but if it’s something you’d still like to see, email me and we can mob this problem together.
Useful Commands
If you visit the Github site, you’ll see what the default username and passwords are. Most of the commands require you to bind to an administrative account. Here are some useful commands for interacting with OpenLDAP.
Searching
ldapsearch -h <host> -w admin -D "cn=Manager,dc=example,dc=com" -b "dc=example,dc=com"
With SSL, but ignoring certificate checks.
LDAPTLS_REQCERT=never ldapsearch -w admin -D "cn=Manager,dc=example,dc=com" -b "dc=example,dc=com" -H ldaps://localhost:636 -vvv
Sample Response
# extended LDIF
#
# LDAPv3
# base <dc=example,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# example.com
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
dc: example
o: example
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
Adding
ldapadd -h <host> -w admin -D "cn=Manager,dc=example,dc=com" -f sample.ldif
Sample Response
adding new entry "ou=intranet,dc=example,dc=com"
adding new entry "ou=people,ou=intranet,dc=example,dc=com"
adding new entry "ou=Test Engineering,ou=people,ou=intranet,dc=example,dc=com"
adding new entry "cn=Steve Tester,ou=people,ou=intranet,dc=example,dc=com"
Deleting
ldapdelete -h <host> -w admin -D "cn=Manager,dc=example,dc=com" "cn=Steve Tester,ou=people,ou=intranet,dc=example,dc=com"
ldapdelete -h <host> -w admin -D "cn=Manager,dc=example,dc=com" "ou=Test Engineering,ou=people,ou=intranet,dc=example,dc=com"
ldapdelete -h <host> -w admin -D "cn=Manager,dc=example,dc=com" "ou=people,ou=intranet,dc=example,dc=com"
ldapdelete -h <host> -w admin -D "cn=Manager,dc=example,dc=com" "ou=intranet,dc=example,dc=com" -h <host>