Traditionally we store public keys in ~/.ssh/authorized_keys, but this means pushing them around all the servers we want to connect to. Instead of doing that let’s put them onto our LDAP server and store them once.
Modify Your LDAP Schema
First we need to modify our LDAP schema so that it has the required storage for sshPublicKeys.
Create an .ldif file called openssh-lpk.ldif and paste in the following:
dn: cn=openssh-lpk,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: openssh-lpk
olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
DESC 'MANDATORY: OpenSSH Public key'
EQUALITY octetStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
DESC 'MANDATORY: OpenSSH LPK objectclass'
MAY ( sshPublicKey $ uid )
)
Then import it into your LDAP config using:
ldapadd -Y EXTERNAL -h ldapi:/// -f openssh-lpk.ldif
For each user you should add an objectClass of ldapPublicKey and then you can go and create attribute(s) for sshPublicKey and paste your current authorised_keys in. You can have more than one sshPublicKey attribute, or have many entries in one attribute. If you paste multiple entries into a single key they will become base64 encoded - just bear that in mind as you’ll need to process that later.
Create a Script to Extract a Users Keys
Modify the following script to suit and put it into /usr/local/bin making it executable.
You will need to ensure that the variables URI, BASE, BINDDN and BINDPW are populated in your /etc/ldap/ldap.conf.
ldap-ssh-publickey.sh
#!/bin/bash
# Find sshPublicKey for the given user and process
# each entry into an authorized_keys format
if [ -z "$1" ]; then
echo "No user id specified"
exit 1;
fi
# Read variables from ldap.conf
CONF=/etc/ldap/ldap.conf
if [ -e "$CONF" ]; then
while read -r var val; do
export "$var"="$val"
done <<< $(grep "^[^#]" $CONF)
fi
# Search LDAP and return the lines with no-wrap
ldapsearch -x -D ${BINDDN} -w ${BINDPW} -H ${URI} \
-b ${BASE} "(&(objectClass=posixAccount)(uid=$1))" \
-o ldif-wrap=no sshPublicKey | while read -r line; do
# Double :: returns are multiline base64 encoded
if [[ "$line" = sshPublicKey::* ]]; then
echo "$line" | sed 's/sshPublicKey:: //' | base64 -d
# Single : are direct public keys
elif [[ "$line" = sshPublicKey:* ]]; then
echo "$line" | sed 's/sshPublicKey: //'
fi
done
chmod +x /usr/local/bin/ldap-ssh-publickey.sh
You can test the script from the command line:
/usr/local/bin/ldap-ssh-publickey.sh myuser
Edit /etc/ssh/sshd_config
Add the following entries into sshd_config.
AuthorizedKeysCommand /usr/local/bin/ldap-ssh-publickey.sh
AuthorizedKeysCommandUser nobody
Restart sshd.
sudo systemctl restart sshd
Sshd will now use either the LDAP of file version of the public keys. If you want to disable the use of ~/.ssh/authorized_keys files altogether add the following into sshd_config and restart.
AuthorizedKeysFile none
If you do this then none of your non-LDAP users will be able to use public keys.