Setting up Passwordless SSH Login and Key Management Using LDAPPublicKeys (LPK)

So SSH is awesome, Passwordless SSH using Key-based Authentication is even more awesome...but what if you have dozens and dozens of servers, and what if multiple users need to access said server? Do you really want to waste time copying SSH keys out to EVERY server you have in your environment?? Sure, you COULD use configuration management systems like Puppet or bcfg2 to handle this for you, but those are a real pain to set up.

Now, most shops I've worked in, have had LDAP servers in place for authentication between servers...my current workplace is no different. So that got me thinking, What if I could store SSH Keys within an LDAP directory? Then wherever I go on the network, my public key goes with me. Cool concept right?

Well, turns out it's been done before, but much of the documentation is spotty, lost to the ever-whirling eddies of the interwebz, or it just plain sucks and is a chore to read. So, here's me throwing my hat into the ring to show you all how to set this up.

For the purposes of this tutorial, we'll be assuming you're running a CentOS5/RHEL5-based environment, because that's what I'm running here at the office.

So first you'll need a few things: The sources for OpenSSH, the patch that hooks openldap-devel into OpenSSH at compile-time, the actual LDAP schema for OpenLDAP (there's actually one for Sun LDAP as well, if you're running Solaris) that sets up the LdapPublicKey ObjectType and sshPublicKey attribute, and you'll also need to install the openldap-devel and pam-devel packages.

So to start off, let's install those dependencies:

$ yum -y install gcc openldap-devel pam-devel zlib-devel openssl-devel

Once those are installed, go grab the OpenSSH sources:

$ wget -qO - http://ftp.jaist.ac.jp/pub/OpenBSD/OpenSSH/portable/openssh-5.4p1.tar.gz | tar zxf -

See what I did there? Favourite little bash trick of mine...download and unpack a tarball all in one shot. ;)

So now dive into the directory, download the patch and apply it:

$ cd openssh-5.4p1
$ wget -q http://openssh-lpk.googlecode.com/svn/trunk/patch/contrib/contrib-openssh-lpk-5.4p1-0.3.13.patch 
$ patch < contrib-openssh-lpk-5.4p1-0.3.13.patch

With the patch applied, it's time to do the ol' configure/make shuffle (Make sure you use these EXACT configure flags!):

$ ./configure --with-ldap --sysconfdir=/etc/ssh --prefix=/usr --with-pam
$ make

Now, we're going to stop here a second...normally you'd issue a make install here, but not yet...chances are OpenSSH is ALREADY installed, and as such, if you try to run a make install, it will fail miserably and leave the old (non-LPK'd) binaries behind. So for this next part, make sure you have some kind of local or out-of-band access to the machine you're working on, because at this point, you have to wipe ssh clean from the system.

BUT WAIT!!! DON'T DO ANYTHING JUST YET!!

 There's one more thing you should do here, and that's back up your current sshd configs as well as your sshd init script, because make certainly isn't going to do that for you (at least not in the case of the init script).

$ cp /etc/ssh /some/dir
$ cp /etc/init.d/sshd /some/dir

Now that you've got all that backed up, wipe out the existing OpenSSH install from a local console:

$ yum -y erase openssh-server

Once that's done, you can finally install the new version:

$ make install

Once the new version is installed, you're 3/4 of the way done on the OpenSSH side. Next up is to move the sshd init script back:

$ mv /dir/where/you/put/it/sshd /etc/init.d

Next up is the sshd_config file that was set up for you by make. Unless you have other custom configurations specific to your environment, you can leave the config alone save for the section regarding LPK, which should read as follows:

 

# here are the new patched ldap related tokens
# entries in your LDAP must have posixAccount & ldapPublicKey objectclass
UseLPK yes
LpkLdapConf /etc/ldap.conf
LpkServers  ldap://<address of your LDAP server>/
LpkUserDN   ou=People,dc=tuxotaku,dc=com
LpkGroupDN  ou=Groups,dc=tuxotaku,dc=com
LpkBindDN cn=Manager,dc=tuxotaku,dc=com
LpkBindPw <your bind password>
LpkServerGroup <whatever OU your "Manager" user is sitting under>
#LpkFilter (hostAccess=master.phear.org)
LpkForceTLS no
LpkSearchTimelimit 3
LpkBindTimelimit 3
LpkPubKeyAttr sshPublicKey

 

Of course I'm assuming you know at least SOMETHING about LDAP, so you'll know what else to change in there.

At this point, effectively you're done and OpenSSH will start without issue. It will however complain at you because there's a directory missing that it uses for privilege separation:

$ mkdir -p /var/empty/sshd/etc

And that's the SSH side taken care of...now for the LDAP server.

First, download the schema to your /etc/openldap/schema directory:

$ wget -q http://openssh-lpk.googlecode.com/files/openssh-lpk_openldap.schema -O /etc/openldap/schema/openssh-lpk_openldap.schema

Now just add an include line in your /etc/openldap/slapd.conf for the new schema:

include /etc/openldap/schema/core.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/inetorgperson.schema
include /etc/openldap/schema/nis.schema
include /etc/openldap/schema/openssh-lpk_openldap.schema

 

Once that's done, you're 90% of the way there; just restart openldap and then functionally, you're done. Though I'm assuming you have some kind of management interface for LDAP. (In our environment at the office, we use phpLDAPadmin.

So log into phpLDAPadmin and browse to the user you want to attach an SSH key to:

Now, under the user's "objectClass" entry, click "Add Value":

You should now see the following screen:

Select "ldapPublicKey" from the list and then hit "Add new ObjectClass".

Now that the ldapPublicKey ObjectClass is available to this user, you can add the sshPublicKey attribute to the user and paste their key in. Just hit "Add new attribute" as shown below, and you will get a dropdown menu.

In the dropdown menu, select "sshPublicKey" and you will see the dropdown change into the following:

Paste the user's key in here, then hit "Update Object", and that's it! You're done...the user now has their Public SSH key stored in your LDAP directory, and as long as their companion private key is available on the machine they're connecting from, they will never need to use a password to log into any machine that's pointed at your LDAP server.