Authentification mutuelle avec Tomcat 7

j'essaie de configurer un service Web Java tournant dans Tomcat 7 pour utiliser l'authentification mutuelle (bidirectionnelle). Il semble que peu importe ce que je fais, se connecter au service sur le port sécurisé ne fonctionne pas.

voici ce que j'ai fait pour créer des certificats et des keystores 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 du serveur.fichier xml:

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

les utilisateurs de tomcat.fichier 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 valeurs suivantes sont 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

finalement, j'ai copié le client.P12 à la machine de mon client, et l'a importé dans les certificats clients de Firefox.

Premier problème: Lorsque j'arrive à un point terminal de mon service (exemple -https://my.server.com:8443/test) de Firefox, je reçois la réponse "secure Connection Failed". SSL a reçu un enregistrement dépassant la longueur maximale permise. (Code d'erreur: ssl_error_rx_record_too_long)

Deuxième problème: Je n'ai pas voulez vraiment exécuter ce connecteur sur le port 8443. Je veux l'exécuter sur le port 7800 (qui est notre standard pour HTTPS). Quand je change le port sur le connecteur en 7800 et que j'essaie de toucher le point final (exemple -https://my.server.com:7800/test) alors il ne résout jamais la page.

donc, quelque part il me manque évidemment une pièce cruciale. N'importe qui peut 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 aussi ajouté-Djavax.net.debug=SSL au démarrage. Cela génère ce qui suit Au début de la catalina.fichier:

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
demandé sur wbj 2014-12-08 19:38:48

4 réponses

Ok-après avoir creusé beaucoup plus, j'ai finalement obtenu ce travail. Un grand merci à @Dave G et à ce tutoriel:http://java-notes.com/index.php/two-way-ssl-on-tomcat d'où la plupart de ces instructions sont paraphrasées.

en général, les étapes à suivre pour obtenir la fonctionnalité d'authentification mutuelle sont les suivantes:

  1. Créer un certificat pour le serveur tomcat. Le client doit faire confiance à ce certificat.
  2. créer un keystore pour le tomcat serveur, et importez le certificat de serveur.
  3. Créer un certificat pour le client. Le serveur doit faire confiance à ce certificat.
  4. Import client certificat dans le serveur keystore
  5. mise à jour du serveur tomcat.fichier xml avec le bon connecteur XML.

Les étapes ci-dessus sont nécessaires sur le serveur. Une fois terminé, pour configurer le client, ne l' suivantes:

  1. copier le certificat client du serveur vers le client.
  2. utilisez le certificat client lorsque vous communiquez 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 installés de façon appropriée. La prochaine étape est de configurer le connecteur dans le tomcat serveur.XML. Ajouter 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" trustststorefile " doivent être des chemins complets. Tomcat ne regarde pas dans le même répertoire que server.xml par défaut.
  3. les attributs "keystorePass" et "trustststorepass" doivent correspondre à la valeur (password) que vous avez utilisée dans la création du tomcat.fichier de magasin de clés.
  4. l'attribut "clientAuth" être défini sur "true". C'est ce qui déclenche l'authentification mutuelle.

de plus, dans le serveur.xml, assurez-vous que vous DO NOT avoir un AprLifecycleListner défini. Le XML de cet écouteur ressemblera à quelque chose comme ceci:

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

cet élément devrait être supprimer/commenté. L'AprLifecycleListener ne se configure pas 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 complète.

J'ai testé mon travail en utilisant Firefox, parce qu'il est facile d'y ajouter des certificats clients. Ouvrez Firefox et essayez de vous connecter à un terminal de votre service tomcat sur le port défini dans votre connecteur.

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

lorsque vous faites cela, vous devriez obtenir L'alerte standard de Firefox à propos d'une connexion non fiable parce que nous avons créé une certificat auto-signé pour notre serveur Tomcat. Ajouter 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 recevoir un message "secure Connection Failed". Le code d'erreur est "ssl_error_bad_cert_alert". Cela confirme que notre serveur Tomcat demande l'authentification du client. La demande échoue parce que nous n'avons pas configuré Firefox pour envoyer notre certificat client de confiance encore.

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-----");
  }
}

Compiler le fichier java avec la commande suivante:

javac DumpPrivateKey.java

nous allons maintenant utiliser ce petit utilitaire pour extraire une clé du client.fichier keystore que nous créons ci-dessus. Copiez le client.keystore et client.les fichiers 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) devrait être le mot de passe que vous avez utilisé pour créer le client.fichier de stockage des clés.

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

Cliquez sur le bouton "Importer" et accédez à la clientèle".p12" fichier qui a été créé précédemment. Vous devriez être invité à entrer le mot de passe pour le certificat client.

en présumant le "client".p12" a été importé avec succès, vous pouvez maintenant vous rafraîchir Firefox page, et vous devriez obtenir une réponse réussie de votre serveur Tomcat endpoint.

27
répondu wbj 2014-12-11 20:29:09

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

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

Cheers.

4
répondu Dmytro Ozarkiv 2016-01-14 15:44:27

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

Étape 1: Créez votre propre CA 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

Etape 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: Tomcat Changements

# 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émarrage Tomcat Server & & check logs pour s'assurer qu'il n'y a pas d'erreurs lors de l'amorçage

Étape 6: Téléchargez Client cert navigateur

Dans votre navigateur, par exemple: firefox, naviguer dans les Préférences -> Avancé -> Certificats> Certificats View -> Vos Certificats

importation "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
répondu karun 2016-08-09 22:42:30

je voudrais essayer les étapes suivantes

  1. déroulez le conteneur comme vous l'avez configuré sur 8443.
  2. lancez votre application client avec-Djavax.net.debug=SSL

cette commande va déverser des tas d'informations. Ce que vous devez vérifier, c'est que le serveur présente une liste de CA qu'il acceptera pour l'authentification mutuelle. Si les AC listés ne contiennent pas votre certificat, le client n'aura aucune idée de la façon de trouver une correspondance. pour le serveur.

ceci peut être rendu beaucoup plus facile en utilisant la commande openssl 's_client'

openssl s_client -connect localhost:8443 -showcerts

qui formateront quelques informations qui peuvent être incalculables dans leur valeur de débogage de ceci.

si le serveur ne présente pas une liste de CAs "acceptables", vous devrez faire de la magie lorsque vous produirez votre jeu de certificats.

dites-moi ce que vous avez trouvé et j'espère pouvoir vous guider dans la bonne direction.

OP ajout d'informations supplémentaires

Ok donc la suite est un peu un problème pour vous:

---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 263 bytes
---

deux choses sortent immédiatement

  1. le serveur n'a pas de certificat Pair
  2. il n'y a pas de noms D'AC des clients

Donc, pour (1):

  1. assurez-vous que votre keystore contient bien l'alias "tomcat" en utilisant keytool.
  2. le truc de mot de passe de magasin/clé dans tomcat est débile. pour pour des raisons de bon sens, ajoutez les attributs keystorePassword et keyPassword à votre connecteur avec des valeurs identiques. documentation pour Tomcat 7 indique que le keystorePass sera par défaut le keyPass s'il n'est pas défini. Si votre keyPass et keystorePass sont les mêmes que l'attribut keyPass.

maintenant pour (2) nous avons vraiment besoin d'avoir (1) travailler d'abord - alors mettez cela en marche et nous verrons où nous en sommes à ce point.

-1
répondu Dave G 2014-12-08 20:13:58