Saturday, February 5, 2011

How to setup LDAP DNS Discovery

LDAP DNS discovery can simplify the client hosts setup. The following need to be added to zone file.
$ORIGIN dev.local.
_ldap._tcp  IN SRV 10 0 389 ldapk1
_ldap._tcp  IN SRV 20 0 389 ldapk2
The client configuration can now look like this (file /etc/ldap/ldap.conf):
# BASE    dc=dev,dc=local
# URI     ldap://ldapk1/
Let test it:
host -t SRV _ldap._tcp

Troubleshooting: dbus-daemon nss_ldap failed to bind to LDAP server

While installing Debian OpenLDAP client with Kerberos (see here) on Gnome desktop you might experience the following errors in auth.log.
dbus-daemon: GSSAPI Error: Unspecified GSS failure.  Minor code may provide more information (Credentials cache file '/tmp/krb5cc_101' not found)
dbus-daemon: nss_ldap: failed to bind to LDAP server ldap://ldapk1.dev.local/: Local error
dbus-daemon: nss_ldap: could not search LDAP server - Server is unavailable
At the same time you will might see a number of errors reported by slapd:
slapd: conn=2806 op=0 UNBIND
slapd: conn=2806 fd=27 closed
slapd: conn=2807 fd=27 ACCEPT from IP=192.168.XX.XXX:XXXXX (IP=0.0.0.0:XXX)
The problem is related to parallel boot of your system. By default dbus and nscd are started in parallel, the problem appears when dbus is launched before nscd daemon. In order to fix that you need to change boot sequence. Make sure you have the following in /etc/init.d/dbus (notice line Should-Start):
# Provides:          dbus
# Should-Start:      nscd
# Required-Start:    $remote_fs $syslog
Once above is done simple re-enable dbus service so it updates everything necessary:
rcconf --off dbus ; rcconf --on dbus
Notice changes in /etc/rc2.d:
# ls /etc/rc2.d/
S17nscd ... S18dbus
You need restart your computer (or at least restart dbus daemon) in order changes take place.

Debian OpenLDAP client with Kerberos

Before we proceed with client setup (let assume our client machine name is deby01.dev.local) you need to setup the following:
  • Kerberos Client (look here).
Once the basic installation of the above is complete, here we go:
  1. We need install few packages:
    apt-get -y install ldap-utils libpam-ldap \
    libsasl2-modules-gssapi-mit nscd libnss-ldap kstart
    
    During installation you will be prompted for few questions:
    • libnss-ldap
      LDAP server URI: ldap://ldapk1.dev.local/
      Distinguished name of the search base: dc=dev,dc=local
      LDAP version to use: 3
      cn=admin,ou=people,dc=dev,dc=local
      LDAP account for root: cn=admin,ou=people,dc=dev,dc=local
      LDAP root account password: <just hit enter>
      
    • libpam-ldap
      Allow LDAP admin account to behave like local root? No
      Does the LDAP database require login? No
      
  2. Reconfigure libpam-runtime and disable LDAP Authentication:
    dpkg-reconfigure libpam-runtime
    
  3. Configure kstart, add the following to /etc/inittab (It will check every 10 minutes of the Kerberos ticket needs to be renewed and set the ticket lifetime to 24 hours:
    KS:2345:respawn:/usr/bin/k5start -U -f /etc/krb5.keytab -K 10 -l 24h
    
    Force init to reload configuration:
    kill -HUP 1
    
    Ensure /tmp/krb5cc_0 file is created:
    ls -lh /tmp/krb5cc_0
    
  4. Kerberise libnss-ldap (file /etc/libnss-ldap.conf), ensure the following:
    base dc=dev,dc=local
    uri ldap://ldapk1.dev.local/
    ldap_version 3
    rootbinddn cn=admin,ou=people,dc=dev,dc=local
    
    # Use SASL and GSSAPI and where to find the 
    # Kerberos ticket cache.
    use_sasl        on
    sasl_mech       gssapi
    krb5_ccname FILE:/tmp/krb5cc_0
    
  5. Set defaults for LDAP clients (file /etc/ldap/ldap.conf). Note client configuration changes if ldap is configured via SSL (see here).
    BASE    dc=dev,dc=local
    URI     ldap://ldapk1.dev.local/
    SASL_MECH GSSAPI
    
  6. Add LDAP support for login process by nscd (file /etc/nsswitch.conf):
    passwd:         compat ldap
    group:          compat ldap
    shadow:         compat ldap
    
  7. Restart Name Service Cache daemon:
    /etc/init.d/nscd restart
    
  8. Configure PAM to automatically create a user home directory (file /etc/pam.d/common-session):
    session  required  pam_mkhomedir.so
    
You should be ready to login with a user created in LDAP and password set in Kerberos.

Troubleshooting

  • You might experience the following error while initializing kerberos ticket in Debian Gnome desktop:
    Cannot resolve network address for KDC in realm DEV.LOCAL
    
    This somehow conflicts with avahi-daemon, you will need disable it:
    rcconf --off avahi-daemon
    
  • If you are using Debian Gnome desktop, have a look at Troubleshooting: dbus-daemon nss_ldap failed to bind to LDAP server, that you can find here.

Debian OpenLDAP with Kerberos Authentication

Before we proceed with ldap kerberization (let assume our server name is ldapk1.dev.local) you need to setup the following:
  • OpenLDAP Server (look here).
  • Kerberos Client (look here).
Once the basic installation of the above is complete, here we go:

Remove Authentication from LDAP

  1. Since we are going to authenticate users with Kerberos we need to prohibit users access to password stored in ldap. Add the following to file access-passwd.ldif:
    dn: olcDatabase={1}hdb,cn=config
    changetype: modify
    #
    # Delete default user access to password
    delete: olcAccess
    olcAccess: {0}to attrs=userPassword,shadowLastChange
      by self write
      by anonymous auth
      by dn="cn=admin,dc=dev,dc=local" write
      by * none
    -
    # Prohibit access to password
    add: olcAccess
    olcAccess: {0}to attrs=userPassword,shadowLastChange
      by * none
    -
    # Only authenticated users have read access 
    # Anonymous users have no access. 
    add: olcAccess
    olcAccess: {1}to *
      by users read
      by * none
    
    and apply changes:
    ldapmodify -QY EXTERNAL -H ldapi:/// -f access-passwd.ldif
    
  2. Delete admin account:
    ldapdelete -cxWD cn=admin,dc=dev,dc=local cn=admin,dc=dev,dc=local
    
    and it access rights in the directory (file access-noadmin.ldif):
    dn: olcDatabase={1}hdb,cn=config
    changetype: modify
    #
    # Revoke admin write rights to the directory
    delete: olcAccess
    olcAccess: {3}to *
      by self write
      by dn="cn=admin,dc=dev,dc=local" write
      by * read
    -
    # Move admin account to people unit
    replace: olcRootDN
    olcRootDN: uid=admin,ou=people,dc=dev,dc=local
    -
    # Remove admin password
    delete: olcRootPW
    
    and apply changes:
    ldapmodify -QY EXTERNAL -H ldapi:/// -f access-noadmin.ldif
    

Setup GSSAPI mapping between OpenLDAP and Kerberos

  1. Install SASL module for Kerberos:
    apt-get install libsasl2-modules-gssapi-mit
    
  2. Add ldap principal:
    kadmin -p admin -q "addprinc -randkey ldap/ldapk1.dev.local"
    
    kadmin -p admin -q "ktadd ldap/ldapk1.dev.local"
    
  3. Allow openldap group (slapd service is running under openldap account) access kerberos information:
    chgrp openldap /etc/krb5.keytab
    chmod g+r,o= /etc/krb5.keytab
    ls -lh /etc/krb5.keytab 
    
  4. Specify authentication mode (file /etc/ldap/ldap.conf):
    SASL_MECH GSSAPI
    
  5. Setup SASL mapping between Kerberos and LDAP accounts (file auth-kerberos.ldif):
    dn: cn=config
    changetype: modify
    #
    # Regular expression that match a simple user name
    # provided by SASL and map it to ldap entry
    add: olcAuthzRegexp
    olcAuthzRegexp: uid=([^,]+),cn=dev.local,cn=gssapi,cn=auth
      uid=$1,ou=people,dc=dev,dc=local
    -
    # Specify SASL Kerberos realm
    add: olcSaslRealm
    olcSaslRealm: DEV.LOCAL
    
    and apply changes:
    ldapmodify -QY EXTERNAL -H ldapi:/// -f auth-kerberos.ldif
    
  6. Restart OpenLDAP service:
    /etc/init.d/slapd restart
    

Verify settings

Verify above changes by querying config:
ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b \
cn=config "(|(cn=config)(olcDatabase={1}hdb))"
Here it is:
dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/slapd/slapd.args
olcLogLevel: stats
olcPidFile: /var/run/slapd/slapd.pid
olcToolThreads: 1
olcAuthzRegexp: {0}uid=([^,]+),cn=dev.local,cn=gssapi,cn=auth uid=$1,ou=people
 ,dc=dev,dc=local
olcSaslRealm: DEV.LOCAL

dn: olcDatabase={1}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {1}hdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=dev,dc=local
olcAccess: {0}to attrs=userPassword,shadowLastChange by * none
olcAccess: {1}to dn.base="" by * read
olcLastMod: TRUE
olcDbCheckpoint: 512 30
olcDbConfig: {0}set_cachesize 0 2097152 0
olcDbConfig: {1}set_lk_max_objects 1500
olcDbConfig: {2}set_lk_max_locks 1500
olcDbConfig: {3}set_lk_max_lockers 1500
olcDbIndex: objectClass eq
olcDbIndex: uid eq
olcDbIndex: cn eq
olcDbIndex: ou eq
olcDbIndex: dc eq
olcRootDN: uid=admin,ou=people,dc=dev,dc=local

Kerberos Authentication Test

  1. Let ensure anonymous has no access
    ldapk1:~/ldap# ldapsearch -xLLL
    No such object (32)
    
  2. Authenticate to Kerberos:
    kinit -p admin
    
  3. Let make the search as authenticated user (you should be able to see organization units people and groups):
    ldapsearch -LLL
    

Troubleshooting

  1. Cannot create replay cache: No such file or directory
    ldap1:~# ldapsearch -LLL
    SASL/GSSAPI authentication started
    ldap_sasl_interactive_bind_s: Other (e.g., implementation specific) 
    error (80) additional info: SASL(-1): generic failure: GSSAPI Error: 
    Unspecified GSS failure.  Minor code may provide more information 
    (Cannot create replay cache: No such file or directory)
    
    The only way recover from this error:
    • Restart slapd daemon
    • Consider add cron job on reboot that restarts slapd (file /etc/cron.d/slapd)
      @reboot root /etc/init.d/slapd restart
      
While authentication provided by Kerberos is secure now, consider protect communication with OpenLDAP by SSL/TLS encryption (read how here).