Akka HTTPS (SSL) Server mit ssl-conf

Akka Version:

Akka 2.4.7

Akka Features:

HTTPS Server Support

Typesafe ssl-config

Sprach: Scala

Ich verwende die HTTP-Serverfunktion von Akka 2.4.7, um mehrere HTTPS Service-Verbindungen an verschiedenen Ports. In dieser Phase muss diese Komponente des Aktorsystems mehrere der HTTPS-Services in einer JVM hosten - es handelt sich um ein Backend, das andere Services verbindet und integriert.

Frag:

Ich möchte das @ verwend Typesafe ssl-config library, um jeden HTTPS-Server zu konfigurieren. Wie mache ich das (Ich bin bei meinen Versuchen erfolglos)?

Was ich versucht habe:

Für jeden Dienst habe ich in der application.conf ssl-config-Konfigurationsblöcke definiert. Ein Beispiel für eine nächste Konfiguration ist:

my-service {
  ssl-config = {
    debug {
      all = true
    }
    sslParameters {
      clientAuth : "none"
    }
    ssl = {
      keyManager = {
        stores = [
          {path: tmp/certs/autumn/devhost.jks, password: "not-real-password", type: "JKS"}
        ]
      }
    }
  }
}

Ich greife auf diesen Teil der Konfiguration zu, indem ich den HOCON-Pfad für @ verwend my-service definiert in application.conf und führen Sie es mit der Referenz-Standardkonfiguration zusammen, um eine SSLConfigSettings zu erstellen.

  def parseSslConfig(config: Config): SSLConfigSettings = {
    val cfg = config.withFallback(ConfigFactory.defaultReference().getConfig("ssl-config"))
    val parser = new SSLConfigParser(EnrichedConfig(cfg), getClass.getClassLoader)
    parser.parse()
  }

Nun mit einem SSLConfigSettings kann ich jetzt ein @ erstell AkkaSSLConfig Objekt, das wiederum inAkka 2.4.7, kann verwendet werden, um ein @ zu erstell HttpsConnectionContext mit dem Funktionsprototyp:

// # https-context-creation // ConnectionContext def https (sslContext: SSLContext, sslConfig: Option [AkkaSSLConfig] = Keine, enabledCipherSuites: Option [immutable.Seq [String]] = Keine, enabledProtocols: Option [immutable.Seq [ String]] = Keine, clientAuth: Option [TLSClientAuth] = Keine, sslParameters: Option [SSLParameters] = Keine) = Neu HttpsConnectionContext (sslContext, sslConfig, enabledCipherSuites, enabledProtocols, clientAuth, sslParameters) // # https-context-creation @ sslParamete

So kann ich einfach einen HTTPS-Server mit folgendem Code starten: (Hinweis: Der Request-Handler wird an einer anderen Stelle definiert, an der das @ angegeben wirFuture[HttpResponse])

val akkaSSLConfig: AkkaSSLConfig = AkkaSSLConfig().withSettings(sslConfigSettings)
val serverConnectionContext = ConnectionContext.https(SSLContext.getDefault, Some(akkaSSLConfig))

  val httpServer = httpServerSystem.bind(interface = "127.0.0.1",
    port = 8991,
    connectionContext = serverConnectionContext)

  val bindingFuture: Future[Http.ServerBinding] = httpServer.to(Sink.foreach {
    connection =>
      system.log.info(s"Accepted HTTP connection " +
        s"[Local: address=${connection.localAddress.getAddress.getHostAddress}, port=${connection.localAddress.getPort};" +
        s" Remote: address=${connection.remoteAddress.getAddress.getHostAddress} port=${connection.remoteAddress.getPort}]" + connection.remoteAddress)
      connection.handleWithAsyncHandler(httpRequest => requestHandler(httpRequest, connection.localAddress, connection.remoteAddress))
  }).run()

Der Server startet ausnahmslos oder fehlerfrei und bindet an 127.0.0.1 auf dem definierten Port 8991.

2016-06-11 14:07:51,403 DEBUG [autumn-backend-akka.actor.default-dispatcher-7] TcpListener - Successfully bound to /127.0.0.1:8991
2016-06-11 14:07:51,404 DEBUG [autumn-backend-akka.actor.default-dispatcher-7] TcpListener - started (akka.io.TcpListener@3d1d819f)
2016-06-11 14:07:51,404 DEBUG [autumn-backend-akka.actor.default-dispatcher-7] TcpListener - now watched by Actor[akka://autumn-backend/system/IO-TCP/selectors/$a#-745039521]
2016-06-11 14:07:51,407 DEBUG [autumn-backend-akka.actor.default-dispatcher-5] TcpListener - now watched by Actor[akka://autumn-backend/user/StreamSupervisor-0/$a#-672917867]

Ich greife über einen Browser oder eine Locke auf den Server zu und das Ergebnis ist nicht gut. Es wird nach einem Client-Zertifikat gefragt, von dem ich weiß, dass es falsch ist, da ich in ssl-conf explizit konfiguriert habe, dass sie nicht benötigt werden, und ssl-conf in JDK8 setzt dies auf nicht benötigt.

curl -v https://localhost:8991
* Rebuilt URL to: https://localhost:8991/
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8991 (#0)
* SSL peer handshake failed, the server most likely requires a client certificate to connect
* Closing connection 0
curl: (35) SSL peer handshake failed, the server most likely requires a client certificate to connect

Weitere Untersuchung mit openssl with _s_client_ option zeigt an, dass kein SSL-Handshake stattfindet und keine Zertifikate zurückgegeben werden, obwohl bekannt ist, dass der Keystore fehlerfrei ist und an anderer Stelle funktioniert.

 openssl s_client -showcerts -connect localhost:8991
CONNECTED(00000003)
140735299473488:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:769:
---
no peer certificate available

No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 317 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
---

Das Akka-Protokoll im Debug-Modus zeigt keine Ausnahmen an und dass eine TCP-Verbindung hergestellt wurde, ein TLS-Akteur startet und stoppt sofort.

2016-06-11 14:09:26,378 DEBUG [autumn-backend-akka.actor.default-dispatcher-6] TcpListener - New connection accepted
2016-06-11 14:09:26,378 DEBUG [autumn-backend-akka.actor.default-dispatcher-9] SelectionHandler - now supervising Actor[akka://autumn-backend/system/IO-TCP/selectors/$a/9#1252313265]
2016-06-11 14:09:26,378 DEBUG [autumn-backend-akka.actor.default-dispatcher-5] TcpIncomingConnection - started (akka.io.TcpIncomingConnection@6f12f120)
2016-06-11 14:09:26,378 DEBUG [autumn-backend-akka.actor.default-dispatcher-5] TcpIncomingConnection - now watched by Actor[akka://autumn-backend/system/IO-TCP/selectors/$a#-745039521]
2016-06-11 14:09:26,381 INFO  [autumn-backend-akka.actor.default-dispatcher-7] ActorSystemImpl - Accepted HTTP connection [Local: address=127.0.0.1, port=8991; Remote: address=127.0.0.1 port=58726]/127.0.0.1:58726
2016-06-11 14:09:26,384 DEBUG [autumn-backend-akka.actor.default-dispatcher-9] StreamSupervisor - now supervising Actor[akka://autumn-backend/user/StreamSupervisor-0/flow-9-0-unknown-operation#149184815]
2016-06-11 14:09:26,385 DEBUG [autumn-backend-akka.actor.default-dispatcher-7] TcpIncomingConnection - now watched by Actor[akka://autumn-backend/user/StreamSupervisor-0/$j#-1999211380]
2016-06-11 14:09:26,385 DEBUG [autumn-backend-akka.actor.default-dispatcher-9] ActorGraphInterpreter - started (akka.stream.impl.fusing.ActorGraphInterpreter@57451dc8)
2016-06-11 14:09:26,385 DEBUG [autumn-backend-akka.actor.default-dispatcher-5] StreamSupervisor - now supervising Actor[akka://autumn-backend/user/StreamSupervisor-0/flow-9-1-unknown-operation#1511230856]
sslConfig.config.loose.disableSNI = false
2016-06-11 14:09:26,387 DEBUG [autumn-backend-akka.actor.default-dispatcher-5] TLSActor - started (akka.stream.impl.io.TLSActor@50f220e8)
2016-06-11 14:09:26,389 DEBUG [autumn-backend-akka.actor.default-dispatcher-5] TLSActor - stopped

Debugging zur Laufzeit zeigt, dass der Keystore abgeholt wird:

akkaSSLConfig = {com.typesafe.sslconfig.akka.AkkaSSLConfig@7851} 
 system = {akka.actor.ActorSystemImpl@7850} "akka://autumn-backend"
 config = {com.typesafe.sslconfig.ssl.SSLConfigSettings@7849} "SSLConfig(None,SSLDebugConfig(false,false,false,None,false,false,false,false,None,false,false,false,false,false),false,Vector(RSA keySize < 2048, DSA keySize < 2048, EC keySize < 224),Vector(MD2, MD4, MD5),None,Some(Vector(TLSv1.2, TLSv1.1, TLSv1)),class com.typesafe.sslconfig.ssl.DefaultHostnameVerifier,KeyManagerConfig(SunX509,List(KeyStoreConfig(None,Some(config/certs/autumn/devhost.jks),Some(A8C7B78Ymb),JKS))),SSLLooseConfig(false,None,None,false,false,false,false),TLSv1.2,None,None,SSLParametersConfig(Default,Vector()),TrustManagerConfig(PKIX,List()))"
  default = false
  protocol = "TLSv1.2"
  checkRevocation = {scala.None$@7905} "None"
  revocationLists = {scala.None$@7905} "None"
  enabledCipherSuites = {scala.None$@7905} "None"
  enabledProtocols = {scala.Some@7906} "Some(Vector(TLSv1.2, TLSv1.1, TLSv1))"
  disabledSignatureAlgorithms = {scala.collection.immutable.Vector@7907} "Vector" size = 3
  disabledKeyAlgorithms = {scala.collection.immutable.Vector@7911} "Vector" size = 3
  sslParametersConfig = {com.typesafe.sslconfig.ssl.SSLParametersConfig@7917} "SSLParametersConfig(Default,Vector())"
  keyManagerConfig = {com.typesafe.sslconfig.ssl.KeyManagerConfig@7918} "KeyManagerConfig(SunX509,List(KeyStoreConfig(None,Some(config/certs/autumn/devhost.jks),Some(A8C7B78Ymb),JKS)))"
   algorithm = "SunX509"
   keyStoreConfigs = {scala.collection.immutable.$colon$colon@7942} "::" size = 1
    0 = {com.typesafe.sslconfig.ssl.KeyStoreConfig@9390} "KeyStoreConfig(None,Some(config/certs/autumn/devhost.jks),Some(not-real-password),JKS)"

Was funktioniert ist, wenn ich einen HttpsConnectionContext manuell erstelle und nicht ssl-conf oder AkkaSSLConfig verwende - aber das ist nicht das Ziel. Wie konfiguriere und erstelle ich eine HTTPS-Konfigurationsverbindung mit einem AkkaSSLconf-Objekt und der Typesafe ssl-config-Bibliothek?

UPDATE 1:

Wenn ich speziell nach einem @ fra TLS Instanz des TLS-Kontexts wie folgt:

val sslCtx = SSLContext.getInstance("TLS")

Ich erhalte die Ausnahme, dass der sslContext nicht initialisiert ist. Aber zuinitm SSLContext muss ich den Keystore, den Truststore, erstellen, der alles in Ordnung und in Ordnung ist, aber es scheint, als würde ich die Vorteile der ssl-conf-Bibliothek, in der all diese Dinge bereits definiert sind, ignoriere

Update 2:

Ich habe festgestellt, dass Sie den HTTPS-Verbindungskontext mit der folgenden Methode erstellen können:

Http().createServerHttpsContext(akkaSSLConfig)

Sie können den HTTPS-Serverkontext mithilfe von AkkaSSLConfig erstellen. Problem beim Testen, der HTTPS-Server funktioniert nicht, hängt nur 1 Minute mit der Ausnahme:

2016-06-12 11:14:53,222 DEBUG [autumn-backend-akka.actor.default-dispatcher-12] RepointableActorRef - Aborting tcp connection because of upstream failure: No elements passed in the last 1 minute.
akka.stream.impl.Timers$IdleTimeoutBidi$anon$7.onTimer(Timers.scala:160)
akka.stream.stage.TimerGraphStageLogic.akka$stream$stage$TimerGraphStageLogic$onInternalTimer(GraphStage.scala:1125)
akka.stream.stage.TimerGraphStageLogic$anonfun$akka$stream$stage$TimerGraphStageLogic$getTimerAsyncCallback$1.apply(GraphStage.scala:1114)
akka.stream.stage.TimerGraphStageLogic$anonfun$akka$stream$stage$TimerGraphStageLogic$getTimerAsyncCallback$1.apply(GraphStage.scala:1114)
akka.stream.impl.fusing.GraphInterpreter.runAsyncInput(GraphInterpreter.scala:572)
akka.stream.impl.fusing.GraphInterpreterShell.receive(ActorGraphInterpreter.scala:420)
akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$processEvent(ActorGraphInterpreter.scala:604)
akka.stream.impl.fusing.ActorGraphInterpreter$anonfun$receive$1.applyOrElse(ActorGraphInterpreter.scala:619)
akka.actor.Actor$class.aroundReceive(Actor.scala:484)

Ich habe die Quelle für createServerHttpsContext auf dem Akka-Repo auf GitHub angeschautHie und gefunden

  // currently the same configuration as client by default, however we should tune this for server-side apropriately (!)
  def createServerHttpsContext(sslConfig: AkkaSSLConfig): HttpsConnectionContext = {
    log.warning("Automatic server-side configuration is not supported yet, will attempt to use client-side settings. " +
      "Instead it is recommended to construct the Servers HttpsConnectionContext manually (via SSLContext).")
    createClientHttpsContext(sslConfig)
  }

Warum funktioniert der HTTPS-Server nicht mit demcreateServerHttpsContext(..)? Insbesondere, da Sie im Grunde genommen manuell einen TLS-SSLContext festlegen, KeyManagerFactory (mit Schlüsselspeichern), eine Instanz von SecureRandom und los geht's.

Antworten auf die Frage(6)

Ihre Antwort auf die Frage