This is the first time I am trying to connect to Kafka server using Asp.Net console app and I ran into a bunch of issues. I solved most but can't shake this one off.
I am testing the producer part and keep getting "SSL Handshake Failed" error. I followed some suggestions here, including setting SslEndpointIdentificationAlgorithm to blank.
This is my producer config section:
_producerConfig = new ProducerConfig
{
BootstrapServers = bootstrapServer,
EnableDeliveryReports = true,
ClientId = Dns.GetHostAddresses(),
//SecurityProtocol = SecurityProtocol.SaslSsl,
SecurityProtocol = SecurityProtocol.Ssl,
SslCaLocation = @"D:\Something\Certificate\myCert.pem",
SslKeyPassword = "blahblah",
SslEndpointIdentificationAlgorithm=SslEndpointIdentificationAlgorithm.None
};
...
public async Task StartSendingMessages(string topicName)
{
using (var producer = new ProducerBuilder<long, string>(_producerConfig)
.SetKeySerializer(Serializers.Int64)
.SetValueSerializer(Serializers.Utf8)
.SetLogHandler((_, message) => Console.WriteLine($"Facility: {message.Facility}-{message.Level} Message: {message.Message}"))
.SetErrorHandler((_, e) => Console.WriteLine($"Error: {e.Reason}. Is Fatal: {e.IsFatal}"))
.Build())
try
{
Console.WriteLine("\nProducer loop started...\n\n");
for (var character = 'A'; character <= 'C'; character++)
{
var message = $"Character #{character} sent at {DateTime.Now:yyyy-MM-dd_HH:mm:ss}";
var deliveryReport = await producer.ProduceAsync(topicName,
new Message<long, string>
{
Key = DateTime.UtcNow.Ticks,
Value = message
});
When I run the application, I get:
Facility: FAIL-Error Message: [thrd:ssl://1.2.3.4:9093/bootstrap]: ssl://1.2.3.4:9093/bootstrap: SSL handshake failed: ssl\statem\statem_clnt.c:1890:tls_post_process_server_certificate error:0A000086:SSL routines::certificate verify failed: broker certificate could not be verified, verify that ssl.ca.location is correctly configured or root CA certificates are installed (add broker's CA certificate to the Windows Root certificate store) (after 46ms in state SSL_HANDSHAKE)
Error: ssl://1.2.3.4:9093/bootstrap: SSL handshake failed: ssl\statem\statem_clnt.c:1890:tls_post_process_server_certificate error:0A000086:SSL routines::certificate verify failed: broker certificate could not be verified, verify that ssl.ca.location is correctly configured or root CA certificates are installed (add broker's CA certificate to the Windows Root certificate store) (after 46ms in state SSL_HANDSHAKE). Is Fatal: False
What am I doing wrong, or missing?
As I mentioned, I resolved the issue by breaking .pem file, provided to us by middleware team, into 3 certificate/key files. I am outlining the steps I took, maybe it will help someone facing the same issue.
Request .PEM version of .JKS certificate and key. Certificate is password protected and therefore they would need to provide the password as well.
In the remainder of these staps, we assume PEM certificate received is called mykafka.pem.
Open mykafka.pem in a text editor, such as Notepad++. This file contains entire certificate chain which needs to be broken up into different certificate documents.
Locate the line starting with "-----BEGIN ENCRYPTED PRIVATE KEY-----"
Copy the text between "-----BEGIN ENCRYPTED PRIVATE KEY-----" and "-----END ENCRYPTED PRIVATE KEY-----", inclusive.
Paste the content of copied text to a new file and name it "mykafka.key"
Locate the text "friendlyName: mykafka"
Copy the content between lines "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----", inclusive.
Paste the content of copied text to a new file and name it "mykafka.cer"
Locate the text sha2ca.cer in certificate section's friendly name (e.g. "friendlyName: blah2021sha2ca.cer")
Copy the content between lines "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----", inclusive.
Paste the content of copied text to a new file and name it as the friendly name that was listed in certificate section (e.g., blah2021sha2ca.cer)
You should now have 3 certificate/key files: mykafka.key, mykafka.cer, blah2021sha2ca.cer.
In your producer class, declare a client config variable and set its SSL settings like below:
public class Producer { private readonly ProducerConfig _producerConfig;
public Producer(string bootstrapServer)
{
_producerConfig = new ProducerConfig
{
BootstrapServers = bootstrapServer,
....
SecurityProtocol = SecurityProtocol.Ssl,
SslCaLocation = "<path_to_certificate_folder>\blah2021sha2ca.cer",
SslCertificateLocation = "<path_to_certificate_folder>mykafka.cer",
SslKeyLocation = "<path_to_certificate_folder>mykafka.key",
SslKeyPassword = "<password_received_from_whoever_provided_pem_file>",
....
EnableSslCertificateVerification = false,
}
}
}
I added the last entry, EnableSslCertificateVerification, because without it I was getting handshake failure.