[[public:apache_kerberos_sso]]

Apache Authentification

Si vous posséder un serveur Active Directory, des utlisateurs dans cet AD, et une application Web, vous avez déjà surement trouvé ou essayé de trouver un moyen d'authentifier les utilisateurs de l'application web via l'AD. Pour ceux qui ont réussi, vous utilisez surement votre appli pour interroger la base LDAP de l'AD. De cette manière, les utilisateurs de votre domaine sont aussi ceux de votre application. C'est facile pour l'utilisateur, un seul mot de passe à retenir ! La ou Geco-iT vous propose d'aller plus loin, c'est que les utilisateurs n'aient même plus besoin de taper ce mot de passe… C'est possible en utilisant le Jeton Kerberos de la machine windows qui est récupéré à l'ouverture de session du user.

Si vous avez un site d'intranet qui tourne sur un server apache, bien souvent vous aurez un CMS, prenons l'exemple de typo3 car c'est un qu'on connait un peu a geco. En temps normal c'est typo3 qui gere l'authentification de vos utilisateurs. C'est à dire que apache laisse passer toutes les requetes, et c'est typo3 qui va se charger d'afficher une page de login, de récupérer les utilisateurs dans votre AD et ensuite d'afficher les pages une fois que le user a été validé ou pas.

Si on veut ne plus taper de mot de passe, on va déléguer l'authentification au serveur apache lui même. Apache va valider l'utilisateur et remplir la variable $REMOTE_USER de php. C'est à partir de cette variable que le CMS pourra connaitre l'utilisateur et afficher seulement les pages auxquelles il a droit.

Nous allons creer une page PHP très simple qui affiche simplement le contenu de la fameuse variable PHP $REMOTE_USER, et aussi quelque headers.

<?php
 
 
echo "<h1>Geco it Kerberos test sample page</h1>";
 
 
if (isset($_SERVER['REMOTE_USER'])) {
    $token = $_SERVER['REMOTE_USER'];
    echo "<p style='color: green'>Kerberos auth succes, you token is : $token</p>";
 
} else {
    echo "<p style='color: red'>Kerberos auth failed or not sent</p>";
}
 
echo "<h2>Here is some headers that may help</h2>";
$headers = apache_request_headers();
foreach ($headers as $header => $value) {
    echo "$header: $value <br />\n";
}
 
?>

Ensuite on va installer ce dont on a besoin sur notre serveur apache !

sudo apt update
sudo apt install libapache2-mod-auth-gssapi krb5-user

On va remplir le fichier /etc/krb5.conf comme ceci :

[libdefaults]
	default_realm = LAN.GECO-IT.NET
 
# The following krb5.conf variables are only for MIT Kerberos.
	kdc_timesync = 1
	ccache_type = 4
	forwardable = true
	proxiable = true
	fcc-mit-ticketflags = true
 
[realms]
    LAN.GECO-IT.NET = {
        kdc          = dc1.lan.geco-it.net
        admin_server = dc1.lan.geco-it.net
    }
 
[domain_realm]
    .lan.geco-it.net     = LAN.GECO-IT.NET
 
[logging]
    kdc              = SYSLOG:NOTICE
    admin_server     = SYSLOG:NOTICE
    default          = SYSLOG:NOTICE

Biensur dans votre cas il faudra remplacer le domaine par le votre et surtout remplacer “dc1” par le nom de votre controller de domaine. A partir de la, on peut essayer notre config !

#UN ping du controleur de domaine
admin@apache2:~$ sudo ping dc1
PING dc1 (172.20.50.10): 56 data bytes
64 bytes from 172.20.50.10: seq=0 ttl=127 time=0.714 ms
^C
--- dc1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.714/0.714/0.714 ms
 
admin@apache2:~$ sudo ping dc1.lan.geco-it.net
PING dc1.lan.geco-it.net (172.20.50.10): 56 data bytes
64 bytes from 172.20.50.10: seq=0 ttl=127 time=0.829 ms
^C
--- dc1.lan.geco-it.net ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.829/0.829/0.829 ms
 
#Et on essaye d'obtenir un ticket kerberos depuis notre AD, vous pouvez utiliser n'importe quel compte, donc je prend le mien, si tout va bien il demandera votre mot de passe
admin@apache2:~$ sudo kinit h.campion@LAN.GECO-IT.NET
Password for h.campion@LAN.GECO-IT.NET: 
 
#Si il n'y a aucun sortie apres la demande du pass c'est que tout va bien, si on fait un klist, on doit trouver notre ticket
admin@apache2:~$ klist
klist: No credentials cache found (filename: /tmp/krb5cc_1000)
admin@apache2:~$ sudo klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: h.campion@LAN.GECO-IT.NET
 
Valid starting       Expires              Service principal
05/05/2021 09:50:19  05/05/2021 19:50:19  krbtgt/LAN.GECO-IT.NET@LAN.GECO-IT.NET
	renew until 06/05/2021 09:50:16

Il va nous falloir maintenant creer un user sur l'AD pour mapper l'authentification kerberos dessus, c'est un user normal de l'AD sauf qu'il faut cocher les options suivantes et mettre un bon password !

Ensuite on va creer le keytab kerberos pour le serveur, donc en etant sur l'ad en powershell :

PS M:\> ktpass -princ HTTP/intranet.geco-it.net@LAN.GECO-IT.NET  -mapuser kerb@LAN.GECO-IT.NET  -crypto AES256-SHA1  -ptype KRB5_NT_PRINCIPAL  -pass Azerty1234  -out C:\tmp\intranet.keytab
Targeting domain controller: DC1.lan.geco-it.net
Successfully mapped HTTP/intranet.geco-it.net to kerb.
Password successfully set!
Key created.
Output keytab to C:\tmp\intranet.keytab:
Keytab version: 0x502
keysize 92 HTTP/intranet.geco-it.net@LAN.GECO-IT.NET ptype 1 (KRB5_NT_PRINCIPAL) vno 6 etype 0x12 (AES256-SHA1) keylengt
h 32 (0xfb589c884bdf6245b3f0bd84c2823d08a518ad26e83726fc3897375628197caa)
PS M:\>

Les différents paramètres sont :

  • -princ : le principal name donc il faudra remplacer intranet.geco-it.net par le nom du vhost apache et @LAN.GECO-IT.NET par votre domaine
  • -mapuser : le nom complet du user sur lequel vous allez mapper kerberos
  • -crypto : l'algo utiliser pour l'echange de clé
  • -ptype
  • -pass : le pass du user sur lequel vous aller mapper kerberos, surtout pas utiliser le même que dans notre exemple……
  • -out : le chemin ou le keytab va etre généré

Il vous faut ensuite récupérer ce keytab et le mettre sur votre serveur apache dans /etc/apache2 et avec les droits www-data si vous etes sur debian, ou ceux du user qui fait tourner apache pour tout autre distrib :

admin@apache2:/etc/apache2$ sudo chown www-data:www-data intranet.keytab 
admin@apache2:/etc/apache2$ l
total 16K
drwxr-xr-x  3 root     root     4,0K mai    5 11:29 .
drwxr-xr-x 77 root     root     4,0K mai    5 09:46 ..
-rw-r--r--  1 www-data www-data   98 mai    5 11:29 intranet.keytab
drwxr-xr-x  2 root     root     4,0K mai    5 09:38 mods-available

Une fois le keytab en place, on va pouvoir le tester :

#On recupère le KVNO pour le principal HTTP/intranet.geco-it.net
sudo kvno HTTP/intranet.geco-it.net@LAN.GECO-IT.NET
HTTP/intranet.geco-it.net@LAN.GECO-IT.NET: kvno = 6
 
admin@apache2:/etc/apache2$ sudo klist -e
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: h.campion@LAN.GECO-IT.NET
 
Valid starting       Expires              Service principal
05/05/2021 09:50:19  05/05/2021 19:50:19  krbtgt/LAN.GECO-IT.NET@LAN.GECO-IT.NET
	renew until 06/05/2021 09:50:16, Etype (skey, tkt): aes256-cts-hmac-sha1-96, aes256-cts-hmac-sha1-96 
05/05/2021 11:41:10  05/05/2021 19:50:19  HTTP/intranet.geco-it.net@LAN.GECO-IT.NET
	Etype (skey, tkt): aes256-cts-hmac-sha1-96, aes256-cts-hmac-sha1-96 
 
admin@apache2:/etc/apache2$ klist -e -k -t /etc/apache2/intranet.keytab
Keytab name: FILE:/etc/apache2/intranet.keytab
KVNO Timestamp           Principal
---- ------------------- ------------------------------------------------------
   6 01/01/1970 00:00:00 HTTP/intranet.geco-it.net@LAN.GECO-IT.NET (aes256-cts-hmac-sha1-96) 

On va maintenant carrement essayer de s'authentiife au nom du service HTTP/intranet.geco-it.net avec notre keytab :

admin@apache2:/etc/apache2$ kinit -k -t /etc/apache2/intranet.keytab HTTP/intranet.geco-it.net
admin@apache2:/etc/apache2$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: HTTP/intranet.geco-it.net@LAN.GECO-IT.NET
 
Valid starting       Expires              Service principal
05/05/2021 12:06:03  05/05/2021 22:06:03  krbtgt/LAN.GECO-IT.NET@LAN.GECO-IT.NET
	renew until 06/05/2021 12:06:03

Maintenant que la partie kerberos est vérifiée, nous allons la mettre en place sur le vhost apache2 :

vim /etc/apache2/sites-available/100-intranet.geco-it.net.conf
<VirtualHost *:80>
 
		DocumentRoot /var/www/intranet.geco-it.net
		ServerName intranet.geco-it.net
 
		RemoteIPHeader X-Forwarded-For
		RemoteIPInternalProxy 172.20.44.1
 
		<Directory /var/www/testsso.lan.imcheck.fr>
				Options +FollowSymLinks
				AllowOverride All
		</Directory>
		<Location />
			AuthType GSSAPI
			AuthName "Intranet of Geco"
			GssapiCredStore keytab:/etc/apache2/intranet.keytab
			Require valid-user
		</Location>
 
		# mod_php enabled
		AddType application/x-httpd-php .php .php3 .php4 .php5
		php_admin_value open_basedir none
 
</VirtualHost>
 
sudo a2enmod auth_gssapi
sudo a2ensite 100-intranet.geco-it.net.conf 
sudo apache2ctl configtest
Syntax OK
sudo apache2ctl restart

SI vous essayez d'aller sur le site, vous tomberez sur une erreur forbidden, pour acceder au site, il faudra deja y acceder d'une machine de votre domaine, depuis une session utilisateur de votre domaine. Ensuite on va devoir indiquer à firefox d'envoyer la negociation kerberos pour l'url intranet.geco-it.net. Pour cela il faut taper about:config dans la barre d'addresse de firefox pour accéder aux options avancées. Tapez ensuite “trust” pour rechercher les deux options qui nous interessent :

Une fois que c'est correctement renseigné, un petit test vous confirmera le bon fonctionnement :

C'est bien mais demander a tout vos user d'aller dans about:config de firefox c'est pas recevable… heureusement la magie des gpo va venir à notre rescousse ! Si on resume les navigateurs les plus courants, on a :

  • Internet explorer, il suffit de placer l'url http://intranet.geco-it.net dans le groupes des sites “Intranet local”
  • Chrome qui va se baser sur les settings Internet Explorer
  • Edge qui va se baser sur les settings Internet Explorer
  • Firefox qui a besoin des settings network.negotiate-auth.trusted-uris ET network.automatic-ntlm-auth.trusted-uris

Pour firefox il faudra ajouter les ADMX de firefox à votre AD et utiliser la version ESR de firefox pour pouvoir le piloter par GPO !

$ a2enmod ldap authnz_ldap
 
$ cat /etc/apache2/sites-available/intranet2.conf 
<VirtualHost *:80>
     ServerAdmin admin@intranet2.lan.cereg.com
     ServerName intra2.cereg.com
     ServerAlias intranet.lan.cereg.com
 
     DocumentRoot /var/www/intra2
 
     <Directory /var/www/intra2>
       AuthType Basic
       AuthName "LDAP Authentication"
       AuthBasicProvider ldap
 
       AuthLDAPURL "ldaps://dcmon.lan.cereg.com/OU=CEREG,DC=lan,DC=cereg,DC=com?sAMAccountName?sub?(objectClass=User)"
       AuthLDAPBindDN agilap
       AuthLDAPBindPassword SuperPasswd
       #Require valid-user
 
       AuthLDAPGroupAttributeIsDN On
       require ldap-group CN=ALLOW_INTRANET,OU=01-GLOBAL,OU=Groups,OU=CEREG,DC=lan,DC=cereg,DC=com
     </Directory>
 </VirtualHost>
 
$ chgrp www-data /etc/apache2/sites-available/intranet2.conf
$ chmod 640 /etc/apache2/sites-available/intranet2.conf
  • public/apache_kerberos_sso.txt
  • Dernière modification: 14/12/2023/ 19:20
  • par c.duchenoy