2017-01-30 2 views
3

Ich habe eine vorhandene Anwendung, die die org.restlet.engine.ssl.DefaultSslContextFactory und eine Schlüsselspeicher-Datei verwendet, die geladen wird, wenn der Server gestartet wird. Ich habe eine andere Anwendung, die Zertifikate erstellt, die dynamisch in die Keystore-Datei hinzugefügt werden müssen, während der Server ausgeführt wird. Um dies durchzuführen, habe ich das Zertifikat und den privaten Schlüssel im Code erstellt und dann in ein Verzeichnis schreiben. Das Verzeichnis wird von einem Bash-Skript überwacht, das nach neuen Dateien sucht. Wenn eines erscheint, wird es in die vorhandene Keystore-Datei importiert.Java DefaultSslContextFactory Schlüsselspeicher dynamisch aktualisiert

Aber wenn man versucht, den Server mit dem neu eingeführten Zertifikat für den Zugriff auf die Handshake fehlschlägt. Nur beim Neustart des Servers kann der Zugriff erfolgreich abgeschlossen werden, was bedeutet, dass das hinzugefügte Zertifikat nicht vom Server neu geladen wird.

Gibt es eine Möglichkeit, die laufende Anwendung mit dem neuen Eintrag in der Schlüsselspeicherdatei zu aktualisieren?

+0

Haben Sie sich diese Antwort angesehen? http://stackoverflow.com/questions/859111/how-can-i-use-different-certificates-on-specific-connections – Tom

Antwort

0

das neue Zertifikat in Keystore- Importieren nicht Ihren aktuellen SSLConext wie nichts aktualisieren erzählt die JVM, dass der Schlüsselspeicher geändert hat.

Dazu müssen Sie Ihrer Anwendung mitteilen, dass ein neues Zertifikat in Ihren Keystore hinzugefügt wurde, aber anstatt den Keystore neu zu laden - soweit ich weiß, dass es nicht möglich sein sollte -, was übrigens möglich ist ist, dass Sie das neue Zertifikat in Ihren aktuellen SSLContext See here hinzufügen können.

Um das zu erreichen, haben Sie bewusst das neue Zertifikat -Vielleicht die Komponente eine Bohne, die Ihren bash Script- nennen, in dem Sie eine SSL-Kontext Instanz injiziert.

Es ist auch interessant, wenn Sie Ihre Anwendung unter Verwendung einer Micro-Service-Architektur aufteilen, zu einem Modul die Tatsache delegieren, um mit Zertifikaten umzugehen und sie neu zu laden (mit der richtigen configure LB), wenn Keystore aktualisiert wird.

+0

Ich verstehe nicht, was Sie mit dem letzten Absatz meinen !? Das Bash-Skript läuft von alleine, also wo genau würde ich die Instanz injizieren? – wasp256

+0

In Java-Code, es ist bis zu aktualisieren, um Ihren Code in Speicherzertifikatskette –

+0

, das wie ein sehr schmutziger Hack klingt ... – wasp256

0

Da dies scheint eine ziemlich unmögliche Aufgabe zu sein, beschloss ich, eine Abhilfe zu schaffen. Ich habe nginx als Proxy vor der Anwendung verwendet. Nginx kann Client-Authentifizierung mit mehreren CA-Root-Zertifikaten durchführen, was genau das ist, was ich brauche. Die Verbindung zwischen der Anwendung und nginx kann einfach über HTTP erfolgen, da sie sich auf demselben Host befinden (nur unterschiedliche Ports).

0

hässliche Hack Alarm

Die folgenden Werke für mich. Ich überschreibe DefaultSSLContextFactory, speichere jeden erstellten SSLContext und rufe seine Methode init erneut auf.

den Reload aufzurufen ich UglyHackSSLContextFactory.reloadKeyStore()

package test; 

import java.io.FileInputStream; 
import java.io.IOException; 
import java.security.KeyManagementException; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 
import java.security.NoSuchAlgorithmException; 
import java.security.NoSuchProviderException; 
import java.security.SecureRandom; 
import java.security.UnrecoverableKeyException; 
import java.security.cert.CertificateException; 
import java.util.ArrayList; 

import javax.net.ssl.SSLContext; 

import org.restlet.engine.ssl.DefaultSslContextFactory; 

public class UglyHackSSLContextFactory extends DefaultSslContextFactory { 

    private SSLContext _context = null; 
    public static ArrayList<UglyHackSSLContextFactory> instances = new ArrayList<UglyHackSSLContextFactory>(); 

    // we need all used SSLContextFactories later, so store them 
    public UglyHackSSLContextFactory() { 
     instances.add(this); 
    } 

    // create a new context once and store it. 
    @Override 
    public SSLContext createSslContext() throws Exception { 
     if (this._context == null) { 
      this._context = super.createSslContext(); 
     } 
     return this._context; 
    } 

    // re-init all _context instances 
    public static void reload() throws KeyManagementException, UnrecoverableKeyException, 
      KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException, 
      CertificateException, IOException { 
     for (final UglyHackSSLContextFactory f : instances) { 
      f.reinit(); 
     } 
    } 

    // this is mostly copied from 
    // org.restlet.engine.ssl.DefaultSslContextFactory 
    private void reinit() throws KeyManagementException, KeyStoreException, 
      NoSuchProviderException, NoSuchAlgorithmException, CertificateException, IOException, 
      UnrecoverableKeyException { 

     javax.net.ssl.KeyManagerFactory kmf = null; 

     if ((getKeyStorePath() != null) || (getKeyStoreProvider() != null) 
       || (getKeyStoreType() != null)) { 
      // Loads the key store. 
      final KeyStore keyStore = (getKeyStoreProvider() != null) ? KeyStore.getInstance(
        (getKeyStoreType() != null) ? getKeyStoreType() : KeyStore.getDefaultType(), 
        getKeyStoreProvider()) : KeyStore 
        .getInstance((getKeyStoreType() != null) ? getKeyStoreType() : KeyStore 
          .getDefaultType()); 
      FileInputStream keyStoreInputStream = null; 

      try { 
       keyStoreInputStream = ((getKeyStorePath() != null) && (!"NONE" 
         .equals(getKeyStorePath()))) ? new FileInputStream(getKeyStorePath()) 
         : null; 
       keyStore.load(keyStoreInputStream, getKeyStorePassword()); 
      } finally { 
       if (keyStoreInputStream != null) { 
        keyStoreInputStream.close(); 
       } 
      } 

      // Creates the key-manager factory. 
      kmf = javax.net.ssl.KeyManagerFactory.getInstance(getKeyManagerAlgorithm()); 
      kmf.init(keyStore, getKeyStoreKeyPassword()); 
     } 

     javax.net.ssl.TrustManagerFactory tmf = null; 

     if ((getTrustStorePath() != null) || (getTrustStoreProvider() != null) 
       || (getTrustStoreType() != null)) { 
      // Loads the trust store. 
      final KeyStore trustStore = (getTrustStoreProvider() != null) ? KeyStore 
        .getInstance(
          (getTrustStoreType() != null) ? getTrustStoreType() : KeyStore 
            .getDefaultType(), getTrustStoreProvider()) : KeyStore 
        .getInstance((getTrustStoreType() != null) ? getTrustStoreType() : KeyStore 
          .getDefaultType()); 
      FileInputStream trustStoreInputStream = null; 

      try { 
       trustStoreInputStream = ((getTrustStorePath() != null) && (!"NONE" 
         .equals(getTrustStorePath()))) ? new FileInputStream(getTrustStorePath()) 
         : null; 
       trustStore.load(trustStoreInputStream, getTrustStorePassword()); 
      } finally { 
       if (trustStoreInputStream != null) { 
        trustStoreInputStream.close(); 
       } 
      } 

      // Creates the trust-manager factory. 
      tmf = javax.net.ssl.TrustManagerFactory.getInstance(getTrustManagerAlgorithm()); 
      tmf.init(trustStore); 
     } 

     SecureRandom sr = null; 

     if (getSecureRandomAlgorithm() != null) { 
      sr = SecureRandom.getInstance(getSecureRandomAlgorithm()); 
     } 

     this._context.init(kmf != null ? kmf.getKeyManagers() : null, 
       tmf != null ? tmf.getTrustManagers() : null, sr); 

    } 

} 

this helps rufen Sie einfach an!

Verwandte Themen