htp #20214 more docs on https context configuring
This commit is contained in:
parent
4750698a03
commit
6e1b32e6ea
11 changed files with 240 additions and 32 deletions
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
|
||||
*/
|
||||
|
||||
package docs.http.javadsl;
|
||||
|
||||
import akka.actor.AbstractActor;
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.http.javadsl.*;
|
||||
import akka.http.javadsl.model.HttpRequest;
|
||||
import akka.http.javadsl.model.HttpResponse;
|
||||
import akka.japi.Pair;
|
||||
import akka.japi.pf.ReceiveBuilder;
|
||||
import akka.stream.ActorMaterializer;
|
||||
import akka.stream.Materializer;
|
||||
import akka.stream.javadsl.Flow;
|
||||
import akka.stream.javadsl.Sink;
|
||||
import akka.stream.javadsl.Source;
|
||||
import com.typesafe.sslconfig.akka.AkkaSSLConfig;
|
||||
import scala.concurrent.ExecutionContextExecutor;
|
||||
import scala.util.Try;
|
||||
|
||||
import java.util.concurrent.CompletionStage;
|
||||
|
||||
import static akka.http.javadsl.ConnectHttp.toHost;
|
||||
import static akka.pattern.PatternsCS.pipe;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class HttpsExamplesDocTest {
|
||||
|
||||
// compile only test
|
||||
public void testConstructRequest() {
|
||||
String unsafeHost = "example.com";
|
||||
//#disable-sni-connection
|
||||
final ActorSystem system = ActorSystem.create();
|
||||
final ActorMaterializer mat = ActorMaterializer.create(system);
|
||||
final Http http = Http.get(system);
|
||||
|
||||
// WARNING: disabling SNI is a very bad idea, please don't unless you have a very good reason to.
|
||||
final AkkaSSLConfig defaultSSLConfig = AkkaSSLConfig.get(system);
|
||||
final AkkaSSLConfig badSslConfig = defaultSSLConfig
|
||||
.convertSettings(s -> s.withLoose(s.loose().withDisableSNI(true)));
|
||||
final HttpsConnectionContext badCtx = http.createClientHttpsContext(badSslConfig);
|
||||
|
||||
http.outgoingConnection(ConnectHttp.toHostHttps(unsafeHost).withCustomHttpsContext(badCtx));
|
||||
//#disable-sni-connection
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -45,8 +45,33 @@ to rely on the configured default client-side ``HttpsContext``.
|
|||
If no custom ``HttpsContext`` is defined the default context uses Java's default TLS settings. Customizing the
|
||||
``HttpsContext`` can make the Https client less secure. Understand what you are doing!
|
||||
|
||||
Detailed configuration and workarounds
|
||||
--------------------------------------
|
||||
|
||||
Akka HTTP relies on `Typesafe SSL-Config`_ which is a library maintained by Lightbend that makes configuring
|
||||
things related to SSL/TLS much simpler than using the raw SSL APIs provided by the JDK. Please refer to its
|
||||
documentation to learn more about it.
|
||||
|
||||
All configuration options available to this library may be set under the ``akka.ssl-context`` configuration for Akka HTTP applications.
|
||||
|
||||
.. note::
|
||||
When encountering problems connecting to HTTPS hosts we highly encourage to reading up on the excellent ssl-config
|
||||
configuration. Especially the quick start sections about `adding certificates to the trust store`_ should prove
|
||||
very useful, for example to easily trust a self-signed certificate that applications might use in development mode.
|
||||
|
||||
.. warning::
|
||||
While it is possible to disable certain checks using the so called "loose" settings in SSL Config, we **strongly recommend**
|
||||
to instead attempt to solve these issues by properly configuring TLS–for example by adding trusted keys to the keystore.
|
||||
|
||||
If however certain checks really need to be disabled because of misconfigured (or legacy) servers that your
|
||||
application has to speak to, instead of disabling the checks globally (i.e. in ``application.conf``) we suggest
|
||||
configuring the loose settings for *specific connections* that are known to need them disabled (and trusted for some other reason).
|
||||
The pattern of doing so is documented in the folowing sub-sections.
|
||||
|
||||
.. _adding certificates to the trust store: http://typesafehub.github.io/ssl-config/WSQuickStart.html#connecting-to-a-remote-server-over-https
|
||||
|
||||
Hostname verification
|
||||
---------------------
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Hostname verification proves that the Akka HTTP client is actually communicating with the server it intended to
|
||||
communicate with. Without this check a man-in-the-middle attack is possible. In the attack scenario, an alternative
|
||||
|
|
@ -57,9 +82,43 @@ The default ``HttpsContext`` enables hostname verification. Akka HTTP relies on
|
|||
to implement this and security options for SSL/TLS. Hostname verification is provided by the JDK
|
||||
and used by Akka HTTP since Java 7, and on Java 6 the verification is implemented by ssl-config manually.
|
||||
|
||||
.. note::
|
||||
We highly recommend updating your Java runtime to the latest available release,
|
||||
preferably JDK 8, as it includes this and many more security features related to TLS.
|
||||
For further recommended reading we would like to highlight the `fixing hostname verification blog post`_ by blog post by Will Sargent.
|
||||
|
||||
.. _Typesafe SSL-Config: https://github.com/typesafehub/ssl-config
|
||||
.. _Typesafe SSL-Config: http://typesafehub.github.io/ssl-config
|
||||
.. _fixing hostname verification blog post: https://tersesystems.com/2014/03/23/fixing-hostname-verification/
|
||||
.. _akka.http.javadsl.Http: @github@/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala
|
||||
|
||||
|
||||
Server Name Indication (SNI)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
SNI is an TLS extension which aims to guard against man-in-the-middle attacks. It does so by having the client send the
|
||||
name of the virtual domain it is expecting to talk to as part of the TLS handshake.
|
||||
|
||||
It is specified as part of `RFC 6066`_.
|
||||
|
||||
Disabling TLS security features, at your own risk
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. warning::
|
||||
It is highly discouraged to disable any of the security features of TLS, however do acknowlage that workarounds may sometimes be needed.
|
||||
|
||||
Before disabling any of the features one should consider if they may be solvable *within* the TLS world,
|
||||
for example by `trusting a certificate`_, or `configuring the trusted cipher suites`_.
|
||||
There's also a very important section in the ssl-config docs titled `LooseSSL - Please read this before turning anything off!`_.
|
||||
|
||||
If disabling features is indeed desired, we recommend doing so for *specific connections*,
|
||||
instead of globally configuring it via ``application.conf``.
|
||||
|
||||
The following shows an example of disabling SNI for a given connection:
|
||||
|
||||
.. includecode:: ../../code/docs/http/scaladsl/HttpsExamplesSpec.scala
|
||||
:include: disable-sni-connection
|
||||
|
||||
The ``badSslConfig`` is a copy of the default ``AkkaSSLConfig`` with with the slightly changed configuration to disable SNI.
|
||||
This value can be cached and used for connections which should indeed not use this feature.
|
||||
|
||||
.. _RFC 6066: https://tools.ietf.org/html/rfc6066#page-6
|
||||
.. _LooseSSL - Please read this before turning anything off!: http://typesafehub.github.io/ssl-config/LooseSSL.html#please-read-this-before-turning-anything-off
|
||||
.. _trusting a certificate: http://typesafehub.github.io/ssl-config/WSQuickStart.html
|
||||
.. _configuring the trusted cipher suites: http://typesafehub.github.io/ssl-config/CipherSuites.html
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
|
||||
*/
|
||||
|
||||
package docs.http.scaladsl
|
||||
|
||||
import akka.actor.{ ActorLogging, ActorSystem }
|
||||
import akka.http.scaladsl.Http
|
||||
import akka.stream.ActorMaterializer
|
||||
import akka.util.ByteString
|
||||
import com.typesafe.sslconfig.akka.AkkaSSLConfig
|
||||
import org.scalatest.{ Matchers, WordSpec }
|
||||
|
||||
class HttpsExamplesSpec extends WordSpec with Matchers {
|
||||
|
||||
"disable SNI for connection" in {
|
||||
pending // compile-time only test
|
||||
|
||||
val unsafeHost = "example.com"
|
||||
//#disable-sni-connection
|
||||
implicit val system = ActorSystem()
|
||||
implicit val mat = ActorMaterializer()
|
||||
|
||||
// WARNING: disabling SNI is a very bad idea, please don't unless you have a very good reason to.
|
||||
val badSslConfig = AkkaSSLConfig().mapSettings(s => s.withLoose(s.loose.withDisableSNI(true)))
|
||||
val badCtx = Http().createClientHttpsContext(badSslConfig)
|
||||
Http().outgoingConnectionHttps(unsafeHost, connectionContext = badCtx)
|
||||
//#disable-sni-connection
|
||||
}
|
||||
}
|
||||
|
|
@ -45,8 +45,33 @@ to rely on the configured default client-side ``HttpsContext``.
|
|||
If no custom ``HttpsContext`` is defined the default context uses Java's default TLS settings. Customizing the
|
||||
``HttpsContext`` can make the Https client less secure. Understand what you are doing!
|
||||
|
||||
Detailed configuration and workarounds
|
||||
--------------------------------------
|
||||
|
||||
Akka HTTP relies on `Typesafe SSL-Config`_ which is a library maintained by Lightbend that makes configuring
|
||||
things related to SSL/TLS much simpler than using the raw SSL APIs provided by the JDK. Please refer to its
|
||||
documentation to learn more about it.
|
||||
|
||||
All configuration options available to this library may be set under the ``akka.ssl-context`` configuration for Akka HTTP applications.
|
||||
|
||||
.. note::
|
||||
When encountering problems connecting to HTTPS hosts we highly encourage to reading up on the excellent ssl-config
|
||||
configuration. Especially the quick start sections about `adding certificates to the trust store`_ should prove
|
||||
very useful, for example to easily trust a self-signed certificate that applications might use in development mode.
|
||||
|
||||
.. warning::
|
||||
While it is possible to disable certain checks using the so called "loose" settings in SSL Config, we **strongly recommend**
|
||||
to instead attempt to solve these issues by properly configuring TLS–for example by adding trusted keys to the keystore.
|
||||
|
||||
If however certain checks really need to be disabled because of misconfigured (or legacy) servers that your
|
||||
application has to speak to, instead of disabling the checks globally (i.e. in ``application.conf``) we suggest
|
||||
configuring the loose settings for *specific connections* that are known to need them disabled (and trusted for some other reason).
|
||||
The pattern of doing so is documented in the folowing sub-sections.
|
||||
|
||||
.. _adding certificates to the trust store: http://typesafehub.github.io/ssl-config/WSQuickStart.html#connecting-to-a-remote-server-over-https
|
||||
|
||||
Hostname verification
|
||||
---------------------
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Hostname verification proves that the Akka HTTP client is actually communicating with the server it intended to
|
||||
communicate with. Without this check a man-in-the-middle attack is possible. In the attack scenario, an alternative
|
||||
|
|
@ -57,9 +82,40 @@ The default ``HttpsContext`` enables hostname verification. Akka HTTP relies on
|
|||
to implement this and security options for SSL/TLS. Hostname verification is provided by the JDK
|
||||
and used by Akka HTTP since Java 7, and on Java 6 the verification is implemented by ssl-config manually.
|
||||
|
||||
.. note::
|
||||
We highly recommend updating your Java runtime to the latest available release,
|
||||
preferably JDK 8, as it includes this and many more security features related to TLS.
|
||||
For further recommended reading we would like to highlight the `fixing hostname verification blog post`_ by blog post by Will Sargent.
|
||||
|
||||
.. _Typesafe SSL-Config: https://github.com/typesafehub/ssl-config
|
||||
.. _Typesafe SSL-Config: http://typesafehub.github.io/ssl-config
|
||||
.. _fixing hostname verification blog post: https://tersesystems.com/2014/03/23/fixing-hostname-verification/
|
||||
.. _akka.http.scaladsl.Http: @github@/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala
|
||||
|
||||
Server Name Indication (SNI)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
SNI is an TLS extension which aims to guard against man-in-the-middle attacks. It does so by having the client send the
|
||||
name of the virtual domain it is expecting to talk to as part of the TLS handshake.
|
||||
|
||||
It is specified as part of `RFC 6066`_.
|
||||
|
||||
Disabling TLS security features, at your own risk
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. warning::
|
||||
It is highly discouraged to disable any of the security features of TLS, however do acknowlage that workarounds may sometimes be needed.
|
||||
|
||||
Before disabling any of the features one should consider if they may be solvable *within* the TLS world,
|
||||
for example by `trusting a certificate`_, or `configuring the trusted cipher suites`_ etc.
|
||||
|
||||
If disabling features is indeed desired, we recommend doing so for *specific connections*,
|
||||
instead of globally configuring it via ``application.conf``.
|
||||
|
||||
The following shows an example of disabling SNI for a given connection:
|
||||
|
||||
.. includecode:: ../../code/docs/http/scaladsl/HttpsExamplesSpec.scala
|
||||
:include: disable-sni-connection
|
||||
|
||||
The ``badSslConfig`` is a copy of the default ``AkkaSSLConfig`` with with the slightly changed configuration to disable SNI.
|
||||
This value can be cached and used for connections which should indeed not use this feature.
|
||||
|
||||
.. _RFC 6066: https://tools.ietf.org/html/rfc6066#page-6
|
||||
.. _trusting a certificate: http://typesafehub.github.io/ssl-config/WSQuickStart.html
|
||||
.. _configuring the trusted cipher suites: http://typesafehub.github.io/ssl-config/CipherSuites.html
|
||||
|
|
@ -12,6 +12,7 @@ import scala.compat.java8.OptionConverters
|
|||
|
||||
object ConnectionContext {
|
||||
//#https-context-creation
|
||||
// ConnectionContext
|
||||
/** Used to serve HTTPS traffic. */
|
||||
def https(sslContext: SSLContext): HttpsConnectionContext =
|
||||
scaladsl.ConnectionContext.https(sslContext)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import akka.http.javadsl.model.ws._
|
|||
import akka.http.javadsl.settings.{ ConnectionPoolSettings, ClientConnectionSettings, ServerSettings }
|
||||
import akka.{ NotUsed, stream }
|
||||
import akka.stream.TLSProtocol._
|
||||
import com.typesafe.sslconfig.akka.AkkaSSLConfig
|
||||
import scala.concurrent.Future
|
||||
import scala.util.Try
|
||||
import akka.stream.scaladsl.Keep
|
||||
|
|
@ -657,6 +658,12 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension {
|
|||
def setDefaultClientHttpsContext(context: HttpsConnectionContext): Unit =
|
||||
delegate.setDefaultClientHttpsContext(context.asInstanceOf[akka.http.scaladsl.HttpsConnectionContext])
|
||||
|
||||
def createClientHttpsContext(sslConfig: AkkaSSLConfig): HttpsConnectionContext =
|
||||
delegate.createClientHttpsContext(sslConfig)
|
||||
|
||||
def createDefaultClientHttpsContext(): HttpsConnectionContext =
|
||||
delegate.createDefaultClientHttpsContext()
|
||||
|
||||
private def adaptTupleFlow[T, Mat](scalaFlow: stream.scaladsl.Flow[(scaladsl.model.HttpRequest, T), (Try[scaladsl.model.HttpResponse], T), Mat]): Flow[Pair[HttpRequest, T], Pair[Try[HttpResponse], T], Mat] = {
|
||||
implicit val _ = JavaMapping.identity[T]
|
||||
JavaMapping.toJava(scalaFlow)(JavaMapping.flowMapping[Pair[HttpRequest, T], (scaladsl.model.HttpRequest, T), Pair[Try[HttpResponse], T], (Try[scaladsl.model.HttpResponse], T), Mat])
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ trait ConnectionContext extends akka.http.javadsl.ConnectionContext {
|
|||
|
||||
object ConnectionContext {
|
||||
//#https-context-creation
|
||||
// ConnectionContext
|
||||
def https(sslContext: SSLContext,
|
||||
enabledCipherSuites: Option[immutable.Seq[String]] = None,
|
||||
enabledProtocols: Option[immutable.Seq[String]] = None,
|
||||
|
|
|
|||
|
|
@ -744,26 +744,27 @@ trait DefaultSSLContextCreation {
|
|||
private[this] def log = system.log
|
||||
|
||||
def validateAndWarnAboutLooseSettings() = {
|
||||
if (sslConfig.config.loose.disableHostnameVerification)
|
||||
log.warning("Detected that Hostname Verification (via ssl-config) is disabled globally for the Http extension! " +
|
||||
"This is very dangerous and may expose you to man-in-the-middle attacks. " +
|
||||
"If you are forced to interact with a server that is behaving such that you must disable this setting, " +
|
||||
"please disable it for a given connection instead, by configuring a specific HttpsConnectionContext " +
|
||||
"for use only for the trusted target that hostname verification would have blocked.")
|
||||
val WarningAboutGlobalLoose = "This is very dangerous and may expose you to man-in-the-middle attacks. " +
|
||||
"If you are forced to interact with a server that is behaving such that you must disable this setting, " +
|
||||
"please disable it for a given connection instead, by configuring a specific HttpsConnectionContext " +
|
||||
"for use only for the trusted target that hostname verification would have blocked."
|
||||
|
||||
if (sslConfig.config.loose.disableSNI)
|
||||
log.warning("Detected that Server Name Indication (SNI) is disabled globally (via ssl-config) for the Http extension! " +
|
||||
"This is very dangerous and may expose you to man-in-the-middle attacks. " +
|
||||
"If you are forced to interact with a server that is behaving such that you must disable this setting, " +
|
||||
"please disable it for a given connection instead, by configuring a specific HttpsConnectionContext " +
|
||||
"for use only for the trusted target that hostname verification would have blocked.")
|
||||
if (sslConfig.config.loose.disableHostnameVerification)
|
||||
log.warning("Detected that Hostname Verification is disabled globally (via ssl-config's akka.ssl-config.loose.disableHostnameVerification) for the Http extension! " +
|
||||
WarningAboutGlobalLoose)
|
||||
|
||||
if (sslConfig.config.loose.disableSNI) {
|
||||
log.warning("Detected that Server Name Indication (SNI) is disabled globally (via ssl-config's akka.ssl-config.loose.disableSNI) for the Http extension! " +
|
||||
WarningAboutGlobalLoose)
|
||||
|
||||
}
|
||||
}
|
||||
// --- end of log warnings ---
|
||||
|
||||
final def createDefaultClientHttpsContext(): HttpsConnectionContext =
|
||||
createDefaultClientHttpsContext(sslConfig)
|
||||
def createDefaultClientHttpsContext(): HttpsConnectionContext =
|
||||
createClientHttpsContext(sslConfig)
|
||||
|
||||
def createDefaultClientHttpsContext(sslConfig: AkkaSSLConfig): HttpsConnectionContext = {
|
||||
def createClientHttpsContext(sslConfig: AkkaSSLConfig): HttpsConnectionContext = {
|
||||
val config = sslConfig.config
|
||||
|
||||
val log = Logging(system, getClass)
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import akka.event.Logging
|
|||
import akka.http.scaladsl.model.HttpMethods._
|
||||
import akka.http.scaladsl.model._
|
||||
import akka.stream.ActorMaterializer
|
||||
import akka.testkit.{EventFilter, TestKit, TestProbe}
|
||||
import com.typesafe.config.{Config, ConfigFactory}
|
||||
import org.scalatest.{Matchers, WordSpec}
|
||||
import akka.testkit.{ EventFilter, TestKit, TestProbe }
|
||||
import com.typesafe.config.{ Config, ConfigFactory }
|
||||
import org.scalatest.{ Matchers, WordSpec }
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
|
|
@ -40,12 +40,12 @@ class SslConfigWarningsSpec extends WordSpec with Matchers {
|
|||
val p = TestProbe()
|
||||
system.eventStream.subscribe(p.ref, classOf[Logging.LogEvent])
|
||||
|
||||
EventFilter.warning(start = "Detected that Server Name Indication (SNI) is disabled globally", occurrences = 1) intercept {
|
||||
EventFilter.warning(start = "Detected that Server Name Indication (SNI) is disabled globally ", occurrences = 1) intercept {
|
||||
Http()(system)
|
||||
}
|
||||
|
||||
// the very big warning shall be logged only once per actor system (extension)
|
||||
EventFilter.warning(start = "Detected that Server Name Indication (SNI) is disabled globally", occurrences = 0) intercept {
|
||||
EventFilter.warning(start = "Detected that Server Name Indication (SNI) is disabled globally ", occurrences = 0) intercept {
|
||||
Http()(system)
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ class SslConfigWarningsSpec extends WordSpec with Matchers {
|
|||
val p = TestProbe()
|
||||
system.eventStream.subscribe(p.ref, classOf[Logging.LogEvent])
|
||||
|
||||
val msgStart = "Detected that Hostname Verification (via ssl-config) is disabled globally for the Http extension"
|
||||
val msgStart = "Detected that Hostname Verification is disabled globally "
|
||||
|
||||
EventFilter.warning(start = msgStart, occurrences = 1) intercept { Http()(system) }
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ object Dependencies {
|
|||
val reactiveStreams = "org.reactivestreams" % "reactive-streams" % "1.0.0" // CC0
|
||||
|
||||
// ssl-config
|
||||
val sslConfigAkka = "com.typesafe" %% "ssl-config-akka" % "0.2.0" // ApacheV2
|
||||
val sslConfigAkka = "com.typesafe" %% "ssl-config-akka" % "0.2.1" // ApacheV2
|
||||
|
||||
// For akka-http spray-json support
|
||||
val sprayJson = "io.spray" %% "spray-json" % "1.3.2" // ApacheV2
|
||||
|
|
|
|||
|
|
@ -716,6 +716,10 @@ object MiMa extends AutoPlugin {
|
|||
// #19390 Add flow monitor
|
||||
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.stream.scaladsl.FlowOpsMat.monitor"),
|
||||
|
||||
// #20214
|
||||
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.http.scaladsl.DefaultSSLContextCreation.createClientHttpsContext"),
|
||||
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.http.scaladsl.DefaultSSLContextCreation.validateAndWarnAboutLooseSettings"),
|
||||
|
||||
// #20080, #20081 remove race condition on HTTP client
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.http.scaladsl.Http#HostConnectionPool.gatewayFuture"),
|
||||
ProblemFilters.exclude[IncompatibleMethTypeProblem]("akka.http.scaladsl.Http#HostConnectionPool.copy"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue