Centralized authentication with LDAP
From wiki.titan2x.com
Contents |
Objective
- A central server with LDAP for authentication and NFS for user home directories.
- Firewalls, etc are not covered here, but use the most secure native setup for components (especially LDAP).
- All steps and selected options well explained, with links to more details.
Although this HOWTO is based on Ubuntu 8.04 (Hardy Heron), by understanding the steps it shouldn't be too hard to adopt in other systems.
NFS setup
NFS server/client setup is detailed in its own HOWTO: NFS server/client setup
LDAP server setup
The FQDN of the LDAP server is crucial. It is used in the server certificate, and in the name of the root dn entry. If the FQDN of the server host changes, the certificate will have to be reissued and the database rebuilt.
- If your DNS can resolve the FQDN, great.
- If your DNS cannot resolve the FQDN, add an entry in /etc/hosts like this:
192.168.1.123 vm-ldap.myexample.com vm-ldap
- That is, make sure the FQDN is there in the 2nd column.
- Confirm that hostname returns your correct hostname (vm-ldap).
- Confirm that hostname -d returns the correct domain name (example.com).
- Note: To change the hostname in linux you typically need to write it to /etc/hostname and reboot. (Running hostname HOSTNAME is not enough.)
Server side
The main goal here is not simply to get an LDAP server running, but to run it with high security. By default LDAP accepts unencrypted clients. We will reconfigure it to accept only encrypted clients. For that we will need to create a server certificate and signed certificate requests for the clients. Only clients with signed certificate requests will be accepted to use the LDAP service, and they will only talk to the LDAP server that signed their certificate request.
apt-get install openssl slapd ldap-utils
- openssl: for creating certificate authority and server TLS certificates
- slapd: the LDAP server itself
- ldap-utils: LDAP command line tools such as ldapsearch
You will be asked to set a password for the admin entry of the directory. Choose a difficult password that you will not forget. The installer will not ask for the rootdn, it will be determined automatically from the domain name.
- Confirm the correct rootdn with
sudo slapcat
- The first line should reflect your correct domain name like this
dn: dc=example,dc=com
- If the dn entry is not correct, reconfigure slapd with
- The first line should reflect your correct domain name like this
sudo dpkg-reconfigure slapd
- Note that this command effectively reinitalizes the LDAP database, with the option to backup an existing database. It also rewrites configuration files, so use it with care.
At this point slapd is already running, with insecure settings, so stop it with
sudo /etc/init.d/slapd stop
Before we start slapd we will create a secure configuration.
- The server will accept insecure connections on the local interface only, network interfaces will require secure connections.
- The server will accept connections only from clients with a signed certificate.
- Likewise, clients will communicate with a server that matches the given certificate.
Create server certificate authority
A certificate authority (CA) is used to create certificates, certificate requests, and sign them.
sudo su -
mkdir ca
cd ca
/usr/lib/ssl/misc/CA.sh -newca
After running the CA.sh script, you will be prompted to enter a certificate filename or press Enter for a new certificate. Simply press Enter.
Next you'll be prompted for a PEM passphrase. This passphrase will be used when signing certificates. Keep it well.
The questions that follow are mostly regarding your organization and not terribly important, enter the correct information for your company or organization.
Country Name (2 letter code) [AU]: JP State or Province Name (full name) [Some-State]: Ibaraki Locality Name (eg, city) []: Tsukuba Organization Name (eg, company) [Internet Widgits Pty Ltd]: University of Tsukuba Organizational Unit Name (eg, section) []: Akiyama Lab Common Name (eg, YOUR name) []: vm-ldap.example.com Email Address []: ldapadmin@example.com
The Common Name is CRUCIAL. It must be the fully qualified domain name pointing to the LDAP server. Incorrect CN values will completely break encryption, and there exist countless examples of this error on mailing lists and forums throughout the Internet.
You will also be prompted for a challenge password and optional company name, which you can leave blank. OpenLDAP does not support password-protected private keys.
Create a certificate request and private key
The next command will create a new certificate request in newreq.pem and a key in slapdkey.pem. Similar questions will be asked as in the case of server certificate, enter values similarly again. Most importantly, Common Name must be the FQDN of the server.
openssl req -new -nodes -out newreq.pem -keyout slapdkey.pem -days 365
The next command will sign the certificate request in newreq.pem with certificate authority and output to newcert.pem.
/usr/lib/ssl/misc/CA.sh -sign
Finally, copy the files to the LDAP installation, and change permissions for security.
sudo mkdir /etc/ldap/ssl
sudo cp demoCA/cacert.pem /etc/ldap/ssl
sudo mv newcert.pem slapdkey.pem /etc/ldap/ssl
sudo chown openldap /etc/ldap/ssl/slapdkey.pem
sudo chmod 600 /etc/ldap/ssl/slapdkey.pem
Configure slapd to use TLS
Edit /etc/ldap/slapd.conf
- It is a good idea to change loglevel none to loglevel 256.
- man slapd.conf explains the meaning of loglevels.
- loglevel 256 prints messages about connections, LDAP operations and results, useful when debugging.
- LDAP logs go to /var/log/syslog
- After everything is configured you may want to change the loglevel back.
- Configure LDAP to use the certificates we just created, add to the end of the configuration file:
#TLSCipherSuite HIGH:MEDIUM TLSCipherSuite TLS_RSA_ARCFOUR_SHA1 TLSCACertificateFile /etc/ldap/ssl/cacert.pem TLSCertificateFile /etc/ldap/ssl/newcert.pem TLSCertificateKeyFile /etc/ldap/ssl/slapdkey.pem
- Only one of the TLSCipherSuite lines is needed, depending on whether LDAP was linked with openssl or gnutls. Try and see which one works. To get a complete list of supported ciphers use these commands:
openssl ciphers -v gnutls-cli -l
Start LDAP server
Edit /etc/defaults/slapd and uncomment the line
SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:///"
- This way LDAP service will accept unencrypted clients only on the local interface (port 389), and accept encrypted (TLS) clients on all network interfaces (port 636).
Try to start slapd with
sudo /etc/init.d/slapd start
If it doesn't start due to some errors, try to debug with
sudo slapd -d 16383
Client side
apt-get install ldap-utils
- This includes utilities like ldapsearch, ldapadd, etc...
Adjust the system-wide LDAP client configuration to use secure connection and to require the server to match the certificate created on the server side. Edit /etc/ldap/ldap.conf
# # LDAP Defaults # # See ldap.conf(5) for details # This file should be world readable but not world writable. #BASE dc=example,dc=com BASE dc=example,dc=com #URI ldap://ldap.example.com ldap://ldap-master.example.com:666 URI ldaps://vm-ldap.example.com:636 TLS_CACERT /etc/ldap/ssl/cacert.pem TLS_REQCERT demand #SIZELIMIT 12 #TIMELIMIT 15 #DEREF never
The /etc/ldap/ssl/cacert.pem file specified above in the TLS_CACERT setting is the certificate created on the server. That is, you must copy this file from the server.
To verify access to the LDAP server run
ldapsearch -x
Troubleshooting
- Try ldapsearch -x and monitor /var/log/syslog on the server.
- Make sure loglevel 256 is configured in the server to see something interesting.
LDAP operations
There are two fundamentally different methods of performing LDAP operations:
- Operate directly on the LDAP database.
- This method is possible even when the LDAP server is not running. (offline editing)
- The user needs filesystem access and permissions to the database files. (typically, root only)
- For write operations the LDAP server should not be running.
- Examples:
- sudo slapcat
- Open a connection to the LDAP server, bind as a dn, and perform operations.
- The LDAP server must be running.
- By default the user binds as anonymous.
- To bind as privileged dn the user must authenticate.
- The user is subject to access control as per the bind dn and as configured for slapd.
- Examples:
- ldapsearch -x
- ldapadd -x -D cn=admin,dc=example,dc=com -W -f records.ldif
Migrate LDAP users from /etc/passwd, /etc/shadow, /etc/group
apt-get install migrationtools
- migrationtools: perl scripts to generate LDIF records from /etc/passwd, /etc/group, etc and import to LDAP
LDAP has a tree structure. After a clean install there are only two entries in it, the top-level entry (here: dc=example,dc=com) and an LDAP administrator entry (here: cn=admin,dc=example,dc=com).
- Add the following entry to be the parent of users:
dn: ou=People,dc=example,dc=com objectClass: organizationalUnit ou: People
- Put this into a file people.ldif and run:
-
ldapadd -x -D cn=admin,dc=example,dc=com -W -f people.ldif
-
- Put this into a file people.ldif and run:
- Add the following entry to be the parent of groups:
dn: ou=Group,dc=example,dc=com objectClass: organizationalUnit ou: Group
- Put this into a file group.ldif and run:
-
ldapadd -x -D cn=admin,dc=example,dc=com -W -f group.ldif
-
- Put this into a file group.ldif and run:
- You probably don't want to migrate all users to LDAP. Make a copy of /etc/passwd, edit it, delete the users you don't want to store in LDAP.
- Run migrate_passwd.pl to generate an LDIF file of all the users in the password file.
-
LDAP_BASEDN=dc=example,dc=com sudo -E /usr/share/migrationtools/migrate_passwd.pl ./passwd > passwd.ldif
-
- The reason to run this with sudo is to be able to read passwords from /etc/shadow
- Use LDAP_BASEDN environmental variable to override the default dn (padl.com)
- Add the migrated user accounts with:
-
ldapadd -x -D cn=admin,dc=example,dc=com -W -f passwd.ldif
-
- Repeat similarly for migrating groups, use migrate_group.pl for that.
VERY IMPORTANT
- On ALL your LDAP client systems, make sure you have a local user who is in the admin group. This is so that in case the LDAP server is down, you can still ssh to the machine and perform administrative tasks with sudo.
- Tip: to add a user to the admin group, use the command: sudo adduser USERNAME admin
Migrate LDAP users from another LDAP server
- Dump users of the source LDAP server.
-
sudo slapcat > source.ldif
-
- Move the output file to the target system.
- Make a copy of the file, and work on the copy.
- The base dn of the target database and the base dn of the source database should be compatible, or you need to make them compatible by either of these two ways:
- Recreate the target database with matching base dn.
- Edit the dump file to use matching base dn.
- Make sure the target database does not have entries conflicting with the source database.
- Stop slapd:
-
sudo /etc/init.d/slapd stop
-
- Add the migrated entries:
-
sudo slapadd -l new.ldif
-
- Confirm:
-
sudo slapcat
-
- Start slapd:
-
sudo /etc/init.d/slapd start
-
VERY IMPORTANT
- On ALL your LDAP client systems, make sure you have a local user who is in the admin group. This is so that in case the LDAP server is down, you can still ssh to the machine and perform administrative tasks with sudo. Tip: to add a user to the admin group, use the command: sudo adduser USERNAME admin
PAM setup
Client side
apt-get install libpam-ldap libnss-ldap ldap-auth-config
- libpam-ldap: Pluggable Authentication Module allowing LDAP interfaces
- libnss-ldap: NSS module for using LDAP as a naming service
- ldap-auth-config: Config package for LDAP authentication
The ldap-auth-config package is very helpful. It will ask a number of questions:
- LDAP server Uniform Resouce Identifier: ldaps://vm-ldap.example.com:636/
- Distinguished name of the search base: dc=example,dc=com
- LDAP version to use: 3
- Make local root Database admin: no
- The consequences of this step are important:
- no: local root will have no power over LDAP users (will not be able to change passwords, etc). Users will still be able to change their own passwords.
- yes: the LDAP admin password will be saved in a file /etc/ldap.secret. Being a security risk, I discourage this option.
- The consequences of this step are important:
If you chose no to the question Make local root Database admin then root won't be able to change user passwords with passwd. (Note that users can always change their own passwords, unless they forgot it.) So, what if a user forgot his password? You can connect to the LDAP server as the admin dn and generate a new password for the user.
ldappasswd -x -D cn=admin,dc=example,dc=com -W uid=test1,ou=People,dc=example,dc=com
You will have to enter the LDAP admin password, and a random password will be generated for the user and printed to the screen. Give this password to the user, he will be able to login and change it.
To enable LDAP PAM modules, make the following changes to files in /etc/pam.d:
- Add sufficient rules with pam_ldap.so before required/requisite lines with pam_unix.so
- In the case of auth method, also append the option use_first_pass to pam_unix.so module.
- See the examples below.
# /etc/pam.d/common-account account sufficient pam_ldap.so account required pam_unix.so
# /etc/pam.d/common-auth auth sufficient pam_ldap.so auth requisite pam_unix.so nullok_secure use_first_pass
# /etc/pam.d/common-password password sufficient pam_ldap.so password requisite pam_unix.so nullok obscure md5
# /etc/pam.d/common-session session sufficient pam_ldap.so session required pam_unix.so
- Also change /etc/nsswitch.conf
passwd: compat ldap group: compat ldap shadow: compat ldap
- Note: be aware that if there is a record in /etc/passwd for an LDAP user, then the record in /etc/passwd will mask LDAP account information such as home directory, shell, etc. Depending on what you want to achieve, you might resolve this by removing the user record from /etc/passwd or by switching the order of compat and ldap in /etc/nsswitch.conf. (Or, well, just be happy with things as they are...)
- Now try to login at a client site with an LDAP user. Worked? Great!
- Also try to change the password with passwd.
Server side
There's nothing to do on the server, really. However, if you want LDAP users to be able to login on the server too, then obviously you need to perform the client-steps on that machine too.
Troubleshooting
- LDAP user cannot login at client site.
- On the server, monitor syslog with tail -f /var/log/syslog.
- Now try to login at the client site.
- Make sure loglevel 256 is configured in the server to see something interesting.
User management
- With PAM correctly configured, the passwd tool works as expected and updates LDAP records.
- At the time of this writing, none of the other standard user management tools (like adduser, etc) work with LDAP records.
- As a temporary workaround until system tools improve, I created a repository of simple wrapper scripts around these tools and LDAP to perform simple user management tasks.
- You can check-out the project with the command:
bzr co lp:~janos-gyerik/scripts/ldap
- Project homepage: https://code.launchpad.net/~janos-gyerik/scripts/ldap
LDAP replication
Coming. Some day. Soon but not too soon.
Until I write this up, here's something to get you started.
Primary LDAP server
Uncomment the following in /etc/ldap/slapd.conf
rootdn "cn=admin,dc=example,dc=com"
And right under it add the following:
moduleload syncprov.la overlay syncprov syncprov-checkpoint 100 10 syncprov-sessionlog 100
Replicate LDAP server
Uncomment the following in /etc/ldap/slapd.conf
rootdn "cn=admin,dc=example,dc=com"
And right under it add the following:
syncrepl rid=123 provider=ldap://ldap01.example.com:389 type=refreshAndPersist searchbase="dc=example,dc=com" filter="(objectClass=*)" scope=sub schemachecking=off bindmethod=simple binddn="uid=john,ou=people,dc=example,dc=com" credentials=password
The missing steps?
As far as I can tell, these are the missing steps I need to read up on:
- How is the directory replicated from the primary to the secondary server?
- (When I start the secondary server, will it automatically pull the contents from the primary?)
- How do clients know about the two servers?
- (Is there another variable to set in /etc/ldap/ldap.conf so that clients know where to go in case the primary is down?)
- (If so, then the config files for PAM and NSS will also need to be changed accordingly.)
- (Is there another variable to set in /etc/ldap/ldap.conf so that clients know where to go in case the primary is down?)
Practical tips
- If the LDAP server is down and there is no duplicate server, user logins, etc, anything that uses the LDAP server will take a long time to finish. This is because the client waits for a certain amount time before timing out, concluding the LDAP server unreachable.
- So for example when you start the machines in the network you want to start the LDAP server first.
- And when shutting down the network you want to stop the LDAP server last.
