2017-11-18 7 views
1

Mein Ziel: Ich arbeite an einer Integration von Jetty Embedded, die es einfach zu bedienen machen würde. Die interface würde unter anderem erlauben, externe Quellen für TLS-Zertifikate zu integrieren, ohne den Java-KeyStore zu verwenden.TLS auf Embedded Jetty ohne JKS

Dies würde eine größere Flexibilität beim Erstellen verteilter Webdienste ermöglichen (in meinem Fall ein experimental, self-hosted CDN).

Allerdings habe ich Probleme beim Aufbau der Integration. Die Stub-Implementierung ist in this repository.

Was ich versucht habe: Ich habe versucht, in sie zu jeder Funktion die key manager und die trust manager und stellen Sollbruchstellen zu ersetzen. Beim Versuch, auf den Server zuzugreifen, werden diese Unterbrechungspunkte jedoch nie ausgelöst. Stattdessen bin ich begegnet diesen Fehler:

javax.net.ssl.SSLHandshakeException: no cipher suites in common 
    at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1478) 
    at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:535) 
    at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:813) 
    at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781) 
    at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624) 
    at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.fill(SslConnection.java:621) 
    at org.eclipse.jetty.server.HttpConnection.fillRequestBuffer(HttpConnection.java:322) 
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:231) 
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279) 
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:112) 
    at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:261) 
    at org.eclipse.jetty.io.ssl.SslConnection$3.succeeded(SslConnection.java:150) 
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:112) 
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124) 
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:672) 
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:590) 
    at java.lang.Thread.run(Thread.java:748) 

Ich habe versucht, den „Standard“ Jetty-Setup, die ein Zertifikat von einem Schlüsselspeicher zu analysieren, aber ohne viel Glück. Ich finde den Punkt nicht, an dem Jetty die Verschlüsselungs-/Zertifikatsinformationen erhält, die ich überschreiben sollte.

Meine Frage: Wie kann ich Jetty my own certificate source anstelle des Java KeyStore und TrustStore verwenden?

+1

Diese Ausnahme bedeutet normalerweise, dass der Server keinen privaten Schlüssel und kein passendes Zertifikat finden konnte. Offensichtlich ist Ihr 'KeyManager' nicht korrekt installiert oder hätte vorher aufgerufen. – EJP

+0

Vielen Dank, ich werde versuchen, herauszufinden, wie der Schlüsselmanager in der "Stock" -Version im Vergleich zu meiner eigenen installiert ist. – Janoszen

Antwort

0

@EJP wies mich in die richtige Richtung, so ist hier, wie es geht:

Hier ist, wie es getan werden muss.

Zuerst einrichten Jetty für TLS:

HttpConfiguration https = new HttpConfiguration(); 
https.addCustomizer(new SecureRequestCustomizer()); 
SslContextFactory sslContextFactory = new JettySslContextFactory(configuration.getSslProviders()); 
ServerConnector sslConnector = new ServerConnector(
    server, 
    new SslConnectionFactory(sslContextFactory, "http/1.1"), 
    new HttpConnectionFactory(https) 
); 
sslConnector.setPort(httpsPort); 

Notiere die Klasse JettySslContextFactory. Diese Klasse erweitert die eingebaut in X509ExtendedKeyManager und benötigt die protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception Methode, um Anbieter einen benutzerdefinierten KeyManager, wie dies außer Kraft zu setzen:

@Override 
protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception { 
    return new KeyManager[] { 
     new JettyX509ExtendedKeyManager(certificateProviders) 
    }; 
} 

Zusätzlich dazu werden die folgenden Schritte in jeder Verbindung ausgeführt:

  1. Der SNI-Matcher wird mit dem SNI-Hostnamen konsultiert. Dies scheint der einzige Ort zu sein, an dem der SNI-Hostname sogar verfügbar ist.
  2. Der Schlüsselmanager wird konsultiert, um den Alias ​​(eine Art Schlüssel-ID) für einen bestimmten Schlüsseltyp (EC oder RSA) zu erhalten. Hier müssen wir den Host-Namen aus dem SNI-Matcher holen, da wir ansonsten nicht wissen würden, auf welchen Host-Namen er passen soll.
  3. Basierend auf dem Alias ​​(Schlüssel-ID) können wir dann den privaten Schlüssel und das Zertifikat zurückgeben.

Zumindest ist das, was ich aus dem Debuggen dieses Problems gesammelt habe. Der vollständige Code is online here.

Verwandte Themen