I just want to skip the cert verification (basically the same as curl --insecure).
versions
: scala 2.12, akka-http 10.2.4
I have tried these but neither worked:
- https://gist.github.com/iRevive/4a3c7cb96374da5da80d4538f3da17cb
- https://doc.akka.io/docs/akka-http/current/client-side/client-https-support.html#disabling-hostname-verification
Custom SSLContext
implicit val system: ActorSystem[Nothing] = ActorSystem(Behaviors.empty, "SingleRequest")
implicit val executionContext: ExecutionContextExecutor = system.executionContext
val noCertificateCheckContext = ConnectionContext.https(trustfulSslContext)
private val trustfulSslContext: SSLContext = {
object NoCheckX509TrustManager extends X509TrustManager {
override def checkClientTrusted(chain: Array[X509Certificate], authType: String) = ()
override def checkServerTrusted(chain: Array[X509Certificate], authType: String) = ()
override def getAcceptedIssuers = Array[X509Certificate]()
}
val context = SSLContext.getInstance("TLS")
context.init(Array[KeyManager](), Array(NoCheckX509TrustManager), null)
context
}
val res = Await.result(Http().singleRequest(Get(url), noCertificateCheckContext), 60 seconds)
Result:
java.util.concurrent.TimeoutException: Futures timed out after [60 seconds]
Following the official doc:
implicit val system: ActorSystem[Nothing] = ActorSystem(Behaviors.empty,"SingleRequest")
implicit val executionContext: ExecutionContextExecutor = system.executionContext
val noCertificateCheckContext = ConnectionContext.httpsClient(getConnection _)
def getConnection(host: String, port: Int): SSLEngine = {
val engine = SSLContext.getDefault.createSSLEngine(host,port)
engine.setUseClientMode(true)
engine
}
val res = Http().outgoingConnectionHttps("localhost",4443, connectionContext = noCertificateCheckContext)
val response = Await.result(Source.single(Get(url)).via(res).runWith(Sink.head), 60 seconds)
val responseString =Await.result(Unmarshal(response).to[String], 60 seconds)
println(responseString)
Result:
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
CodePudding user response:
I tried your "Custom SSLContext" reproducer. Besides timing out, it also produced the following stack track in the logging:
Caused by: java.lang.NullPointerException: null
at akka.stream.scaladsl.TLS$.$anonfun$apply$2(TLS.scala:92)
at akka.stream.impl.io.TLSActor.liftedTree1$1(TLSActor.scala:162)
at akka.stream.impl.io.TLSActor.<init>(TLSActor.scala:162)
at akka.stream.impl.io.TLSActor$.$anonfun$props$1(TLSActor.scala:40)
Perhaps you didn't have an slf4j logger on your classpath? It should show a warning in that case. Anyway, after a look at the code this suggests the sslContext
is null
here. And that is indeed the case: you're already passing trustfulSslContext
to ConnectionContext.https
before it has been initialized. When initializing the trustfulSslContext earlier it works for me.
As for your second approach: disabling hostname verification does not disable "the rest of" certificate validation. The JVM will still verify the certificate is valid - it will just no longer verify it belongs to the hostname you are connecting to. To accept invalid certificates, you do have to use a custom SSLContext
. Your example can be adapted to do that as well, but all other things being equal your first approach is simpler and there's no need for the additional indirection in your second approach.