Authentification Kerberos (SASL GSSAPI)
Installation
On installe le paquet krb5-user pour avoir les commandes utiles :
apt-get install krb5-user
On crée ensuite le fichier /etc/krb5.conf :
[libdefaults] default_realm = DOMAIN.TLD dns_lookup_realm = false dns_lookup_kdc = false ticket_lifetime = 24h renew_lifetime = 7d forwardable = true [realms] DOMAIN.TLD = { kdc = AD1.DOMAIN.TLD admin_server = AD1.DOMAIN.TLD } [domain_realm] .DOMAIN.TLD = DOMAIN.TLD DOMAIN.TLD = DOMAIN.TLD
On peut alors tenter une première authentification :
kinit myuser@DOMAIN.TLD
On vérifie ensuite le ticket obtenu :
klist
Pour la suite, on supprime le ticket obtenu :
kdestroy
Création d'un fichier keytab
sudo possiblement).
On crée le fichier keytab (par exemple /etc/myuser.keytab en lançant la commande ktutil (mode interactif) et on entre les commandes suivantes :
ktutil: addent -password -p myuser@DOMAIN.TLD -k 1 -e RC4-HMAC Password for myuser@DOMAIN.TLD: ktutil: wkt /etc/myuser.keytab ktutil: q
On récupère ensuite un ticket en utilisant le fichier keytab :
kinit myuser@DOMAIN.TLD -k -t /etc/myuser.keytab
On vérifie ticket obtenu :
klist
On peut maintenant utiliser ce ticket pour interroger l'annuaire LDAP :
On installe pour commencer les dépendances pour l'authentification SASL GSSAPI :
apt-get install sasl2-bin libsasl2-2 libsasl2-modules libsasl2-modules-gssapi-mit
On peut ensuite interroger l'annuaire LDAP avec ldapsearch :
ldapsearch -H ldaps://AD1.enscp.edu -Y GSSAPI -U 'myuser@DOMAIN.TLD' -b DC=enscp,DC=edu -s base dc
/etc/ldap/ldap.conf : sasl_secprops minssf=0,maxssf=0
Source : https://bugs.launchpad.net/ubuntu/+source/cyrus-sasl2/+bug/1015819
KRB5CCNAME dans le contexte d'exécution des commandes ldapsearch, ldapmodify, etc : export KRB5CCNAME=/path/to/file.keytab
Renouvellement automatique
En cas de besoin de renouvellement automatique (=token utilisé par un cron/service par exemple), un cron doit être mis en place :
- Créer le fichier
/usr/local/bin/renew-keytab:#!/bin/bash DEBUG=0 OWNER= KEYTAB= PRINCIPAL= usage() { [[ "$#" -gt 0 ]] && echo "$*" >&2 echo "Usage: $(realname "$0") keytab principal -o owner [-d]" echo " [keytab] Path of the keytab file (REQUIRED)" echo " [principal] Principal of the user (REQUIRED)" echo " -o/--owner Owner of the keytab file (defaut: the owner of the keytab file)" echo " -d/--debug Enable debug log" [[ "$#" -gt 0 ]] && exit 1 exit 0 } idx=1 while [[ $idx -le $# ]]; do opt=${!idx} case "$opt" in -d|--debug) DEBUG=1 ;; -o|--owner) ((idx++)) OWNER="${!idx}" ;; *) if [[ -z "$KEYTAB" ]]; then KEYTAB=$opt [[ ! -f "$KEYTAB" ]] && usage "Keytab file (${KEYTAB}) not found" elif [[ -z "$PRINCIPAL" ]]; then PRINCIPAL=$opt else usage "Invalid argument '$opt'" fi esac ((idx++)) done [[ -z "$KEYTAB" ]] && usage "Keytab file not specified" [[ -z "$PRINCIPAL" ]] && usage "Principal not specified" [[ -z "$OWNER" ]] && OWNER="$(stat -c %U "$KEYTAB")" debug() { [[ $DEBUG -eq 1 ]] && echo "[DEBUG] $*"; } if [[ "$( whoami )" != "$OWNER" ]]; then debug "This script must be run as $OWNER: rerun it as $OWNER" sudo -u "$OWNER" "$(realpath "$0")" "$@" exit $? fi if ! klist -k "$KEYTAB" | grep -q "$PRINCIPAL"; then if [[ -t 1 ]]; then kinit -k -t "$KEYTAB" "$PRINCIPAL" || exit 1 else echo "No ticket found for $PRINCIPAL in $KEYTAB. You must init first authentification by running $(realpath "$0") manually." exit 1 fi else debug "Ticket found for $PRINCIPAL in $KEYTAB. Try to renew it..." if kinit -R -k -t "$KEYTAB" "$PRINCIPAL"; then debug "Ticket renewed." [[ $DEBUG -eq 1 ]] && klist elif [[ -t 1 ]]; then debug "Failed to renew ticket, obtain new ticket interactively..." kinit -k -t "$KEYTAB" "$PRINCIPAL" || exit 1 else echo "Failed to renew ticket for $PRINCIPAL. You must obtain a new ticket by running $(realpath "$0") manually." exit 1 fi fi
- rendez le exécutable :
chmod 750 /usr/local/bin/renew-keytab
Exemple d'utilisation :
renew-keytab /etc/myuser.keytab myuser@DOMAIN.TLD
-o (ou –owner, par défaut : propriétaire actuel de fichier keytab). Si le script n'est pas lancé en tant que le propriétaire (spécifié ou auto-détecté), le script sera automatiquement relancé en tant que le propriétaire (en utilisant sudo).
Connexion en python (avec python-ldap)
import os import ldap os.environ['KRB5_CLIENT_KTNAME'] = '/etc/myuser.keytab' ldap_conn = ldap.initialize('ldaps://AD1.domain.tld') ldap_conn.sasl_non_interactive_bind_s('GSSAPI') print(ldap_conn.whoami_s())
Connexion en PHP
<?php $conn = ldap_connect("ldaps://AD1.domain.tld", 636) or die("Failed to connect to LDAP host"); ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($conn, LDAP_OPT_REFERRALS, 0); putenv("KRB5_KTNAME=/path/to/file.keytab"); ldap_sasl_bind($conn, null, null, 'GSSAPI') or die("Kerberos auth failure: ".ldap_error($conn));