验证连接到 Kafka 集群的服务器证书时出现问题

问题描述 投票:0回答:1

我目前正在努力通过 tls 方式连接到 Kafka 集群。

我的消费者是一个 spring-kafka java 应用程序(使用 org.springframework.kafka.core.DefaultKafkaConsumerFactory)。它的(相关)配置如下。

我以非 TLS 方式生产/消费没有问题,但遇到了(非常经典的)“无法找到请求目标的有效证书路径”。

错误看起来像这样:

2024-03-26 18:34:12.292 [kafkaMessageListenerContainer-C-1] ERROR o.s.k.l.KafkaMessageListenerContainer - Authentication/Authorization Exception and no authExceptionRetryInterval set
org.apache.kafka.common.errors.SslAuthenticationException: SSL handshake failed
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to re
quested target
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
    ...
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1175)
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
    ...
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)
    ...
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:146)
    at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:127)
    at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
    at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
    ... 36 common frames omitted

我尝试绕过应用程序直接验证我的信任库......成功了:

$> openssl s_client -verify 100 -showcerts -connect  server1.fqdn:9093 -CAfile  <(keytool -list -rfc -keystore /some/path/to/my/truststore.p12 -storepass somepwd)

SSL handshake has read 2440 bytes and written 138 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 3072 bit
Secure Renegotiation IS supported
...
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
...
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)

这让我认为信任库是正确的。 我的信任库仅包含根证书。它是由签署服务器证书的同一机构发出的。 服务器密钥库仅包含自己的证书(CN=server1.fqdn

TLS 连接有两种方式。据我了解(我对 TLS 不太熟悉),第一次协商是与客户端(我)向服务器询问其证书进行的。然后,最新的内容将与我的信任库中的任何内容进行比较(至少将使用我的信任库的根 ca 检查权限)。因此,由于我的错误显示了服务器证书的内容(javax.net.debug=all),我猜我的问题与第一次协商有关,因此与信任库的使用方式有关。

我尝试将信任库提供为 javax.net.ssl.trustStore=/some/path/to/my/truststore.p12 (正如在几个相关帖子中提出的那样),但我遇到了同样的错误。

我还尝试在我的 trusstore 中添加服务器证书(带有自己的别名),但是虽然 openssl 检查确实有效,但 java/kafka 消费者却不起作用。

最终,我只是更改了信任库的密码(ssl.truststore.password**)(以查看它是否被使用,并且我遇到了其他-合法-错误。根据我的说法,它表明它是(正确吗?)已加载。

因此,我被困在这里,听起来像是一个经典错误(原因肯定是我的一个经典且明显的错误)......但我绝对不知道如何解决它!

卡夫卡:3.60
控制器:卡夫
消费者属性

bootstrap.servers=server1.fqdn:9093,server2.fqdn:9093,server3.fqdn:9093
group.id=stg                     
ssl.cipher.suites = null
ssl.enabled.protocols = [TLSv1.2, TLSv1.3]
ssl.endpoint.identification.algorithm = https
ssl.engine.factory.class = null
ssl.key.password = [hidden]
ssl.keymanager.algorithm = SunX509
ssl.keystore.certificate.chain = null
ssl.keystore.key = null
ssl.keystore.location = /some/path/to/my/keystore.p12
ssl.keystore.password = [hidden]
ssl.keystore.type = JKS
ssl.protocol = TLSv1.3
ssl.provider = null
ssl.secure.random.implementation = null
ssl.trustmanager.algorithm = PKIX
ssl.truststore.certificates = null
ssl.truststore.location = /some/path/to/my/truststore.p12
ssl.truststore.password = [hidden]
ssl.truststore.type = JKS
security.protocol = SSL
security.providers = null
sasl.mechanism = GSSAPI
java ssl apache-kafka certificate truststore
1个回答
0
投票

正如所料,我的问题很明显……或者至少现在我知道了。 我专注于根证书,并且由于 openssl 返回“OK”,我理所当然地认为它是。

实际上,(与队友一起)查看远程服务器证书,我们意识到颁发者是“服务器”类型而不是“根”类型。从那里,解决方案是显而易见的:将服务器证书(在顶部或而不是根证书)导入到信任库中......然后魔法就开始起作用了!

旁注:我认为的 openssl 命令可以帮助我显示我的信任库是否正常......并不能用于此目的!

© www.soinside.com 2019 - 2024. All rights reserved.