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

 

Step-by-Step Tutorial: Install and Configure OpenLDAP in CentOS 7 Linux

 

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 not the configuration is kept in cn=config database. So we will install and configure OpenLDAP using cn=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.
NOTE:
If you are configuring only the client side, you won’t need the openldap-servers*.rpm package.
NOTE:
On RHEL system you must have an active subscription to RHN or you can configure a local offline repository using which “yum” package manager can install the provided rpm and it’s dependencies.
[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
NOTE:
Formerly, there was a file named /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 book, 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: arch
imedesThen 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"

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

 

References
Learn CentOS Linux Network Services

 

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.

 

Leave a Reply

Your email address will not be published. Required fields are marked *