Authentication via LDAP - shawfdong/hyades GitHub Wiki

UCSC runs two directory services: Blue & Gold, on ldap-blue.ucsc.edu & ldap-gold.ucsc.edu respectively. The Blue service seems to be open to the world:

# nmap -A -T4 -Pn ldap-blue.ucsc.edu

PORT    STATE SERVICE  VERSION
389/tcp open  ldap     (Anonymous bind OK)
636/tcp open  ssl/ldap (Anonymous bind OK)
| ssl-cert: Subject: commonName=ldap-blue.ucsc.edu/organizationName=University of California, Santa Cruz/stateOrProvinceName=California/countryName=US
| Not valid before: 2011-11-21T22:40:01+00:00
|_Not valid after:  2014-11-21T22:40:01+00:00
|_ssl-date: 2014-08-22T23:13:30+00:00; 0s from local time.
| sslv2: 
|   SSLv2 supported
|_  ciphers: none

Device type: general purpose
Running (JUST GUESSING): FreeBSD 6.X|7.X|8.X|9.X (96%), OpenBSD 4.X (92%), IBM AIX 7.X (86%)
OS CPE: cpe:/o:freebsd:freebsd:6.3 cpe:/o:openbsd:openbsd:4.0 cpe:/o:freebsd:freebsd:7.0 cpe:/o:freebsd:freebsd:8.1 cpe:/o:freebsd:freebsd:9 cpe:/o:ibm:aix:7
Aggressive OS guesses: FreeBSD 6.3-RELEASE (96%), OpenBSD 4.0 (92%), FreeBSD 7.0-RELEASE (90%), FreeBSD 7.1-PRERELEASE 7.2-STABLE (90%), FreeBSD 8.1-RELEASE (90%), FreeBSD 9.0-RELEASE (90%), FreeBSD 6.2-RELEASE (88%), FreeBSD 8.0-RELEASE (88%), FreeBSD 7.0-RELEASE-p5 (88%), FreeBSD 9.1-RELEASE (87%)

while Gold is heavily firewalled; and is probably accessible only from a handful of hardened servers at UCSC.

In this article, I document how to enable Authentication[1] via OpenLDAP to the Blue directory service, on my HP xw8600 Workstation running CentOS 7. The same procedure should work on a RHEL/CentOS 6 box as well, with no or minimal modification.

Table of Contents

Install required packages

# yum -y install openldap openldap-clients openssh-ldap sssd-ldap

Test the Blue directory service

Anonymous access to the Blue directory service, over unencrypted LDAP, works fine, e.g.:

$ ldapsearch -x -H ldap://ldap-blue.ucsc.edu -b "ou=groups,dc=ucsc,dc=edu"  '(cn=sysadmins)'

But if we try to specify a distinguished name with which to authenticate to the server, over unencrypted LDAP, the access will fail (which is good security practice!):

$ ldapsearch -x -H ldap://ldap-blue.ucsc.edu -D 'uid=xxxx,ou=people,dc=ucsc,dc=edu' -W -b "ou=groups,dc=ucsc,dc=edu"  '(cn=sysadmins)'
Enter LDAP Password: 
ldap_bind: Invalid credentials (49) 

However, LDAPS (LDAP over SSL) doesn't work out of box on a CentOS 7 box, while it does on my iMac 2010 (running OS X 10.9):

$ ldapsearch -x -H ldaps://ldap-blue.ucsc.edu -b "ou=groups,dc=ucsc,dc=edu"  '(cn=sysadmins)'
ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)

Enabling debugging (-d1) gives us some hint:

$ ldapsearch -x -H ldaps://ldap-blue.ucsc.edu -b "ou=groups,dc=ucsc,dc=edu"  '(cn=sysadmins)' -d1

TLS: certdb config: configDir='/etc/openldap/certs' tokenDescription='ldap(0)' certPrefix='' keyPrefix='' flags=readOnly
TLS: cannot open certdb '/etc/openldap/certs', error -8018:Unknown PKCS #11 error.
TLS: certificate [CN=GlobalSign Organization Validation CA - G2,O=GlobalSign nv-sa,C=BE] is not valid - error -8179:Peer's Certificate issuer is not recognized..
TLS: error: connect - force handshake failure: errno 0 - moznss error -8179
TLS: can't connect: TLS error -8179:Peer's Certificate issuer is not recognized..

Essentially, it complains that the certificate of the CA (GlobalSign Organization Validation CA - G2) is not installed in /etc/openldap/certs. So let's install the CA certificate.

Install the CA certificate

Tip: We need the CA certificate, rather than the server certificate for Blue.

Download both of the certificates:

# openssl s_client -showcerts -connect ldap-blue.ucsc.edu:636 </dev/null>2>/dev/null |\
    sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' |\
    tee ldap-blue-bundle.crt
where the switch -showcerts is required, otherwise we'll only get the server certificate. ldap-blue-bundle.crt is comprised of two certificates, the first for the server and the second for the CA.

Save the CA certificate as /etc/openldap/certs/GlobalSign.crt.

Note that the stock /etc/openldap/ldap.conf says:

TLS_CACERTDIR	/etc/openldap/certs
 Create a softlink between the CA certificate and its hash:
# cd /etc/openldap/certs/
# HASH=$(openssl x509 -in GlobalSign.crt -hash -noout)
# ln -s GlobalSign.crt $HASH.0

Finally, LDAPS (LDAP over SSL) runs without error, e.g.:

$ ldapsearch -x -H ldaps://ldap-blue.ucsc.edu -b "ou=groups,dc=ucsc,dc=edu"  '(cn=sysadmins)'
### and ###
$ ldapsearch -x -H ldap://ldap-blue.ucsc.edu -D 'uid=xxxx,ou=people,dc=ucsc,dc=edu' -W -b "ou=groups,dc=ucsc,dc=edu"  '(cn=sysadmins)'

Configure LDAP authentication

To enable LDAP authentication on CentOS 7, the hard way is to manually edit a myriad of configuration files, which can be time-consuming and error-prone. The easy way is to use the command-line tool authconfig, which is provided by the eponymous RPM package; the easiest is to use the GUI tool authconfig-gtk (or system-config-authentication), provided by the package authconfig-gtk. Here we use the command-line tool authconfig.

Before we proceed, it is prudent to back up all the configuration files:

# /usr/sbin/authconfig --savebackup CentOS7-default
which saves the old configuration files in /var/lib/authconfig/backup-CentOS7-default/.

Run as root:

# /usr/sbin/authconfig --enableldap --enableldapauth \
    --ldapserver="ldaps://ldap-blue.ucsc.edu" \
    --ldapbasedn="ou=people,dc=ucsc,dc=edu" \
    --enablesssd --enablesssdauth --update

For no particular reason at all, the above command has changed TLS_CACERTDIR in /etc/openldap/ldap.conf, which now reads as follows:

TLS_CACERTDIR /etc/openldap/cacerts
URI ldaps://ldap-blue.ucsc.edu
BASE ou=people,dc=ucsc,dc=edu
TLS_CACERTDIR /etc/openldap/cacerts

LDAPS will again fail. To fix it, we can either rerun authconfig with the switch --ldaploadcacert=file:///etc/openldap/certs/GlobalSign.crt; or simply copy the CA certificate over:

# cd /etc/openldap/cacerts
# cp -a ../certs/* .

Let's test it. My UCSC account name is shaw. Given the configurations in /etc/openldap/ldap.conf (see above), we can now run a much shortened command to retrieve my entry:

$ ldapsearch -x -LLL 'uid=shaw'

dn: uid=shaw,ou=people,dc=ucsc,dc=edu
cn: Shawfeng Dong
homeDirectory: /afs/cats.ucsc.edu/users/t/shaw
loginShell: /usr/bin/bash
objectClass: posixAccount
uid: shaw
uidNumber: 16348
gidNumber: 100000

getent can now get my password entry from the Blue server:

$ getent passwd shaw
shaw:*:16348:100000:Shawfeng Dong:/afs/cats.ucsc.edu/users/t/shaw:/usr/bin/bash

getent can get group entry too:

$ getent group sysadmins
sysadmins:*:100465:cliffp,emulder,garges,jhoman,jsonstro,tjwright,wkoontz

Let's see if we can log in as user shaw:

[dong@hpc ~]$ su - shaw
Password: 
Last login: Wed Aug 27 13:39:14 PDT 2014 on pts/1
su: warning: cannot change directory to /afs/cats.ucsc.edu/users/t/shaw: No such file or directory
id: cannot find name for group ID 100000
mkdir: cannot create directory '/afs': Permission denied
-bash-4.2$ id
uid=16348(shaw) gid=100000 groups=100000
-bash-4.2$ pwd
/home/dong

Well, the LDAP authentication is successful; but the main problem is that the home directory is nonexistent — the other warnings are harmless and can be safely ignored. Let's create some scripts that automatically add a home directory when it doesn't exist (in /home rather than in /afs).

Create /etc/profile.d/00-add-home.sh:

if [ ! -d "$HOME" ]; then
    HOME=/home/$USER
    if [ ! -d "$HOME" ]; then   
        mkdir -p $HOME
        # to copy the hidden files and directories in /etc/skel/        
        cp -r /etc/skel/. $HOME
    fi
    cd $HOME
fi

and /etc/profile.d/00-add-home.csh:

if ( ! -d $HOME ) then
    setenv HOME /home/$USER
    if ( ! -d "$HOME" ) then   
        mkdir -p $HOME
        cp -r /etc/skel/. $HOME
    endif
    cd $HOME
endif

For this to work, we also need to change the permission of /home/ (turning on the sticky bit):

# chmod 1777 /home

Now LDAP authentication works fine, albeit still with some innocuous warnings:

[dong@hpc ~]$ su - shaw
Password: 
Last login: Wed Aug 27 15:17:15 PDT 2014 on pts/1
su: warning: cannot change directory to /afs/cats.ucsc.edu/users/t/shaw: No such file or directory
id: cannot find name for group ID 100000
[shaw@hpc ~]$ pwd
/home/shaw

Technical Notes

Here we employ the System Security Services Daemon (SSSD) to provide access to the identity and authentication provider Blue. SSSD is an intermediary between local clients and any configured data store. What SSSD does is allow a local service to check with a local cache in SSSD, but that cache may be taken from any variety of remote identity providers — an LDAP directory, an Identity Management domain, Active Directory, possibly even a Kerberos realm.[2]

The following configuration files have been modified by authconfig: /etc/sysconfig/authconfig, /etc/nsswitch.conf, /etc/openldap/ldap.conf, /etc/pam.d/password-auth-ac, /etc/pam.d/system-auth-ac, /etc/pam.d/fingerprint-auth-ac, /etc/pam.d/smartcard-auth-ac.

The old-fashioned approach is to configure PAM[3] to access the OpenLDAP service directly, via pam_ldap.so. The basic rule of thumb is to include pam_ldap.so wherever pam_unix.so is included.[4] However, I can't find a package that provides pam_ldap.so in CentOS 7.

Here LDAP is the provider for both identity and authentication. Alternatively, we can use LDAP solely as the identity provider, but use Kerberos as the authentication provider.

References

  1. ^ RHEL6 Deployment Guide - Configuring Authentication
  2. ^ RHEL6 Deployment Guide - SSSD
  3. ^ RHEL6 - PAM
  4. ^ Arch Linux wiki - LDAP authentication Client Setup
⚠️ **GitHub.com Fallback** ⚠️