Fournir, puis demander à un utilisateur un certificat pour l'authentifier sur notre site internet.
::TOC::
Pourquoi faire ça?
A moins de s'appeler le trésor public[1], cette sécurité peut paraître exagérée.
Ça va me servir dans quelques semaines à sécuriser une appli web du travail pour laquelle seuls une dizaine d'utilisateurs auront accès depuis l'extérieur (via un reverse proxy apache) .
Présentation des techniques employées:
La configuration se fait au niveau d'apache et du module SSL. Ce n'est pas compliqué, Mais c'est chiant à expliquer de façon claire. J'en suis à la troisième re-rédaction de ce billet pour tenter d'éclaircir les explications.
Ce billet contient tout un mémo de création d'une chaine de certification avec openSSL et un peu de config Apache.
Sur le serveur (mon Raspberry pi), je vais créer trois sites virtuels (VHOST) dans la configuration d'apache:
- home.tinad.fr (en http)
- home.tinad.fr (en https)
- prive.tinad.fr (en https, avec obligation pour l'utilisateur de posséder un certificat personnel signé par l'autorité de certification qu'on va créer):
Créer son autorité de certification et des certificats pour les deux sites en https
l'autorité de certification
Malheureusement, il n'est pas possible d'obtenir un certificat ayant le rôle "autorité de certification" reconnu par tous les navigateurs. On devra faire en sorte que les utilisateurs ajoutent notre certificat dans leur navigateur. Je ne détaillerai pas ici comment faire, mais il voici trois pistes:
- Créer une page web intermédiaire fournissant le certificat, et expliquant comment et pourquoi l'installer
- Si les utilisateurs sont dans un réseau sur lequel on est l'administrateur réseau : Via une GPO.
- Offrir une boite de kinder chocolat à l'administrateur réseau pour qu'il fasse une GPO.
- L'installer manuellement sur tous les postes.
Configuration
#On créé l'architecture de dossiers et fichiers nécessaires à une gestion des #clés et certificats dans le repertoire /srv/ssl mkdir /srv/ssl cd /srv/ssl mkdir certs crl newcerts private echo 01 > serial touch index.txt echo 01 > crlnumber cp /usr/lib/ssl/openssl.cnf .
Editer le fichier /srv/ssl/openssl.conf et modifiez les parametres suivants:
Dans le bloc CA_default :
- dir=/srv/ssl
Dans le bloc [req_distinguished_name] : .
countryName_default = FR stateOrProvinceName_default = France
Clé privée certificat et signature
#Créer une clé privée openssl genrsa -des3 -out private/cakey.pem 4096 #certif signé openssl req -config openssl.cnf -new -x509 -nodes -sha1 -days 1825 -key private/cakey.pem -out cacert.pem
Adaptez les réponses en fonction,s de votre site, mais ne mettez pas le FDQN dans le common name. Il s'agit du certificat autorité, pas celui de votre site web. Voici mon retour écran:
root@raspberrypi:/srv/ssl# openssl req -config openssl.cnf -new -x509 -nodes -sha1 -days 1825 -key private/cakey.pem -out cacert.pem Enter pass phrase for private/cakey.pem: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [FR]: State or Province Name (full name) [France]: Locality Name (eg, city) []:Rouen Organization Name (eg, company) [Internet Widgits Pty Ltd]:tinad Organizational Unit Name (eg, section) []:Gnieark Common Name (e.g. server FQDN or YOUR name) []:tinad.fr Email Address []:gnieark@free.fr
Publier le certificat de l'autorité de certification
cp /srv/ssl/cacert.pem /var/www/cacert.crt
(Lors de la copie, on change l'extension .pem en .crt, car .crt est un type mime connu dans la configuration standard d'apache)
Enregistrez le certificat dans le magasin de confiance de votre ordinateur local
Ouvrez tout simplement votre navigateur à l'URL http://VotreServeur/cacert.crt et cochez toutes les cases:
Créer un certificat pour le serveur Web home.tinad.fr
changez "home.tinad.fr" par le FDQN de votre serveur pour la suite des tests.
cd /srv/ssl #Création de la clé privée pour home.tinad.fr openssl genrsa -des3 -out home.tinad.fr.key.pem 4096 #demande de certificat: openssl req -config openssl.cnf -new -key home.tinad.fr.key.pem -out home.tinad.fr.csr.pem
Voici mon retour écran:
root@raspberrypi:/srv/ssl# openssl req -config openssl.cnf -new -key home.tinad.fr.key.pem -out home.tinad.fr.csr.pem Enter pass phrase for home.tinad.fr.key.pem: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [FR]: State or Province Name (full name) [France]: Locality Name (eg, city) []:Rouen Organization Name (eg, company) [Internet Widgits Pty Ltd]:tinad Organizational Unit Name (eg, section) []:home Common Name (e.g. server FQDN or YOUR name) []:home.tinad.fr Email Address []:gnieark@free.fr Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
Signature de la demande:
openssl ca -config openssl.cnf -policy policy_anything -out home.tinad.fr.cert.pem -infiles home.tinad.fr.csr.pem
La valeur la plus importante est le common name. Elle corrspond au FDQN pour les autres champs, essayez simplement d'etre logique avec l'autorité de certification Voici mon retour écran:
root@raspberrypi:/srv/ssl# openssl ca -config openssl.cnf -policy policy_anything -out home.tinad.fr.cert.pem -infiles home.tinad.fr.csr.pem Using configuration from openssl.cnf Enter pass phrase for /srv/ssl/private/cakey.pem: Check that the request matches the signature Signature ok Certificate Details: Serial Number: 1 (0x1) Validity Not Before: May 3 19:25:04 2013 GMT Not After : May 3 19:25:04 2014 GMT Subject: countryName = FR stateOrProvinceName = France localityName = Rouen organizationName = tinad organizationalUnitName = home commonName = home.tinad.fr emailAddress = gnieark@free.fr X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 81:4B:C7:3E:9B:C6:EA:60:78:26:B3:8F:77:B4:43:07:07:DE:A8:02 X509v3 Authority Key Identifier: keyid:BE:1D:5D:B9:F1:53:D6:BD:11:90:8E:5C:0F:D2:BC:99:22:BE:F1:48 Certificate is to be certified until May 3 19:25:04 2014 GMT (365 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
Voila, on a notre certificat signé: /srv/ssl/home.tinad.fr.cert.pem et sa clé privée: /srv/ssl/home.tinad.fr.key.pem (chiffrée par un mot de passe là)
On remarque au passage openssl a incrémenté la valeur dans le fichier /srv/ssl/serial .
Créer une clé non protégée par un mot de passe (ça servira à Apache)
cd /srv/ssl openssl rsa -in home.tinad.fr.key.pem -out home.tinad.fr-EnClair.key.pem
Créer un certificat pour le serveur Web prive.tinad.fr
Idem qu'au châpitre précedent, du coup je ne détaille pas:
cd /srv/ssl #Création de la clé privée pour prive.tinad.fr openssl genrsa -des3 -out prive.tinad.fr.key.pem 4096 #demande de certificat: openssl req -config openssl.cnf -new -key prive.tinad.fr.key.pem -out prive.tinad.fr.csr.pem #signature de la demande: openssl ca -config openssl.cnf -policy policy_anything -out prive.tinad.fr.cert.pem -infiles prive.tinad.fr.csr.pem #créer une clé non protégée: openssl rsa -in prive.tinad.fr.key.pem -out prive.tinad.fr-EnClair.key.pem
Configuration du serveur web
cd /var/www #on va créer 5 dossier pour des vhosts: mkdir home.tinad.fr mkdir home.tinad.fr-https mkdir prive.tinad.fr-https #Il me semble que le VHOST par défault d'apache est le premier par ordre alphabétique; #d'où le "0" au début du nom mkdir 0-default mkdir 0-default-https #Supprimer les fichiers de vhosts créés à l’installation d'apache cd /etc/apache2/sites-enabled rm *
configuration des vhost
Comme vous le verrez, je reste sur une configuration méga basique des VHOST, préférant les valeurs par défaut d’apache aux paramètres non ou mal compris. De plus je n'utilise pas de script CGI, donc autant ne pas les activer.
vi /etc/apache2/sites-available/home.tinad.fr
<VirtualHost *:80> ServerName home.tinad.fr DocumentRoot /var/www/home.tinad.fr </VirtualHost>
vi /etc/apache2/sites-available/home.tinad.fr-https
Ce VHOST est chiffré en HTTPS, cependant, aucune restriction d'accès n'est effectuée. Pour le test, j'ai mis le certificat de notre propre autorité de certification. Mais en production, autant mettre un vrai certificat (comptez maxi 30€/an). Pour cette maquette, j'y publie le certificat de l'autorité de certification, j'explique comment l'insérer, et je mets un formulaire qui permettra aux utilisateurs de demander leurs propres certificats. (dans le projet final ce sera l'administrateur qui aura accès au formulaire pour générer les certificats)
<VirtualHost *:443> ServerName home.tinad.fr DocumentRoot /var/www/home.tinad.fr-https SSLEngine On SSLCertificateFile /srv/ssl/home.tinad.fr.cert.pem SSLCertificateKeyFile /srv/ssl/home.tinad.fr-EnClair.key.pem SSLProtocol all -SSLv2 </Virtualhost>
vi /etc/apache2/sites-available/prive.tinad.fr-https
<VirtualHost *:443> ServerName prive.tinad.fr DocumentRoot /var/www/prive.tinad.fr-https SSLEngine On SSLCertificateFile /srv/ssl/prive.tinad.fr.cert.pem SSLCertificateKeyFile /srv/ssl/prive.tinad.fr-EnClair.key.pem SSLProtocol all -SSLv2 SSLCACertificateFile /srv/ssl/cacert.pem SSLCARevocationFile /srv/ssl/crl.pem SSLVerifyClient require SSLVerifyDepth 1 SSLOptions +StdEnvVars </Virtualhost>
Ce VHOST étant le plus intéressant, expliquons les directives
- SSLEngine On : active le SSL
- SSLCertificateFile le fichier contenant le certificat TLS pour prive.tinad.fr
- SSLCertificateKeyFile le fichier contenant la clé qui servira à chiffrer les connexions (à garder bien cachée ;) )
- SSLProtocol all -SSLv2 On accepte tous les protocoles ssl supportés sauf le SSLV2 qui présente une faiblesse)
- SSLCACertificateFile Le fichier certificat de l'autorité qui signe les certificats clients (apache vérifie les signatures)
- SSLCARevocationFile Le fichier qui contient la liste des certificats révoqués (nécessaire si on veut gérer les utilisateurs)
- SSLVerifyClient require Seuls les clients ayant un certificat valide sont admis
- SSLVerifyDepth 1 On limite à une autorité de certification intermédiaire
- SSLOptions +StdEnvVars Cette directive permet d'ajouter les informations concernant le certificat client aux variables d'environnement. On pourra ainsi adapter le code PHP en fonction du certificat de l'utilisateur.
Activation des vhost:
a2ensite home.tinad.fr a2ensite home.tinad.fr-https a2ensite prive.tinad.fr-https /etc/init.d/apache2 reload
Créer un couple certificat-clé client (fichier PKCS#12):
cd /srv/ssl mkdir home.tinad.fr-Clefs-clients cd home.tinad.fr-Clefs-clients
creer clé
openssl genrsa -des3 -out gnieark.home.tinad.fr.key.pem
Créer le certificat:
openssl req -config ../openssl.cnf -new -key gnieark.home.tinad.fr.key.pem -out gnieark.home.tinad.fr.csr.pem
Retour écran de la dernière commande:
Enter pass phrase for gnieark.home.tinad.fr.key.pem: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [FR]: State or Province Name (full name) [France]: Locality Name (eg, city) []:Rouen Organization Name (eg, company) [Internet Widgits Pty Ltd]:tinad Organizational Unit Name (eg, section) []:home Common Name (e.g. server FQDN or YOUR name) []:gnieark Email Address []:gnieark@free.fr Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
Signer le certificat:
openssl ca -config ../openssl.cnf -policy policy_anything -out gnieark.home.tinad.fr.cert.pem -infiles gnieark.home.tinad.fr.csr.pem
Retour écran de la commande:
root@raspberrypi:/srv/ssl/home.tinad.fr-Clefs-clients# openssl ca -config ../openssl.cnf -policy policy_anything -out gnieark.home.tinad.fr.cert.pem -infiles gnieark.home.tinad.fr.csr.pem Using configuration from ../openssl.cnf Enter pass phrase for /srv/ssl/private/cakey.pem: Check that the request matches the signature Signature ok Certificate Details: Serial Number: 2 (0x2) Validity Not Before: May 12 17:18:18 2013 GMT Not After : May 12 17:18:18 2014 GMT Subject: countryName = FR stateOrProvinceName = France localityName = Rouen organizationName = tinad organizationalUnitName = home commonName = gnieark emailAddress = gnieark@free.fr X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 47:E4:92:85:3A:43:6A:BC:43:C7:5B:41:F4:67:66:E2:36:CA:D7:69 X509v3 Authority Key Identifier: keyid:BE:1D:5D:B9:F1:53:D6:BD:11:90:8E:5C:0F:D2:BC:99:22:BE:F1:48 Certificate is to be certified until May 12 17:18:18 2014 GMT (365 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
Concatener et convertir au forlat PKCS#12 (.p12)
openssl pkcs12 -export -inkey gnieark.home.tinad.fr.key.pem -in gnieark.home.tinad.fr.cert.pem -out gnieark.home.tinad.fr.cert.p12 -name "Gnieark"
Ça y est, j'ai une clé à) fournir à l'utilisateur Gnieark, il pourra l'intégrer à Firefox ou Internet Explorer (lol) et ainsi accéder au site que j'ai protégé précédent.
Révoquer un certificat:
En imaginant que je révoque un Zigazou
cd /srv/ssl openssl ca -config openssl.cnf -revoke prive.tinad.fr/zigazou.prive.tinad.fr.cert.pem #générer la liste de révocation: openssl ca -config openssl.cnf -gencrl -out crl.pem #la visualiser: openssl crl -in crl.pem -text
Note
[1] Pour déclarer nos impôts il n'y a plus besoin de certificat personnel, mais les interlocuteurs (fonctionnaires de collectivités) ont leurs propres clés PKCS pour communiquer avec cette administration