Акка HTTPS (SSL) сервер с ssl-conf

Акка Версия:

Акка 2.4.7

Акка Особенности:

Поддержка HTTPS-сервера

Ssl-config Typesafe

язык: Scala

Я использую функцию Http Server в Akka 2.4.7, чтобы обеспечить несколькоHTTPS сервисные соединения на разных портах. На этом этапе требуется, чтобы этот компонент системы-актера размещал несколько служб HTTPS в одной JVM - это серверная часть, которая соединяет и интегрирует другие службы.

Вопрос:

Я хочу использоватьSsl-config Typesafe библиотека для настройки каждого HTTPS-сервера. Как мне это сделать(Я безуспешен в моих попытках)?

Что я пробовал:

Для каждого сервиса я определил блоки конфигурации ssl-config в application.conf. Пример следующей конфигурации:

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"}
        ]
      }
    }
  }
}

Я беру эту часть конфига с использованием пути HOCON длямоя-служба определяется вapplication.conf и объедините его с эталонной конфигурацией по умолчанию, чтобы создать SSLConfigSettings.

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

Теперь, имея SSLConfigSettings, я теперь могу создатьAkkaSSLConfig объект, который, в свою очередь, вАкка 2.4.7, может быть использован для созданияHttpsConnectionContext используя прототип функции:

// # https-context-creation // ConnectionContext def https (sslContext: SSLContext, sslConfig: Option [AkkaSSLConfig] = Нет, enabledCipherSuites: Option [immutable.Seq [String]] = Нет, enabledProtocols: Option [immutable.Seq [String] ]] = Нет, clientAuth: Option [TLSClientAuth] = Нет, sslParameters: Option [SSLParameters] = Нет) = новый HttpsConnectionContext (sslContext, sslConfig, enabledCipherSuites, enabledProtocols, clientAuth, context-sslParameters) // # https

Просто я могу запустить HTTPS-сервер с кодом, подобным следующему(примечание: запрос на определение определяется в другом месте, предоставляяFuture[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()

Сервер запускается без исключений или ошибок и связывается с127.0.0.1 на определенный порт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]

Я получаю доступ к серверу с помощью браузера или скручивания, и результат не очень хороший. Он запрашивает сертификат клиента, который, как я знаю, неверен, поскольку я явно настроил в ssl-conf, что они не нужны, и ssl-conf в JDK8 устанавливает для этого значение по умолчанию.

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

Дальнейшее расследование сOpenSSL с параметром _s_client_ показывает, что рукопожатие SSL не происходит и сертификаты не возвращаются, несмотря на то, что хранилище ключей исправно и работает в другом месте.

 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
---

Журнал Akka в режиме отладки не показывает исключений, и что установлено соединение TCP, субъект TLS запускается, а затем немедленно останавливается.

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

Отладка во время выполнения показывает, что хранилище ключей извлекается:

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

Что работает, если я создаю HttpsConnectionContext вручную и не использую ssl-conf или AkkaSSLConfig - но это не цель. Как настроить и создать соединение конфигурации HTTPS с использованием объекта AkkaSSLconf и библиотеки Typesafe ssl-config?

ОБНОВЛЕНИЕ 1:

Если я специально прошуTLS&nbsp;экземпляр контекста TLS, как это:

val sslCtx = SSLContext.getInstance("TLS")

Я получаю исключение, что sslContext не инициализирован. Ноinit&nbsp;SSLContext, мне нужно создать хранилище ключей, хранилище доверенных сертификатов, которое все в порядке, но мне кажется, что я игнорирую все достоинства библиотеки ssl-conf, в которой все эти вещи уже определены.

Обновление 2:

Я обнаружил, что вы можете создать контекст подключения HTTPS с помощью следующего метода:

Http().createServerHttpsContext(akkaSSLConfig)

Вы можете создать контекст HTTPS-сервера, используя AkkaSSLConfig, и это то, что мне нужно. Проблема в тестировании HTTPS-сервера не работает, он просто зависает на 1 минуту, за исключением:

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)

Я посмотрел на источник для createServerHttpsContext в репо Akka на GitHubВот&nbsp;и нашел:

  // 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)
  }

Почему сервер HTTPS не работает сcreateServerHttpsContext(..)? Особенно учитывая, что вручную вы в основном устанавливаете TLS SSLContext, KeyManagerFactory(с ключевыми магазинами), экземпляр SecureRandom и пошли.