OpenSSH Database – OpenSSH with Public Keys from Database

databasepublic-keyssh

Is it possible to fetch the public keys from a database instead of the authorized_keys file?

I would like to use such a setup to manage ssh access to things like git repositories for multiple users without the need to recreate the authorized_keys file every time a public key is changed or added.

Best Answer

I found this question when trying to answer it myself. After some searching and experimentation, I've found a few other options for this. I'm going to skip the part about distributing keys as an alternative since Matt Simmons covered that. Also, I know there are times when that is not good enough. For example, if you are GitHub and have to store millions of public keys against a single user, continuously updating SSH authorized_keys files and keeping them synchronized across potentially dozens to hundreds of edge boxes is not feasible or desirable.

So,

  1. First of all, RedHat (and variants) have a supported patch for OpenSSH that adds the AuthorizedKeysCommand and AuthorizedKeysCommandRunAs options. The patch has been merged upstream in openssh 6.2. To quote from the man page:

    AuthorizedKeysCommand

    Specifies a program to be used for lookup of the user's public keys. The program will be invoked with its first argument the name of the user being authorized, and should produce on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS in sshd(8)). By default (or when set to the empty string) there is no AuthorizedKeysCommand run. If the AuthorizedKeysCommand does not successfully authorize the user, authorization falls through to the AuthorizedKeysFile. Note that this option has an effect only with PubkeyAuthentication turned on.

    AuthorizedKeysCommandRunAs

    Specifies the user under whose account the AuthorizedKeysCommand is run. Empty string (the default value) means the user being authorized is used.

    In my experiments tonight, I found that out of the box, this doesn't work due to default SELinux policies. You can get around this by turning off SELinux enforcement with setenforce 0. Since turning of SELinux is probably a bad idea, instead you can generate the correct policy. In my case, that was as simple as attempting to log in with the AuthorizedKeysCommand option set up in /etc/ssh/sshd_config and then using audit2allow -a -M local && semodule -i local.pp. This basically looks through the audit logs and finds things that were prevented and generates exceptions for them. If you are likely to have other stuff in there that might get whitelisted, you should probably learn more about audit2allow to make sure you get the new policies just right.

  2. There are other various (probably less tested and trusted) patches out there to add similar functionality. For example there is, openssh-script-auth. You can also find the patch that RedHat used and apply that directly. A quick bout of Googling uncovers https://launchpadlibrarian.net/89063205/openssh-5.3p1-authorized-keys-command.patch and https://launchpadlibrarian.net/105938151/openssh-authorized-keys-command.patch which are based on the RH versions but which have been updated for newer versions of OpenSSH.

  3. Patch OpenSSH to perform key lookups directly from some store (e.g. like GitHub and CodeBaseHQ and others have done). GitHub has not open sourced this patch, to the best of my knowledge, but I know in the past I've come across versions for MySQL and PostgreSQL key lookup. I tried to find them again just now but have not had much luck.

  4. There are also some FUSE-based options. For example there is LPKFuse which lets you serve public keys from LDAP by changing the AuthorizedKeysFile location to one on the LPKFuse filesystem. The LPKFuse FS creates virtual files whose content are backed by fields from a directory server.


All in all, I think option #1 is by far the best as it is officially supported by RedHat. Furthermore, it lets you put any logic you like in that script (including talking to a database) in any language you want.