Authentification SSO depuis Apache sur backend AD via Kerberos

From Deimos.fr / Bloc Notes Informatique
Jump to: navigation, search
Kerberos

Software version 5
Operating System Red Hat 6
Debian 6
Website
Last Update 29/10/2012
Others

1 Introduction

Le but de cet article est d'expliquer comment réaliser une authentification forte de type SSO 'Single Sign-On' d'une application Web hébergée en réseau local sur un serveur Linux avec Apache via un Kerberos sous Windows 2003/2008 Server. Les clients seront des machines Windows ou Linux participant au domaine AD (Active Directory) utilisant un navigateur internet.[1]

On peut résumer le fonctionnement de la manière suivante : un utilisateur ouvre une session sur le domaine et navigue vers une page http protégée du réseau Intranet. Habituellement, on affiche une boite invitant l'utilisateur à saisir son nom d'utilisateur et mot de passe alors qu'il est déjà connu de l'AD, vu qu'il a saisi les mêmes informations pour se connecter à son compte Windows. Le but du Single Sign-On est d'authentifier l'utilisateur sans qu'il soit obligé de resaisir plusieurs fois les mêmes informations.

Kerberos fonctionne avec un système de jetons, qu'on appelera des 'tickets'. L'authentification se passe en plusieurs étapes :

Kerb schema.png

  1. le poste client demande un ticket au serveur Kerberos (ici le DC Win2003)
  2. le KDC retourne un ticket, vu que le client est déjà identifié sur le réseau
  3. le poste client formule la requête au serveur Web en incluant le ticket

Plusieurs avantages de cette méthode :

  • L'utilisateur s'identifie une seule fois et peut ensuite accéder de façon transparente aux différents services
  • Le nom d'utilisateur et son mot de passe ne sont jamais transmis sur le réseau

2 Prérequis

Dans la suite de l'article, je vais supposer que vous avez les éléments suivants :

  • Un 2003 Server configuré en contrôleur de domaine avec le service DNS activé, et au moins un compte utilisateur (dc-1.local.domain)
  • Un serveur Linux avec Apache configuré, capable de servir des pages (lx-1.local.domain)
  • Un client XP ou 2003 enregistré sur le domaine, capable d'ouvrir une session avec un compte du domaine (pc-1.local.domain)
Warning WARNING
Kerberos étant particulièrement sensible aux noms des machines, il est important que toutes les machines apparaissent dans le serveur DNS et qu'elles aient toutes une entrée PTR (reverse DNS) égale au forward DNS (A).

En plus d'être sensible à la nomination, Kerberos est sensible à un quelconque décalage temporel entre les différentes machines. Pour palier à ce problème, je vous conseille donc d'utiliser un service NTP.

Pour finir, il faut choisir un realm Kerberos, par exemple LOCAL.DOMAIN. Notez que le realm s'écrit tout en majuscules. Il n'est pas obligatoirement le nom de domaine, et il peut avoir plusieurs realms sur un réseau ayant un seul domaine. Par contre, le realm s'écrit en majuscules, par exemple LOCAL.DOMAIN.

Warning WARNING
Il est impératif que toutes vos machines soient à la bonne heure, donc connectez les toutes à un serveur NTP.

3 Installation

3.1 Windows Server

Installer les support tools[2].

3.2 Linux Server

Nous allons installer les paquets suivants :

Command aptitude
aptitude install krb5-clients krb5-config krb5-user libkrb53 libapache2-mod-auth-kerb

4 Configuration

4.1 Windows Active Directory

Pour chaque service à Kerberosiser, les opération suivantes sont à prévoir pour générer un Service Principal :

  • Création d'un compte utilisateur pour chaque service. Je vous conseille de choisir un nom qui permette d'identifier le service concerné, par exemple intranet-1 dans l'Active Directory.
Warning WARNING
Ne pas choisir un nom d'utilisateur qui existe déjà comme nom de contrôleur de domaine ou comme nom d'ordinateur

  • Génération d'un KeyTab. Ce fichier sert à authentifier le serveur Kerberosisé (ici le serveur Web) auprès du KDC :
Command ktpass
ktpass -princ HTTP/lx-1.local.domain@LOCAL.DOMAIN -crypto DES-CBC-MD5 -ptype KRB5_NT_PRINCIPAL -mapuser intranet-1 -pass azerty -out C:\temp\keytab.txt

Copiez le fichier généré sur le serveur Linux dans /etc/krb5.keytab.

4.2 Serveur Linux

Commencez par sécuriser le keytab copié précedemment :

Command
chown www-data:root /etc/krb5.keytab
chmod 640 /etc/krb5.keytab

Configurez les DNS :

Configuration File /etc/resolv.conf
search local.domain
nameserver 192.168.22.1

Vérifiez que modauthkerb est activé :

Command a2enmod
a2enmod auth_kerb

Créez un .htaccess ou éditez apache2.conf pour sécuriser le site :

Configuration File .htaccess
<Files "*">
        <Limit GET POST>
                AuthName "Kerberos Login"
                AuthType Kerberos
                Krb5Keytab /etc/krb5.keytab
                KrbAuthRealms LOCAL.DOMAIN
                KrbMethodNegotiate On
                KrbMethodK5Passwd Off
                KrbVerifyKDC off
                Require valid-user
        </Limit>
</Files>

Reloadez votre serveur Apache

Je rappelle que le realm s'écrit en majuscule. Dans cet exemple, on active le mode SSO via Negotiate et on désactive l'authentification par mot de passe ; si l'authentification automatique est impossible une page d'erreur 401 Authorization Required s'affichera.

Le dernier fichier à configurer est /etc/krb5.conf :

Configuration File /etc/krb5.conf
[libdefaults]
        ticket_lifetime = 24000
        default_realm = LOCAL.DOMAIN
        dns_lookup_realm = true
        dns_lookup_kdc = false
        default_keytab_name = FILE:/etc/krb5.keytab
 
[realms]
        LOCAL.DOMAIN = {
                kdc = dc-1.local.domain
                admin_server = dc-1.local.domain
}
 
[domain_realm]
        .local.domain = LOCAL.DOMAIN
        local.domain = LOCAL.DOMAIN
 
[appdefaults]
        pam = {
                debug = false
                ticket_lifetime = 36000
                renew_lifetime = 36000
                forwardable = true
                krb4_convert = false
        }

5 Validation

A ce stage, vous avez normalement une configuration fonctionnelle. Nous allons cependant effectuer quelques vérifications parce qu'il existe beaucoup d'erreurs de configuration possibles.

  • Test de connexion :
Command kinit
kinit <username>@LOCAL.DOMAIN

Saisissez le mot de passe de l'utilisateur, il ne doit pas avoir d'erreur.

La commande klist permet de vérifier l'état des tickets :

Command klist
> klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: <nom d'utilisateur>@LOCAL.DOMAIN
 
Valid starting     Expires            Service principal
08/12/09 11:42:08 08/12/09 18:22:08 krbtgt/LOCAL.DOMAIN@LOCAL.DOMAIN
 
 
Kerberos 4 ticket cache: /tmp/tkt0
klist: You have no tickets cached

  • Si tout va bien, vérifiez ensuite votre authentification de service :
Command kvno
> kvno HTTP/lx-1.local.domain@LOCAL.DOMAIN
HTTP/lx-1.local.domain@LOCAL.DOMAIN: kvno = 28

Il ne doit pas avoir d'erreur non plus mais voici quelques messages d'erreurs classiques et leur signification :

kvno: No credentials cache found while getting client principal name

Vous n'avez pas de ticket valide : lancez la commande :

Command kinit
> kinit <username>
kvno: Server not found in Kerberos database while getting credentials for HTTP/lx-1.local.domain@LOCAL.DOMAIN

Plusieurs possibilités ici :

  • Vous avez mal généré votre keytab ; essayez de le regénérer
  • Vous avez affecté le même SPN à plusieurs utilisateurs (voir les pièges)

Pour finir, ce test de keytab ne doit pas retourner d'erreur :

Command kinit
kinit -k -t /etc/krb5.keytab HTTP/lx-1.local.domain@LOCAL.DOMAIN

Warning WARNING
Ne passez pas à la suite tant que les trois tests précédents génèrent des erreurs !

6 Navigateur web

6.1 Internet Explorer

  • Dans les options avancées, vérifiez que l'Authentification Windows est activée : "Enable Integrated Windows Authentication"
  • Ensuite ajoutez le site sécurisé dans la zone Local intranet : http://lx-1.local.domain

Acceptez les changements, et naviguez sur http://lx-1.local.domain : le site s'affiche sans authentification par mot de passe.

6.2 Firefox

Lancez Firefox et tapez about:config dans la barre d'adresse, puis filtrez avec le mot auth. Modifiez network.negotiate-auth.trusted-uris et network.negotiate-auth.delegation-uris avec comme valeur le domaine "local.domain".

7 FAQ

7.1 Nom de service sur plusieurs comptes

Si vous avez créé plusieurs comptes pour expérimenter, il n'est pas impossible qu'un même nom de service ou SPN se retrouve associé à plusieurs comptes, ce qui n'est pas possible. Un compte doit être unique pour chaque service Kerberosisé (intranet-1, intranet-2...) et un même nom de service (HTTP/lx-1.local.domain@LOCAL.DOMAIN) ne peut être associé à plusieurs comptes. Si vous avez utilisé ktpass pour associer le même SPN à plusieurs compte, utilisez setspn pour corriger :

Command setspn
C:\Program Files\Support Tools>setspn
Usage: setspn [switches data] computername
Where "computername" can be the name or domain\name
 
Switches:
-R = reset HOST ServicePrincipalName
    Usage: setspn -R computername
-A = add arbitrary SPN
    Usage: setspn -A SPN computername
-D = delete arbitrary SPN
    Usage: setspn -D SPN computername
-L = list registered SPNs
    Usage: setspn [-L] computername
Examples:
setspn -R daserver1
It will register SPN "HOST/daserver1" and "HOST/{DNS of daserver1}"
setspn -A http/daserver daserver1
It will register SPN "http/daserver" for computer "daserver1"
setspn -D http/daserver daserver1
It will delete SPN "http/daserver" for computer "daserver1"

Pour lister les SPN associés a un utilisateur, utilisez l'option "-L", pour supprimer, utilisez l'option "-D", par exemple :

Command setspn
setspn -D HTTP/lx-1.local.domain lx-1

7.2 Choix du nom d'utilisateur

Le nom d'utilisateur est libre, par contre, le nom ne doit pas déjà utilisé comme nom d'ordinateur ou comme contrôleur de domaine.

8 References

  1. ^ https://www.slashorg.net/index.php?act=read&id=110&lang=
  2. ^ http://www.microsoft.com/downloads/details.aspx?FamilyID=96a35011-fd83-419d-939b-9a772ea2df90&displaylang=en