Apache et Subversion peuvent être configurés de manière à permettre un accès fortement sécurisé (ie. par système de clés asymétriques et contrôle d'accès) à un ensemble de référentiels ou dépôts. Ce mécanisme permet:
Nous présentons ici un mini-guide de mise en oeuvre de cette solution sur une architecture Linux Ubuntu 6.06.
Les paquetages suivanst sont supposés être installés:
Installer le paquetage libapache2-svn
$> sudo apt-get install libapache2-svn
Sous Ubuntu (et Debian), la configuration d'apache est centralisée dans le répertoire /etc/apache2. Pour configurer un site sécurisé (accessible par SSL avec authentification par certificats), on crée un (ou plusieurs) serveurs virtuels écoutant sur le port 443 en créant un fichier /etc/apache2/sites-available/secure (exemple) dont le contenu est détaillé dans les paragraphes suivants.
La configuration précise sur quels ports et quel(s) interfaces (ie. adresses IP de l'hôte) sera activé cette instance de serveur:
On active ensuite le moteur SSL et on définit les clés et autorités de certification à utiliser pour l'authentification des clients.
Dans le cas présent, le serveur est sa propre autorité de certification et signe son certificat (ceci suppose que les clients savent à qui ils ont affaire et font confiances au serveur sur sa "bonne mine" !).
Pour créer ces différents fichiers, on utilise la suite de commandes suivantes:
Pour créer une clé privée :
$> sudo openssl genrsa -out osquare.key 1024 $> sudo chmod 0400 osquare.key
La clé est ici non cryptée ce qui évite de devoir saisir un mot de passe au démarrage du serveur apache. Il faut alors absolument la protéger pour qu'elle soit lisible uniquement par root.
Pour créer un certificat auto-signé:
$> sudo openssl req -x509 -new -key osquare.key -out osquare.crt -days 3650 -subj '/CN=projects.oqube.com'
Le paramétre <code>-subj '/CN=projects.oqube.com'</code> doit faire correspondre le nom commun (CN) du certificat au nom du serveur[1]. Ce certificat peut êter utilisé pour signer les certificats clients et authentifier le serveur.
On notera que cette configuration est très simple. Elle est bien adapté pour un site à faible trafic où la base d'utilisateur est stable et bien connue. Dans le cas contraire, on préférera mettre en place une vraie autorité de certification (éventuellement basée sur un certificat racine atuthentifiée par une "vraie" autorité, donc généralement payant) et une gestion des listes de révocation
Pour accéder à ce serveur, le client devra posséder un certificat authentifié par (c'est à dire signé ou crypté par la clé privée de) l'autorité de certification choisie. Pour produire un tel certificat au format PKCS#12 c'est à dire utilisable dans un navigateur moderne, la marche à suivre est la suivante.
Générer une clé privée pour l'utilisateur (appelons-le dupont) :
$> sudo openssl genrsa -out dupont.key 1024
Générer une demande de certificat
$> openssl req -new -batch -subj "/CN=dupont" -key dupont.key -out dupont.req
Générer un certificat signé. Le paramètre -days indique la durée de validité du certificat. Si la clé osquare.key est cryptée, le mot de passe sera demandée pour la décrypter et signer le certificat :
$> openssl x509 -req -days 180 -in req \ -CAkey /etc/apache2/ssl/osquare.key \ -CA /etc/apache2/ssl/osquare.crt -out dupont.crt
Générer une archive PKCS#12 contenant le certificat signé et la clé privée de l'utilisateur. Le mot de passe -passout sert à crypter l'archive et sera demandé à l'utilisateur lorsqu'il souhaitera importer cette archive dans son navigateur ou l'utiliser dans n'importe quel client:
$> openssl pkcs12 -export -passout pass:"dupont" \ -in dupont.crt \ -inkey dupont.key \ -out dupont.p12
La balise <Location /> gére le processus d'authenfication pour toutes les URI servies par ce serveur. Dans le cas présent:
La définition de la ressource /svn configure une URI d'accés à un ensemble de référentiels servis par le protocole WebDAV au travers du serveur Apache:
LoadModule dav_module /usr/lib/apache2/modules/mod_dav.so LoadModule dav_svn_module /usr/lib/apache2/modules/mod_dav_svn.so LoadModule authz_svn_module /usr/lib/apache2/modules/mod_authz_svn.so
<LimitExcept GET PROPFIND OPTIONS REPORT> Require valid-user </LimitExcept>
L'authentification se faisant au moyen d'un échange de signatures par clés asymétriques, le fichier utilisé par la directive AuthUserFile ne sert qu'à identifier les utilisateurs pouvant accéder à la ressource. Ce fichier contient un suite de lignes de la forme
/CN=abailly:xxj31ZMTZzkVA /CN=dupont:xxj31ZMTZzkVA
En fait, la directive +FakeBasicAuth extrait le DN du certificat présenté par le client, après validation SSL, et positionne en interne l'identité de l'utilisateur à cette valeur et son mot de passe à la valeur encrypée de passwrd. Il est donc important de définir le DN de manière uniforme et précise.
Le fichier svn.passwd doit donc contenir tous les DN des utilisateurs susceptibles de se connecter. Pour extraire un certificat d'un fichier PKCS#12:
$> openssl pkcs12 -in export.p12 -clcerts -nokeys -out usercert.pem
et Pour extraire le DN d'un certificat :
$> openssl x509 -subject -noout -in certificat
Le fichier de configuration d'accès décrit les droits d'accès de chaque utilisateur authentifié pour des chemins d'accès. Voici un exemple complet de fichier de configuration ACL (fichier /etc/apache2/pass.d/svn.acl) est la suivante :
[groups] # groupe admin - AB admin=/CN=Arnaud Bailly oqube=/CN=dupont,/CN=durand siteoqube=/CN=durand [/] @admin=rw @oqube=r [site-oqube:/] @admin= rw @siteoqube=rw
Les différents groupes correspondent à :
Il est aussi possible de positionner des droits individuellement (par DN).
[site-oqube:/] @admin= rw @siteoqube=rw /O=client/CN=martin=rw
La configuration du client pour accéder de manière transparente aux référentiels servis par HTTPS dépend bien évidemment de chaque client. Nous donnons ici deux configurations possibles:
Il suffit de configurer le fichier $HOME/.subversion/servers (UNIX) ou %USER_PROFILE%/Application Data/Subversion/servers (WinXP) :
[groups] oqube=*.oqube.com [srvue] ssl-client-cert-file = /chemin/vers/lecertifcat/dupont.p12 ssl-client-cert-password = motdepasse
Le mot de passe ne peut pas contenir d'espace. Si ce fichier n'est pas configuré, le client demande le chemin d'accès au certificat et le mot de passe à chaque tentative d'utilisation du référentiel.
On notera que cette configuration suppose que le mot de passe (du certificat) est en clair dans le fichier de configuration, ce qui suppose que l'on utilise d'autres mécanismes liés au systéme d'exploitation sous-jacent pour sécuriser cette donnée sensible (voir la FAQ subversion à ce sujet).
Maven étant basé sur Java et utilisant la bibliothèque HttpClient, il utilise les mécanismes de ces plateformes pour l'authentification par SSL. Il est nécessaire de positionner des propriétés Java et de construire un magasin de certificat pour le cenrtificat du serveur (dans le cas oú celui-ci est auto-signé).
Les propriétés à définir sont:
Pour savoir ce qui se passe en cas de problème, on peut ajouter javax.net.debug avec la valeur ssl comme propriété. Dans le cas où l'accés au référentiel se fait au travers d'un proxy, ajouter la canfiguration:
Ces valeurs peuvent être positionnées de plusieurs manières:
Par example, dans le premier cas:
$> mvn -Djavax.net.ssl.trustStore=/chemin/vers/certificat/serveur\
-Djavax.net.ssl.trustStorePassword=YYYY\
-Djavax.net.ssl.keyStore=/chemin/vers/cle/prive\
-Djavax.net.ssl.keyStoreType=pkcs12\
-Djavax.net.ssl.keyStorePassword=XXXXXX install
MAVEN_OPTS="-Xmx512m -Djavax.net.ssl.trustStore=/chemin/vers/certificat/serveur\
-Djavax.net.ssl.trustStorePassword=YYYY\
-Djavax.net.ssl.keyStore=/chemin/vers/cle/prive\
-Djavax.net.ssl.keyStoreType=pkcs12\
-Djavax.net.ssl.keyStorePassword=XXXXXX"
Il faut importer le certificat du serveur dans un magasin correspondant au certificats de confiance. Pour cela, on utilise l'outil keytool fournit dans toute bonne distribution Java (Voir aussi le Guide JSSE) :
$> keytool -v -alias projets -import -file projets.cert -keystore trust.jks
Enter keystore password: xxxxxxx
Owner: EMAILADDRESS=ue@oqube.fr, CN=projets.oqube.fr, OU=UE, O=Oqube SA, L=Lille, ST=Nord, C=FR
Issuer: EMAILADDRESS=adminsys@oqube.fr, CN=projets.oqube.fr, OU=UE, O=Oqube SA, L=Lille, ST=Nord, C=FR
Serial number: 893f5f919f21bae9
Valid from: Mon Feb 21 22:34:25 CET 2005 until: Thu Feb 19 22:34:25 CET 2015
Certificate fingerprints:
MD5: A7:60:F2:00:E9:A5:30:96:A7:16:BD:C9:89:32:7F:7B
SHA1: 62:00:11:0D:57:62:8D:A9:7F:33:FF:E6:D7:1A:0E:25:CF:95:19:1B
Trust this certificate? [no]: yes
Certificate was added to keystore
[Storing trust.jks]
$>
Ce fichier trust.jks peut éventuellement être généré une seule fois (du côté serveur) et distribué aux clients.
Footnotes: [1] Dans la version 2.0.x d'apache, il n'est pas possible d'avoir
plusieurs certificats différents pour des serveurs virtuels nommés différents.
[2] Les clés correspondent à des attributs utilisées dans les
annuaires X.500