This is a multi-part article where I will cover different areas of configuration of OpenLDAP server in CentOS 7 Linux node. You can use below links to refer different parts of this tutorial
Basics LDAP Tutorial for
Beginners – Understanding Terminologies & Usage
Step-by-Step Tutorial: Install and Configure OpenLDAP
Step-by-Step
Tutorial:Configure OpenLDAP with TLS certificates CentOS 7 Linux
Step-by-Step
Tutorial:Configure LDAP client to authenticate with LDAP server

Install and Configure OpenLDAP
In my last article I gave you an overview on OpenLDAP and it’s
terminologies. Before starting with this article to install and
configure openldap in Linux you must be aware of basic terminologies.
For the demonstration of this article I am using CentOS 7. In this
article I will share detailed steps to install and configure OpenLDAP on
Linux platform using ldapmodify. In legacy releases of openldap, the
configuration was performed using slapd.conf but now the configuration
is kept incn=config database. So we will install and configure
OpenLDAP usingcn=config and ldapmodify.
Installing OpenLDAP
To get the OpenLDAP server and client components up and running, these packages are required on Fedora, RHEL, and CentOS systems:
- openldap-2*.rpm- Provides the configuration files and libraries for OpenLDAP.
- openldap-clients*.rpm - Provides the client programs needed for accessing and modifying OpenLDAP directories.
- openldap-servers*.rpm- Provides the servers (
slapd,slurpd) and other utilities necessary to configure and run LDAP.
openldap-servers*.rpm package.
[root@ldap-server ~]# yum -y install openldap-clients openldap-servers
We make sure that the slapd service is configured to boot
automatically, and we start the service.
[root@ldap-server ~ ]# systemctl start slapd
[root@ldap-server ~ ]# systemctl enable slapd
ln -s '/usr/lib/systemd/system/slapd.service' '/etc/systemd/system/multi-user.target.wants/slapd.service'
Check the status of the service
[root@ldap-server ~]# systemctl status slapd
● slapd.service - OpenLDAP Server Daemon
Loaded: loaded (/usr/lib/systemd/system/slapd.service; disabled; vendor preset: disabled)
Active: active (running) since Sat 2019-02-09 21:46:23 IST; 17min ago
Docs: man:slapd
man:slapd-config
man:slapd-hdb
man:slapd-mdb
file:///usr/share/doc/openldap-servers/guide.html
Process: 17350 ExecStart=/usr/sbin/slapd -u ldap -h ${SLAPD_URLS} $SLAPD_OPTIONS (code=exited, status=0/SUCCESS)
Process: 17336 ExecStartPre=/usr/libexec/openldap/check-config.sh (code=exited, status=0/SUCCESS)
Main PID: 17352 (slapd)
Tasks: 3
Memory: 13.5M
CGroup: /system.slice/slapd.service
└─17352 /usr/sbin/slapd -u ldap -h ldapi:/// ldap:///
Feb 09 22:01:32 ldap-server.example.com slapd[17352]: conn=1007 op=0 RESULT tag=97 err=0 text=
Feb 09 22:01:32 ldap-server.example.com slapd[17352]: conn=1007 op=1 MOD dn="olcDatabase={0}config,cn=config"
Feb 09 22:01:32 ldap-server.example.com slapd[17352]: conn=1007 op=1 MOD attr=olcRootDN
Feb 09 22:01:32 ldap-server.example.com slapd[17352]: ldif_read_file: checksum error on "/etc/openldap/slapd.d/cn=config/olcDatabase={0}config.ldif"
Feb 09 22:01:32 ldap-server.example.com slapd[17352]: conn=1007 op=1 RESULT tag=103 err=0 text=
Feb 09 22:01:32 ldap-server.example.com slapd[17352]: conn=1007 op=2 MOD dn="olcDatabase={0}config,cn=config"
Feb 09 22:01:32 ldap-server.example.com slapd[17352]: conn=1007 op=2 MOD attr=olcRootPW
Feb 09 22:01:32 ldap-server.example.com slapd[17352]: conn=1007 op=2 RESULT tag=103 err=0 text=
Feb 09 22:01:32 ldap-server.example.com slapd[17352]: conn=1007 op=3 UNBIND
Feb 09 22:01:32 ldap-server.example.com slapd[17352]: conn=1007 fd=11 closed
Customizing the Installation
Once installed, we have to generate a password for the admin user. In
this example, we use a simple password: “redhat”
[root@ldap-server cn=config]# slappasswd
New password:
Re-enter new password:
{SSHA}6zHtA20qkTmdLrJSfxo+VV3QLGS7m0CZ
/etc/openldap/slapd.d/slapd.conf in
which the configuration of the OpenLDAP server was kept. But now the
configuration is kept in the LDAP database itself.
[root@ldap-server ~]# ls /etc/openldap/slapd.d/
cn=config cn=config.ldif
Modifying Objects
Replace olcSuffix and olcRootDN attribute
OpenLDAP actually stores its information in storage back ends. We could
think of these back ends as the databases used by OpenLDAP. One of the
most used back ends has always been the Berkeley DB back ends, such as
bdb, or the more recent hdb. The information stored in the hdb back
end can be found in the
/etc/openldap/slapd.d/cn=config/olcDatabase={2}hdb.ldif file.
In an LDIF file, we first identify the element we want to add, change,
etc. To uniquely identify an element, we use the dn (distinguished
name) attribute, which was created precisely for that reason. So, the
first line of our LDIF file could be something like this:
dn: olcDatabase={2}hdb,cn=config
Next, we specify if we want to add an attribute, modify it, etc.
changeType: modify
If we want to modify an entry, we also must clarify whether we’ll be replacing an attribute, deleting it, etc.
replace: olcSuffix
And, finally, we type the new value of the modified attribute.
olcSuffix: dc=example,dc=com
You’ll see many LDIF examples throughout the article, but for now, let’s
get back to the
/etc/openldap/s-lapd.d/cn=config/olcDatabase={2}hdb.ldif file. We have
to modify (at least) these two entries:
olcSuffix: dc=my-domain,dc=com
olcRootDN: cn=Manager,dc=my-domain,dc=com
To make all these changes with ldapmodify , we have to prepare an LDIF
file such as this:
[root@ldap-server ~]# cat my_config.ldif
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=example,dc=com
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=admin,dc=example,dc=com
The first line identifies the main entry in the LDAP that we are going
to change. Just a moment ago, we saw the parameter olcSuffix inside
the /etc/openldap/slapd.d/cn=config/olcDatabase={2}hdb.ldif file. In
this file, the dn attribute is dn: olcDatabase={2}hdb, and as the file
is inside the config folder, the full dn attribute
is dn: olcDatabase={2}hdb,cn=config.
Another, and maybe better, way to identify the data we require to create
the LDIF file could be to use the ldapsearchcommand.
[root@ldap-server ~]# ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config olcDatabase=\*
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
# extended LDIF
#
# LDAPv3
# base <cn=config> with scope subtree
# filter: olcDatabase=*
# requesting: ALL
#
# {-1}frontend, config
dn: olcDatabase={-1}frontend,cn=config
objectClass: olcDatabaseConfig
objectClass: olcFrontendConfig
olcDatabase: {-1}frontend
# {0}config, config
dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external
,cn=auth" manage by * none
# {1}monitor, config
dn: olcDatabase={1}monitor,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {1}monitor
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external
,cn=auth" read by dn.base="cn=Manager,dc=my-domain,dc=com" read by * none
# {2}hdb, config
dn: olcDatabase={2}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {2}hdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=my-domain,dc=com
olcRootDN: cn=Manager,dc=my-domain,dc=com
olcDbIndex: objectClass eq,pres
olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub
# search result
search: 2
result: 0 Success
# numResponses: 5
# numEntries: 4
We save the LDIF file with an appropriate name, for example,
my_config.ldif, and we execute ldapmodify.
[root@ldap-server ~]# ldapmodify -Y EXTERNAL -H ldapi:/// -f my_config.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "olcDatabase={2}hdb,cn=config"
modifying entry "olcDatabase={2}hdb,cn=config"
Add olcRootPW attribute
To add a new attribute we use “add” and then the attribute name as
shown in the below example.
Here we create another LDIF file (my_config2.ldif) to add the
olcRootPW attribute.
[root@ldap-server ~]# cat my_config2.ldif
dn: olcDatabase={2}hdb,cn=config
changeType: modify
add: olcRootPW
olcRootPW: {SSHA}6zHtA20qkTmdLrJSfxo+VV3QLGS7m0CZ
And we execute ldapmodify again.
[root@ldap-server ~]# ldapmodify -Y EXTERNAL -H ldapi:/// -f my_config2.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "olcDatabase={2}hdb,cn=config"
Replace olcAccess attribute
We also have to allow access to the LDAP database to the admin user we
just specified before (cn=admin,dc=example,dc=com). If we take a look
at the olcDatabase={1}monitor.ldif, file we’ll see the following line:
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external, cn=auth" read by dn.base="cn=manager,dc=my-domain,dc=com" read by * none
We’ll have to edit the file or use ldapmodify to change the entry. If we use ldapmodify, the LDIF file should be something like this:
[root@ldap-server ~]# cat my_config3.ldif
dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external, cn=auth" read by dn.base="cn=admin,dc=example,dc=com" read by * none
Once again, we execute ldapmodify by passing the new LDIF file as a
parameter.
[root@ldap-server ~]# ldapmodify -Y EXTERNAL -H ldapi:/// -f my_config3.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "olcDatabase={1}monitor,cn=config"
Validate the new attribute values
Now we can check with ldapsearch whether the value for the attribute
was actually changed.
[root@ldap-server ~]# ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config olcDatabase=\*
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
# extended LDIF
#
# LDAPv3
# base <cn=config> with scope subtree
# filter: olcDatabase=*
# requesting: ALL
#
# {-1}frontend, config
dn: olcDatabase={-1}frontend,cn=config
objectClass: olcDatabaseConfig
objectClass: olcFrontendConfig
olcDatabase: {-1}frontend
# {0}config, config
dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external
,cn=auth" manage by * none
# {1}monitor, config
dn: olcDatabase={1}monitor,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {1}monitor
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external
, cn=auth" read by dn.base="cn=admin,dc=example,dc=com" read by * none
# {2}hdb, config
dn: olcDatabase={2}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {2}hdb
olcDbDirectory: /var/lib/ldap
olcDbIndex: objectClass eq,pres
olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub
olcRootPW: {SSHA}6zHtA20qkTmdLrJSfxo+VV3QLGS7m0CZ
olcSuffix: dc=example,dc=com
olcRootDN: cn=admin,dc=example,dc=com
# search result
search: 2
result: 0 Success
# numResponses: 5
# numEntries: 4
As we can see, the value was changed according to what we specified in the LDIF file.
Another tool we can use to check the configuration is the slaptest
command.
[root@ldap-server ~]# slaptest -u
config file testing succeeded
Adding Objects
Now we have to manually create an entry for dc=example,dc=com in our
LDAP server. The easiest way to do this is to create an LDIF file for
this entry and pass it to the ldapadd command.
So, we create a file named example.ldif, with the following content:
[root@ldap-server ~]# cat example.ldif
dn: dc=example,dc=com
objectClass: dcObject
objectClass: organization
dc: example
o: example
We specify a series of attributes, such as distinguished name (dn), domain component (dc), and organization (o). We also define the new entry as an object of the type dcObject and organization.
Now we execute ldapadd and pass it the example.ldif file as a parameter. We specify with (-f) the name of the file, the admin user (-D), and the password we defined for that admin user (-w).
[root@ldap-server ~]# ldapadd -f example.ldif -D cn=admin,dc=example,dc=com -w redhat
adding new entry "dc=example,dc=com"
We can check whether the entry was created successfully by using the ldapsearch command.
[root@ldap-server ~]# ldapsearch -x -b dc=example,dc=com
# extended LDIF
#
# LDAPv3
# base <dc=example,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# example.com
dn: dc=example,dc=com
objectClass: dcObject
objectClass: organization
dc: example
o: example
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
You just saw how to add the object dc=example,dc=com to our LDAP. Now
you’ll see how to add organizational units , groups, and users.
Adding an Organizational Unit
Maybe we’d like to have an organizational unit (OU) called users in
which to store all LDAP users. To do so, we’ll create a new LDIF file
named users.ldif, with the following content:
[root@ldap-server ~]# cat users.ldif
dn: ou=users,dc=example,dc=com
objectClass: organizationalUnit
ou: users
We execute ldapadd again to create the OU.
[root@ldap-server ~]# ldapadd -f users.ldif -D cn=admin,dc=example,dc=com -w redhat
adding new entry "ou=users,dc=example,dc=com"
Adding a User
We can now include a user inside the organizational unit. The procedure
is quite similar to what we have seen so far. First, we create a file
named archimedes.ldif, with the following content:
[root@ldap-server ~]# cat archimedes.ldif
dn: cn=Archimedes of Syracuse,ou=users,dc=example,dc=com
cn: Archimedes
sn: Syracuse
objectClass: inetOrgPerson
userPassword: eureka
uid: archimedes
Then we execute ldapadd
again.
[root@ldap-server ~]# ldapadd -f archimedes.ldif -x -D cn=admin,dc=example,dc=com -w redhat
adding new entry "cn=Archimedes of Syracuse,ou=users,dc=example,dc=com"
ldap_add: Invalid syntax (21)
additional info: objectClass: value #0 invalid per syntax
What this message means is that the object inetOrgPerson isn’t loaded
in the core schema, so we’ll have to include it. In the
/etc/openldap/schema folders, there are many LDIF files to extend the
schema when we need it. We can see there is an inetorgperson.ldif
file, which contains the schema definition for the inetOrgPerson
object.
The schema itself is contained in the LDAP database, so we can add new
definitions to it with the ldapadd command. As we’re going to modify
the configuration itself, instead of the data, we’ll authenticate
ourselves as the external root user (-Y EXTERNAL).
[root@ldap-server ~]# ldapadd -Y EXTERNAL -H ldapi:// -f /etc/openldap/schema/inetorgperson.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=inetorgperson,cn=schema,cn=config"
ldap_add: Other (e.g., implementation specific) error (80)
additional info: olcObjectClasses: AttributeType not found: "audio"
As we can see, we get an error, because the attribute type audio isn’t defined. So, we have to include this definition in the schema too .
If we perform a search of the string audio in the files located in the
/etc/openldap/schema/ folder, we’ll see that the attribute audio is
defined in the cosine.ldif file. So, we extend the schema with this
LDIF file first.
[root@ldap-server ~]# ldapadd -Y EXTERNAL -H ldapi:// -f /etc/openldap/schema/cosine.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=cosine,cn=schema,cn=config"
Now we do the same thing with the inetorgperson.ldif file.
[root@ldap-server ~]# ldapadd -Y EXTERNAL -H ldapi:// -f /etc/openldap/schema/inetorgperson.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=inetorgperson,cn=schema,cn=config"
Next we also add nis.ldif file
[root@ldap-server ~]# # ldapadd -Y EXTERNAL -H ldapi:// -f /etc/openldap/schema/nis.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=nis,cn=schema,cn=config"
Now we can add the user with the archimedes.ldif file we created
before.
[root@ldap-server ~]# ldapadd -f archimedes.ldif -x -D cn=admin,dc=example,dc=com -w redhat
adding new entry "cn=Archimedes of Syracuse,ou=users,dc=example,dc=com"
If at some point we have to take a look at the currently used schema, we
can use the slapcat command like this:
[root@ldap-server ~]# slapcat -b "cn=schema,cn=config"
dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/openldap/slapd.args
olcPidFile: /var/run/openldap/slapd.pid
olcTLSCACertificatePath: /etc/openldap/certs
olcTLSCertificateFile: "OpenLDAP Server"
olcTLSCertificateKeyFile: /etc/openldap/certs/password
structuralObjectClass: olcGlobal
entryUUID: 35694bfc-c0d9-1038-87ee-811b58b4e51a
creatorsName: cn=config
createTimestamp: 20190209170930Z
entryCSN: 20190209170930.732544Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20190209170930Z
--
--
<OUTPUT TRUNCATED>
--
--
dn: olcDatabase={2}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {2}hdb
olcDbDirectory: /var/lib/ldap
olcDbIndex: objectClass eq,pres
olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub
structuralObjectClass: olcHdbConfig
entryUUID: 3569c776-c0d9-1038-87f4-811b58b4e51a
creatorsName: cn=config
createTimestamp: 20190209170930Z
olcRootPW:: e1NTSEF9NnpIdEEyMHFrVG1kTHJKU2Z4bytWVjNRTEdTN20wQ1o=
olcSuffix: dc=example,dc=com
olcRootDN: cn=admin,dc=example,dc=com
entryCSN: 20190209171424.210710Z#000000#000#000000
modifiersName: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
modifyTimestamp: 20190209171424Z
Adding a Group
To add a
group, we repeat the same process . First we create the group.ldif
file with the following content:
[root@ldap-server ~]# cat group.ldif
dn: cn=scientists,ou=users,dc=example,dc=com
cn: scientists
objectClass: groupOfNames
member: cn=Archimedes of Syracuse,ou=users,dc=example,dc=com
And we add the group with ldapadd.
[root@ldap-server ~]# ldapadd -f group.ldif -x -D cn=admin,dc=example,dc=com -w redhat
adding new entry "cn=scientists,ou=users,dc=example,dc=com"
Deleting Objects
Apart from adding or editing, we can also delete objects from the LDAP
server. The procedure is even easier, as we don’t have to create any
LDIF file. We just execute ldapdel with the cn we want to delete.
[root@ldap-server ~]# ldapdelete "cn=Archimedes of Syracuse,ou=users,dc=example,dc=com" -D cn=admin,dc=example,dc=com -w redhat
We can check that the entry was actually suppressed.
[root@ldap-server ~]# ldapsearch -x -b "dc=example,dc=com" "(cn=Archimedes)"
# extended LDIF
#
# LDAPv3
# base <dc=example,dc=com> with scope subtree
# filter: (cn=Archimedes)
# requesting: ALL
#
# search result
search: 2
result: 0 Success
# numResponses: 1
Conclusion
In this tutorial I have shared step by step instructions to install and configure openldap from scratch on a CentOS 7 Linux node. I have tried to be descriptive while explaining every step throughout the tutorial, although I would recommend for freshers to first learn more about the openldap terminologies before jumping into the configuration.
Lastly I hope the steps from the article to install and configure OpenLDAP on Linux was helpful. So, let me know your suggestions and feedback using the comment section.
What’s Next
Now since our ldap server is configured, next we will
- Create TLS certificates to enable secure communication between ldap client and server.
- Configure LDAP Client using SSSD
References
I have used below external references for this tutorial guide
Learn CentOS Linux Network
Services
