YubiKey LDAP — schema and tools for YubiKey LDAP support

Yubico YubiKey is an affordable OTP generator with a convenient USB interface. One of the strenghts of YubiKeys is a very mature Linux support, for example the ability to use it for PAM authentication. Sadly there is a catch...

PAM authentication with YubiKey requires a list of YubiKey IDs for each user who is allowed to login. Typically in the form of a system file, for example /etc/yubikeys with entries similar to these:

    joe.user:abcdefgh1234:xyzxyz123456:...
    some.one:hgfedcba9876:hijklmnopqrs:...

The pam_yubico module is then used with authfile=/etc/yubikeys parameter:

    auth require pam_yubico.so authfile=/etc/yubikeys ...

That works well for one or two servers. However once you begin deploying YubiKey authentication across a handful or more servers you soon realise that a manual synchronisation of /etc/yubikeys file is PITA.

If you already authenticate your users against LDAP it would only make sense to keep these YubiKey IDs in LDAP as well, together with all other user details.

Sadly there seems to be no "official" LDAP schema provided by Yubico, the company behind YubiKeys. Their official stance, as of the time of this writing, is to store the YubiKey IDs in one of the unused LDAP attributes. What? Seriously?

Look no more. Follow the instructions below to cleanly add YubiKey IDs to your LDAP database:

    dn: uid=joe.user,ou=People,cn=example,cn=com
    objectClass: posixAccount
    objectClass: yubiKeyUser
    objectClass: ...
    uid: joe.user
    ...
    yubiKeyId: abcdefgh1234
    yubiKeyId: xyzxyz123456

This is the way to keep the YubiKey IDs in LDAP. Not through exploiting some 'shoeSize' or 'favouriteColour' attribute, OMG!

Download & Installation

Check out our LDAP schema and tools for Yubico YubiKey authentication project on the GitHub and follow the instructions in the README file. Come back for more when you're done.

Assigning YubiKeys to Users

Now that we've got the yubico schema installed it's time to store some keys. The easiest is to use the provided script yubikey-ldap. Set your LDAP configuration in yubikey-ldap.conf and run:

    root@ldap ~/yubico-ldap # ./yubikey-ldap
    yubikey-ldap manager (written by Michal Ludvig)
    Use Ctrl+D to exit at any time
    Use Enter to return one level up
    
    Enter username (<tab> to autocomplete) or YubiKey Id to manage                                                                                                                                                                   
    Username or YubiKey: joe.user
    Joe User [joe.user] has no assigned YubiKeys
    
    (a) add / <Enter> change user
    Command: a
    Enter YubiKey ID (12 chars minimum, best way is to touch the key)
    YubiKey ID: abcdefgh1234hicvekhvbrudddkffebtcchrufhggvb
    
    Assigning YubiKey 'abcdefgh1234' to 'joe.user'                                                                                                                                                                                  
    Commit? [Y/n] <Enter>
    Joe User [joe.user] has 1 assigned YubiKey
      1)  abcdefgh1234
    
    (a) add / (d) delete / <Enter> change user
    Command: Ctrl+D
    
    root@ldap ~/yubico-ldap #

Rinse and repeat for your other users. Assign as many YubiKey IDs to every user as you like. And don't forget to use the convenient <tab>-completion ;)

When ready move on to PAM+YubiKey+LDAP configuration.

YubiKey + PAM + LDAP

Here I assume you have a working LDAP authentication configured and you only need the YubiKey part added. First of all get a pam_yubico module for your system. Either compile it from source or install a ready-made package.

When done add the following statement to the appropriate file in /etc/pam.d/.... For existing pam-yubico configs replace authfile= with the LDAP parameters:

    auth require pam_yubico.so authfile=/etc/yubikeys \
          ldap_uri=ldap://ldap.example.com/     \
          ldapdn=ou=People,dc=example,dc=com    \
          user_attr=uid                         \
          yubi_attr=yubiKeyId ...

That's it. Try to SSH to the target system as joe.user, enter the password immediately followed by the YubiKey and you should be logged in :)

Troubleshooting

If things don't quite work as expected check the following:

Is SELinux enabled? Are egress firewalls enabled?
Note that for YubiCloud authentication the server daemon (e.g. sshd) has to make a HTTPS connection to the YubiCloud servers. Firewalls or SELinux may prevent it to do that.
Can the SSH server connect to LDAP server?
Again, there could be a firewall, broken DNS, etc.
Can each user read its yubiKeyId LDAP attributes?
Your LDAP access control lists (ACL) may prevent that (by default they shouldn't but check that with ldapsearch logging in as uid=joe.user.
Enable pam_yubico debug output
Temporarily add 'debug' at the end of pam_yubico parameters list. It will spit out a lot of potentially useful debug informations.

Donations

Have you found this project useful? Do you use it in production? Support its author by a PayPal or CreditCard donation. Thanks!


 

Assigning YubiKeys - low level approach

Yeah I know — you're a tough man and don't need any convenience tools. Let's work it the low-level way!

There are two steps involved:

  1. Figure out the ID of the given YubiKey token.
  2. Add objectClass: yubiKeyUser to each .. well .. YubiKey User object.
  3. Store the YubiKey IDs to the yubiKeyID LDAP attributes.

(Quite a self-explanatory naming, isn't it? ;)

You can indeed use your LDAP manager of choice (nah!), or rely on the classic proven command line tools as we do here (yeah!).

Figure out the YubiKey ID

This is very simple - insert YubiKey to your USB slot, open a text editor and touch the key. You'll see something like:

    abcdefgh1234uunnvfjueirijbtkneubfdefgddkgflv

The first 12 characters are the ID: abcdefgh1234
Simple as that.

Put it into LDAP

Open yubikey-add.ldif and enter the following few lines (change the dn: and they yubiKeyId: values of course!):

    #
    # Sample LDIF that stores two YubiKey IDs to uid=joe.user
    #
    dn: uid=joe.user,ou=People,dc=example,dc=com
    changetype: modify
    add: objectClass
    objectClass: yubiKeyUser
    -
    add: yubiKeyId
    yubiKeyId: abcdefgh1234
    yubiKeyId: xyzxyz123456

Now run ldapmodify to make the changes and verify with ldapsearch:

    ~# ldapmodify -W -x -D cn=Manager,dc=example,dc=com -f yubikey-add.ldif
          modifying entry "uid=joe.user,ou=People,dc=example,dc=com"

    ~# ldapsearch -W -x -D cn=Manager,dc=example,dc=com '(uid=joe.user)'
          # ...
          dn: uid=joe.user,ou=People,cn=example,cn=com
          objectClass: posixAccount
          objectClass: yubiKeyUser
          objectClass: ...
          uid: joe.user
          ...
          yubiKeyId: abcdefgh1234
          yubiKeyId: xyzxyz123456