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 11 ans · 1 révisions