Skip to content

Authentification Kerberos

L'authentification ssh de certains serveurs repose sur kerberos interfacé avec notre annuaire d'utilisateur (Active Directory lui même synchronisé avec le LDAP UCA). La génération d'un ticket Kerberos étant obligatoire à chaque connexion il n'est pas possible d'utiliser les clés ssh pour une connexion sans mot de passe.

Toutefois il est possible de générer un keytab permettant d'obtenir un ticket kerberos sans taper de mot de passe.

serveurs kerberisés

  • perso
  • turing
  • ada
  • certaines VM étudiantes
  • bastion (double facteur d'authentification pour cette machine. Elle requiert également une clé SSH)

Pré requis

echo -e "krb5-config krb5-config/default_realm string LOCAL.ISIMA.FR" | debconf-set-selections

ou

Taper le nom du Realm (ici: LOCAL.ISIMA.FR - En majuscules) quand il vous sera demandé

apt install krb5-user krb5-config

Authentification

kinit <username-uca>
# ou
kinit <username-uca>@LOCAL.ISIMA.FR

Le Realm (LOCAL.ISIMA.FR) n'a pas besoin d'être renseigné, s'il est défini par défaut lors de l'installation des requirements

Il faut saisir le mot de passe

la commande klist liste les tickets

$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: <username-uca>@LOCAL.ISIMA.FR

Valid starting     Expires            Service principal
08/24/20 10:10:37  08/24/20 20:10:37  krbtgt/LOCAL.ISIMA.FR@LOCAL.ISIMA.FR
        renew until 08/25/20 10:10:37

Vous pouvez tester la connexion en forçant le transfert du ticket kerberos obtenu avec l'option -K. Cela peut-être nécessaire pour accéder à des ressources depuis la session que vous ouvrez sur le serveur (e.g. un accès à un partage NFS Kerberisé).

ssh -K <username-uca>@perso.isima.fr

kdestroy permet de détruire un ticket. À faire avant de continuer avec le keytab pour bien s'assurer qu'on récupère un ticket KRB5 avec le keytab sans saisie du mot de passe.

Création du keytab

La commande interactive ktutil permet de créer un fichier keytab.

$ ktutil
ktutil:  ?
Available ktutil requests:

clear_list, clear        Clear the current keylist.
read_kt, rkt             Read a krb5 keytab into the current keylist.
read_st, rst             Read a krb4 srvtab into the current keylist.
write_kt, wkt            Write the current keylist to a krb5 keytab.
write_st, wst            Write the current keylist to a krb4 srvtab.
add_entry, addent        Add an entry to the current keylist.
delete_entry, delent     Delete an entry from the current keylist.
list, l                  List the current keylist.
list_requests, lr, ?     List available requests.
quit, exit, q            Exit program.

ktutil:  addent -password -p <username-uca>@LOCAL.ISIMA.FR -k 1 -e aes256-cts-hmac-sha1-96
Password for <username-uca>@LOCAL.ISIMA.FR: 
ktutil:  wkt my.keytab
ktutil:  exit

Un secret dérivé du mot de passe est généré dans le fichier ~/my.keytab

Bonne pratique

À l'image de vos clés SSH, il est prudent de mettre votre keytab (qui je le rappelle est un secret) dans un répertoire avec les droits 0700 (accès au propriétaire seulement).

mkdir ~/.krb5
chmod 0700 ~/.krb5
mv my.keytab ~/.krb5

Authentification avec KeyTab (sans mot de passe)

Remarques

Il n'est pas possible de demander à ssh de récupérer le ticket auprès du KDC/AD, seul la commande kinit le peut (ainsi que libpam-krb5). SSH ne peut utiliser que le ticket déjà présent sur la session. Il faut donc d'abord faire un kinit sur keytab, puis faire un ssh -K qui utilisera ton ticket pour s'authentifier sur un serveur SSH Kerberisé.

Ce keytab permet d'obtenir un ticket KDC/AD sans saisir ton mot de passe.

$ kinit -k -t ~/.krb5/my.keytab <username-uca>@LOCAL.ISIMA.FR
$ klist 
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: <username-uca>@LOCAL.ISIMA.FR

Valid starting     Expires            Service principal
08/24/20 10:31:13  08/24/20 20:31:13  krbtgt/LOCAL.ISIMA.FR@LOCAL.ISIMA.FR
        renew until 08/25/20 10:31:13

vous pouvez tester la connexion en forçant l'envoie du ticket kerberos obtenu avec l'option -K

ssh -K <username-uca>@perso.isima.fr

Il peut être intéressant de récupérer un ticket Kerberos via le kinit depuis votre .bashrc. Ainsi, vous avez un ticket Kerberos toujours disponible pour vous connecter aux serveurs de l'ISIMA/LIMOS.

Dans votre fichier ~/.bashrc ajoutez :

if timeout 0.4 ping -c1 192.168.100.75 > /dev/null 2>&1;; then
  if ! klist -s; then
      kinit -k -t ~/.krb5/my.keytab <username-uca>@LOCAL.ISIMA.FR 2> /dev/null
      true
  fi
fi

Si vous n'avez pas déjà un ticket KRB5, alors vous en réclamez un au controlleur de domaine. On ne veut pas afficher le message d'erreur de la commande kinit (2> /dev/null), car dans le cas où vous ne seriez pas à l'ISIMA, vous recevriez toujours une erreur lors de l'ouverture d'un terminal.

J'ai placé un timeout de 0,4 seconde sur la commande ping. Dans le cas où le controlleur de domaine ne serait pas joignable (vous n'êtes pas à l'ISIMA ni sur le VPN), alors la procédure ne ralentie que de peut l'ouverture d'un shell (ce timeout peut engendrer un echec du sondage avec la commande ping que j'ai evalué de 1 à 2 %, le cas échéant, le ticket est quand même récupérable par le lancement de la commande kinit comme décrit ci-dessus).

CI / Gitlab

exporter son keytab en hexadécimal

hexdump -v -e '1/1 "%02x"'  ~/.krb5/my.keytab > ~/.krb5/my.keytab.hex

récupérer le keytab à partir de sa version hexadécimal

sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI'  ~/.krb5/my.keytab.hex | xargs printf

variable CI gitlab

sur le gitlab, dans CI / CD > Variables [collapse] > créer l'entrée suivante:

  • key: KEYTAB
  • value: (le contenu du fichier ~/.krb5/my.keytab.hex)

exemple de fichier .gitlab-ci.yml pour déployer avec pelican sur sa page perso

image: ubuntu:xenial

cache:
  paths:
    - output/ # le répertoire où se trouve le HTML statique généré

build:
  stage: build
  script:
    # dépendances pelican thèmes
    - apt-get install -y --force-yes build-essential python-dev python-pip git nodejs nodejs-legacy npm
    - pip install --upgrade pip==9.0.3
    - pip install -r requirements.txt
    - cd content && npm install && cd ..
    - sed -i "s/RELATIVE_URLS = True/RELATIVE_URLS = False/" pelicanconf.py
    - apt-get install -y --force-yes locales
    - locale-gen fr_FR
    - locale-gen fr_FR.UTF-8
    - update-locale LANG=fr_FR.UTF-8
    - . /etc/default/locale
    # génération du HTML statique dans le répertoire output
    - pelican content
    # dépendance pour l'authentification kerberos
    - echo -e "krb5-config krb5-config/default_realm string LOCAL.ISIMA.FR" | debconf-set-selections
    - apt-get install -y --force-yes krb5-user krb5-config
    # récupération du KEYTAB en hexa 
    - echo "$KEYTAB" > my.keytab.hex
    # conversion du KEYTAB en hexa en binaire
    - sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' my.keytab.hex | xargs printf > my.keytab
    # génération du ticket kerberos
    - kinit -k -t my.keytab vimazeno@LOCAL.ISIMA.FR
    # préparation du répertoire servi par apache
    - ssh -K vimazeno@perso.local.isima.fr "mkdir -p ~/public_html/"
    - ssh -K vimazeno@perso.local.isima.fr "echo 'Options +FollowSymLinks' >  ~/public_html/.htaccess"
    - ssh -K vimazeno@perso.local.isima.fr "echo 'RewriteEngine on' >>  ~/public_html/.htaccess"
    - ssh -K vimazeno@perso.local.isima.fr "echo 'RewriteCond %{HTTP_HOST} ^perso.isima.fr$' >>  ~/public_html/.htaccess"
    - ssh -K vimazeno@perso.local.isima.fr "echo 'RewriteRule (.*) https://perso.limos.fr%{REQUEST_URI} [R=301,L]' >>  ~/public_html/.htaccess"
    # rsync du HTML statique généré
    - apt-get install -y --force-yes rsync
    - rsync -az --exclude '_' -e "ssh -K" output/ vimazeno@perso.local.isima.fr:~/public_html/
  # le déploiement se fera uniquement lorsque je clique sur le "play" de la CI via l'interface gitlab
  when: manual

Kerberiser un serveur SSH

Il faut d'abord que l'host soit bind au domaine (utiliser le role join-ad de la stack). Ensuite il faut modifier le service SSH.

Dans le fichier /etc/ssh/sshd_config éditer les entrées suivantes :

PasswordAuthentication yes
# Kerberos options
KerberosAuthentication yes
# GSSAPI options
GSSAPIAuthentication yes

On restart le service sshd: ```bash systemctl restart sshd