We will begin this article by outlining some LDAP basics (what it is, where it is used and why) and show how to set up a LDAP server and configure a client to authenticate against it using Red Hat Enterprise Linux 7 systems.
As we will see, there are several other possible application scenarios, but in this guide we will focus entirely on LDAP-based authentication. In addition, please keep in mind that due to the vastness of the subject, we will only cover its basics here, but you can refer to the documentation outlined in the summary for more in-depth details.
For the same reason, you will note that I have decided to leave out several references to man pages of LDAP tools for the sake of brevity, but the corresponding explanations are at a fingertip’s distance (man ldapadd, for example).
That said, let’s get started.
Our Testing Environment
Our test environment consists of two RHEL 7 boxes:
Server: 192.168.0.18. FQDN: rhel7.mydomain.com Client: 192.168.0.20. FQDN: ldapclient.mydomain.com
If you want, you can use the machine installed in Part 12: Automate RHEL 7 installations using Kickstart as client.
What is LDAP?
LDAP stands for Lightweight Directory Access Protocol and consists in a set of protocols that allows a client to access, over a network, centrally stored information (such as a directory of login shells, absolute paths to home directories, and other typical system user information, for example) that should be accessible from different places or available to a large number of end users (another example would be a directory of home addresses and phone numbers of all employees in a company).
Keeping such (and more) information centrally means it can be more easily maintained and accessed by everyone who has been granted permissions to use it.
The following diagram offers a simplified diagram of LDAP, and is described below in greater detail:
Explanation of above diagram in detail.
- An entry in a LDAP directory represents a single unit or information and is uniquely identified by what is called a Distinguished Name.
- An attribute is a piece of information associated with an entry (for example, addresses, available contact phone numbers, and email addresses).
- Each attribute is assigned one or more values consisting in a space-separated list. A value that is unique per entry is called a Relative Distinguished Name.
That being said, let’s proceed with the server and client installations.
Installing and Configuring a LDAP Server and Client
In RHEL 7, LDAP is implemented by OpenLDAP. To install the server and client, use the following commands, respectively:
# yum update && yum install openldap openldap-clients openldap-servers # yum update && yum install openldap openldap-clients nss-pam-ldapd
Once the installation is complete, there are some things we look at. The following steps should be performed on the server alone, unless explicitly noted:
1. Make sure SELinux does not get in the way by enabling the following booleans persistently, both on the server and the client:
# setsebool -P allow_ypbind=0 authlogin_nsswitch_use_ldap=0
Where allow_ypbind is required for LDAP-based authentication, and authlogin_nsswitch_use_ldap may be needed by some applications.
2. Enable and start the service:
# systemctl enable slapd.service # systemctl start slapd.service
Keep in mind that you can also disable, restart, or stop the service with systemctl as well:
# systemctl disable slapd.service # systemctl restart slapd.service # systemctl stop slapd.service
3. Since the slapd service runs as the ldap user (which you can verify with ps -e -o pid,uname,comm | grep slapd), such user should own the /var/lib/ldap directory in order for the server to be able to modify entries created by administrative tools that can only be run as root (more on this in a minute).
Before changing the ownership of this directory recursively, copy the sample database configuration file for slapd into it:
# cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG # chown -R ldap:ldap /var/lib/ldap
4. Set up an OpenLDAP administrative user and assign a password:
# slappasswd
as shown in the next image:
and create an LDIF file (ldaprootpasswd.ldif) with the following contents:
dn: olcDatabase={0}config,cn=config changetype: modify add: olcRootPW olcRootPW: {SSHA}PASSWORD
where:
- PASSWORD is the hashed string obtained earlier.
- cn=config indicates global config options.
- olcDatabase indicates a specific database instance name and can be typically found inside /etc/openldap/slapd.d/cn=config.
Referring to the theoretical background provided earlier, the ldaprootpasswd.ldif
file will add an entry to the LDAP directory. In that entry, each line represents an attribute: value pair (where dn, changetype, add, and olcRootPW are the attributes and the strings to the right of each colon are their corresponding values).
You may want to keep this in mind as we proceed further, and please note that we are using the same Common Names (cn=)
throughout the rest of this article, where each step depends on the previous one.
5. Now, add the corresponding LDAP entry by specifying the URI referring to the ldap server, where only the protocol/host/port fields are allowed.
# ldapadd -H ldapi:/// -f ldaprootpasswd.ldif
The output should be similar to:
and import some basic LDAP definitions from the /etc/openldap/schema
directory:
# for def in cosine.ldif nis.ldif inetorgperson.ldif; do ldapadd -H ldapi:/// -f /etc/openldap/schema/$def; done
6. Have LDAP use your domain in its database.
Create another LDIF file, which we will call ldapdomain.ldif
, with the following contents, replacing your domain (in the Domain Component dc=) and password as appropriate:
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=Manager,dc=mydomain,dc=com" read by * none dn: olcDatabase={2}hdb,cn=config changetype: modify replace: olcSuffix olcSuffix: dc=mydomain,dc=com dn: olcDatabase={2}hdb,cn=config changetype: modify replace: olcRootDN olcRootDN: cn=Manager,dc=mydomain,dc=com dn: olcDatabase={2}hdb,cn=config changetype: modify add: olcRootPW olcRootPW: {SSHA}PASSWORD dn: olcDatabase={2}hdb,cn=config changetype: modify add: olcAccess olcAccess: {0}to attrs=userPassword,shadowLastChange by dn="cn=Manager,dc=mydomain,dc=com" write by anonymous auth by self write by * none olcAccess: {1}to dn.base="" by * read olcAccess: {2}to * by dn="cn=Manager,dc=mydomain,dc=com" write by * read
Then load it as follows:
# ldapmodify -H ldapi:/// -f ldapdomain.ldif
7. Now it’s time to add some entries to our LDAP directory. Attributes and values are separated by a colon (:)
in the following file, which we’ll name baseldapdomain.ldif
:
dn: dc=mydomain,dc=com objectClass: top objectClass: dcObject objectclass: organization o: mydomain com dc: mydomain dn: cn=Manager,dc=mydomain,dc=com objectClass: organizationalRole cn: Manager description: Directory Manager dn: ou=People,dc=mydomain,dc=com objectClass: organizationalUnit ou: People dn: ou=Group,dc=mydomain,dc=com objectClass: organizationalUnit ou: Group
Add the entries to the LDAP directory:
# ldapadd -x -D cn=Manager,dc=mydomain,dc=com -W -f baseldapdomain.ldif
8. Create a LDAP user called ldapuser (adduser ldapuser), then create the definitions for a LDAP group in ldapgroup.ldif
.
# adduser ldapuser # vi ldapgroup.ldif
Add following content.
dn: cn=Manager,ou=Group,dc=mydomain,dc=com objectClass: top objectClass: posixGroup gidNumber: 1004
where gidNumber is the GID in /etc/group for ldapuser) and load it:
# ldapadd -x -W -D "cn=Manager,dc=mydomain,dc=com" -f ldapgroup.ldif
9. Add a LDIF file with the definitions for user ldapuser (ldapuser.ldif
):
dn: uid=ldapuser,ou=People,dc=mydomain,dc=com objectClass: top objectClass: account objectClass: posixAccount objectClass: shadowAccount cn: ldapuser uid: ldapuser uidNumber: 1004 gidNumber: 1004 homeDirectory: /home/ldapuser userPassword: {SSHA}fiN0YqzbDuDI0Fpqq9UudWmjZQY28S3M loginShell: /bin/bash gecos: ldapuser shadowLastChange: 0 shadowMax: 0 shadowWarning: 0
and load it:
# ldapadd -x -D cn=Manager,dc=mydomain,dc=com -W -f ldapuser.ldif
Likewise, you can delete the user entry you just created:
# ldapdelete -x -W -D cn=Manager,dc=mydomain,dc=com "uid=ldapuser,ou=People,dc=mydomain,dc=com"
10. Allow communication through the firewall:
# firewall-cmd --add-service=ldap
11. Last, but not least, enable the client to authenticate using LDAP.
To help us in this final step, we will use the authconfig utility (an interface for configuring system authentication resources).
Using the following command, the home directory for the requested user is created if it doesn’t exist after the authentication against the LDAP server succeeds:
# authconfig --enableldap --enableldapauth --ldapserver=rhel7.mydomain.com --ldapbasedn="dc=mydomain,dc=com" --enablemkhomedir --update
Summary
In this article we have explained how to set up basic authentication against a LDAP server. To further configure the setup described in the present guide, please refer to Chapter 13 – LDAP Configuration in the RHEL 7 System administrator’s guide, paying special attention to the security settings using TLS.
Feel free to leave any questions you may have using the comment form below.
This is about eighth tutorial on LDAP I have tried. Yet again, suffering by some issues – this time “ldap_bind: Invalid credentials (49)” while running query. The LDAP solution is so fragile and pain to administer. Looking at the logs – no suggestion at all that could go wrong. Considering the fact that the LDAP setup is “ten” commands and still going wrong is a joke.
Hi, I got this error
Created symlink from /etc/systemd/system/multi-user.target.wants/slapd.service to /usr/lib/systemd/system/slapd.service.
Job for slapd.service failed because the control process exited with error code. See “systemctl status slapd.service” and “journalctl -xe” for details.
Job for slapd.service failed because the control process exited with error code. See “systemctl status slapd.service” and “journalctl -xe” for details.
Hi, I am using CentOS 7, and getting the below error
Please let me know what to do.
@Sriram,
Please check your slapd.conf configuration and correct if any errors and restart the service again.
Check this thread – https://unix.stackexchange.com/questions/443528/failed-to-start-openldap-server-daemon
I get “ldap_sasl_interactive_bind_sL Local error (-2)” when I try to “ldapadd -H ldap:/// -f ldaprootpasswd.ldif” following the recipe here. Shouldn’t it be something like “ldapmodify” with EXTERNAL, etc… ?
Maybe you guys should verify this stuff.
If you end up with ldap_bind: Invalid credentials (49) play with the formatting of your .ldif files I’m using a windows admin tool called LDAP Admin and I noticed that olcRootPW was under olcDatabase={0}config and when I created it under {2}hdb the auth issues went away, its late and I’ve been fighting this all day, else I would validate what I got wrong in the .ldif I loaded before baseldapdomain.ldif.
I reformatted it like this and it was happy
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=Manager,dc=4uii,dc=com" read by * none
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=4uii,dc=com
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=Manager,dc=4uii,dc=com
dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}PASSWORD
dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {0}to attrs=userPassword,shadowLastChange by dn="cn=Manager,dc=4uii,dc=com" write by anonymous auth by self write by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by dn="cn=Manager,dc=4uii,dc=com" write by * read
Well that didn’t post as I thought I should. I using vi I hit tab in front of all the lines except the ones starting with dn and changetype.
How to change DN attribute in openldap-2.4.39
from dn: uid=66003310,ou=users,dc=hcl,dc=com
to dn: employeeNumber=66003310,ou=users,dc=hcl,dc=com
Facing issue in step 6
[root@ldaptest ~]# ldapmodify -H ldapi:/// -f ldapdomain.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
ldapmodify: invalid format (line 5) entry: “olcDatabase={1}monitor,cn=config”
vi ldapdomain.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=Manager,dc=rhe7,dc=local” read by * none
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=rhe7,dc=local
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=Manager,dc=rhe7,dc=local
dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}My password
dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {0}to attrs=userPassword,shadowLastChange by
dn=”cn=Manager,dc=rhe7,dc=local” write by anonymous auth by self write by * none
olcAccess: {1}to dn.base=”” by * read
olcAccess: {2}to * by dn=”cn=Manager,dc=rhe7,dc=local” write by * read
Can you just show example me how to create new ldapuser and how to reset ldapuser passwd?
one more think i have setup ldapuser server successfully and mounted on client machine every think is fine but i try to login as ldapuser using other console but it don’t working. I mean its not login
Very nice article. However, it seems that every dn entry in the file ldapdomain.ldif needed to be separated by an empty line.
hi,
i am having problem in point 6 when load as follow.
[root@dika ~]# ldapmodify -H ldapi:/// -f ldapdomain.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
ldapmodify: invalid format (line 5) entry: “olcDatabase={1}monitor,cn=config”
i am following the script, excep for password and domain component / dc=
im stuck in that point.
by the way, it was a great tutorial for me to learn before facing exam.
thanks a lot and very apreciate for your response.
The lines that are not keys must be indented, the dn key must have a new line on his top
Having problems with step 5 on a Linux server that is using LDAP already for user authentication. I have installed openLDAP as a local authentication provider for an application but can not configure it:
ldap_sasl_interactive_bind_s: Local error (-2)
additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (SPNEGO cannot find mechanisms to negotiate)
how to migrate “389 directory server” from one machine to another?
@Anand,
That is out of the scope of the exam so we did not cover it in this article. We offer professional support services to help our readers in requirements like this if you’re interested.
Hi Everyone, in step 4 to create a LDIF file ( ldaprootpasswd.ldif ) these files created under that directory ?
I am having the same issue as several others in the comments are. I have to use “-Y EXTERNAL” in order for any of the commands with ldapadd or ldapmodify to work. That being said, I get stuck on step 7, when running that command it asks for a password. I input the password I used to generate the hashed string and I get “Invalid credentials (49)” every time. I have tried changing the -x to -Y EXTERNAL but it still has issue on that command. I do have everything you recommend installing and I have dug around and installed some extra packages that people elsewhere citing similar bugs mention possibly needing but to no avail, still stuck on step 7.
Sorry, it’s actually step 6 that is giving issues, not step 7.
Hi! Your article is very useful, thanx. But I have a problem with my client. After adding ldapuser I try to login by ldapuser and there is a promt where I should type a password for him. But I haven’t set it. In your ldif file there is userPassword: {SSHA}fiN0YqzbDuDI0Fpqq9UudWmjZQY28S3M. So what password should I type? Or how can I login without password and then set it?
@Olga,
Use the password you set with slappasswd in Step 4. Let us know how it goes. Best of luck!
Although the server config went as shown the very last step, step 11 didnt. On the client I installed the software, set SE booleans, pasted the command in, below, changed the fields for server and mydomain on the client and entered it. No errors were reported but nothing else was done either. Client machine continued to log in just as it did before, no mention of ldapclient. Would there be anything Ive done wrong ? Client machine can see the server with ping, no problem with name resolution. Thanks for any help.
authconfig –enableldap –enableldapauth –ldapserver=rhel7.mydomain.com –ldapbasedn=”dc=mydomain,dc=com” –enablemkhomedir –update
Great article, well laid out. I did have problems though with every instance of ldapadd and ldapmodify asking for a password and then afterwards reporting Invalid credentials (49). Using -Y EXTERNAL solved this problem. All my screen outputs then looked like yours.
what are the system requirements to configure the LDAP
ldapmodify -Y EXTERNAL -H ldapi:/// -f ldapdomain.ldif
not
ldapmodify -H ldapi:/// -f ldapdomain.ldif
Dear Gabriel .
On Step 5 when i run the command “ldapadd -H ldapi:/// -f ldaprootpasswd.ldif ” , It give me this error
SASL/GSS-SPNEGO authentication started
ldap_sasl_interactive_bind_s: Local error (-2)
additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (SPNEGO cannot find mechanisms to negotiate)
Have you installed all the packages listed at the top of this article? Also, please refer to this entry in Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1206910. Let us know if you need further help.
A great article, excellent !
Many thanks – it saved me a lot of time !
(The ldapadd and ldapmodify commands worked only with the option
-Y EXTERNAL
Don’t know why..)
@Harry,
It’s always good to receive feedback like yours. Thank you for taking the time to comment on this post. See you around!
Hai Gabrel while configuration ldap server getting this error please can you help me
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry “olcDatabase={0}config,cn=config”
ldap_modify: Inappropriate matching (18)
additional info: modify/add: olcRootPW: no equality matching rule
You have a type in that line
# setsebool -P allow_ypbind=0 authlogin_nsswitch_use_ldap=0
You are talking about enabling that booleans, but disabling it.
@Zach,
I will agree with you that the official guides provided by Red Hat only touch the surface on some IMHO very important topics, and LDAP is not an exception. I have given your script an overall look and it seems impressive – you attention to detail is what amazes me the most.
You must have noticed that I did not build Mozilla certificates in this article but that’s because it’s intended to be a starting point rather than a complete how-to. But I commend you for your efforts and dedication, and thank you for sharing your script so that other members of the Tecmint community can benefit from it.
Please see my script to install LDAP on CentOS 7. I could not set up LDAP without building Mozilla NSS certificates. The RHEL guide is not very helpful on this point. Please see my script at github.com/aikidouke/RHELAB for steps.