admin管理员组

文章数量:1402995

We have a non-negotiable (compliance) requirement to verify a client certificate against a third-party REST service during SSL handshake for our Quarkus-based webservice. We implemented this using a Vertx customizer like this:

@ApplicationScoped
class VertxCustomizer(private val externalService: ExternalService) : HttpServerOptionsCustomizer {

    @Override
    override fun customizeHttpsServer(options: HttpServerOptions) {
        // we inject a custom trust manager here which verifies certificates categories
        options.trustOptions = CustomTrustOptions(options.trustOptions, externalService)
    }
}

In there we create a custom TrustManagerFactory which finally produces this custom TrustManager that verifies the client certificate during SSL handshake:

class CustomTrustManager(private val manager: X509TrustManager, private val externalService: ExternalService) : X509TrustManager {
    override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
       val certificate = chain[0]
       // this next call will block the thread.
       if (!externalService.verifyCertificate(certificate)) {
           throw CertificateException("Certificate is unknown in external service")
       }
    }

    ...
}

The problem with this is, that this call will block the vert.x event loop while the call to the external system is running which can take anywhere from 1-3 seconds. This means that during this time no other requests to the server will be processed, which obviously is a bad thing. For code that is running after the TLS handshake we can have worker threads or coroutines which fix this problem nicely. However for stuff that is running during the TLS handshake, we only have this non-reactive JDK TrustManager API and we were unable to find anything that would allow us to do this call without blocking the whole server. Has anyone ever done such a thing during a TLS-handshake with Quarkus and could give some hints on how we could approach the situation?

We have a non-negotiable (compliance) requirement to verify a client certificate against a third-party REST service during SSL handshake for our Quarkus-based webservice. We implemented this using a Vertx customizer like this:

@ApplicationScoped
class VertxCustomizer(private val externalService: ExternalService) : HttpServerOptionsCustomizer {

    @Override
    override fun customizeHttpsServer(options: HttpServerOptions) {
        // we inject a custom trust manager here which verifies certificates categories
        options.trustOptions = CustomTrustOptions(options.trustOptions, externalService)
    }
}

In there we create a custom TrustManagerFactory which finally produces this custom TrustManager that verifies the client certificate during SSL handshake:

class CustomTrustManager(private val manager: X509TrustManager, private val externalService: ExternalService) : X509TrustManager {
    override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
       val certificate = chain[0]
       // this next call will block the thread.
       if (!externalService.verifyCertificate(certificate)) {
           throw CertificateException("Certificate is unknown in external service")
       }
    }

    ...
}

The problem with this is, that this call will block the vert.x event loop while the call to the external system is running which can take anywhere from 1-3 seconds. This means that during this time no other requests to the server will be processed, which obviously is a bad thing. For code that is running after the TLS handshake we can have worker threads or coroutines which fix this problem nicely. However for stuff that is running during the TLS handshake, we only have this non-reactive JDK TrustManager API and we were unable to find anything that would allow us to do this call without blocking the whole server. Has anyone ever done such a thing during a TLS-handshake with Quarkus and could give some hints on how we could approach the situation?

Share Improve this question asked Mar 27 at 13:15 Jan ThomäJan Thomä 13.6k6 gold badges60 silver badges84 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

Unfortunately, we cannot make the handshake asynchronous. However, a potential solution would be to delay the verification to a later stage (like in a Quarkus REST interceptor or an HTTP route). In these later stages, you can execute your blocking I/O on a worker thread.

本文标签: Quarkus How to run longish IO tasks during the SSLhandshake without blocking the event loopStack Overflow