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:
Listen 443 active le serveur en écoute sur le port 443et NameVirtualHost précise sur quels interfaces sont autorisés lesserveurs virtuels nommés (ie. distingués par leur nom)<VirtualHost *:443> configure une nouvelle instance deserveur, ici nommé projects.oqube.com (directive ServerName, elledoit être définie dans chaque hôte virtuel)On active ensuite le moteur SSL et on définit les clés et autorités de certification à utiliser pour l'authentification des clients.
SSLCertificateFile définit le certificat authentifiant le serveurauprés des clients ;SSLCertificateKeyFile définit la clé privée du serveur utiliséepour signer l'échange de clé entre client et serveur SSLCACertificateFile est le certificat de l'autorité decertification utilisée pour authentifier les 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.reqIci, 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
La balise <Location /> gére le processus d'authenfication pour toutes les URI servies par ce serveur. Dans le cas présent:
SSLRequireSSL s'assure de la présence du moteur SSL pour toute requêteSSLVerifyClient require rend obligatoire l'utilisation decertificats client pour s'authentifier auprés du serveur. Unargument optional premet de mélanger différents modes d'identificationSSLVerifyDepth 1 définit la profondeur de vérification des chainesde certificats. Dans le cas d'une autorité auto-certifiée, cetteprofondeur est toujours de 1 ! SSLOptions +OptRenegotiate +FakeBasicAuth permettent de: subject) du certificat client commeidentifiant dans une liste de contrôle d'accès simulant uneauthentification par login/mot de passe. Ce mécanisme permetd'affiner les autorisations d'accès au niveau de chaquerépertoire ou chemin.allow from all autorise l'accès depuis n'importe quel hôteOptions FollowSymLinks autorise le déréférencement de lienssymboliques ce qui peut parfois compromettre la sécuritéAllowOverride None interdit toute modification des options dans lessous-confguration 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:
DAV svn demande d'utiliser le module DAV de subversion. Attention,ce module doit avoir été chargé par une directive LoadModule. Dansle cas d'une distribution Ubuntu ou debian, ce chargement estautomatiquement fait par des directives d'inclusion au niveau dufichier de configuration principal d'apache(/etc/apache2/apache2.conf) et du répertoire mods-enabledLoadModule 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
SVNParentPath /var/lib/svn définit le répertoire racine pour tousles référentiels subversions servis. Chaque référentiel est alorsaccessible en suffixant la ressource avec le nom du référentielAuthzSVNAccessFile /etc/apache2/pass.d/svn.acl précise la liste decontrôle d'accès utilisée pour les habilitions des différentsutilisateurs (voir Gestion des droitsAuthType, AuthName et AuthUserFile ont la mêmesignification que pour une authentification classique basée sur lesmots de passe. Le plus important est le fichier des mots de passedécrits plus loinRequire valid-user enfin exige que l'utilisateur soit authentifiépour accéder au répertoire. Dans un contexte "public", on peutvouloir autoriser les accés anonymes en lecture ce qui se fera par:<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:xxj31ZMTZzkVALa 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
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 à :
oqube ayant accès en lecture à tous les projets pardéfaut ;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:
javax.net.ssl.trustStore : contient le chemin d'accès au magasin decertificats de confiancejavax.net.ssl.trustStorePassword : contient le mot de passesécurisant l'accés à ce certificatjavax.net.ssl.keyStore : chemin d'accès au certificat client. Enfait, cette variable contient aussi une référence à un magasin decertificats pour le client, mais le format PKCS#12 peut faireoffice de magasin de certificatsjavax.net.ssl.keyStoreType : type du magasin. Dans notre cas, savaleur est pkcs12javax.net.ssl.keyStorePassword : mot de passe protégeant le magasinde certificats clientsPour 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:
https.proxy : nom/adresse IP du proxy à utiliser ;https.proxyPort : port d'accès au serveur proxyCes valeurs peuvent être positionnées de plusieurs manières:
MAVEN_OPTS$HOME/.mavenrc définissant la variabled'environnement MAVEN_OPTS. Ce fichier est lu par le script delancement de Maven. 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 installet 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"
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