How to add Kerberos to a Debian Machine

From CSLabsWiki
Revision as of 00:00, 20 September 2019 by Northug (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

This article will hopefully help you get started enrolling a Debian client machine in Central Authentication.

Get these packages: libpam-ldap libpam-krb5 libnss-ldap nfs-client krb5-user. The first two have a collection of PAM modules, the next is for NameSpace Switch, and the last is NFS. These packages will ask for a lot of configuration information that you should already know (e.g., the LDAP server's URI, "ldaps://", the search base, "dc=cslabs,dc=clarkson,dc=edu", the default realm "CSLABS.CLARKSON.EDU", LDAP version 3 [as recommended], no login required for accessing the database, etc.), so give it what you can. When it asks for a LDAP administrator DN and password, you can (and probably will want to) elide them--they're optional, and even if you stash them "securely" on the client, don't forget that our users have local root regularly. Similarly, you shouldn't let that account act like a local root--we use group membership for that.

Note: Using ldaps: is highly recommended; however, our setup with our own CA certificate requires you to get it first, or the secure handshake will fail. See OpenSSL CA for how to install the certificate on the machine. Once that's done, return here.

Setting up NSS

libnss-ldap doesn't configure /etc/nsswitch.conf for you by default--which is a good thing. Go ahead and edit that file as root, and append "ldap" to at least the "passwd" and "group" entries--in practice, I also do so for "gpasswd" and "shadow", and the latter may be necessary for auth to work. For example, here's what a couple lines should look like:

passwd:         compat ldap
group:          compat ldap
shadow:         compat ldap

Files on your local machine may vary, but that's the general template.

Save and exit, and, assuming your configuration is valid, you should be able to issue this command:

getent passwd

...and the terminal should spit out at you both the set of local users (like root and various system accounts) as well as users present in LDAP (as you've made them). If you're not seeing one or the other, check your nsswitch file, your LDAP configuration, and the presence of that CA certificate in /etc/ssl/ (assuming you're using LDAPS--yes, please use it).


If you can see the list of LDAP users (in the 1000000+ UIDs), skip this section. Otherwise, if you're having trouble, read on.

First things first, make sure you can see Talos; try pinging, then try pinging If the former doesn't work, check your network. If the former does but the latter doesn't, check your DNS settings; while our DNS is delegated to the public Internet, we generally use Talos itself for name resolution (id est, try dropping a nameserver line in your /etc/resolv.conf).

If it still doesn't work, try reloading the passwd cache (nscd -i passwd) and trying again. If not, still try reloading the passwd cache after each following step.

Check that you can query Talos; on Debian machines, install the ldap-utils package and try this command:

ldapsearch -H ldaps:// -D '' -b dc=cslabs,dc=clarkson,dc=edu

EDIT: Actually, this is probably what we want here.

ldapsearch -ZH ldap:// -D '' -b dc=cslabs,dc=clarkson,dc=edu

(This command, and plenty of others, are better explained in the Talos book.) If this gives you an error indicative of an authentication failure (such as a SASL error), make sure you've installed the CA certificate correctly; try wget (its failure is also indicative of a OpenSSL CA issue) until it works.

If that works, but (after reloading the passwd cache) getent passwd still doesn't work, you might have misconfigured the nss module; on Debian, try editing /etc/libnss-ldap.conf and read through the configuration file carefully (e.g., look for three slashes in a URI instead of two), making sure everything lines up with how it should be on Talos.

If that still doesn't help, restart the machine. Should that fail, hyrdology cannot save you.

Setting up Kerberos

Now we'll need to set up Kerberos. The default configuration file is in /etc/krb5.conf, and you'll need to edit it. Under the header [realms], be sure a section exists that looks like this:

		kdc =
		admin_server =
		default_domain =

Similarly, under [domain_realm], be sure a mapping that looks like this is present:


While that should technically do it, in case DNS is being stupid, it's good practice to edit this stanza near the top of the file, too:

	default_realm = CSLABS.CLARKSON.EDU

Now you should be able to kinit <your_principal/user_name> and get a ticket for yourself. You can later kdestroy this if you'd like, but it might be handy to keep around for NFS (later).

Setting up PAM

Once you're sure that's working, go into /etc/pam.d/ and prepare to look at some files. Debian generally configures them in a somewhat useful, though silly way. Enter common-auth and be sure that:

  1. The ordering is the line first, followed by, then
  2. All of these modules contain "try_first_pass" as their parameter (replace "use_first_pass" if necessary).
  3. Perhaps most importantly, make sure the "success=N" lines properly count the number of lines to the default line (so that it skips over that if they succeed).

That will do it for authentication--but you should really test this by using su or another terminal before you rescind your root terminal. Don't disconnect until you're sure it's working, or you're going to have a bad time!

Now, we need to make `passwd` command work. Enter common-password and remove the "use_authtok" parameter to Write out the file and exit; to test this, change to a user account (`su`, as above--you should have made sure this worked before :) and try `passwd`. You may be prompted to enter Kerberos credentials; if this is undesirable, press Enter (leave it blank) to skip past that part.

Oops: If you accidentally make it impossible to login to a machine (even as root), don't worry! You will need to reboot it (most machines respond to a press of the power button to power-off); usually, the machine will then boot to GRUB or another such bootloader. You will need to find a way to edit the kernel command line (TAB in GRUB and PXE); I would recommend using the "(recovery mode)" option to start, and appending init=/bin/sh, which will run a root shell as init. This will give you immediate and unrestricted root access to the machine (and pretty fast boot times), under the careful notice that, as init, you will be responsible for setting up certain things (like network interfaces) if you need them. FreeBSD has a similar "Single-user" mode available in its bootloader that has similar functionality. Finally, as a last resort, you can boot the machine into a recovery disk, such as a CRUX CD or a flash drive, and mount the local disk partition. One such useful partition may be network-bootable as a "Diagnostic" option, so stay tuned :)

I mentioned in the passing that LDAP DNs and Kerberos principals can have diverging passwords, which can be problematic. Luckily, the default common-password will take care of updating both at the same time--but only if they converge to begin with. Since this is going to be an issue at first, I've put a nag message in common-session to ensure that users are instructed to use kpasswd to change their Kerberos password at their leisure (or bug an administrator to do so) when the session mode of fails--most likely, because they logged in with a local or LDAP account and, thus, are not associated with a principal and a TGT key. Reconstructing this is left as another exercise to the reader, but I'll give you a hint: it makes clever use of the skip directives you've already seen, and with a local file. As an administrator, you will need to wrangle these into place.

Setting up sudo

It is generally a good idea to ensure that someone has the keys to the system other than yourself for better survivability (so that other people can maintain it). Options for sudo are controlled via the file /etc/sudoers (possibly in /usr/local/ on BSD), whose format is miserably documented. Luckily, you can usually use the default as a template :) . You should probably know that the ALL=(ALL) ALL or ALL=(ALL:ALL) ALL is basically root access. On Debian, the default "%sudo" group can be left alone and used with local accounts (and the "%wheel" group as well on BSD's sudo); however, you'll probably want to make sure certain other groups (ones managed via LDAP) can administrate the machine as well:

  • %admins, administrators, who, by necessity, need to be able to administrate all of the services (and who can freely change LDAP data to accomplish these ends); these should almost always be added.
  • %services, service principals, which are automatic accounts that need to be able to administrate services (and have total LDAP control as well); services like Ansible and automated backups fall into this category, and should almost always be added.
  • %maintainers, maintainers who will be freely capable of ensuring that the services keep functioning; giving them root access is generally a good idea so they can reconfigure system services if needed.
  • %users, the group for all network users, which need not be trusted, but generally receive the same permissions as csguest (including sudo access on the open lab machines). In some cases it may be worth explicitly denying access to users in PAM; see the configuration on Talos for a reference.

Other groups may be configured at a later time; be sure someone has a good rationale for making them! As mentioned above, time required to login to a service using a network account goes up linearly with the number of groups :)

Setting up NFS

In order to get NFS working, we first have to provision a "host key" or machine key. This is going to be used by rpc.gssd to attest the identity of the connecting machine; if we were so inclined, we could base much of our access control on the machines accessing the share. This is, however, usually unnecessary in our setup :)

That said, at least one key valid on the realm is needed to access the share in an automated fashion (it doesn't confer any particular user permissions). You'll want to add that to the keytab on the local machine so it can mount Bacon's NFS shares. For that, you'll need kadmin (replacing with a proper FQDN or some other unique identifier):

kadmin: addprinc -randkey host/
kadmin: ktadd host/
kadmin: q

Now, in order to make sure this happens mostly automatically, you'll want to add this line to /etc/fstab which describes the necessary mount parameters:      /mnt        nfs4         sec=krb5i,nolock         0         0

(where those long runs of spaces are supposed to be tab stops, which isn't easy to confer in this format). It should be noted that sec=krb5i must correspond with a valid -sec= mode on Bacon, which is currently set to krb5i:krb5p. I've mentioned previously on Talos why krb5 and krb5p are usually bad ideas, so I won't reiterate that here.

Note the nolock option; applications that heavily depend on locks (like most severe software projects; web browsers, office applications, etc.) will run far too slow without it. It's common to also include nosuid for untrusted network mounts, but we're not too worried about this on our open clients :)

See if it works! Try mount /mnt. If you get an error saying that "an incorrect parameter was specified", you will probably need to run rpc.gssd and try again. Don't worry about that transient error; rpc.gssd is a startup service and should start normally on the next reboot, allowing /mnt to be automatically mounted on startup with the rest of the filesystems.

At this point, you can try to su - or login to your Kerberos/LDAP account; assuming you've done everything properly, you should be in your networked home directory (and capable of viewing and modifying files in it :)

NFS4 Warning

NFS4 seems somewhat more strict in its Kerberos authentication. It may be necessary to change /etc/hostname to reflect the fully qualified domain name of the machine and assign in /etc/hosts to this FQDN as well You may need to reboot and ktrem and ktadd the client machine principle again.

Setting up SSH

There's one other good use of Kerberos/GSSAPI: SSH authentication. Using this, you only need to authenticate once--the time you get the Kerberos ticket. Afterward, through GSSAPI magic, any SSHd you connect to can verify your identity through the ticket, rather than you having to enter a password again.

Software based on OpenSSH already supports this natively, but you'll need to make sure the configuration is enabled, and you may need an extra key. For starters, let's enable it on the server; from there (and as root), edit /etc/ssh/sshd_config, finding and uncommenting or adding this line:

GSSAPIAuthentication yes

You can also enable it on the clients with the same directive in /etc/ssh/ssh_config (note the lack of a "d"); in practice, I've found it usually is, but it doesn't hurt to check.

The SSH GSSAPI implementation requires an exactly matching qualified domain name in its Kerberos host/... key. So, for example, for Phoenix, we'd need to make a key that exactly matches its FQDN (host/ You, of course, should have already created a key of this sort when mounting NFS, above.

That's usually all there is to it! One more neat trick: if you're using non-standard ports with SSH (we are), you may want to also edit your user-local SSH config, ~/.ssh/config to add the following lines:

Host myhost
    Port <port>
Host myhost.fq.dn
    Port <port>

Repeat, of course, for every host that you wish to so configure; once you're done, you should be able to get into any service you're authorized for with a simple ssh host. As long as your NFS home is mounted wherever your sessions are, this configuration should follow you around too :)



config_file_version = 2
domains =
services = nss, pam

id_provider = ldap
ldap_uri = ldap://
ldap_id_use_start_tls = true
ldap_search_base = dc=cslabs,dc=clarkson,dc=edu
ldap_tls_cacert = /etc/ssl/certs/ca-certificates.crt

auth_provider = krb5
chpass_provider = krb5
krb5_server =
krb5_kpasswd =
cache_credentials = true

min_id = 1000000
max_id = 1100000
enumerate = true

filter_groups = root
filter_users = root
reconnection_retries = 3

reconnection_retries = 3
offline_credentials_expiration = 2
offline_failed_login_attempts = 3
offline_failed_login_delay = 5