Exercise2 : enable Kerberos logins to a host

This is to connect a server to an existing Kerberos/LDAP infrastructure. In part 1 we'll just enable Kerberos authentication, and in part 2 we'll enable LDAP authorization for uid/gid mapping.

Part 1: Kerberos authentication

Your machine must already be working as a Kerberos client (i.e. /etc/krb5.conf is setup correctly)

Sync your clock

Kerberos only works if your clocks are in close sync (certainly within 5 minutes). You can do a one-off clock sync like this:

# ntpdate ntp.ubuntu.com

But it's better to install the ntp daemon, which will continuously keep your clock in accurate sync.

# apt-get install ntp

Enable kerberos for sshd

In the sshd_config file, uncomment the GSSAPIAuthentication line and set it to yes; also add GSSAPIKeyExchange yes. Then restart sshd.

# editor /etc/ssh/sshd_config
...
# GSSAPI options
GSSAPIAuthentication yes
GSSAPIKeyExchange yes
....

# service ssh restart

You're also going to add some extra lines to the end of krb5.conf, because of a current limitation in the kadmin utility.

# editor /etc/krb5.conf
...

[realms]
WS.NSRC.ORG = {
    admin_server = kdc1.ws.nsrc.org
}

Now you need to set up a shared key between the KDC and the host's keytab. Call over an instructor to do this for you (because we're not letting you have admin access to the workshop Kerberos server :-) Here's what they will do:

# kadmin -p nsrc/admin
... enter secret instructor password
addprinc -randkey host/pcN.ws.nsrc.org
ktadd host/pcN.ws.nsrc.org
^D

This has (1) created the principal on the KDC, and (2) has copied the key into a local keytab file.

You can examine your own keytab using either klist -k for a summary, or ktutil for more detailled information. Inside ktutil use '?' for help and ^D (ctrl-D) to exit.

# ktutil
rkt /etc/krb5.keytab
list -e
^D

(The key will be listed multiple times, for use with different encryption algorithms)

Now you're going to allow ssh logins for 'testuser'. Because we don't have LDAP configured yet, we'll have to create a local account - but there's no need to set a password.

# useradd -m -s /bin/bash testuser

Now you're ready to test it. You can try logging in from your own machine to yourself, and you can get someone else to login to your machine.

$ kinit testuser         # use password from exercise 1
$ ssh testuser@pcN.ws.nsrc.org

If instead of logging straight in you see a password prompt from ssh, then there's a problem which needs investigating.

Debugging

The first things to check are:

If those are correct, then in another window you can start a new instance of sshd in debug mode on a different port:

# /usr/sbin/sshd -d -p99

Then try to connect to it:

$ ssh -v -p99 testuser@pcN.ws.nsrc.org

You will see logs at both the client and server side.


Part 2: LDAP authorization

This centralises your user/uid/gid/homedir management, and removes the need to add local users.

We're going to configure it manually. In practice you'd probably just make a tarball containing all the preconfigured files and drop them onto each server which needed it.

Install LDAP utils

# apt-get install ldap-utils libsasl2-modules-gssapi-mit

# editor /etc/ldap/ldap.conf
BASE    dc=ws,dc=nsrc,dc=org
URI     ldap://ldap.ws.nsrc.org

Now this is configured, you should be able to query the LDAP directory - but the server is set up only to allow read access if you have a Kerberos ticket.

$ kinit testuser
$ ldapsearch
... should list everything in ldap
$ ldapsearch "(cn=*test*)"
... should list only entries matching the search query

Automated Kerberos ticket

For security, the LDAP server only permits connections which are Kerberos authenticated and encrypted. This means that the host itself needs a Kerberos ticket when doing LDAP lookups. (We could instead have used TLS security, but that would involve setting up a Certificate Authority, and we may as well leverage our Kerberos setup)

We will run a cronjob every hour, using our existing keytab entry to obtain a ticket for host/pcN.ws.nsrc.org

# editor /etc/cron.hourly/kerberos
#!/bin/sh
/usr/bin/kinit -k host/`hostname` -c /tmp/krb5cc_host

Make it executable, and then run it once manually:

# chmod +x /etc/cron.hourly/kerberos
# /etc/cron.hourly/kerberos

You can use this keytab to be able to do 'ldapsearch' when logged in as root:

# KRB5CCNAME=/tmp/krb5cc_host ldapsearch

Note: our LDAP queries will come from the caching daemon (nscd) which runs as root, and so this is all we need. If you wanted to run nscd as a different user, you would have to extend the cron script to make the ticket readable to that user. e.g.

#!/bin/sh
/usr/bin/kinit -k host/`hostname` -c /tmp/krb5cc_host

umask 077
cp /tmp/krb5cc_host /tmp/krb5cc_nscd
chown nscd /tmp/krb5cc_nscd

Install nss_ldap

This is the library which intercepts password/group lookups and redirects them to LDAP.

# apt-get install libnss-ldap nscd

(Beware: there is an alternative package libnss-ldapd with a trailing "d". These exercises have been tested using libnss-ldap)

Answer prompted questions as:

LDAP server                            [ldap://ldap.ws.nsrc.org]
Distinguished name of search base      [dc=ws,dc=nsrc,dc=org]
LDAP version to use                    [3]
Make local root database admin         [No]
Does the LDAP database require login?  [No]

NOTE: The LDAP server starts with ldap:// not ldapi:// !

The configuration file is /etc/ldap.conf. We're going to replace it with a simple one which uses Kerberos authentication:

# mv /etc/ldap.conf /etc/ldap.conf.example
# editor /etc/ldap.conf
krb5_ccname /tmp/krb5cc_host
use_sasl on
rootuse_sasl on
base dc=ws,dc=nsrc,dc=org
uri ldap://ldap.ws.nsrc.org
ldap_version 3
sasl_secprops minssf=56
nss_initgroups_ignoreusers backup,bin,bind,daemon,games,gnats,irc,libuuid,list,lp,mail,man,news,nslcd,ntp,openldap,proxy,root,sshd,sync,sys,syslog,uucp,www-data

We are also going to tweak nscd.conf to reduce caching of group information from 3600 to 600 seconds.

# editor /etc/nscd.conf
...
positive-time-to-live   group           600
...

Configure nsswitch

This is the point where we actually start to use LDAP for lookups.

# editor /etc/nsswitch.conf
...
passwd:         compat ldap
group:          compat ldap
shadow:         compat ldap
...

# service nscd restart

At this point you're ready to test: you should be able to map a username to a uid over LDAP, even though it doesn't exist in your local /etc/passwd file

# id ldapuser
uid=10004(ldapuser) gid=100(users) groups=100(users)

If it fails, places to look are:

Home directory creation

When a user first logs into a machine, you can create their home directory automatically via PAM (Pluggable Authentication Modules).

# editor /etc/pam.d/common-session
...
session required        pam_mkhomedir.so umask=0022 skel=/etc/skel/
...

Miscellaneous Notes

Using kadmin to extract the key on the target host itself is almost always the best way to set up the shared host/service key.

If joining a Microsoft Active Directory domain: you will need a third-party tool such as css_adkadmin (or it may be possible to use bits from samba). This may be a starting point:

kinit Administrator
css_adkadmin -r AD.NSRC.ORG -s dc1.ad.nsrc.org -q "ank -k -attr description=$HOSTNAME +randkey host/$HOSTNAME"
css_adkadmin -r AD.NSRC.ORG -s dc1.ad.nsrc.org -q "xst +randkey host/$HOSTNAME"

The alternative is to set a manual password on a host principal and then use ktutil to create a keytab with the same password. This is awkward, because (1) you need to use the right kvno, and (2) you need to repeat it for each encryption type which might be used on your network.

[KDC side]
kadmin
addprinc host/pcX.ws.nsrc.org
... you are prompted for password
getprinc host/pcX.ws.nsrc.org
... make a note of the kvno

[host side]
# ktutil
ktutil:  addent -password -p host/pcX.ws.nsrc.org -k 4 -e aes256-cts
Password for host/pcX.ws.nsrc.org@WS.NSRC.ORG: 
ktutil:  addent -password -p host/pcX.ws.nsrc.org -k 4 -e arcfour-hmac
Password for host/pcX.ws.nsrc.org@WS.NSRC.ORG: 
ktutil:  addent -password -p host/pcX.ws.nsrc.org -k 4 -e des3-hmac-sha1
Password for host/pcX.ws.nsrc.org@WS.NSRC.ORG: 
ktutil:  list
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
   1    4         host/pcX.ws.nsrc.org@WS.NSRC.ORG
   2    4         host/pcX.ws.nsrc.org@WS.NSRC.ORG
   3    4         host/pcX.ws.nsrc.org@WS.NSRC.ORG
ktutil:  wkt /etc/krb5.keytab