Issue
My setup:
- JDK 11.0.6
- Spring Boot 2.2.4.RELEASE
- spring-kafka 2.4.1
I have verified my Zookeeper / Kafka / client application in PLAINTEXT, all works fine. I have also verified my keystores / trust stores with the Kafka client tools.
I am using the KafkaAdmin bean to configure my topics, it appears to be failing on the SSL connection:
@Bean
public KafkaAdmin kafkaAdmin() {
Map<String, Object> configs = new HashMap<>();
configs.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, getKafkaHost());
configs.put("security.protocol", "SSL");
configs.put("ssl.key.password", "xxx");
configs.put("ssl.keystore.location", "/keystore/client.keystore.jks");
configs.put("ssl.keystore.password", "xxx");
configs.put("ssl.truststore.location", "/keystore/kafka.truststore.jks");
configs.put("ssl.truststore.password", "xxx");
return new KafkaAdmin(configs);
}
my two JKS files are in src/main/resources/keystore in my Project. /keystore
doesn't work... it seems like they are getting picked up if I specify /src/main/resources/keystore/client.keystore.jks
... is that going to work in the real world? At runtime in a standalone tomcat, there is going to be a /src/main/resources/keystore
?
From my understanding, paths are relative to the target/classes
folder, no?
Solution
Kafka client or Spring couldn't resolve .jks
file provided directly with the path even if you provide an absolute path. Provide a relative path like src/main/resources/keystore
is not a good idea because after the build your resources
directory content would directly copy into target/classes
as you know already.
So, bind the file directly to a org.springframework.core.io.Resource
type instance using value annotation from classpath
.
@Value("classpath:certs/keystore/kafka.keystore.jks")
private Resource keystore;
@Value("classpath:certs/truststore/kafka.truststore.jks")
private Resource truststore;
Then get the absolute path from that instance like this;
configs.put("ssl.keystore.location", keystore.getFile().getAbsolutePath());
configs.put("ssl.truststore.location", truststore.getFile().getAbsolutePath());
As you can see, Keystore
and Truststore
file should be in the classpath
. In my case, they are in src/resources/certs/keystore
and src/resources/certs/truststore
directories respectively.
Answered By - Sachith Dickwella
Answer Checked By - Katrina (JavaFixing Volunteer)