The blog for Design Patterns, Linux, HA and Myself!
The document presents the installation steps for OpenLDAP in an Ubuntu server and some practical examples of LDAP commands that will help you in setting up the OpenLDAP server once the installation is complete. This document is divided into the following topics:
Adding TLS for the OpenLDAP server using Nginx(To be updated soon)
In this step we will install the OpenLDAP server. I’ll be using the root
user for the installation. Here’s the OS
version:
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=21.04
DISTRIB_CODENAME=hirsute
DISTRIB_DESCRIPTION="Ubuntu 21.04"
NAME="Ubuntu"
VERSION="21.04 (Hirsute Hippo)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 21.04"
VERSION_ID="21.04"
VERSION_CODENAME=hirsute
UBUNTU_CODENAME=hirsute
OpenLDAP server can be installed using the following command:
$ apt install slapd ldap-utils
while the installation will be ongoing it will ask for the Administrator user’s password. We can add a temporary password here as we’ll change the Administrator password later in this document.
Please enter the same password for it to continue.
$ apt install slapd ldap-utils
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
:
:
Processing triggers for ufw (0.36-7.1)
Processing triggers for man-db (2.9.4-2)
Processing triggers for libc-bin (2.33-0ubuntu5)
Once the installation is complete, we can find the OpenLDAP server’s configuration in the /etc/ldap/sladp.d
directory:
$ cd /etc/ldap/slapd.d/
$ ls
'cn=config.ldif' 'cn=config'
$ tree
.
├── cn=config
│ ├── cn=module{0}.ldif
│ ├── cn=schema
│ │ ├── cn={0}core.ldif
│ │ ├── cn={1}cosine.ldif
│ │ ├── cn={2}nis.ldif
│ │ └── cn={3}inetorgperson.ldif
│ ├── cn=schema.ldif
│ ├── olcDatabase={0}config.ldif
│ ├── olcDatabase={-1}frontend.ldif
│ └── olcDatabase={1}mdb.ldif
└── cn=config.ldif
2 directories, 10 files
The configuration present here is in the LDAP directory format instead of a text file. To update the configuration we’ll
have to use the ldapmodify
command in which we’ll have to pass the ldif
files that will contain the updates.
Here’s the content of the olcDatabase={1}mdb.ldif
file. It contains the default Suffix(olcSuffix
), Administrator’s
Distinguished Name(olcRootDN
), and it’s password(olcRootPW
) along with the several other configuration keys.
$ cat cn\=config/olcDatabase\=\{1\}mdb.ldif
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 bc731387
dn: olcDatabase={1}mdb
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: {1}mdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=nodomain
olcAccess: {0}to attrs=userPassword by self
write by anonymous auth by * none
olcAccess: {1}to attrs=shadowLastChange by self
write by * read
olcAccess: {2}to * by * read
olcLastMod: TRUE
olcRootDN: cn=admin,dc=nodomain
olcRootPW:: e1NTSEF9amtIOXY5Sm1ScnJjTVNrUC***
olcDbCheckpoint: 512 30
olcDbIndex: objectClass eq
olcDbIndex: cn,uid eq
olcDbIndex: uidNumber,gidNumber eq
olcDbIndex: member,memberUid eq
olcDbMaxSize: 1073741824
structuralObjectClass: olcMdbConfig
entryUUID: b809a076-6545-103b-914f-910c8b7d4efd
creatorsName: cn=admin,cn=config
createTimestamp: 20210619122921Z
entryCSN: 20210619122921.571612Z#000000#000#000000
modifiersName: cn=admin,cn=config
modifyTimestamp: 20210619122921Z
Next, we’ll update the olcSuffix
, olcRootDN
and olcRootPW
configuration. To update the administrator’s password
we’ve to first encrypt the new password. We can use slappasswd
to do that:
$ slappasswd
New password:
Re-enter new password:
{SSHA}sZyeF53/dQio+iLUiBaHXKb2nL/NuWEj
Here’s the mdb.ldif
file that I’ve created for updating those configurations. I’ve changed the olcSuffix
to
dc=codiwan,dc=com
, olcRootDN
to cn=ldapadmin,dc=codiwan,dc=com
and olcRootPW
to the output of the previous
command.
$ cat ldap-changes/mdb.ldif
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=codiwan,dc=com
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=ldapadmin,dc=codiwan,dc=com
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcRootPW
# Same as the slappasswd command output
olcRootPW: {SSHA}sZyeF53/dQio+iLUiBaHXKb2nL/NuWEj
We can update the configuration using the ldapmodify
.
$ ldapmodify -Y EXTERNAL -H ldapi:/// \
-f ldap-changes/mdb.ldif
SASL/EXTERNAL authentication started
SASL SSF: 0
modifying entry "olcDatabase={1}mdb,cn=config"
modifying entry "olcDatabase={1}mdb,cn=config"
modifying entry "olcDatabase={1}mdb,cn=config"
Now that our configuration is complete we can move to the section on adding users and groups into OpenLDAP.
In this section we’ll create a dummy hierarchy containing two groups and two users and then we’ll perform the search
using ldapsearch
on those entries. The hierarchy looks like this:
dc=codiwan,dc=com
.People
and Groups
.People
organization unit there are two Persons, Alice
and Bob
.Groups
organization unit there are two Groups, codiwanadmin
and codiwangeneral
.Alice
is a member of codiwanadmin
.Bob
is a member of codiwangeneral
.The first step is to add the suffix:
$ cat ldap-changes/add-suffix.ldif
dn: dc=codiwan,dc=com
dc: codiwan
objectClass: top
objectClass: domain
$ ldapadd -x -D cn=ldapadmin,dc=codiwan,dc=com -W \
-f ldap-changes/add-suffix.ldif
Enter LDAP Password:
adding new entry "dc=codiwan,dc=com"
Then we create the two organization units:
People
$ cat ldap-changes/add-people-org-unit.ldif
dn: ou=People,dc=codiwan,dc=com
objectClass: organizationalUnit
ou: People
$ ldapadd -x -D cn=ldapadmin,dc=codiwan,dc=com -W \
-f ldap-changes/add-people-org-unit.ldif
Enter LDAP Password:
adding new entry "ou=People,dc=codiwan,dc=com"
Groups
$ cat ldap-changes/add-groups-org-unit.ldif
dn: ou=Groups,dc=codiwan,dc=com
objectClass: organizationalUnit
ou: Groups
$ ldapadd -x -D cn=ldapadmin,dc=codiwan,dc=com -W \
-f ldap-changes/add-groups-org-unit.ldif
Enter LDAP Password:
adding new entry "ou=Groups,dc=codiwan,dc=com"
Now we’ll add the two users: Alice
and Bob
:
$ cat ldap-changes/add-alice.ldif
dn: uid=alice,ou=People,dc=codiwan,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: alice
sn: Doe
givenName: Alice
cn: Alice Doe
displayName: Alice Doe
uidNumber: 10001
gidNumber: 5001
userPassword: {CRYPT}password
loginShell: /bin/bash
homeDirectory: /home/alice
$ ldapadd -x -D cn=ldapadmin,dc=codiwan,dc=com -W \
-f ldap-changes/add-alice.ldif
Enter LDAP Password:
adding new entry "uid=alice,ou=People,dc=codiwan,dc=com"
$ cat ldap-changes/add-bob.ldif
dn: uid=bob,ou=People,dc=codiwan,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: bob
sn: Doe
givenName: Bob
cn: Bob Doe
displayName: Bob Doe
uidNumber: 10002
gidNumber: 5001
userPassword: {CRYPT}password
loginShell: /bin/bash
homeDirectory: /home/bob
$ ldapadd -x -D cn=ldapadmin,dc=codiwan,dc=com -W \
-f ldap-changes/add-bob.ldif
Enter LDAP Password:
adding new entry "uid=bob,ou=People,dc=codiwan,dc=com"
The password for both these users can be ignored right now as we’ll update their passwords in the later steps in this
document. Their objectClass
is different from the previous entries we made for the organization units. Due to these
different organization units we can add the field like displayName
or givenName
because they are defined inside the
inetOrgPerson
objectClass.
Next we add the codiwanadmin
and codiwangeneral
groups:
$ cat ldap-changes/add-codiwan-admin-group.ldif
dn: cn=codiwanadmin,ou=Groups,dc=codiwan,dc=com
objectClass: posixGroup
cn: codiwanadmin
gidNumber: 5001
$ ldapadd -x -D cn=ldapadmin,dc=codiwan,dc=com -W -f \
ldap-changes/add-codiwan-admin-group.ldif
Enter LDAP Password:
adding new entry \
"cn=codiwanadmin,ou=Groups,dc=codiwan,dc=com"
$ cat ldap-changes/add-codiwan-general-group.ldif
dn: cn=codiwangeneral,ou=Groups,dc=codiwan,dc=com
objectClass: posixGroup
cn: codiwangeneral
gidNumber: 5002
$ ldapadd -x -D cn=ldapadmin,dc=codiwan,dc=com -W -f \
ldap-changes/add-codiwan-general-group.ldif
Enter LDAP Password:
adding new entry \
"cn=codiwangeneral,ou=Groups,dc=codiwan,dc=com"
Now that we’ve created our users, and the groups, we can now proceed to add the users into the groups.
Here we add Alice
user to the codiwanadmin
group and the user Bob
to the codiwangeneral
group:
$ cat ldap-changes/add-alice-to-codiwanadmin.ldif
dn: cn=codiwanadmin,ou=Groups,dc=codiwan,dc=com
changetype: modify
add: memberUid
memberUid: alice
$ ldapadd -x -D cn=ldapadmin,dc=codiwan,dc=com -W \
-f ldap-changes/add-alice-to-codiwanadmin.ldif
Enter LDAP Password:
modifying entry \
"cn=codiwanadmin,ou=Groups,dc=codiwan,dc=com"
$ cat ldap-changes/add-bob-to-codiwangeneral.ldif
dn: cn=codiwangeneral,ou=Groups,dc=codiwan,dc=com
changetype: modify
add: memberUid
memberUid: bob
$ ldapadd -x -D cn=ldapadmin,dc=codiwan,dc=com -W \
-f ldap-changes/add-bob-to-codiwangeneral.ldif
Enter LDAP Password:
modifying entry \
"cn=codiwangeneral,ou=Groups,dc=codiwan,dc=com"
You can notice here that we’ve used the uid
attribute to reference the users.
ldappasswd
As we’ve not configured the correct passwords for the users, let’s do it now. To update the Alice’s password execute:
$ ldappasswd -x -D cn=ldapadmin,dc=codiwan,dc=com -W \
-S uid=alice,ou=People,dc=codiwan,dc=com
New password:
Re-enter new password:
Enter LDAP Password:
We’re using the administrator user to update the password. The first and the second field is for the Alice’s password, however, the 3rd prompt is for the administrator’s password.
We perform the same operation for the user Bob as well:
$ ldappasswd -x -D cn=ldapadmin,dc=codiwan,dc=com -W \
-S uid=bob,ou=People,dc=codiwan,dc=com
New password:
Re-enter new password:
Enter LDAP Password:
Just like the administrator the user can also change their password:
$ ldappasswd -x -D uid=bob,ou=People,dc=codiwan,dc=com -W \
-S uid=bob,ou=People,dc=codiwan,dc=com
New password:
Re-enter new password:
Enter LDAP Password:
However, they cannot change someone else’s password:
$ ldappasswd -x -D uid=bob,ou=People,dc=codiwan,dc=com -W \
-S uid=alice,ou=People,dc=codiwan,dc=com
New password:
Re-enter new password:
Enter LDAP Password:
Result: Insufficient access (50)
$ ldappasswd -x -D uid=alice,ou=People,dc=codiwan,dc=com -W \
-S uid=bob,ou=People,dc=codiwan,dc=com
New password:
Re-enter new password:
Enter LDAP Password:
Result: Insufficient access (50)
ldapsearch
In this section we’ll look into ldapsearch
command to find the users.
Here’s a simple search query to find the user Bob. We’ve set the filter to (uid=bob)
.
$ ldapsearch -x -D "uid=alice,ou=People,dc=codiwan,dc=com" -W \
-b "ou=People,dc=codiwan,dc=com" '(uid=bob)'
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <ou=People,dc=codiwan,dc=com> with scope subtree
# filter: (uid=bob)
# requesting: ALL
#
# bob, People, codiwan.com
dn: uid=bob,ou=People,dc=codiwan,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: bob
sn: Doe
givenName: Bob
cn: Bob Doe
displayName:: Qm9iIERvZSA=
uidNumber: 10002
gidNumber: 5001
loginShell: /bin/bash
homeDirectory: /home/bob
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
The previous ldapsearch
was executed using the alice
user and this why we did not get the password field in the
results. If we execute the same search using the ldapadmin
then userPassword
field will be shown.
$ ldapsearch -x -D "cn=ldapadmin,dc=codiwan,dc=com" -W \
-b "ou=People,dc=codiwan,dc=com" '(uid=bob)'
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <ou=People,dc=codiwan,dc=com> with scope subtree
# filter: (uid=bob)
# requesting: ALL
#
# bob, People, codiwan.com
dn: uid=bob,ou=People,dc=codiwan,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: bob
sn: Doe
givenName: Bob
cn: Bob Doe
displayName:: Qm9iIERvZSA=
uidNumber: 10002
gidNumber: 5001
loginShell: /bin/bash
homeDirectory: /home/bob
userPassword:: e1NTSEF9RkhiTGFmZkIzM2
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
To search for the groups that the user Bob is part of, execute the following command, the filter criteria is
(memberuid=bob)
. We used to same attribute name to add the user into the group.
$ ldapsearch -x -D "cn=ldapadmin,dc=codiwan,dc=com" -W \
-b "dc=codiwan,dc=com" '(memberuid=bob)'
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <dc=codiwan,dc=com> with scope subtree
# filter: (memberuid=bob)
# requesting: ALL
#
# codiwangeneral, Groups, codiwan.com
dn: cn=codiwangeneral,ou=Groups,dc=codiwan,dc=com
objectClass: posixGroup
cn: codiwangeneral
gidNumber: 5002
memberUid: bob
# search result
search: 2
result: 0 Success
The process of removing a user from the group is very same as adding. Instead of the add
attribute we need to put the
delete
attribute:
$ cat ldap-changes/remove-bob-from-codiwangeneral.ldif
dn: cn=codiwangeneral,ou=Groups,dc=codiwan,dc=com
changetype: modify
delete: memberUid
memberUid: bob
$ ldapadd -x -D cn=ldapadmin,dc=codiwan,dc=com -W \
-f ldap-changes/remove-bob-from-codiwangeneral.ldif
Enter LDAP Password:
modifying entry "cn=codiwangeneral,ou=Groups,dc=codiwan,dc=com"
$ ldapsearch -x \
-D "cn=ldapadmin,dc=codiwan,dc=com" -W \
-b "dc=codiwan,dc=com" '(memberuid=bob)'
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <dc=codiwan,dc=com> with scope subtree
# filter: (memberuid=bob)
# requesting: ALL
#
# search result
search: 2
result: 0 Success
# numResponses: 1
Until now, we’ve not provided the OpenLDAP server’s URI to any of the commands we’ve used. This is because it has
started on the default host and the port without TLS. The configuration for the hostname and the port, along with the
other configuration, are present in the file /etc/default/slapd
. The hostname and port can be changed here:
$ cat slapd
# SLAPD_SERVICES="ldap:/// ldapi:///"
SLAPD_SERVICES="ldap://192.168.56.104:3389/"
Update the SLAPD_SERVICES
config to the desired host and the port and then restart the slapd
service:
$ systemctl restart slapd
$ systemctl status slapd
● slapd.service - LSB: OpenLDAP standalone server
Loaded: loaded (/etc/init.d/slapd; generated)
Drop-In: /usr/lib/systemd/system/slapd.service.d
└─slapd-remain-after-exit.conf
Pass the new hostname and port to the ldap commands using the -H
flag:
$ ldapsearch -x -H ldap://192.168.56.104:3389 \
-D "cn=ldapadmin,dc=codiwan,dc=com" -W \
-b "dc=codiwan,dc=com" '(memberuid=bob)'
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <dc=codiwan,dc=com> with scope subtree
# filter: (memberuid=bob)
# requesting: ALL
#
# search result
search: 2
result: 0 Success
# numResponses: 1