Search code examples
mongodbapache-kafka-connectdebeziumstrimzi

Connecting MongoDB debezium source connector on Strimzi Kafka Connect cluster with tlsCAFile


I am trying to create debezium mongo source connector in Strimzi Kafka Connect cluster. Mongo cluster has tls enabled. To pass the .pem file I created the secrets and loaded them as ext config in Kafka Connect yaml as explained here I verified that these files .pem are actually written in Kafka Connect pods using

kubectl exec kc-pod -- ls /opt/kafka/external-configuration/connector-config 

the file is present but when I deploy the connector I get this error

com.mongodb.MongoSocketWriteException: Exception sending message
        at com.mongodb.internal.connection.InternalStreamConnection.translateWriteException(InternalStreamConnection.java:665)
        at com.mongodb.internal.connection.InternalStreamConnection.sendMessage(InternalStreamConnection.java:542)
        at com.mongodb.internal.connection.InternalStreamConnection.sendCommandMessage(InternalStreamConnection.java:368)
        at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:317)
        at com.mongodb.internal.connection.CommandHelper.sendAndReceive(CommandHelper.java:88)
        at com.mongodb.internal.connection.CommandHelper.executeCommand(CommandHelper.java:36)
        at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initializeConnectionDescription(InternalStreamConnectionInitializer.java:129)
        at com.mongodb.internal.connection.InternalStreamConnectionInitializer.startHandshake(InternalStreamConnectionInitializer.java:71)
        at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:167)
        at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.lookupServerDescription(DefaultServerMonitor.java:195)
        at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:151)
        at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:353)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:296)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:291)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:654)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:473)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:369)
        at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
        at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:183)
        at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172)
        at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1506)
        at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1416)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:456)
        at java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:921)
        at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1291)
        at com.mongodb.internal.connection.SocketStream.write(SocketStream.java:99)
        at com.mongodb.internal.connection.InternalStreamConnection.sendMessage(InternalStreamConnection.java:539)
        ... 10 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
        at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
        at java.base/sun.security.validator.Validator.validate(Validator.java:264)
        at java.base/sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:313)
        at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:222)
        at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:129)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:638)
        ... 24 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
        at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
        at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
        at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
        ... 30 more

In my connection string I only use tlsCAFile I have only one pem file and I am using mongodb.connection.string as per debezium mongo documentation. in connector yaml file


Solution

  • I don't think the mongo driver used by the debezium connector supports tlsCAFile. Here are the connection options of the Mongo sync java driver used by debezium.

    Note how in the Mongo connection string doc it mentions for tlsCAFile

    This option is not supported by all drivers. Refer to the Drivers documentation.

    So it's driver specific, and what works for mongosh may not work for other drivers.

    You can instead configure it using jvmOptions on the Strimzi KafkaConnect like so:

    jvmOptions:
     javaSystemProperties:
       - name: javax.net.ssl.trustStore
         value: /opt/kafka/external-configuration/mongo-cert/mongodb-custom-truststore.jks
       - name: javax.net.ssl.trustStorePassword
         value: "123456"
    

    Where you mount in a custom truststore (and keystore if you are using mutual TLS). The mongo official connector has some docs on how to create them.

    https://www.mongodb.com/docs/kafka-connector/current/security-and-authentication/tls-and-x509/#ssl-tls-and-x.509-certificates

    Note: YMMV, if other connectors in the same connect cluster need TLS, changing the JVM stores could affect their connections, so it's a bit ugly.

    Also see another recent question with similar problems.