samedi 10 mars 2012

Authentification SSL client avec Apache

Dans ce billet, nous allons voir comment sécuriser une application WEB afin qu'elle soit accessible uniquement à des terminaux autorisés. Pour cela, nous allons utiliser des certificats clients et faire en sorte que le serveur impose au client de lui présenter un certificat signé par une autorité de certification particulière.

Création des certificats

Création d'une autorité de certification

La première étape consiste à créer notre propre autorité de certification. Nous générons pour cela une clé RSA que nous stockons sous ca.key. A partir de cette clé, nous allons générer un certificat auto-signé. Grace aux commandes openssl ci dessous, nous obtenons les éléments suivants :
ca.key
La clé RSA de notre autorité de certification
ca.crt
Le certificat auto-signé de notre autorité
ca.public.key
La clé publique de notre autorité de certification
openssl genrsa -out ca.key
openssl req -new -key ./ca.key -out ./ca.csr
openssl x509 -req -days 365 -in ./ca.csr -out ./ca.crt -signkey ./ca.key
openssl x509 -in ca.crt -text
openssl rsa -in ca.key -passin pass:XXXX -pubout -out ca.public.key

Création et signature du certificat serveur

Il faut ensuite créer la clé et le certificat qui seront utilisé par le serveur. Le certificat serveur sera signé par notre propre autorité de certification créée à l'étape précédente. Lors de la création de la certificate signing request, il est demandé de renseigner un Distinguished Name (DN). La valeur de ce champ devra être identique à la valeur du ServerName utilisé dans le fichier de configuration Apache httpd.conf. En plus de la clé et du certificat, il peut être intéressant de générer une clé qui ne soit pas protégée par un mot de passe. Cela permet de ne pas avoir à saisir de mot de passe à chaque démarrage du serveur Apache.
openssl genrsa -des3 -out server.key
openssl req -new -key ./server.key -out server.csr
openssl x509 -req -in ./server.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out ./server.crt -days 365
openssl pkcs12 -export -in server.crt -inkey server.key -out server.p12 -name "server certificate"
openssl pkcs12 -info -in server.p12
openssl rsa -in server.key -passin pass:XXXX -pubout -out server.public.key
openssl rsa -in server.key -out server.nopassphrase.key

Création et signature du certificat client

Nous allons maintenant créer de manière similaire un certificat client qui sera utiliser par le client pour s'authentifier auprès du serveur distant. Le certificat client sera signé par la même autorité de certification que le certificat du serveur.
openssl genrsa -des3 -out client.key
openssl req -new -key ./client.key -out client.csr
openssl x509 -req -in ./client.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out ./client.crt -days 365
openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name "client certificate"
openssl pkcs12 -info -in client.p12
openssl rsa -in client.key -passin pass:XXXX -pubout -out client.public.key

Configuration du serveur Apache

Il convient maintenant de configurer le serveur Apache que seuls les clients disposant d'un certificat signé par notre propre autorité de certification soient autorisés à se connecter. Dans le VirtualHost du port SSL par défaut, il suffit d'utiliser les directives suivantes :
# Doit correspondre au DN du certificat server
ServerName domain

# Encryption et certificat serveur
SSLEngine On
SSLCertificateFile conf/certs/server.crt
SSLCertificateKeyFile conf/certs/server.nopassphrase.key

# Impose la présentation d'un certificat client
SSLVerifyClient require
SSLVerifyDepth 2

# Certificat de l'autorité de certification reconnue pour les clients
SSLCACertificateFile conf/certs/ca.crt
SSLVerifyClient
La valeur require permet d'imposer au client la présentation d'un certificat X509 lors de la phase de négociation SSL.
SSLVerifyDepth
Indique le nombre maximum de niveau que le serveur va analyser pour décider s'il juge le certificat client acceptable. Une valeur de 0 permet de n'autoriser que les certificats clients auto-signés. Une valeur de 1 permet d'accepter les certificats clients auto-signés ou certifiés par une autorité de certification directement connue par le serveur. Dans notre cas, nous utilisons la valeur 2 afin de n'accepter que les certificats clients signés par une autorité de certification directement connue par le serveur.
SSLCACertificateFile
Cette directive permet de spécifier le certificat de l'autorité de certification reconnue par le serveur. Seuls les certificats clients signés par l'autorité de certification identifiée par ce certificat seront acceptés.
Dans un prochain article, nous verrons comment configurer un client Android pour accéder à ce serveur sécurisé.
Fork me on GitHub