Centralisation et distribution des clés RSA publiques¶
- Contenu
- Centralisation et distribution des clés RSA publiques
- Stockage des clés dans l'annuaire
- Stockage local des fichiers authorized_keys
- Script
- Cron
L'intégration ldap-pam-nss permet de provisionner les comptes d'utilisateurs sur les serveurs, et de contrôler quel utilisateur peut ouvrir une session sur quelle machine.
Si les clés RSA publiques des utilisateurs étaient également centralisées sur le LDAP, on disposerait d'un système complet de contrôle d'accès aux machines.
Il existe un patch pour openssh qui répond exactement à ce besoin: OpenSSH LDAP Public Key patch (http://code.google.com/p/openssh-lpk). Le serveur openssh patché interroge un annuaire ldap pour connaître les clés autorisées.
Je ne suis pas très chaud pour sortir openssh de la gestion automatique des paquets. En attendant que cette fonctionnalité soit éventuellement intégrée au code mainstream, on va donc faire autrement. Un simple script shell exécuté en cron devrait pouvoir faire l'affaire.
Le script devra parcourir le ldap et installer ou mettre à jour les clés des utilisateurs autorisés à se connecter.
Le script ne devra pas supprimer les clés des comptes locaux destinés à se connecter en cas de défaillance du ldap.
Note: j'ai cru voir quelque part qu'on peut installer les clés des users hors de leur home. Cela permettrait d'installer la clé d'un user qui ne s'est pas encore loggé et n'a donc pas encore eu son /home créé par pam.
Edit: oui, utiliser AuthorizedKeysFile dans /etc/ssh/sshd_config (http://www.openbsd.org/cgi-bin/man.cgi?query=sshd_config&sektion=5 - exemple: AuthorizedKeysFile %h/.ssh/authorized_keys /var/ldap_authorized_keys/%u)
Edit2: FIXME WHEEZY - dans squeeze, AuthorizedKeysFile ne permet de spécifier qu'un seul emplacement => on utilise à la place le paramètre AuthorizedKeysFile2, qui disparaît avec l'arrivée de Wheezy => penser à faire la modification lors du passage de Squeeze à Wheezy.
Stockage des clés dans l'annuaire¶
Le schéma d'openssh-lpk fournit une classe et un attribut servant à stocker des clés RSA.
openssh-lpk.schema
#
# LDAP Public Key Patch schema for use with openssh-ldappubkey
# Author: Eric AUGE <eau@phear.org>
#
# Based on the proposal of : Mark Ruijter
#
# octetString SYNTAX
attributetype ( 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 )
# printableString SYNTAX yes|no
objectclass ( 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 )
)
openssh-lpk.ldif
dn: cn=openssh-lpk,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: openssh-lpk
olcAttributeTypes: {0}( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' DES
C 'MANDATORY: OpenSSH Public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.
1.1466.115.121.1.40 )
olcObjectClasses: {0}( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' DESC
'MANDATORY: OpenSSH LPK objectclass' SUP top AUXILIARY MAY ( sshPublicKey $
uid ) )
Stockage local des fichiers authorized_keys¶
Les fichiers sont stockés dans /var/ldap_authorized_keys/, sous le nom du user concerné, avec owner root, en 644.
Configurer AuthorizedKeysFile [ou AuthorizedKeysFile2 sous Squeeze] dans /etc/ssh/sshd_config pour que cet emplacement supplémentaire soit pris en compte:
Version Wheezy
#AuthorizedKeysFile %h/.ssh/authorized_keys AuthorizedKeysFile %h/.ssh/authorized_keys /var/ldap_authorized_keys/%u
Version Squeeze
#AuthorizedKeysFile %h/.ssh/authorized_keys AuthorizedKeysFile %h/.ssh/authorized_keys AuthorizedKeysFile2 /var/ldap_authorized_keys/%u
service ssh restart
Script¶
Note: penser à modifier le paramètre thishost.
#!/bin/bash
# ------------------------------------------------------------------------------
# ldap_authorized_files
# ------------------------------------------------------------------------------
# synchronisation des clés publiques avec le LDAP
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Paramètres
# ------------------------------------------------------------------------------
# emplacement du fichier pid
pidfile=/var/run/ldap_authorized_files.pid
# uri de l'annuaire ldap
ldapuri=ldap://127.0.0.1
# Note: c'est le "127.0.0.1" qu'on retrouve dans les ACL. Si on remplace par
# "localhost", ça ne fonctionne plus en IPv6, ou alors il faudrait
# ajouter ::1 dans les ACL
# base de recherche des données dns sur l'annuaire
ldapusersbase="ou=users,ou=unix,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR"
ldapgroupsbase="ou=groups,ou=unix,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR"
# nom d'hôte
thishost=rigel
# chemin des fichiers allowed_keys
allowed_keys_path=/var/ldap_authorized_keys
# ------------------------------------------------------------------------------
# Logs
# ------------------------------------------------------------------------------
erreur=0
date_log () {
echo -n "`date +\"%d/%m/%y-%X\"`: "
echo $1
}
sortie_erreur () {
date_log "exécution terminée avec le code d'erreur $erreur"
exit $erreur
}
# ------------------------------------------------------------------------------
# Vérification du pid
# ------------------------------------------------------------------------------
if [ -f $pidfile ]; then
pid=`cat $pidfile`
if [ $? != 0 ]; then
date_log "lecture du fichier $pidfile impossible - pas d'exécution"
erreur=13
sortie_erreur
fi
ps -p $pid 1>/dev/null 2>/dev/null
if [ $? == 0 ]; then
date_log "lancement impossible - script en cours d'exécution sous le pid $pid"
erreur=10
sortie_erreur
fi
fi
echo $$ >$pidfile
# ------------------------------------------------------------------------------
# Traitement
# ------------------------------------------------------------------------------
for cn in $( ldapsearch -P 3 -H $ldapuri -x -b "ou=groups,ou=unix,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR" "(&(objectClass=posixGroup)(|(cn=login$thishost)(cn=loginall)(cn=sudo$thishost)(cn=sudoall)))" memberUid | grep "memberUid:" | sed 's/memberUid: \(.*\)/\1/' )
do
date_log "cn $cn"
allowed_keys_file=$allowed_keys_path/$cn
if [ ! -f $allowed_keys_file.ok ]; then
tempfile=$( mktemp )
touch $tempfile
chmod 644 $tempfile
IFS=$'\n'
for key in $(ldapsearch -P 3 -H $ldapuri -x -b "cn=$cn,$ldapusersbase" -LLL "(&(objectClass=posixAccount)(cn=$cn))" sshPublicKey | sed 's/^ //g' | tr -d '\n' | sed -e "s/sshPublicKey: /\n/g" | tail -n +2 )
do
date_log "key $key"
echo $key >>$tempfile
done
unset $IFS
diff -q $tempfile $allowed_keys_file 1>/dev/null 2>&1
if [ "$?" != "0" ]; then
mv $allowed_keys_file $allowed_keys_file.old 1>/dev/null 2>&1
mv $tempfile $allowed_keys_file
else
rm $tempfile
fi
touch $allowed_keys_file.ok
fi
done
rm $allowed_keys_path/*.ok
exit 0
Cron¶
# m h dom mon dow command # installation des clés publiques depuis le ldap # (http://www.illyse.org/projects/illyseinfra/wiki/Ldap-authorized_keys) 0 * * * * /usr/local/bin/ldap_authorized_keys 1>/dev/null 2>&1
Mis à jour par Pierre-Arnaud Poudret il y a plus de 12 ans · 1 révisions