Outils personnels

Kerberos et mod auth kerb pour SSO sur Active Directory

De wikiGite

Le SSO (Single-Sign On) permettant à un poste sous Windows de s'authentifier automatiquement sur un site web est possible en utilisant Kerberos sur le serveur Web, pour valider l'utilisateur sur un contrôleur Active Directory.

Le schéma est le suivant :
- L'utilisateur s'authentifie sur sa session Windows, dans le domaine, donc via Active Directory
- Il obtient un ticket Kerberos (puisqu' AD fonctionne avec Kerberos sous Win2000 SP2 et suivant, et n'utilise plus NTLM qu'en mode dégradé pour compatibilité (ancien systèmes 98, anciennes versions de navigateurs)
- Lorsqu'il lance IE (6 et supérieurs) ou Firefox (3), s'ils sont bien configurés, ce ticket est envoyé dans le flux HTTP
- Le serveur web récupère ce ticket grâce à mod_auth_kerb, le valide auprès du contrôleur Active Directory (grâce à son propre client Kerberos)
- Si le ticket est OK, on obtient le login de l'utilisateur dans les variables REMOTE_USER et PHP_AUTH_USER, il n'y a plus qu'à les traiter au niveau de l'applicatif hébergé pour valider l'accès

L'utilisateur n'a donc pas à se ré-authentifier via une fenêtre de login lorsqu'il accède au site protégé, tout est automatique.

Documentation

La procédure la plus pertinente est celle de Achim Grolms

Installation

Important

Le serveur web doit être exactement à la même heure que le contrôleur de domaine Active Directory, sinon Kerberos ne réussira pas à valider le ticket. Le plus simple est d'activer le serveur NTP sur le contrôleur, d'installer openntpd sur le serveur web et de le faire pointer sur le contrôleur AD.

Sur serveur WEB CentOS

On a travaillé ici sur un serveur CentOS4/BlueQuartz.

Client Kerberos

Les paquet clients Kerberos doivent être installés :

yum install krb5-libs krb5-workstation

Ce paquets étant pobablement déjà installés.

On construit le fichier de configuration Kerberos avec ces informations au minimum :

  • DOMAIN.COM est le domaine (nom long DNS) du domaine Active directory
  • dc1 est le nome d'hôte d'un contrôleur de domaine Active Directory
  • NOTE : les majuscules/minuscules sont importantes !
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = DOMAIN.COM
 dns_lookup_realm = false
 dns_lookup_kdc = false

[realms]
 DOMAIN.COM = {
 kdc = dc1:88
 admin_server = dc1:749
 default_domain = domain.com
 }

[domain_realm]
 .domain.com = DOMAIN.COM
 domain.com = DOMAIN.COM

Test du client Kerberos : il s'agit d'obtenir un ticket de la part du contrôleur Active Directory, comme le font les postes Windows

kinit <utilisateur windows>@DOMAIN.COM

kinit doit demander le mot de passe de l'utilisateur, et ne renvoyer aucune erreur après saisie de celui-ci.
On voit le ticket obtenu par

klist

Si tout est bon, on peut détruire ce ticket de test pour éviter des conflits ultérieurs

kdestroy

mod_auth_kerb

Ce module permet à Apache d'intercepter les données Kerberos dans le flux HTTP.
Le module fourni dans les repository CentOS ET REDHAT est en version 5.0 et ne fonctionne à priori pas... On va donc compiler une version à jour (5.4 en avril 2009).

Installer l'environnement de développement sur la BlueQuartz, ainsi que les sources Kerberos, et les outils de compilation Apache (apxs) :

yum install gcc krb5-devel http-devel

Récupérer les sources mod_auth_kerb sur Sourceforge (par wget sur le serveur, ou via un poste):

http://sourceforge.net/project/showfiles.php?group_id=51775

Puis :

tar -xvzf mod_auth_kerb-xx.xx.tar.gz
cd mod_auth_kerb-xx.xx
./configure --without-kerb4
make
make install

Paramétrer le VirtualHost Apache à protéger en ajoutant à sa configuration (dans la config du vhost ou un include, pas en .htaccess) :

# /etc/httpd/conf/vhosts/site1.include
# user customizations can be added here.
<Directory "/home/.sites/28/site1/web" >
  AuthType kerberos
  AuthName "Login Kerberos"
  Krb5Keytab /etc/httpd/conf/apache.ktab
  KrbAuthRealms DOMAIN.COM
  KrbMethodNegotiate on
  KrbServiceName Any
  KrbMethodK5Passwd off
  Require valid-user
</Directory>

Note : ces paramètres sont valables aussi, selon les préférences, dans une stanza "<Location />" avec un chemin relatif à la racine du site et non plus à la racine du système.


Info : avec cette version de mod_auth_kerb, on a les messages de debug Kerberos si on active ceux-ci dans Apache, dans httpd.conf :

LogLevel debug

Les messages sont dans l'error_log d'Apache OU dans l'error_log du virtualhost selon les configurations. Penser à remettre ce paramètre comme avant ("warn" à priori, ou 'info") pour éviter trop de logs ensuite !

On peut aussi activer des logs Kerberos sur le contrôleur de domaine Active Directory, ça ne génère pas beaucoup de messages, mais ça peut aider en cas de problème. Lancer regedit et modifier ou créer la clé :

HKML/SYSTEM/CurrentControlSet/Control/Lsa/Kerberos/Parameters/Loglevel

en REG_DWORD, avec la valeur 0x1.
Les logs sont visible dans le journal "Système".
Si les quelques lignes ci-dessus sont du chinois pour vous, laissez tomber, c'est trop sensible pour qui ne maitrise pas.


Sur serveur WEB Debian

Client Kerberos

Les paquet clients Kerberos doivent être installés :

apt-get update
apt-get install krb5-config krb5-user

On construit le fichier de configuration Kerberos avec ces informations au minimum :

  • DOMAIN.COM est le domaine (nom long DNS) du domaine Active directory
  • dc1 est le nome d'hôte d'un contrôleur de domaine Active Directory
  • NOTE : les majuscules/minuscules sont importantes !
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = DOMAIN.COM
 dns_lookup_realm = false
 dns_lookup_kdc = false

[realms]
 DOMAIN.COM = {
 kdc = dc1:88
 admin_server = dc1:749
 default_domain = domain.com
 }

[domain_realm]
 .domain.com = DOMAIN.COM
 domain.com = DOMAIN.COM

Sur le contrôleur Active Directory

procédure sur Windows 2003

LA VERSION DE KTPASS.EXE EST IMPORTANTE. Une mauvaise version peut générer un fichier ktab sans erreur, mais ce fichier ne sera pas utilisable (exemple : erreur "Preauthentication failed while getting initial credentials" dûe non pas à un problème de mot de passe mais à un cryptage erroné).

Donc vérifier systématiquement, au besoin, charger les derniers support tools (par exemple ici http://www.microsoft.com/downloads/en/details.aspx?FamilyId=6EC50B78-8BE1-4E81-B3BE-4E7AC4F0912D&displaylang=en) et les réinstaller.

Créer un utilisateur AD pour le lier au serveur web. En effet, Apache va envoyer une requête et doit être reconnu par Active Directory pour que celui-ci lui réponde (comme une ouverture de session utilisateur).
Cocher dans les propriétés de l'utilisateur, onglet "Compte" :

  • le mot de passe n'expire jamais
  • le compte est autorisé pour le délégation
  • utiliser le type de cryptage DES

Cependant, cet utilisateur ne pourra pas être utilisé tel quel, car Apache envoie quelque chose du genre "HTTP/<serveur>@DOMAIN" pour s'authentifier. Un tel nom d'utilisateur n'est pas autorisé dans AD, il faut donc le lier à l'utilisateur créé ci-dessus... Tout le monde suit ?

Pour ça, il nous faut le resource kit sur le contrôleur, ou tout au moins l'outils "ktpass" (qu'on peut trouver individuellement sur internet en cherchant bien). Une fois celui-ci installé, il va :

  • Générer un fichier dit "keytab" que le serveur web va utiliser pour s'authentifier
  • Modifier l'utilisateur AD en remplaçant le nom de compte par le "principal" kerberos

Lancer sur le contrôleur, sur une seule ligne :

ktpass -out c:\un_repertoire_au_choix\apache.ktab -princ HTTP/<server web>.domain.com@DOMAIN.COM \
-mapuser <utilisateur AD> -pass <mot_de_passe> -crypto <crypto> -ptype <protocol type>

-crypto peut être DES-CBC-MD5 ou RC4-HMAC-NT selon les version de Windows server

-ptype peut être KRB5_NT_PRINCIPAL ou KRB5_NT_SRV_HST

NOTE IMPORTANTE : A priori, c'est le nom de la MACHINE et non celui du VHOST qu'on met dans HTTP/<server web>.domain.com@DOMAIN.COM.

procédure sur Windows 2003 R2

Même procédure que pour 2003 (avec "-crypto DES-CBC-MD5 -ptype KRB5_NT_PRINCIPAL"), avec en plus :

  • Cocher "Ne nécessite pas une préauthentification..."

Si l'onglet "Delegation" n'apparait pas dans les propriétés de l'utilisateur, ajouter le SPN manuellement :

  • Lancer adsiedit.msc
    • propriété de l'utilisateur
    • onglet attribute editor
    • paramètre serviceprincipalname : "Edit"
    • ajouter HTTP/<server web>.domain.com@DOMAIN.COM , puis "Add"

procédure sur Windows 2008

  • créer sur le domaine AD un utilisateur (exemple : "user1") pour la synchronisation des comptes et des groupes et l'accès à Active Directory
  • Cocher "le mot de passe n'expire jamais"
  • Activer les "fonctionnalités avancées" dans le menu affichage de la console ADUC
  • Modifier le paramètre "userPrincipalName" dans l'onglet "Editeur d'attributs", avec :
      HTTP/<nom complet en minuscules (fqdn) du serveur>@<DOMAINE DNS en majuscules>
  • Dans une fenêtre DOS, lancer :
      setspn –A http/<nom complet en minuscules (fqdn) du serveur>@<DOMAINE DNS en majuscules> <DOMAINE NETBIOS (nom court) en majuscules>\user1

NOTE : en raison de l'UAC (User Access Control) de Win2008, cette commande doit être lancée par l'Administrateur (même un membre du groupe "Admins du domaine" n'a pas assez de droits). Pour ça :
- soit se connecter en tant qu'Administrateur sur le DC,
- soit lancer un "shell élevé" (clic-droit, "lancer en tant qu'Administrateur" -> bien sûr il faut avoir le droit de le faire, donc être dans le groupe admins du domaine !).

  • Réinitialiser le mot de passe de l'utilisateur. (Important, sinon le "key version number" (kvno) n'est pas bon !)
  • Cocher "Utiliser le chiffrement DES via Kerberos pour ce compte" dans l'onglet compte
  • Un nouvel onglet a dû apparaitre : "Délégation". Cocher "Approuver cet utilisateur pour la délégation à tous les services (Kerberos uniquement)"
  • Générer un fichier ktab :
ktpass -out kerb5.ktab -princ HTTP/<nom complet en minuscules (fqdn) du serveur>@<DOMAINE DNS en majuscules>  -mapuser user1@<DOMAINE DNS en majuscules> -pass <mot-de-passe> -crypto all -ptype KRB5_NT_PRINCIPAL

Une fois généré, transférer le fichier .ktab sur le serveur web, par exemple dans /etc/httpd/conf/.
Tester ce fichier avec kinit :

kinit -k -t /etc/apache2/apache.ktab HTTP/<server web>.domain.com@DOMAIN.COM

Il ne doit pas y avoir de message d'erreur. Visualiser et nettoyer le ticket avec :

klist
kdestroy

Sur le client

Le poste client qui se connecte à ce site doit évidemment être intégré au domaine AD, puisqu'il doit avoir obtenu un ticket au moment de l'ouverture de session Windows, ticket qu'il va réutiliser ici.

EDIT : PROBLEME DE TYPE DE CHIFFREMENT AVEC LES CLIENTS WINDOWS 7.

Windows 7 n'utilise plus par défaut le chiffrement DES-CBC-MD5 utilisé par le module apache kerberos. Il faut le forcer.

Sur le poste Windows 7, exécuter "gpedit.msc"
Dans la console, aller sur
Configuration Ordinateur / Paramètres Windows / Paramètres de sécurité / Stratégies locales/ Options de sécurité
Dans la panneau de droite, Double-cliquer sur l'option "Sécurité réseau : configurer les types de chiffrement autorisés pour Kerberos"

Cocher les cases "DES-CBC-MD5" et "RC4_HMAC_MD5". Valider.
Fermer la console stratégies locales.

Paramétrer le navigateur pour envoyer les informations Kerberos :

IE (6 et >)

Dans Outils/Options internet/Sécurité, choisir "Intranet local". Dans "Sites", "Avancé", entrer l'URL du serveur web protégé par kerberos.
Ensuite dans "Personnaliser le niveau", s'assurer dans "Authentification utilisateur" que c'est la "connexion automatique uniquement dans la zone intranet" qui est cochée.

Firefox

Dans la barre d'adresse, taper "about:config".
Chercher "network.negociate-auth.trusted-uris" et y ajouter l'URL du serveur web protégé par kerberos.

Firefox peut aider à debugguer une connexion difficile via son module NegociateAuth utilisé pour Kerberos. Utiliser les variables :

NSPR_LOG_MODULES=negociateauth:5
NSPR_LOG_FILE=/tmp/negociateauth.log (ou c:\temp\negociateauth.log)

dans l'environnement utilisateur avant de lancer Firefox, pour que les messages de debug soit envoyés vers le fichier negociateauth.log.

Utilisation du SSO

Sur le serveur Web, on peut créer une page PHP pour afficher ce qu'il reçoit en cas d'authentification réussie :

<?
echo $_SERVER['REMOTE_USER'];
echo $_SERVER['PHP_AUTH_USER'];
echo $_SERVER['AUTH_TYPE']:
?>

Ces variables ne sont remplies QUE si la connexion est réussie. On peut donc utiliser REMOTE_USER pour ensuite autoriser ou non l'accès à telle ou telle page du site.

Troubleshooting

  • Attention à bien avoir UN SEUL utilsateur Active Directory pour UN serveur web (avec ses VirtualHosts). Si pendant les tests, deux utilisateurs ont été liés au même serveur avec ktpass, aucun des deux ne fonctionnera ! (le message "gss_accept_sec_context() failed: A token was invalid (Token header is malformed or corrupt)" peut apparaître dans ce cas dans l'error_log).
  • kinit peut retourner des messages d'erreur :
Client not found in Kerberos database while getting credentials

le principal (HTTP/....) donné sur la ligne de commande ne correspond pas à celui enregistré dans le fichier keytab.

Cannot contact any KDC for requested realm while getting initial credentials

ou autres messages équivalents : typiquement une erreur de configuration du krb5.conf, kerberos ne trouve pas le contrôleur de domaine.

Key table entry not found while getting initial credentials

Le "credential" demandé par kinit n'existe pas dans le fichier ktab. On peut essayer :

klist -ke -t <fichier ktab>

pour lister son contenu.

kdc has no support for encryption type while getting initial credentials

Commencer par réinitialiser le mot de passe du compte auquel on veut se connecter avec kinit. Si on est sur un serveur 2008, on peut essayer d'activer tous les cryptages (même procédure que pour Win7 par gpedit.msc), puis réinitialiser le mot de passe et ré-essayer kinit.

Password incorrect while getting initial credentials

Réinitialiser le mot de passe de l'utilisateur sur lequel a été généré le fichier ktab

  • Si la session Windows n'est pas connectée au domaine (le poste de travail n'a pas été intégré au domaine) :
[Fri Apr 10 09:12:09 2009] [debug] src/mod_auth_kerb.c(1391): [client 192.168.37.17] Verifying client data using KRB5 GSS-API 
[Fri Apr 10 09:12:09 2009] [debug] src/mod_auth_kerb.c(1407): [client 192.168.37.17] Client didn't delegate us their credential
[Fri Apr 10 09:12:09 2009] [debug] src/mod_auth_kerb.c(1435): [client 192.168.37.17] Warning: received token seems to be NTLM, which isn't
supported by the Kerberos module. Check your IE configuration.
[Fri Apr 10 09:12:09 2009] [debug] src/mod_auth_kerb.c(1107): [client 192.168.37.17] GSS-API major_status:00090000, minor_status:861b6d0c
[Fri Apr 10 09:12:09 2009] [error] [client 192.168.37.17] gss_accept_sec_context() failed: A token was invalid (, Token header is malformed
or corrupt)
  • Le site n'est pas dans les sites de confiance IE (fenêtre de login) :
[Sat Apr 11 14:49:39 2009] [debug] src/mod_auth_kerb.c(1634): [client 192.168.37.32] kerb_authenticate_user entered with user (NULL) and
auth_type kerberos
[Sat Apr 11 14:49:39 2009] [debug] src/mod_auth_kerb.c(1246): [client 192.168.37.32] Acquiring creds for HTTP/cerbere.example.net@EXAMPLE.NET
[Sat Apr 11 14:49:39 2009] [debug] src/mod_auth_kerb.c(1107): [client 192.168.37.32] GSS-API major_status:000d0000, minor_status:025ea101
[Sat Apr 11 14:49:39 2009] [error] [client 192.168.37.32] gss_acquire_cred() failed: Miscellaneous failure (, No principal in keytab matches
desired name)
  • Activation de la journalisation kerberos sur le contrôleur de domaine :

http://support.microsoft.com/default.aspx?scid=kb;en-us;262177

  • Patch pour DC lorsque le réseau a été mis à jour de Win2003 vers win2008

http://support.microsoft.com/kb/978055/fr