confluentinc / librdkafka

The Apache Kafka C/C++ library
Other
245 stars 3.15k forks source link

SSL Connection verification requires CA certificates in specific order in a CA bundle #3409

Open JoergSiebahn opened 3 years ago

JoergSiebahn commented 3 years ago

Description

When certificates for the Kafka brokers are signed with a custom CA, it is required that the signing CA is the first with the same CN in a bundle that is configured with ssl.ca.location. If the CA is updated, you can't add the new one besides the old one. Either the connection will break before you update the signed certificates or after you update the signed certificates. This way a rolling update is not possible.

We are using librdkafka as a library through Confluent Kafka Go and were able to reproduce the issue with kafkacat.

How to reproduce

In the error case a log with crypto error similar to this will appear:

%3|1622131073.586|SSL|rdkafka#consumer-1| [thrd:sasl_ssl://kafka:9093/bootstrap]: sasl_ssl://kafka:9093/bootstrap: crypto/rsa/rsa_pk1.c:67: error:0407008A:rsa routines:RSA_padding_check_PKCS1_type_1:invalid padding: 
%3|1622131073.586|SSL|rdkafka#consumer-1| [thrd:sasl_ssl://kafka:9093/bootstrap]: sasl_ssl://kafka:9093/bootstrap: crypto/rsa/rsa_ossl.c:662: error:04067072:rsa routines:rsa_ossl_public_decrypt:padding check failed: 
%3|1622131073.586|SSL|rdkafka#consumer-1| [thrd:sasl_ssl://kafka:9093/bootstrap]: sasl_ssl://kafka:9093/bootstrap: crypto/asn1/a_verify.c:179: error:0D0C5006:asn1 encoding routines:ASN1_item_verify:EVP lib: 
%3|1622131073.610|SSL|rdkafka#consumer-1| [thrd:sasl_ssl://kafka:9093/bootstrap]: sasl_ssl://kafka:9093/bootstrap: crypto/rsa/rsa_pk1.c:67: error:0407008A:rsa routines:RSA_padding_check_PKCS1_type_1:invalid padding: 
%3|1622131073.610|SSL|rdkafka#consumer-1| [thrd:sasl_ssl://kafka:9093/bootstrap]: sasl_ssl://kafka:9093/bootstrap: crypto/rsa/rsa_ossl.c:662: error:04067072:rsa routines:rsa_ossl_public_decrypt:padding check failed: 
%3|1622131073.610|SSL|rdkafka#consumer-1| [thrd:sasl_ssl://kafka:9093/bootstrap]: sasl_ssl://kafka:9093/bootstrap: crypto/asn1/a_verify.c:179: error:0D0C5006:asn1 encoding routines:ASN1_item_verify:EVP lib: 
%3|1622131074.764|SSL|rdkafka#consumer-1| [thrd:sasl_ssl://kafka:9093/bootstrap]: sasl_ssl://kafka:9093/bootstrap: crypto/rsa/rsa_pk1.c:67: error:0407008A:rsa routines:RSA_padding_check_PKCS1_type_1:invalid padding: 
%3|1622131074.764|SSL|rdkafka#consumer-1| [thrd:sasl_ssl://kafka:9093/bootstrap]: sasl_ssl://kafka:9093/bootstrap: crypto/rsa/rsa_ossl.c:662: error:04067072:rsa routines:rsa_ossl_public_decrypt:padding check failed: 
%3|1622131074.764|SSL|rdkafka#consumer-1| [thrd:sasl_ssl://kafka:9093/bootstrap]: sasl_ssl://kafka:9093/bootstrap: crypto/asn1/a_verify.c:179: error:0D0C5006:asn1 encoding routines:ASN1_item_verify:EVP lib: 

A working example to reproduce the error in a Docker Compose setup is available here.

IMPORTANT: Always try to reproduce the issue on the latest released version (see https://github.com/edenhill/librdkafka/releases), if it can't be reproduced on the latest version the issue has been fixed.

Checklist

IMPORTANT: We will close issues where the checklist has not been completed.

Please provide the following information:

edenhill commented 2 years ago

I'm not an expert in TLS and we're simply using OpenSSL to set it all up. Maybe you can inspect our use of OpenSSL in https://github.com/edenhill/librdkafka/blob/master/src/rdkafka_ssl.c and https://github.com/edenhill/librdkafka/blob/master/src/rdkafka_cert.c to see if we're doing something wrong. Thanks

JoergSiebahn commented 2 years ago

I'm not an expert in TLS …

I'm not an export in C 🤣 and not an expert with OpenSSL as well 😞 . So it's hard for me to find out how you are using OpenSSL.

I tried another way and skipped the part of your implementation and directly used openssl. Based on the generated keys, I created for reproducing the situation, I played a little bit with openssl commands and came up with this:

$ ./generate-ssl.sh 
Cleaning up
Generating a 2048 bit RSA private key
...
$ openssl verify -verbose -CAfile out/pass-bundle.pem out/kafka-ca1-signed.pem 
out/kafka-ca1-signed.pem: OK
$ openssl verify -verbose -CAfile out/fail-bundle.pem out/kafka-ca1-signed.pem 
out/kafka-ca1-signed.pem: C = DE, L = Hamburg, O = Demo Org, OU = Demo, CN = kafka
error 7 at 0 depth lookup:certificate signature failure
4674969260:error:04FFF06A:rsa routines:CRYPTO_internal:block type is not 01:/System/Volumes/Data/SWE/macOS/BuildRoots/220e8a1b79/Library/Caches/com.apple.xbs/Sources/libressl/libressl-56.60.2/libressl-2.8/crypto/rsa/rsa_pk1.c:103:
4674969260:error:04FFF072:rsa routines:CRYPTO_internal:padding check failed:/System/Volumes/Data/SWE/macOS/BuildRoots/220e8a1b79/Library/Caches/com.apple.xbs/Sources/libressl/libressl-56.60.2/libressl-2.8/crypto/rsa/rsa_eay.c:680:
4674969260:error:0DFFF006:asn1 encoding routines:CRYPTO_internal:EVP lib:/System/Volumes/Data/SWE/macOS/BuildRoots/220e8a1b79/Library/Caches/com.apple.xbs/Sources/libressl/libressl-56.60.2/libressl-2.8/crypto/asn1/a_verify.c:155:

So it seems like this behavior is already in openssl verify. In other contexts, I assume that the multiple certificates in the single file are split and verified separately. At least one of our customer uses such a certificate bundle in Java services for Kafka and MongoDB with common libraries and the connections are verified. But I wonder if such an implementation is worth the effort and code complexity in librdkafka when you have a library like OpenSSL already available.