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.

Installation

Les paquetages suivanst sont supposés être installés:

  • apache2
  • apache2-ssl
  • subversion-server
  • openssl

Installer le paquetage libapache2-svn

$> sudo apt-get install libapache2-svn

Configuration Apache 2

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.

Définition des ports et interfaces d'écoute

La configuration précise sur quels ports et quel(s) interfaces (ie. adresses IP de l'hôte) sera activé cette instance de serveur:  

Configuration SSL

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" !).

SSL côté serveur

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

SSL côté client

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
Ici, le paramètre -subj est important, c'est lui qui sera utilisé pour identifier le client lors de connexions au serveur. La valeur de ce paramètre est une séquence de couples clés/valeurs séparées par des caractéres '/'[2].  

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 \
  -extensions v3_usr \
  -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

Authentification générale

La balise <Location /> gére le processus d'authenfication pour toutes les URI servies par ce serveur. Dans le cas présent:

Configuration accès Subversion

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:

Identification des utilisateurs

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
La chaìne xxj31ZMTZzkVA est la version encodée par
htpasswd de la chaîne password et n'est pas utilisée par le processus d'authentification.  

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

Gestion des droits d'accès par projet

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 à :  

  • un groupe administrateur ayant par défaut accès en R/W à tous lesréférentiels. On notera que ces droits doivent être repositionnésindividuellement par projet car le système d'ACL utilise les droitsattachés au chemin le plus précis possible ;
  • un groupe oqube ayant accès en lecture à tous les projets pardéfaut ;
  • des groupes par projet ayant a priori accès en R/W aux éléments duprojet.

Il est aussi possible de positionner des droits individuellement (par DN).  

[site-oqube:/]
@admin= rw
@siteoqube=rw
/O=client/CN=martin=rw


Configuration du client

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:  

  • l'une pour une utilisation du client en ligne de commande standardde subversion ;
  • l'autre pour une utilisation dans maven

Ligne de commande et TortoiseSVN

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

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é).  

Propriétés

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:  

  1. sur la ligne de commande d'invocation de maven ;
  2. on peut aussi définir ces valeurs de manière permanente pouréviter de les redéfinir à chaque commande, en définissant unevariable d'environnement nommée MAVEN_OPTS
    • Sous linux, créer un fichier $HOME/.mavenrc définissant la variabled'environnement MAVEN_OPTS. Ce fichier est lu par le script delancement de Maven.
    • sous windows, définir la variable dans les variablesd'environnement de l'utilisateur.

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
et dans le second  
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"

Magasin de certificat  du serveur

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 virtuelsnommés différents.

[2]  Les clés correspondent à des attributs utilisées dans les annuaires X.500