To get the "wow" factor for the initial exercises, showing how easy it is to add clients and servers to a Kerberised network, we need to have a Kerberos/LDAP environment already up and running.
Build the NOC machine and ensure forward and reverse DNS is fully working, if not already done.
Create kdc1 as an alias to whatever machine will be running the primary KDC (probably also the NOC), and add the Kerberos service records.
# apt-get install bind9 bind9-utils
# editor /etc/bind/named.conf.local
zone "ws.nsrc.org" { type master; file "/etc/bind/ws.nsrc.org"; };
zone "10.in-addr.arpa" { type master; file "/etc/bind/10.in-addr.arpa"; };
# editor /etc/bind/ws.nsrc.org
$TTL 600
@ IN SOA noc.ws.nsrc.org. root.noc.ws.nsrc.org. (
1 ; Serial
604800 ; Refresh
600 ; Retry
2419200 ; Expire
600 ) ; Negative Cache TTL
@ IN NS noc.ws.nsrc.org.
_kerberos IN TXT "WS.NSRC.ORG"
_kerberos-master._udp IN SRV 0 0 88 kdc1
_kerberos-adm._tcp IN SRV 0 0 749 kdc1
_kpasswd._udp IN SRV 0 0 464 kdc1
; List all active Kerberos servers here
_kerberos._udp IN SRV 0 0 88 kdc1
ldap IN A 10.10.254.250
noc IN A 10.10.254.250
kdc1 IN A 10.10.254.250
$GENERATE 1-20 $ IN PTR pc$.ws.nsrc.org.
# editor /etc/bind/10.in-addr.arpa
$TTL 600
@ IN SOA noc.ws.nsrc.org. root.noc.ws.nsrc.org. (
1 ; Serial
604800 ; Refresh
600 ; Retry
2419200 ; Expire
600 ) ; Negative Cache TTL
@ IN NS noc.ws.nsrc.org.
$GENERATE 1-20 $.1.10 IN PTR pc$.ws.nsrc.org.
250.254.10 IN PTR noc.ws.nsrc.org.
# editor /etc/resolv.conf
search ws.nsrc.org
nameserver 127.0.0.1
Test it:
# dig pc1
# dig -x 10.10.1.1
# dig _kerberos._udp.ws.nsrc.org. srv
If the NOC machine also has an entry for itself in /etc/hosts, make sure its FQDN is the first one listed.
# editor /etc/hosts
...
10.10.254.250 noc.ws.nsrc.org noc
You like resilience don't you? :-) And it sets a good example!
See also the MIT Kerberos docs (esp. install guide) at http://web.mit.edu/kerberos/krb5-1.8/#documentation
Install ntp:
# apt-get install ntp
Install kdc packages:
# apt-get install krb5-kdc krb5-admin-server
Answer the annoying debconf questions:
Default Kerberos 5 realm: [WS.NSRC.ORG]
Kerberos servers for your realm: [kdc1.ws.nsrc.org]
Administrative server: [kdc1.ws.nsrc.org]
Create the client library config:
# mv /etc/krb5.conf /etc/krb5.conf.example
# editor /etc/krb5.conf
[libdefaults]
default_realm = WS.NSRC.ORG
dns_lookup_realm = true
dns_lookup_kdc = true
[realms]
WS.NSRC.ORG = {
admin_server = kdc1.ws.nsrc.org
}
(note that kadmin doesn't yet support looking up the admin server via DNS; hence we have to list it in krb5.conf)
Create Kerberos database:
kdb5_util create -r WS.NSRC.ORG -s
# You will be asked to choose a database master password. We use "abcd"
Create the ACL file and grant admin rights to all */admin principals:
# editor /etc/krb5kdc/kadm5.acl
*/admin@WS.NSRC.ORG *
Now create some principals: a host principal for the host itself, putting the random key into its own keytab file; an instructor principal ("nsrc"); and an instructor KDC admin principal ("nsrc/admin")
# kadmin.local
addprinc -randkey host/noc.ws.nsrc.org
ktadd host/noc.ws.nsrc.org
addprinc nsrc
-- you'll be prompted to choose a password
addprinc nsrc/admin
-- you'll be prompted to choose a password
^D
Now start the daemons:
# /etc/init.d/krb5-kdc start
# /etc/init.d/krb5-admin-server start
At this point, you should be able to kinit nsrc
and get a ticket. If you
get "Cannot resolve network address for KDC" then check the DNS.
Note: new principals can now be added using kadmin
instead of
kadmin.local
, and you can use it from any remote machine where you can
kinit. (So you never need to do a local login to the KDC)
If you want to build a slave KDC, see the instructions at http://web.mit.edu/kerberos/krb5-1.8/krb5-1.8.3/doc/krb5-install.html#Install%20the%20Slave%20KDCs
Add another _kerberos._udp
srv entry in the DNS pointing to kdc2 so that
clients know about both of them.
The first exercise requires students to make a single-signon ssh login.
Create a 'testuser' kerberos principal in the KDC, which the students will login as.
$ kadmin -p nsrc/admin
addprinc testuser
... choose a password which will be given to the students, e.g. nsrc2020
^D
On the machine(s) where the students will be allowed to login via kerberos, create a 'testuser' account (but don't set any local password) and enable Kerberos authentication for sshd. Note we're not doing LDAP yet.
# useradd -m -s /bin/bash testuser
# editor /etc/ssh/sshd_config
...
GSSAPIAuthentication yes
GSSAPIKeyExchange yes
...
# service ssh restart
Now we'll test it. You can either do this from the noc to itself, or you can use a separate throw-away client VM, or your own laptop. If using a separate machine you'll first have to make it a Kerberos client like this:
# apt-get install krb5-user
# mv /etc/krb5.conf /etc/krb5.conf.example
# editor /etc/krb5.conf
[libdefaults]
default_realm = WS.NSRC.ORG
dns_lookup_realm = true
dns_lookup_kdc = true
Check that /etc/ssh/ssh_config
has GSSAPIAuthentication yes
and
if supported GSSAPIKeyExchange yes
(On Mac OSX: /etc/ssh_config
)
Now it should work:
$ kinit testuser
$ ssh testuser@noc
If it still doesn't work after this, Kerberos problems can be tricky to debug. First check both machines have accurately synced clocks, and that forward and reverse DNS is working. Then you can try starting another sshd in debug mode on another port:
# /usr/sbin/sshd -d -p99
Then on the client:
$ ssh -v -p99 nsrc@noc
If Apache isn't already installed on the noc, install it, and also curl for testing.
# apt-get install apache2 curl
Create a test directory and test page:
# mkdir /var/www/secure
# editor /var/www/secure/index.html
... whatever you like
-- check it works and is not yet protected
# curl http://noc.ws.nsrc.org/secure/
Now we're going to kerberize it.
# apt-get install libapache2-mod-auth-kerb
# editor /etc/apache2/conf.d/topsecret
<Location /secure>
AuthName "Hello Kerberos World"
AuthType Kerberos
# Allow fallback to Basic Auth?
KrbMethodK5Passwd Off
KrbAuthRealms WS.NSRC.ORG
Krb5Keytab /etc/apache2/krb5/krb5.keytab
# require user nsrc@WS.NSRC.ORG
require valid-user
</Location>
# service apache2 restart
Check that the page is no longer visible (curl gives a 403 error)
We now have to create a service principal, and extract its key into the keytab specified in the config above, readable to the apache daemon.
# mkdir /etc/apache2/krb5
# kadmin -p nsrc/admin
addprinc -randkey HTTP/noc.ws.nsrc.org
ktadd -k /etc/apache2/krb5/krb5.keytab HTTP/noc.ws.nsrc.org
^D
# chown -R www-data:www-data /etc/apache2/krb5
# chmod 550 /etc/apache2/krb5
# chmod 440 /etc/apache2/krb5/krb5.keytab
Check that the page is visible while you have a ticket with a client which
supports HTTP Negotiate (and also check it isn't after kdestroy
)
# curl --negotiate -u: http://noc.ws.nsrc.org/secure/
If you want to test from Firefox or Chrome, see the presentation.
NOTE: testing suggests that modauthnzldap only does anonymous binds or fixed simple binds (i.e. I couldn't get it to use SASL, even if the www-data user has a ticket). We can gloss over this for now.
This is by far the hardest part of the operation, due to the cryptic way
OpenLDAP 2.4 now stores its configs within LDAP instead of in a config file.
See man slapd-config
There is a good series of articles here: http://www.opinsys.fi/en/setting-up-openldap-on-ubuntu-10-04-alpha2 But there are many others which user openldap <2.4 and slapd.conf
Install the slapd server and Kerberos bits:
# apt-get install slapd ldap-utils libsasl2-modules-gssapi-mit
Set up the service principal with keytab readable by slapd:
# mkdir /etc/ldap/krb5
# kadmin -p nsrc/admin
addprinc -randkey ldap/noc.ws.nsrc.org
ktadd -k /etc/ldap/krb5/krb5.keytab ldap/noc.ws.nsrc.org
^D
# chown -R openldap:openldap /etc/ldap/krb5
# chmod 550 /etc/ldap/krb5
# chmod 440 /etc/ldap/krb5/krb5.keytab
# editor /etc/default/slapd
...
export KRB5_KTNAME=/etc/ldap/krb5/krb5.keytab
# service slapd restart
Install the schemas we need:
# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/cosine.ldif
# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/nis.ldif
# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/inetorgperson.ldif
# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/misc.ldif
NOTE: For a real production LDAP server, read the files in
/usr/share/doc/slapd
carefully, especially README.Debian.gz
and README.DB_CONFIG.gz
Now we need to run some scripts. First is create_database.sh
ldapadd -Y EXTERNAL -H ldapi:/// <<EOS
# Load hdb backend module
dn: cn=module{0},cn=config
objectClass: olcModuleList
cn: module
olcModulepath: /usr/lib/ldap
olcModuleload: {0}back_hdb
EOS
ldapadd -Y EXTERNAL -H ldapi:/// <<EOS
# Create the hdb database and place the files under /var/lib/ldap
dn: olcDatabase={1}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {1}hdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=ws,dc=nsrc,dc=org
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
olcLastMod: TRUE
olcDbCheckpoint: 512 30
olcDbIndex: uid pres,eq
olcDbIndex: cn,sn,mail pres,eq,approx,sub
olcDbIndex: objectClass eq
EOS
(Note: we have no olcRootDN or olcRootPW. This is a pure Kerberos config)
Next is init_database.sh
ldapadd -Y EXTERNAL -H ldapi:/// <<EOS
dn: dc=ws,dc=nsrc,dc=org
objectClass: dcObject
objectclass: organization
o: ws.nsrc.org
dc: ws
description: LDAP root
dn: ou=People,dc=ws,dc=nsrc,dc=org
objectClass: top
objectClass: organizationalUnit
ou: People
dn: ou=Groups,dc=ws,dc=nsrc,dc=org
objectClass: top
objectClass: organizationalUnit
ou: Groups
EOS
And finally config.sh
# Because these are 'replace' operations it's safe to modify this script
# and re-run it
ldapmodify -Y EXTERNAL -H ldapi:/// <<EOS
dn: cn=config
replace: olcSaslSecProps
olcSaslSecProps: noanonymous,noplain,minssf=56
dn: olcDatabase={1}hdb,cn=config
replace: olcAccess
olcAccess: {0}to * by dn.regex="^uid=([^@,]+)/admin,cn=gssapi,cn=auth$" manage by users read
-
replace: olcRequires
olcRequires: SASL
EOS
The following tweak disables unused sasl mechanisms, and means that
-Y GSSAPI
can be omitted form the ldapsearch command line.
# editor /etc/ldap/sasl2/slapd.conf
mech_list: gssapi external
(On the same machine, or on a separate client)
# 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
$ kinit nsrc
$ ldapsearch [-Y GSSAPI] [-b "dc=ws,dc=nsrc,dc=org"]
This should dump back the (mostly empty) LDAP database, as long as you have a Kerberos ticket
We are going to create a central user called "ldapuser"
Firstly in Kerberos:
$ kadmin -p nsrc/admin
addprinc ldapuser
... password: foo123bar
^D
And now in LDAP:
$ kinit nsrc/admin
$ ldapadd <<EOS
dn: uid=ldapuser,ou=People,dc=ws,dc=nsrc,dc=org
objectClass: account
objectClass: posixAccount
cn: ldapuser
uid: ldapuser
uidNumber: 10004
gidNumber: 100
homeDirectory: /home/ldapuser
loginShell: /bin/bash
gecos: ldapuser
description: User account
EOS
$ kdestroy
Now configure LDAP nscd/nsswitch, as per part 2 of exercise 2.
To verify all is working:
$ id ldapuser
You should see a result with the uid and gid. Repeated operations should be quick as nscd will be caching them.
Troubleshooting:
/etc/cron.hourly/kerberos
if necessary.For easier management you can install the ldapscripts
package, but see
the patches at the end of exercise 4.
OpenLDAP replication is left as an exercise to the reader. You can configure round-robin DNS for ldap.ws.nsrc.org and it should work.