web-dev-qa-db-fra.com

Authentification mutuelle avec Tomcat 7

J'essaie de mettre en place un Java fonctionnant dans Tomcat 7 pour utiliser l'authentification mutuelle (bidirectionnelle). Il semble que peu importe ce que je fais, se connecter au service sur le serveur sécurisé le port ne fonctionne pas.

Voici ce que j'ai fait pour créer des certificats et des magasins de clés et autres:

//create the key and certificate for the Tomcat server.
keytool -genkey -v -alias Tomcat -keyalg RSA -validity 3650 -keystore Tomcat.keystore

//create the key and certificate for the client machine.
keytool -genkey -v -alias clientkey -keyalg RSA -storetype PKCS12 -keystore client.p12

//export the client key
keytool -export -alias clientkey -keystore client.p12 -storetype PKCS12 -rfc -file client.cer

//import the client key into the server keystore
keytool -import -v -file client.cer -keystore Tomcat.keystore

Voici le connecteur dans le fichier server.xml:

<Connector port="8443"
    maxThreads="150"
    scheme="https"
    secure="true"
    sslProtocol="TLS"
    clientAuth="true"
    keystoreFile="Tomcat.keystore"
    keystorePass="Tomcat"
    truststoreFile="Tomcat.keystore"
    truststorePass="Tomcat"/>

Le fichier Tomcat-users.xml ressemble à ceci:

<Tomcat-users>
    <role rolename="Tomcat"/>
    <role rolename="admin"/>
    <!-- note that the actual values for CN, OU, O, L, ST are different, but they match the values created in the client certificate -->
    <user username="CN=name, OU=unit, O=org, L=locality, ST=state, C=US" password="null" roles="admin" />
</Tomcat-users>

Les paramètres suivants sont définis au démarrage:

-Djavax.net.ssl.keyStoreType=jks
-Djavax.net.ssl.keyStore=Tomcat.keystore
-Djavax.net.ssl.keyStorePassword=Tomcat
-Djavax.net.ssl.trustStore=Tomcat.keystore
-Djavax.net.ssl.trustStorePassword=Tomcat
-Djavax.net.debug=SSL

Enfin, j'ai copié le fichier client.p12 sur ma machine cliente et l'ai importé dans les certificats clients de Firefox.

Premier problème: lorsque je frappe un point de terminaison sur mon service (exemple - https://my.server.com:8443/test ) de Firefox, j'obtiens la réponse "Échec de la connexion sécurisée". SSL a reçu un enregistrement dépassant la longueur maximale autorisée. (Code d'erreur: ssl_error_rx_record_too_long)

Deuxième problème: je ne veux pas vraiment exécuter ce connecteur sur le port 8443. Je veux l'exécuter sur le port 7800 (qui est la norme de notre société pour HTTPS). Lorsque je change le port du connecteur en 7800 et que j'essaie de toucher le point de terminaison (exemple - https://my.server.com:7800/test ), il ne résout jamais la page.

Donc, quelque part, je manque évidemment une pièce cruciale. Quelqu'un peut-il voir mon erreur?

MISE À JOUR: après les commentaires de @Dave G

Exécution de la commande:

openssl s_client -connect localhost:8443 -showcerts

produit la sortie suivante:

CONNECTED(00000003)
140642290976584:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:766:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 263 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---

J'ai également ajouté -Djavax.net.debug = SSL au démarrage. Cela génère ce qui suit au début du fichier catalina.out:

trustStore is: Tomcat.keystore
trustStore type is : jks
trustStore provider is :
init truststore
adding as trusted cert:
  Subject: CN=localhost, OU=unit, O=org, L=Springfield, ST=MO, C=US
  Issuer:  CN=localhost, OU=unit, O=org, L=Springfield, ST=MO, C=US
  Algorithm: RSA; Serial number: 0x5485b5a5
  Valid from Mon Dec 08 14:28:53 UTC 2014 until Thu Dec 05 14:28:53 UTC 2024

adding as trusted cert:
  Subject: CN=William Jackson, OU=unit, O=org, L=Springfield, ST=MO, C=US
  Issuer:  CN=William Jackson, OU=unit, O=org, L=Springfield, ST=MO, C=US
  Algorithm: RSA; Serial number: 0x5485b6af
  Valid from Mon Dec 08 14:33:19 UTC 2014 until Sun Mar 08 14:33:19 UTC 2015

trigger seeding of SecureRandom
done seeding SecureRandom

Et puis BEAUCOUP de:

Ignoring unavailable cipher suite: <suite name>
Ignoring unsupported cipher suite: <suite name>
17
wbj

Ok - après avoir creusé beaucoup plus, j'ai finalement réussi à travailler. Un grand merci à @Dave G et à ce tutoriel: Configuration de l'authentification SSL bidirectionnelle sur Tomcat à partir de laquelle la plupart de ces instructions sont paraphrasées.

Généralement, les étapes pour obtenir une fonctionnalité d'authentification mutuelle sont les suivantes:

  1. Créez un certificat pour le serveur Tomcat. Le client doit faire confiance à ce certificat.
  2. Créez un fichier de clés pour le serveur Tomcat et importez-y le certificat de serveur.
  3. Créez un certificat pour le client. Le serveur doit faire confiance à ce certificat.
  4. Importez le certificat client dans le magasin de clés serveur
  5. Mettez à jour le fichier Tomcat server.xml avec le connecteur XML correct.

Les étapes ci-dessus sont nécessaires sur le serveur. Une fois terminé, pour configurer le client, procédez comme suit:

  1. Copiez le certificat client du serveur vers le client.
  2. Utilisez le certificat client lors de la communication avec le serveur (ce processus varie selon la nature de l'application client).

Pour la configuration du certificat, j'ai exécuté ce qui suit sur la machine serveur:

# For the following commands, set the values in parenthesis to be whatever makes sense for your environment.  The parenthesis are not necessary for the command.

# This is an all-in-one command that generates a certificate for the server and places it in a keystore file, while setting both the certifcate password and the keystore password.
# The net result is a file called "Tomcat.keystore". 

keytool -genkeypair -alias (serveralias) -keyalg RSA -dname "CN=(server-fqdn),OU=(organizationalunit),O=(organization),L=(locality),ST=(state),C=(country)" -keystore Tomcat.keystore -keypass (password) -storepass (password)

# This is the all-in-one command that generates the certificate for the client and places it in a keystore file, while setting both the certificate password and the keystore password.
# The net result is a file called "client.keystore"

keytool -genkeypair -alias (clientalias) -keyalg RSA -dname "CN=(client),OU=(organizationalunit),O=(organization),L=(locality),ST=(state),C=(country)" -keypass (password) -keystore client.keystore -storepass (password) 

# This command exports the client certificate.  
# The net result is a file called "client.cer" in your home directory.

keytool -exportcert -rfc -alias (clientalias) -file client.cer -keypass (password) -keystore client.keystore -storepass (password)

# This command imports the client certificate into the "Tomcat.keystore" file.

keytool -importcert -alias (clientalias) -file client.cer -keystore Tomcat.keystore -storepass (password) -noprompt

Les certificats doivent maintenant être configurés de manière appropriée. L'étape suivante consiste à configurer votre connecteur dans Tomcat server.xml. Ajoutez un élément de connecteur qui ressemble à ceci:

<Connector port="8443"
    maxThreads="150"
    scheme="https"
    secure="true"
    SSLEnabled="true"
    truststoreFile="/full/path/to/Tomcat.keystore"
    truststorePass="(password)"
    keystoreFile="/full/path/to/Tomcat.keystore"
    keystorePass="(password)"
    clientAuth="true"
    keyAlias="serverkey"
    sslProtocol="TLS"/>      

Notez que dans le XML ci-dessus:

  1. L'attribut "port" peut être ce que vous voulez.
  2. Les attributs "keystoreFile" et "truststoreFile" doivent être des chemins d'accès complets. Tomcat ne regarde pas dans le même répertoire que server.xml par défaut.
  3. Les attributs "keystorePass" et "truststorePass" doivent correspondre à la valeur (mot de passe) que vous avez utilisée lors de la création du fichier Tomcat.keystore.
  4. L'attribut "clientAuth" doit être défini sur "true". C'est ce qui déclenche l'authentification mutuelle.

De plus, dans le fichier server.xml, assurez-vous que NE PAS avoir un AprLifecycleListner défini. Le XML de cet écouteur ressemblera à ceci:

<Listener className="org.Apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

Cet élément doit être supprimé/mis en commentaire. AprLifecycleListener n'est pas configuré de la même manière que décrit ci-dessus et ne fonctionnera pas avec ces instructions.

Redémarrez Tomcat. La configuration du serveur doit être terminée.

J'ai testé mon travail avec Firefox, car il est facile d'y ajouter des certificats clients. Ouvrez Firefox et essayez de vous connecter à un point de terminaison de votre service Tomcat sur le port défini dans votre connecteur.

Ex: https://mytomcatdomain.com:8443/test

Lorsque vous faites cela, vous devriez recevoir l'alerte standard de Firefox concernant une connexion non fiable car nous avons créé un certificat auto-signé pour notre serveur Tomcat. Ajoutez une exception pour le certificat afin que notre client (Firefox) fasse confiance à notre serveur (Tomcat).

Une fois que vous avez ajouté l'exception, vous devriez obtenir un message "Échec de la connexion sécurisée". Le code d'erreur est "ssl_error_bad_cert_alert". Cela confirme que notre serveur Tomcat demande une authentification au client. La demande échoue car nous n'avons pas encore configuré Firefox pour envoyer notre certificat client de confiance.

Pour configurer Firefox, nous devons faire un peu plus de magie:

// Create a file called DumpPrivateKey.Java.  The contents should look like so:
public class DumpPrivateKey {
public static void main(String[] args) throws Exception {
  final String keystoreName = args[0];
    final String keystorePassword = args[1];
    final String alias = args[2];
    Java.security.KeyStore ks = Java.security.KeyStore.getInstance("jks");
    ks.load(new Java.io.FileInputStream(keystoreName), keystorePassword.toCharArray());
    System.out.println("-----BEGIN PRIVATE KEY-----");
    System.out.println(new Sun.misc.BASE64Encoder().encode(ks.getKey(alias, keystorePassword.toCharArray()).getEncoded()));
    System.out.println("-----END PRIVATE KEY-----");
  }
}

Compilez le fichier Java avec la commande suivante:

javac DumpPrivateKey.Java

Nous allons maintenant utiliser ce petit utilitaire pour extraire une clé du fichier client.keystore que nous créons ci-dessus. Copiez les fichiers client.keystore et client.cer dans le même répertoire que votre classe DumpPrivateKey. Exécutez ce qui suit:

# This extracts the client key from the client keystore

Java DumpPrivateKey client.keystore (password) clientkey > clientkey.pkcs8

# This creates a client.p12 file that can be used by Firefox

openssl pkcs12 -export -in client.cer -inkey clientkey.pkcs8 -password pass:(password) -out client.p12

Notez que dans le code ci-dessus, (mot de passe) doit être le mot de passe que vous avez utilisé pour créer le client.keystore.

Ouvrez les préférences de Firefox. Cliquez sur l'onglet "Certificats". Cliquez sur le bouton "Afficher les certificats". Cliquez sur l'onglet "Vos certificats".

Cliquez sur le bouton "Importer" et recherchez le fichier "client.p12" créé précédemment. Vous devez être invité à saisir le mot de passe du certificat client.

En supposant que le "client.p12" a été importé avec succès, vous pouvez maintenant actualiser votre page Firefox et vous devriez obtenir une réponse réussie de votre point de terminaison de serveur Tomcat.

29
wbj

@wbj, l'exportation de PrivateKeyEntry de JKS vers PKCS # 12 peut être beaucoup plus facile:

keytool -importkeystore -srckeystore client.keystore -destkeystore client.p12 -deststoretype PKCS12 -srcalias client -deststorepass <password> -destkeypass <password>

À votre santé.

4
Dmytro Ozarkiv

Il m'a fallu un certain temps pour le faire fonctionner correctement en utilisant les certificats Openssl, en rédigeant mes notes pour que cela puisse aider les autres à visiter cette page.

Étape 1: Créez votre propre autorité de certification racine

~/openssl$ mkdir -m 0700 /home/ubuntu/openssl/CA /home/ubuntu/openssl/CA/certs /home/ubuntu/openssl/CA/crl /home/ubuntu/openssl/CA/newcerts /home/ubuntu/openssl/CA/private
~/openssl$ touch /home/ubuntu/openssl/CA/indext.txt
~/openssl$ echo 1000 >> /home/ubuntu/openssl/CA/serial
~/openssl$ mv karun-Tomcat-root-ca.key CA/private/

~/openssl$ Sudo vi /etc/openssl.cnf
    # Make changes here
    dir = /home/ubuntu/openssl/CA
    #optionally change policy definitions as well
~/openssl$ openssl genrsa -des3 -out karun-Tomcat-root-ca.key 2048

  #In below command make sure to use CN=<hostname of your machine>
~/openssl$ openssl req -new -x509 -days 36520 -key karun-Tomcat-root-ca.key -out karun-Tomcat-root-ca.crt -config openssl.cnf

~$ Sudo cp ~/openssl/CA/certs/karun-Tomcat-root-ca.crt /usr/share/ca-certificates/

  # make sure in the UI you enable/select the certificate created above
~$ Sudo dpkg-reconfigure ca-certificates
  # Now reboot ubuntu machine just to make sure certificates are loaded successfully and Tomcat picks it

Étape 2: créer la paire de clés du serveur Tomcat

~$ openssl genrsa -out Tomcat-server.key 2048

   # Use common name = <Give IP address>, department = Tomcat Server CSR
~$ openssl req -new -sha256 -config ~/openssl/openssl.cnf -key Tomcat-server.key -out Tomcat-server.csr
~$ openssl x509 -req -sha256 -days 36520 -in Tomcat-server.csr -signkey Tomcat-server.key -CA ~/openssl/CA/certs/karun-Tomcat-root-ca.crt -CAkey ~/openssl/CA/private/karun-Tomcat-root-ca.key -CAcreateserial -out Tomcat-server.crt 
~$ openssl pkcs12 -export -name karun-Tomcat-server-cert -in Tomcat-server.crt -out Tomcat-server.p12 -inkey Tomcat-server.key -CAfile ~/openssl/CA/certs/karun-Tomcat-root-ca.crt -caname karun-root -chain

~$ keytool -importkeystore -destkeystore Tomcat-server.jks -srckeystore Tomcat-server.p12 -srcstoretype pkcs12 -alias karun-Tomcat-server-cert

~$ keytool -import -alias karun-root -keystore Tomcat-server.jks -trustcacerts -file ~/openssl/CA/certs/karun-Tomcat-root-ca.crt

# **(LATER)** Run this once client cert is generated
~$ keytool -importkeystore -alias karun-Tomcat-client-cert -srckeystore ~/client-certs/Tomcat-client.p12 -srcstoretype PKCS12 -destkeystore Tomcat-server.jks -deststoretype JKS

# **(LATER)** Run this once Tomcat server started successfully
~$ openssl s_client -connect localhost:8443 -cert ~/client-certs/Tomcat-client.crt -key ~/client-certs/Tomcat-client.key -debug -showcerts 

Étape 3: Créer une paire de clés côté client

~$ openssl genrsa -out Tomcat-client.key 2048
  # Use common name = <Tomcat-user.xml's user say 'admin'>, department = Tomcat Client CSR
~$ openssl req -new -sha256 -config ~/openssl/openssl.cnf -key Tomcat-client.key -out Tomcat-client.csr
~$ openssl x509 -req -sha256 -days 36520 -in Tomcat-client.csr -signkey Tomcat-client.key -CA ~/openssl/CA/certs/karun-Tomcat-root-ca.crt -CAkey ~/openssl/CA/private/karun-Tomcat-root-ca.key -CAcreateserial -out Tomcat-client.crt 
~$ openssl pkcs12 -export -name karun-Tomcat-client-cert -in Tomcat-client.crt -out Tomcat-client.p12 -inkey Tomcat-client.key -CAfile ~/openssl/CA/certs/karun-Tomcat-root-ca.crt -caname karun-root -chain
~$ (optional step) keytool -importkeystore -destkeystore Tomcat-client.jks -srckeystore Tomcat-client.p12 -srcstoretype pkcs12 -alias karun-Tomcat-client-cert
~$ (optional step) keytool -import -alias root -keystore Tomcat-client.jks -trustcacerts -file ~/openssl/CA/certs/karun-Tomcat-root-ca.crt

Étape 4: modifications de Tomcat

# Make this change in server.xml of Tomcat server
<Connector port="8443" protocol="org.Apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
           keystoreFile="/opt/Tomcat/openssl-certs/Tomcat-server.jks"
           keystorePass="password"
           keyAlias="karun-Tomcat-server-cert"
           truststoreFile="/opt/Tomcat/openssl-certs/Tomcat-server.jks"
           truststorePass="password"
           clientAuth="true" sslProtocol="TLS" />

Étape 5: redémarrez le serveur Tomcat et vérifiez les journaux pour vous assurer qu'il n'y a aucune erreur au démarrage

Étape 6: Téléchargez le certificat client sur le navigateur

Dans votre navigateur, par exemple: Firefox, naviguez Préférences -> Avancé -> Certificat -> Afficher les certificats -> Vos certificats

Importez "Tomcat-client.p12"

https://<Tomcat ip>:8443/

Références

http://pages.cs.wisc.edu/~zmiller/ca-howto/

http://www.area536.com/projects/be-your-own-certificate-authority-with-openssl/

3
karun