Utilisation de certificats X509 pour CAS

Ce document est une aide à l'utilisation de certificats X509 pour le fonctionnement du serveur CAS.


Vincent  Mathieu 
Université Nancy 2

Dates de modification
Revision 1.0 12 février 2006 reprise de la doc en ancien format
Revision 1.01 24 mai 2007 modification des lien de la FAQ du CRU
1. Références
2. Pourquoi utiliser des certificats pour CAS
2.1. côté serveur https
2.1.1. Apache en frontal
2.1.2. Tomcat 'standalone'
2.2. Côté client https
3. Configuration de CAS avec des certificats auto-signés (pour des tests)
3.1. Création du certificat
3.1.1. Génération du couple de clés
3.1.2. Exportation du certificat auto-signé
3.2. Ajout du certificat dans le magasin global du JDK
3.3. Enregistrement du certificat dans un keystore 'privé'
3.4. Configuration de Tomcat
4. Configuration de CAS et uPortal avec des certificats de la PKI pilote du CRU
4.1. Création du keystore pour le serveur CAS
4.1.1. Récupération/installation de Jetty
4.1.2. Génération du certificat serveur au format pkcs12
4.2. Génération du magasin de clé
4.2.1. Ajout de la chaine d'autorités de certification
4.2.2. Supprimer les fichiers intermédiaires
4.3. Paramétrer tomcat pour https
4.4. Prise en compte de l'autorité de CA
4.4.1. Transformation du format du certificat de l'autorité racine
4.4.2. Intégration de l'autorité de certification du CRU dans Java

1. Références

2. Pourquoi utiliser des certificats pour CAS

Le serveur CAS doit travailler en HTTPS pour pouvoir utiliser pleinement ses fonctionnalités.

En particulier, pour l'URL de login, afin de crypter les échanges de mot de passe, et lors du transport du PGT, celui-ci devant être protégé.

Il est donc fortement recommandé que le serveur CAS ne soit accessible qu'en HTTPS.

Lors de la récupération d'un PGT, le serveur CAS génère une connexion https vers le proxy CAS; il faut donc que cette URL de 'callback' soit également accessible en HTTPS.

Ce document décrit deux méthodes de configuration de CAS :

Pour comprendre les besoins, il faut distinguer les deux types d'usage des certificats liés aux communications https directes entre une appli cliente java et un serveur https, l'appli cliente étant dans notre cas une servlet de même que l'appli serveur.

2.1. côté serveur https

L'application serveur https doit être accessible en ... https.

C'est donc le serveur W3 qui doit être paramétré pour supporter le https. C'est dans la configuration du serveur W3 qu'on doit indiquer où trouver la clé privée du serveur, le certificat (qui contient lui-même la clé publique correspondante), et les certificats éventuels des Autorités de Certification faisant partie de la chaine de certification de délivrance du certificat du serveur, dans le cas d'un certificat non auto-signé).

Deux cas sont traité ici :

2.1.1. Apache en frontal

On utilise habituellement mod_ssl. Voir la documentation à ce sujet. D'une manière très succinte :

2.1.2. Tomcat 'standalone'

Il faut préparer un keystore (magasin de certificat) qui doit contenir à la fois la clé privée du serveur https, et le certificat du serveur et éventuellement celui des AC de la chaine de certification.

Voir le document officiel tomcat.

2.2. Côté client https

Il faut que l'application cliente génère des connexions https vers le serveur. Il est donc nécessaire de lui faire connaitre les serveurs auxquels elle peut faire confiance. Il faut donc lui communiquer le certificat (pas la clé privée, bien sur) du serveur https, ou de l'une des AC de la chaine de certification éventuelle.

Dans l'environnement java, ceci se fait également avec un keystore, qui peut être paramétré de plusieurs façons :

3. Configuration de CAS avec des certificats auto-signés (pour des tests)

On suppose ici que le serveur CAS et uPortal fonctionnement avec la même instance de tomcat. Cette partie explique comment faire fonctionner CAS avec des certificats auto-signés.

Cette partie de documentation n'est utile que pour des tests ; il est déconseillé d'utiliser des certificats auto-signés en production, une PKI devient vite obligatoire.

3.1. Création du certificat

On procède d'abord par la génération du bi-clé, dans un keystore (magasin de certificats) java.

On désire ensuite enregistrer juste le certificat dans un keystore de certificats 'trusted' (autorisés).

On peut l'enregistrer dans le keystore de la JVM ; cette méthode n'est pas la meilleure. Il est préférable de l'enregistrer dans un keystore spécifique, qui sera pris en compte lors du lancement de tomcat au lieu du keystore de la JVM.

3.1.1. Génération du couple de clés

On commence par générer un couple de clés (certificat auto-signé) pour le serveur (cas.univ-xxx.fr) et on stocke dans le magasin serveur.keystore :

% keytool -genkey -alias tomcat -dname "CN=cas.univ-xxx.fr,OU=X,O=Y,L=Z,S=XY,C=YZ" -keyalg RSA -storepass yyyyyy -keystore cas.keystore
Enter key password for <tomcat>
(RETURN if same as keystore password):

cas.keystore contient à la fois la clé privée du serveur, et le certificat auto-signé qui contient la clé publique.

3.1.2. Exportation du certificat auto-signé

On exporte ensuite le certificat dans un fichier (cas.cert) :

% keytool -export -alias tomcat -storepass yyyyyy -file cas.cert -keystore cas.keystore 
Certificate stored in file <cas.cert> 

cas-cert ne contient que le certificat, sans la clé privée.

3.2. Ajout du certificat dans le magasin global du JDK

Pas souhaitable. IL est préférable d'enregistrer ce certificat dans un kestore dédié à une instance de tomcat. Voir le paragraphe suivant.

Rappel : le mot de passe par défaut du magasin global de Java est "changeit".

% keytool -import -v -trustcacerts -alias tomcat -file cas.cert -keystore $JAVA_HOME/jre/lib/security/cacerts -keypass xxxxxx -storepass changeit
Owner: CN=cas.ifsic.univ-rennes1.fr, OU=X, O=Y, L=Z, ST=XY, C=YZ 
Issuer: CN=cas.ifsic.univ-rennes1.fr,   OU=X, O=Y, L=Z, ST=XY, C=YZ 
Serial number: 3eb79610 
Valid from: Tue May 06   13:01:36 CEST 2003 until: Mon Aug 04 13:01:36 CEST 2003 
Certificate fingerprints:
   MD5: 0B:20:52:BC:7C:EA:28:58:16:FB:3C:2F:C4:D2:E2:35 
   SHA1: 00:5A:F5:81:B1:07:1C:EB:C3:1F:C4:89:5E:76:87:43:D7:8F:F0:5F   
Trust this certificate? [no]: yes 
Certificate was added to keystore 
[Saving /usr/java/j2sdk1.4.1_02/jre/lib/security/cacerts] 

Contrôle :

% keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
Keystore type: jks
Keystore provider: SUN

Your keystore contains 16 entries

[...]
tomcat, May 6, 2003, trustedCertEntry,
Certificate fingerprint (MD5): 0B:20:52:BC:7C:EA:28:58:16:FB:3C:2F:C4:D2:E2:35
[...]

Copier le fichier serveur.keystore dans un répertoire non listable HTTP (par exemple /etc/x509).

3.3. Enregistrement du certificat dans un keystore 'privé'

C'est la méthode préconisée. Au lieu d'enregistrer le certificat (qui ne contient que la clé publique du serveur) dans le keystore global de la JVM, on va l'enregistrer dans un keystore (cas-cacerts) qui sera déclaré lors du lancement de tomcat, et utilisé à la place du keystore global.

keytool -import -v -trustcacerts -alias tomcat -file cas.cert -keystore cas-cacerts -keypass xxxxxx -storepass changeit

Maintenant, lors du lancement de tomcat qui doit faire confiance à CAS :

CATALINA_OPTS="-Djavax.net.ssl.trustStore=cas-cacerts";export CATALINA_OPTS 

3.4. Configuration de Tomcat

Modifier le fichier server.xml de tomcat :

<!-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->    
  <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"    
             port="8443" minProcessors="5" maxProcessors="75"
             enableLookups="true"
             acceptCount="10" debug="0"    scheme="https" secure="true"
             useURIValidationHack="false">
    <Factory className="org.apache.coyote.tomcat4.CoyoteServerSocketFactory"    
             clientAuth="false" protocol="TLS"
             keystoreFile="/etc/x509/cas.keystore" keystorePass="yyyyyyy"/>
  </Connector>

4. Configuration de CAS et uPortal avec des certificats de la PKI pilote du CRU

On suppose ici que le serveur CAS est porté sur la machine cas.univ-xxx.fr, et uportal sur la machine uportal.univ-xxx.fr

On dispose des fichiers suivants, générés par le CRU (stockés dans /etc/x509) :

Est décrite ici l'installation du certificat sur la machine cas. La procédure est similaire pour la machine uportal.

Important

il est possible, avec la PKI du CRU, de travailler différemment ; c'est plus simple dans un environnement java.

Il suffit, à l'aide de keytools, de générer la bi-clé et une requête de certification.

Il faut alors d'envoyer cette requête de certification au CRU, qui va nous retourner le certificat X509 correspondant.

Toute la procédure pour générer le keystore peut alors se faire uniquement avec l'utilitaire keytools, sans avoir besoin d'autres outils.

Voir la doc correspondante.

4.1. Création du keystore pour le serveur CAS

Il faut au préalable récupérer le package org.mortbay.jetty-jdk1.2.jar livré avec la distribution de Jetty.

On va ensuite procéder en plusieurs étapes :

Si on n'ajoute pas la chaine de certification, celle-ci n'est pas transmise aux navigateurs clients, ce qui peut poser problème.

4.1.1. Récupération/installation de Jetty

Récupérer Jetty-x.y.z.tgz de http://jetty.mortbay.org (dernière version 4.2.9) et installer :

% cd /usr/local
% mv /tmp/Jetty-4.2.9.tgz src
% tzxf src/Jetty-4.2.9.tgz 

Le package contient l'utilitaire PKCS12Import qui sait créer un fichier keystore à partir d'un certificat pkcs12.

4.1.2. Génération du certificat serveur au format pkcs12

On génère le certif pkcs12 depuis la clé privée du serveur et son certificat PEM (on entre le mot de passe xxxxxx en interactif) :

% cd /etc/x509
% openssl pkcs12 -export -inkey cas.univ-xxx.fr.key -in cas.univ-xxx.fr.cert -out cas.pkcs12
Enter Export Password: xxxxxx
Verifying - Enter Export Password: xxxxxx

On peut le contrôler (keytool sait lire un fichier pkcs12) :

% keytool -list -v -keystore cas.pkcs12 -storetype pkcs12 -storepass xxxxxx
Type Keystore : pkcs12
Fournisseur Keystore : SunJSSE
 
Votre Keystore contient 1 entrée(s)
 
Nom dalias : {0}
Date de création : 23 juin 2003
Type d'entrée : keyEntry
Longueur de chaîne du certificat : 1
Certificat[1]:
Propriétaire : EMAILADDRESS=reseau@univ-xxx.fr, CN=cas.univ-nancy2.fr, O=Universite xxx, C=FR
Émetteur : EMAILADDRESS=ca-admin@cru.fr, CN=ac-serveur, O=CRU, C=FR
Numéro de série : 6
Valide du : Wed Jun 04 17:13:25 CEST 2003 au : Fri Jun 04 17:13:25 CEST 2004
Empreintes de certificat :
         MD5 :  09:10:0D:03:77:A6:D2:2D:DA:92:7D:65:E8:A3:1E:90
         SHA1: C5:55:94:B1:39:8A:67:09:1B:E4:F0:C4:FE:2D:31:96:8F:9C:31:AC 

4.2. Génération du magasin de clé

C'est le keystore qui va contenir clés privée et publique, et le certificat ; c'est celui qui devra être déclaré dans le fichier server.xml du serveur tomcat de CAS.

On utilise l'utilitaire PKCS12Import (on donne un mot de passe yyyyyy au nouveau magasin) :

% java -classpath /usr/local/Jetty-4.2.9/lib/org.mortbay.jetty-jdk1.2.jar org.mortbay.util.PKCS12Import cas.pkcs12 cas.keystore
Enter input keystore passphrase: xxxxxx
Enter output keystore passphrase: yyyyyy
Alias 0: 1
Adding key for alias 1

Le nom d'alias créé est 1. Si on veut le changer (en cas, par exemple) :

% keytool -keyclone -keystore cas.keystore -alias 1 -dest cas -storepass yyyyyy
Spécifiez le mot de passe de la clé pour <cridev>
        (appuyez sur Entrée si le résultat est identique à <1>)

Contrôle (le magasin doit maintenant contenir les 2 alias) :

% keytool -list -keystore cas.keystore -storepass yyyyyy
Type Keystore : jks
Fournisseur Keystore : SUN
 
Votre Keystore contient 2 entrée(s)
 
1, 23 juin 2003, keyEntry,
Empreinte du certificat (MD5) : 09:10:0D:03:77:A6:D2:2D:DA:92:7D:65:E8:A3:1E:90
cas, 23 juin 2003, keyEntry,
Empreinte du certificat (MD5) : 09:10:0D:03:77:A6:D2:2D:DA:92:7D:65:E8:A3:1E:90

On peut ensuite effacer le premier :

% keytool -delete -alias 1 -keystore cas.keystore -storepass yyyyyy
% keytool -list -keystore cas.keystore -storepass yyyyyy
Type Keystore : jks
Fournisseur Keystore : SUN
 
Votre Keystore contient 1 entrée(s)
 
cridev, 23 juin 2003, keyEntry,
Empreinte du certificat (MD5) : 09:10:0D:03:77:A6:D2:2D:DA:92:7D:65:E8:A3:1E:90

4.2.1. Ajout de la chaine d'autorités de certification

Récupérer le fichier cachain.txt contenant les certificats des AC ac-racine et ac-serveur (donc, la chaine de certification) à http://igc.cru.fr/ac-serveur/, choisir 'Chaine de certification).

Pour cela, on concatène le fichier cas.univ-xxx.crt avec cachain.pem (le echo sert à ajouter un CR au fichier cas.univ-xxx.crt) :

% (cat cas.univ-xxx.crt ; echo ; cat cachain.txt) > certchain-cas.pem

keytool n'aime pas ce format de fichier. 2 solutions, le transformer en format DER avec openssl, ou plus simple, éditer ce fichier pour éliminer tout ce qui n'est pas entre des lignes -----BEGIN CERTIFICATE----- et -----END CERTIFICATE-----

On choisit cette seconde méthode, ce qui donne quelque chose du genre :

----BEGIN CERTIFICATE-----
MIIEBzCCAu+gAwIBAgICANcwDQYJKoZIhvcNAQEEBQAwUDELMAkGA1UEBhMCRlIx
... certif de serv.univ.fr ...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIID1zCCAr+gAwIBAgIBAzANBgkqhkiG9w0BAQQFADBPMQswCQYDVQQGEwJGUjEM
... certif de l'ac-serveur ...
nbnQ04fo+LDLFWa9qCI8mLX1JGcP4WDKJ9hk
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIID1jCCAr6gAwIBAgIBADANBgkqhkiG9w0BAQQFADBPMQswCQYDVQQGEwJGUjEM
... certif de l'ac-racine ...
6cKi0FjWaBYjBOH6/ULalf1g4P38vbUAT4A=
-----END CERTIFICATE-----

et on importe dans le keystore :

% keytool -import -alias cas -trustcacerts -file certchain-cas.pem -keystore cas.keystore -storepass yyyyyy
Certificat du plus haut niveau dans la réponse :
 
Propriétaire : EMAILADDRESS=ca-admin@cru.fr, CN=ac-racine, O=CRU, C=FR
Émetteur : EMAILADDRESS=ca-admin@cru.fr, CN=ac-racine, O=CRU, C=FR
Numéro de série : 0
Valide du : Thu Apr 17 16:16:24 CEST 2003 au : Sun Apr 14 16:16:24 CEST 2013
Empreintes de certificat :
         MD5 :  25:44:35:56:18:E4:EF:65:02:25:99:C6:4E:17:00:38
         SHA1: 33:88:49:67:76:43:8F:58:4D:1F:93:9B:55:CF:C3:A5:37:23:39:B4
 
... n'est pas digne de confiance. Installer la réponse quand même ? [non] :  oui
Réponse de certificat installée dans le Keystore

Contrôle (cas.keystore doit contenir une entrée de type keyEntry, une longueur de chaine de certif de 3, et les 3 certificats de la chaîne de confiance) :

% keytool -list -v -keystore cas.keystore
Type Keystore : jks
Fournisseur Keystore : SUN

Votre Keystore contient 1 entrée(s)

Nom dalias : {0}
   Date de création : 23 juin 2003
   Type d'entrée : keyEntry
   Longueur de chaîne du certificat : 3
   Certificat[1]:
   Propriétaire : EMAILADDRESS=reseau@univ-nancy2.fr, CN=cridev.univ-nancy2.fr,    O=Universite de Nancy 2, C=FR
   Émetteur : EMAILADDRESS=ca-admin@cru.fr, CN=ac-serveur, O=CRU, C=FR
   Numéro de série : 6
   Valide du : Wed Jun 04 17:13:25 CEST 2003 au : Fri Jun 04 17:13:25 CEST 2004
   Empreintes de certificat :
   MD5 : 09:10:0D:03:77:A6:D2:2D:DA:92:7D:65:E8:A3:1E:90
   SHA1: C5:55:94:B1:39:8A:67:09:1B:E4:F0:C4:FE:2D:31:96:8F:9C:31:AC
   Certificat[2]:
   Propriétaire : EMAILADDRESS=ca-admin@cru.fr, CN=ac-serveur, O=CRU, C=FR
   Émetteur : EMAILADDRESS=ca-admin@cru.fr, CN=ac-racine, O=CRU, C=FR
   Numéro de série : 3
   Valide du : Fri May 16 11:39:11 CEST 2003 au : Fri Dec 14 10:39:11 CET 2012
   Empreintes de certificat :
   MD5 : 1D:51:5F:45:D1:CC:E9:C4:DA:4A:F6:F6:F9:CD:E3:11
   SHA1: 4E:27:8C:05:B5:6C:03:EA:A1:5B:F0:01:AE:D1:86:43:E9:03:6D:B6
   Certificat[3]:
   Propriétaire : EMAILADDRESS=ca-admin@cru.fr, CN=ac-racine, O=CRU, C=FR
   Émetteur : EMAILADDRESS=ca-admin@cru.fr, CN=ac-racine, O=CRU, C=FR
   Numéro de série : 0
   Valide du : Thu Apr 17 16:16:24 CEST 2003 au : Sun Apr 14 16:16:24 CEST 2013
   Empreintes de certificat :
   MD5 : 25:44:35:56:18:E4:EF:65:02:25:99:C6:4E:17:00:38
   SHA1: 33:88:49:67:76:43:8F:58:4D:1F:93:9B:55:CF:C3:A5:37:23:39:B4

4.2.2. Supprimer les fichiers intermédiaires

/bin/rm certchain-cas.pem cas.pkcs12

4.3. Paramétrer tomcat pour https

La procédure est la même que pour l'installation rapide. Dans le fichier server.xml de tomcat :

<!-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
  <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
             port="8443" minProcessors="5" maxProcessors="75" 
             enableLookups="true" acceptCount="10" debug="0" 
             scheme="https" secure="true" useURIValidationHack="false"    
             disableUploadTimeout="true">
     <Factory className="org.apache.coyote.tomcat4.CoyoteServerSocketFactory"    
             clientAuth="false" protocol="TLS" 
             keystoreFile="/etc/x509/cas.keystore" keystorePass="yyyyyy"/>
  </Connector>

Tester en accédant https://cas.univ-xxx.fr:8443.

4.4. Prise en compte de l'autorité de CA

Les paragraphes précédents ont permis de faire fonctionner les 2 serveurs tomcat (uportal et cas) en HTTPS.

Ces 2 serveurs vont avoir besoin de dialoguer directement entre eux en HTTPS. Il faut donc qu'ils puissent valider mutuellement le certificat de l'autre, sinon :

ERROR - YaleCASContext: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Couldn't find trusted certificate 

Pour celà, on va déclarer l'autorité de CA ac-racine dans le keystore de la machine virtuelle java.

4.4.1. Transformation du format du certificat de l'autorité racine

L'utilitaire keytool veut du format DER (en fait, il peut utiliser du format pem, mais expurgé du 'superflu' : il ne faut laisser que les infos entre 'BEGIN CERTIFICATE' et 'END CERTIFICATE'). On transforme donc les certificats comme ceci :

% openssl x509 -in ac-racine.pem -out ac-racine.der -outform DER

Pour s'assurer de la lisibilité du certificat :

% keytool -printcert -file ac-racine.der
Propriétaire : EMAILADDRESS=ca-admin@cru.fr, CN=ac-racine, O=CRU, C=FR
Émetteur : EMAILADDRESS=ca-admin@cru.fr, CN=ac-racine, O=CRU, C=FR
Numéro de série : 0
Valide du : Thu Apr 17 16:16:24 CEST 2003 au : Sun Apr 14 16:16:24 CEST 2013
Empreintes de certificat :
         MD5 :  25:44:35:56:18:E4:EF:65:02:25:99:C6:4E:17:00:38
         SHA1: 33:88:49:67:76:43:8F:58:4D:1F:93:9B:55:CF:C3:A5:37:23:39:B4

4.4.2. Intégration de l'autorité de certification du CRU dans Java

2 méthodes :

Les 2 solutions sont présentées.

4.4.2.1. Intégration de l'autorité de certification du CRU dans la JVM

% keytool -import -alias CRU-ac-racine -file ac-racine.der -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
Propriétaire : EMAILADDRESS=ca-admin@cru.fr, CN=ac-racine, O=CRU, C=FR
Émetteur : EMAILADDRESS=ca-admin@cru.fr, CN=ac-racine, O=CRU, C=FR
Numéro de série : 0
Valide du : Thu Apr 17 16:16:24 CEST 2003 au : Sun Apr 14 16:16:24 CEST 2013
Empreintes de certificat :
         MD5 :  25:44:35:56:18:E4:EF:65:02:25:99:C6:4E:17:00:38
         SHA1: 33:88:49:67:76:43:8F:58:4D:1F:93:9B:55:CF:C3:A5:37:23:39:B4
Faire confiance à ce certificat ? [non] :  oui
Certificat ajouté au Keystore

Contrôle :

% keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
Votre keystore contient 17 entrée(s)
Type Keystore : jks
Fournisseur Keystore : SUN

[...]
cru-ac-racine, 23 juin 2003, trustedCertEntry,
Empreinte du certificat (MD5) : 25:44:35:56:18:E4:EF:65:02:25:99:C6:4E:17:00:38

4.4.2.2. Intégration de l'autorité de certification du CRU dans un keystore 'privé'

L'objectif est de faire en sorte que le serveur de servlet (en l'occurence, tomcat) utilise un keystore qui lui est dédié pour les autorités de certification 'trusted', au lieu du keystore de la JVM.

Création du kestore :

keytool -import -v -trustcacerts -alias CRU-ac-racine -file ac-racine.der -keystore cru-ac-racine.cert -storepass yyyyyy

Maintenant, lors du lancement de tomcat qui doit faire confiance à CAS :

CATALINA_OPTS="-Djavax.net.ssl.trustStore=cru-ac-racine.cert";export CATALINA_OPTS