From b14b90009b3abfa0ef3b7ae9ec60c84bcf60ab55 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Tue, 3 Aug 2021 09:51:42 +0200 Subject: [PATCH 1/6] ssl-config-core 0.5.0 (was 0.4.3) --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index a08d6d45..fe6b4cfd 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -34,7 +34,7 @@ object Dependencies { val javaxInject = Seq("javax.inject" % "javax.inject" % "1") - val sslConfigCore = Seq("com.typesafe" %% "ssl-config-core" % "0.4.3") + val sslConfigCore = Seq("com.typesafe" %% "ssl-config-core" % "0.5.0") val scalaXml = Seq("org.scala-lang.modules" %% "scala-xml" % "2.0.0") From c18defba90029871ece901bcd322fd008255d7c2 Mon Sep 17 00:00:00 2001 From: Matthias Kurz Date: Tue, 3 Aug 2021 21:20:23 +0200 Subject: [PATCH 2/6] ssl-config 0.6.0 + cachecontrol 2.1.0 --- project/Dependencies.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index fe6b4cfd..cd39cf40 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -34,13 +34,13 @@ object Dependencies { val javaxInject = Seq("javax.inject" % "javax.inject" % "1") - val sslConfigCore = Seq("com.typesafe" %% "ssl-config-core" % "0.5.0") + val sslConfigCore = Seq("com.typesafe" %% "ssl-config-core" % "0.6.0") val scalaXml = Seq("org.scala-lang.modules" %% "scala-xml" % "2.0.0") val oauth = Seq("oauth.signpost" % "signpost-core" % "2.1.1") - val cachecontrol = Seq("com.typesafe.play" %% "cachecontrol" % "2.0.0") + val cachecontrol = Seq("com.typesafe.play" %% "cachecontrol" % "2.1.0") val asyncHttpClient = Seq("org.asynchttpclient" % "async-http-client" % "2.12.3") From a2a5d06764ef5be644bfd198fc7dd21494fa7476 Mon Sep 17 00:00:00 2001 From: Will Sargent Date: Mon, 9 Aug 2021 22:50:57 -0700 Subject: [PATCH 3/6] Remove useless specs --- .../play/api/libs/ws/ahc/AhcConfig.scala | 55 +------- .../libs/ws/ahc/AhcConfigBuilderSpec.scala | 118 ------------------ project/Dependencies.scala | 2 +- 3 files changed, 2 insertions(+), 173 deletions(-) diff --git a/play-ahc-ws-standalone/src/main/scala/play/api/libs/ws/ahc/AhcConfig.scala b/play-ahc-ws-standalone/src/main/scala/play/api/libs/ws/ahc/AhcConfig.scala index 8acb724e..caf7daea 100644 --- a/play-ahc-ws-standalone/src/main/scala/play/api/libs/ws/ahc/AhcConfig.scala +++ b/play-ahc-ws-standalone/src/main/scala/play/api/libs/ws/ahc/AhcConfig.scala @@ -4,8 +4,6 @@ package play.api.libs.ws.ahc -import java.security.KeyStore -import java.security.cert.CertPathValidatorException import javax.inject.Inject import javax.inject.Provider import javax.inject.Singleton @@ -248,14 +246,6 @@ class AhcConfigBuilder(ahcConfig: AhcWSClientConfig = AhcWSClientConfig()) { Protocols.recommendedProtocols.filter(existingProtocols.contains).toArray } - if (!sslConfig.loose.allowWeakProtocols) { - val deprecatedProtocols = Protocols.deprecatedProtocols - for (deprecatedProtocol <- deprecatedProtocols) { - if (definedProtocols.contains(deprecatedProtocol)) { - throw new IllegalStateException(s"Weak protocol $deprecatedProtocol found in ws.ssl.protocols!") - } - } - } definedProtocols } @@ -266,17 +256,9 @@ class AhcConfigBuilder(ahcConfig: AhcWSClientConfig = AhcWSClientConfig()) { configuredCiphers.filter(existingCiphers.contains(_)).toArray case None => - Ciphers.recommendedCiphers.filter(existingCiphers.contains(_)).toArray + existingCiphers } - if (!sslConfig.loose.allowWeakCiphers) { - val deprecatedCiphers = Ciphers.deprecatedCiphers - for (deprecatedCipher <- deprecatedCiphers) { - if (definedCiphers.contains(deprecatedCipher)) { - throw new IllegalStateException(s"Weak cipher $deprecatedCipher found in ws.ssl.ciphers!") - } - } - } definedCiphers } @@ -288,7 +270,6 @@ class AhcConfigBuilder(ahcConfig: AhcWSClientConfig = AhcWSClientConfig()) { // context! val sslContext = if (sslConfig.default) { logger.info("buildSSLContext: play.ws.ssl.default is true, using default SSLContext") - validateDefaultTrustManager(sslConfig) SSLContext.getDefault } else { // break out the static methods as much as we can... @@ -328,38 +309,4 @@ class AhcConfigBuilder(ahcConfig: AhcWSClientConfig = AhcWSClientConfig()) { def buildTrustManagerFactory(ssl: SSLConfigSettings): TrustManagerFactoryWrapper = { new DefaultTrustManagerFactoryWrapper(ssl.trustManagerConfig.algorithm) } - - def validateDefaultTrustManager(sslConfig: SSLConfigSettings): Unit = { - // If we are using a default SSL context, we can't filter out certificates with weak algorithms - // We ALSO don't have access to the trust manager from the SSLContext without doing horrible things - // with reflection. - // - // However, given that the default SSLContextImpl will call out to the TrustManagerFactory and any - // configuration with system properties will also apply with the factory, we can use the factory - // method to recreate the trust manager and validate the trust certificates that way. - // - // This is really a last ditch attempt to satisfy https://wiki.mozilla.org/CA:MD5and1024 on root certificates. - // - // http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/sun/security/ssl/SSLContextImpl.java#79 - - val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm) - tmf.init(null.asInstanceOf[KeyStore]) - val trustManager: X509TrustManager = tmf.getTrustManagers()(0).asInstanceOf[X509TrustManager] - - val constraints = sslConfig.disabledKeyAlgorithms - .map(a => AlgorithmConstraintsParser.parseAll(AlgorithmConstraintsParser.expression, a).get) - .toSet - val algorithmChecker = new AlgorithmChecker(loggerFactory, Set(), constraints) - for (cert <- trustManager.getAcceptedIssuers) { - try { - algorithmChecker.checkKeyAlgorithms(cert) - } catch { - case e: CertPathValidatorException => - logger.warn( - "You are using play.ws.ssl.default=true and have a weak certificate in your default trust store! (You can modify play.ws.ssl.disabledKeyAlgorithms to remove this message.)", - e - ) - } - } - } } diff --git a/play-ahc-ws-standalone/src/test/scala/play/api/libs/ws/ahc/AhcConfigBuilderSpec.scala b/play-ahc-ws-standalone/src/test/scala/play/api/libs/ws/ahc/AhcConfigBuilderSpec.scala index 3ecd86ce..17132dc7 100644 --- a/play-ahc-ws-standalone/src/test/scala/play/api/libs/ws/ahc/AhcConfigBuilderSpec.scala +++ b/play-ahc-ws-standalone/src/test/scala/play/api/libs/ws/ahc/AhcConfigBuilderSpec.scala @@ -6,7 +6,6 @@ package play.api.libs.ws.ahc import com.typesafe.config.Config import com.typesafe.config.ConfigFactory -import com.typesafe.sslconfig.ssl.Ciphers import com.typesafe.sslconfig.ssl.Protocols import com.typesafe.sslconfig.ssl.SSLConfigFactory import com.typesafe.sslconfig.ssl.SSLConfigSettings @@ -58,7 +57,6 @@ class AhcConfigBuilderSpec extends Specification with Mockito { actual.isFollowRedirect must_== defaultWsConfig.followRedirects actual.getCookieStore must_== null - actual.getEnabledCipherSuites.toSeq must not contain Ciphers.deprecatedCiphers actual.getEnabledProtocols.toSeq must not contain Protocols.deprecatedProtocols } @@ -189,48 +187,6 @@ class AhcConfigBuilderSpec extends Specification with Mockito { asyncClientConfig.getSslEngineFactory must not(beNull) } - "use the default with a current certificate" in { - // You can't get the value of SSLContext out from the JSSE SSL engine factory, so - // checking SSLContext.getDefault from a default = true is hard. - // Unless we can mock this, it doesn't seem like it's easy to unit test. - pending("AHC 2.0 does not provide a reference to a configured SSLContext") - - //val tmc = TrustManagerConfig() - //val wsConfig = defaultWsConfig.copy(ssl = SSLConfig(default = true, trustManagerConfig = tmc)) - //val config = defaultConfig.copy(wsClientConfig = wsConfig) - //val builder = new AhcConfigBuilder(config) - // - //val asyncClientConfig = builder.build() - //val sslEngineFactory = asyncClientConfig.getSslEngineFactory - } - - "log a warning if sslConfig.default is passed in with an weak certificate" in { - import scala.collection.JavaConverters._ - // Pass in a configuration which is guaranteed to fail, by banning RSA, DSA and EC certificates - val underlyingConfig = parseSSLConfig(""" - |play.ws.ssl.default=true - |play.ws.ssl.disabledKeyAlgorithms=["RSA", "DSA", "EC"] - """.stripMargin) - val sslConfigSettings = SSLConfigFactory.parse(underlyingConfig) - - val wsConfig = defaultWsConfig.copy(ssl = sslConfigSettings) - val config = defaultConfig.copy(wsClientConfig = wsConfig) - - // clear the logger of any messages... - TestLoggerFactory.clear() - val builder = new AhcConfigBuilder(config) - - // Run method that will trigger the logger warning - builder.configureSSL(sslConfig = sslConfigSettings) - - val loggerFactory = TestLoggerFactory.getInstance() - val logger = loggerFactory.getLogger(builder.getClass) - val messages = logger.getLoggingEvents.asList().asScala.map(_.getMessage) - messages must contain( - "You are using play.ws.ssl.default=true and have a weak certificate in your default trust store! (You can modify play.ws.ssl.disabledKeyAlgorithms to remove this message.)" - ) - } - "should validate certificates" in { val sslConfig = SSLConfigSettings() val wsConfig = defaultWsConfig.copy(ssl = sslConfig) @@ -279,47 +235,6 @@ class AhcConfigBuilderSpec extends Specification with Mockito { actual.toSeq must containTheSameElementsAs(Seq("derp", "baz", "quux")) } - - "throw exception on deprecated protocols from explicit list" in { - val deprecatedProtocol = Protocols.deprecatedProtocols.head - - // the enabled protocol list has a deprecated protocol in it. - val underlyingConfig = - parseSSLConfig(s"""play.ws.ssl.enabledProtocols=["$deprecatedProtocol", "goodOne", "goodTwo"]""") - val sslConfig = SSLConfigFactory.parse(underlyingConfig) - val wsConfig = defaultWsConfig.copy(ssl = sslConfig) - val config = defaultConfig.copy(wsClientConfig = wsConfig) - - val builder = new AhcConfigBuilder(config) - - // The existing protocols is larger than the enabled list, and out of order. - val existingProtocols = Array("goodTwo", "badOne", "badTwo", deprecatedProtocol, "goodOne") - - builder.configureProtocols(existingProtocols, sslConfig).must(throwAn[IllegalStateException]) - } - - "not throw exception on deprecated protocols from list if allowWeakProtocols is enabled" in { - val deprecatedProtocol = Protocols.deprecatedProtocols.head - - // the enabled protocol list has a deprecated protocol in it. - val underlyingConfig = parseSSLConfig(s""" - |play.ws.ssl.enabledProtocols=["$deprecatedProtocol", "goodOne", "goodTwo"] - |play.ws.ssl.loose.allowWeakProtocols=true - """.stripMargin) - val sslConfig = SSLConfigFactory.parse(underlyingConfig) - val wsConfig = defaultWsConfig.copy(ssl = sslConfig) - val config = defaultConfig.copy(wsClientConfig = wsConfig) - - val builder = new AhcConfigBuilder(config) - - // The existing protocols is larger than the enabled list, and out of order. - val existingProtocols = Array("goodTwo", "badOne", "badTwo", deprecatedProtocol, "goodOne") - - val actual = builder.configureProtocols(existingProtocols, sslConfig) - - // We should only have the list in order, including the deprecated protocol. - actual.toSeq must containTheSameElementsAs(Seq(deprecatedProtocol, "goodOne", "goodTwo")) - } } "with ciphers" should { @@ -336,39 +251,6 @@ class AhcConfigBuilderSpec extends Specification with Mockito { actual.toSeq must containTheSameElementsAs(Seq("goodone", "goodtwo")) } - - "throw exception on deprecated ciphers from the explicit cipher list" in { - val underlyingConfig = parseSSLConfig( - s"""play.ws.ssl.enabledCipherSuites=[${Ciphers.deprecatedCiphers.head}, "goodone", "goodtwo"]""" - ) - val enabledCiphers = Seq(Ciphers.deprecatedCiphers.head, "goodone", "goodtwo") - val sslConfig = SSLConfigFactory.parse(underlyingConfig) - val wsConfig = defaultWsConfig.copy(ssl = sslConfig) - val config = defaultConfig.copy(wsClientConfig = wsConfig) - val builder = new AhcConfigBuilder(config) - val existingCiphers = enabledCiphers.toArray - - builder.configureCipherSuites(existingCiphers, sslConfig).must(throwAn[IllegalStateException]) - } - - "not throw exception on deprecated ciphers if allowWeakCiphers is enabled" in { - // User specifies list with deprecated ciphers... - val underlyingConfig = parseSSLConfig(""" - |play.ws.ssl.enabledCipherSuites=[badone, "goodone", "goodtwo"] - |play.ws.ssl.loose.allowWeakCiphers=true - """.stripMargin) - - val sslConfig = SSLConfigFactory.parse(underlyingConfig) - val wsConfig = defaultWsConfig.copy(ssl = sslConfig) - val config = defaultConfig.copy(wsClientConfig = wsConfig) - val builder = new AhcConfigBuilder(config) - val existingCiphers = Array("badone", "goodone", "goodtwo") - - val actual = builder.configureCipherSuites(existingCiphers, sslConfig) - - actual.toSeq must containTheSameElementsAs(Seq("badone", "goodone", "goodtwo")) - } - } } } diff --git a/project/Dependencies.scala b/project/Dependencies.scala index d4a0ee83..88c9dea8 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -45,7 +45,7 @@ object Dependencies { val asyncHttpClient = Seq("org.asynchttpclient" % "async-http-client" % "2.12.3") val akkaStreams = Seq("com.typesafe.akka" %% "akka-stream" % "2.6.15") - val akkaHttp = Seq("com.typesafe.akka" %% "akka-http" % "10.1.14") + val akkaHttp = Seq("com.typesafe.akka" %% "akka-http" % "10.2.4") val reactiveStreams = Seq("org.reactivestreams" % "reactive-streams" % "1.0.3") From 21b95fb4aa31872c21c9e5da84be4f47c68ec672 Mon Sep 17 00:00:00 2001 From: Matthias Kurz Date: Tue, 10 Aug 2021 11:00:17 +0200 Subject: [PATCH 4/6] Make MiMa happy --- build.sbt | 1 + 1 file changed, 1 insertion(+) diff --git a/build.sbt b/build.sbt index cdf68389..c9ad6d33 100644 --- a/build.sbt +++ b/build.sbt @@ -56,6 +56,7 @@ lazy val mimaSettings = Seq( ), // these exclusions are only for main branch and are targeting 2.2.x mimaBinaryIssueFilters ++= Seq( + ProblemFilters.exclude[DirectMissingMethodProblem]("play.api.libs.ws.ahc.AhcConfigBuilder.validateDefaultTrustManager"), ProblemFilters.exclude[MissingTypesProblem]("play.api.libs.ws.ahc.AhcWSClientConfig$"), ProblemFilters.exclude[IncompatibleResultTypeProblem]("play.api.libs.ws.ahc.AhcWSClientConfig.$default$6"), ProblemFilters.exclude[IncompatibleResultTypeProblem]("play.api.libs.ws.ahc.AhcWSClientConfig.$default$8"), From 33d2d33d315f408150ae44ffca53ba524077af73 Mon Sep 17 00:00:00 2001 From: Matthias Kurz Date: Tue, 10 Aug 2021 11:00:30 +0200 Subject: [PATCH 5/6] akka-http 10.2.6 --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 88c9dea8..9db2ac02 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -45,7 +45,7 @@ object Dependencies { val asyncHttpClient = Seq("org.asynchttpclient" % "async-http-client" % "2.12.3") val akkaStreams = Seq("com.typesafe.akka" %% "akka-stream" % "2.6.15") - val akkaHttp = Seq("com.typesafe.akka" %% "akka-http" % "10.2.4") + val akkaHttp = Seq("com.typesafe.akka" %% "akka-http" % "10.2.6") val reactiveStreams = Seq("org.reactivestreams" % "reactive-streams" % "1.0.3") From dfe3ea0fd7edd90781a10828f34364c161938814 Mon Sep 17 00:00:00 2001 From: Will Sargent Date: Wed, 11 Aug 2021 08:21:21 -0700 Subject: [PATCH 6/6] remove unused import --- .../test/scala/play/api/libs/ws/ahc/AhcConfigBuilderSpec.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/play-ahc-ws-standalone/src/test/scala/play/api/libs/ws/ahc/AhcConfigBuilderSpec.scala b/play-ahc-ws-standalone/src/test/scala/play/api/libs/ws/ahc/AhcConfigBuilderSpec.scala index 17132dc7..20251303 100644 --- a/play-ahc-ws-standalone/src/test/scala/play/api/libs/ws/ahc/AhcConfigBuilderSpec.scala +++ b/play-ahc-ws-standalone/src/test/scala/play/api/libs/ws/ahc/AhcConfigBuilderSpec.scala @@ -14,7 +14,6 @@ import org.specs2.mutable.Specification import play.api.libs.ws.WSClientConfig import play.shaded.ahc.org.asynchttpclient.proxy.ProxyServerSelector import play.shaded.ahc.org.asynchttpclient.util.ProxyUtils -import uk.org.lidalia.slf4jtest.TestLoggerFactory import scala.concurrent.duration._