I've been trying to make two ssl to secure the communication between microservices. It is actually working when service A want to register into EurekaServer. But when I try to register eureka into the same eureka server or other instance of eureka I always got a bad certificate exception.
This is my application.yml from eureka server
server:
port: ${SERVER_SSL_PORT:${PORT:10100}}
ssl:
enabled: true
client-auth: need
key-alias: ${JKS_ALIAS}
key-password: ${JKS_KEY_PASSWORD}
key-store-type: ${JKS_TYPE}
key-store-provider: ${JKS_PROVIDER:SUN}
key-store: ${JKS_PATH}
key-store-password: ${JKS_KEY_PASSWORD}
trust-store: ${JKS_PATH}
trust-store-password: ${JKS_KEY_PASSWORD}
trust-store-provider: ${JKS_PROVIDER:SUN}
trust-store-type: ${JKS_TYPE}
## EUREKA CONFIGURATION
eureka:
client:
enabled: true
register-with-eureka: true
fetch-registry: false
service-url:
defaultZone: ${SVC_REGISTRY:https://localhost:14102/eureka}
prefer-same-zone-eureka: true
healthcheck:
enabled: true
tls:
enabled: true
key-store: ${JKS_PATH}
key-password: ${JKS_KEY_PASSWORD}
key-store-type: ${JKS_TYPE}
key-store-password: ${JKS_KEYSTORE_PASSWORD}
trust-store: ${JKS_PATH}
trust-store-password: ${JKS_KEY_PASSWORD}
trust-store-type: ${JKS_TYPE}
instance:
instance-id: ${SERVER_NAME:${spring.application.name}:${server.port}}@${eureka.instance.hostname}
hostname: ${SERVER_HOST:localhost}
home-page-url: https://${eureka.instance.hostname}:${server.port}${server.contextPath:}
status-page-url: https://${eureka.instance.hostname}:${server.port}${server.contextPath:}${management.endpoints.web.base-path:}/info
health-check-url: https://${eureka.instance.hostname}:${server.port}${server.contextPath:}${management.endpoints.web.base-path:}/health
secure-health-check-url: https://${eureka.instance.hostname}:${server.port}${server.contextPath:}${management.endpoints.web.base-path:}/health
lease-renewal-interval-in-seconds: 10
prefer-ip-address: true
metadata-map:
instanceId: ${eureka.instance.instance-id}
zone: ${SERVER_ZONE:local}
non-secure-port-enabled: false
secure-port-enabled: true
secure-port: ${server.port}
I also try to add this configuration to modify the JerseyClient
@Bean
@SneakyThrows
public DiscoveryClient.DiscoveryClientOptionalArgs discoveryClientOptionalArgs2() {
DiscoveryClient.DiscoveryClientOptionalArgs args = new DiscoveryClient.DiscoveryClientOptionalArgs();
EurekaJerseyClientImpl.EurekaJerseyClientBuilder clientBuilder = new EurekaJerseyClientImpl.EurekaJerseyClientBuilder()
.withClientName("DiscoveryClient-HTTPClient-Custom")
.withUserAgent("Java-EurekaClient")
.withConnectionTimeout(config.getEurekaServerConnectTimeoutSeconds() * 1000)
.withReadTimeout(config.getEurekaServerReadTimeoutSeconds() * 1000)
.withMaxConnectionsPerHost(config.getEurekaServerTotalConnectionsPerHost())
.withMaxTotalConnections(config.getEurekaServerTotalConnections())
.withConnectionIdleTimeout(config.getEurekaConnectionIdleTimeoutSeconds() * 1000)
.withEncoderWrapper(CodecWrappers.getEncoder(config.getEncoderName()))
.withDecoderWrapper(CodecWrappers.resolveDecoder(config.getDecoderName(), config.getClientDataAccept()))
.withCustomSSL(sslContext());
EurekaJerseyClient jerseyClient = clientBuilder.build();
args.setEurekaJerseyClient(jerseyClient);//Provide custom EurekaJerseyClient to override default one
return args;
}
@Bean
public SSLContext sslContext() throws Exception {
log.info("initialize ssl context bean with keystore {} ", env.getProperty("JKS_PATH"));
char[] password = env.getProperty("JKS_KEY_PASSWORD").toCharArray();
return new SSLContextBuilder()
.loadTrustMaterial(ResourceUtils.getFile(env.getProperty("JKS_PATH")), password).build();
}
But I keep getting this error
2022-09-01 18:44:01.522 INFO 26829 --- [tbeatExecutor-0] c.n.d.s.t.d.RedirectingEurekaHttpClient : Request execution error. endpoint=DefaultEndpoint{ serviceUrl='https://XXXXXXXXXXXXXXXXXXXX:DDDD/eureka/}, exception=javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate stacktrace=com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate at com.sun.jersey.client.apache4.ApacheHttpClient4Handler.handle(ApacheHttpClient4Handler.java:187) at com.sun.jersey.api.client.Client.handle(Client.java:652) at com.sun.jersey.api.client.WebResource.handle(WebResource.java:682) at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74) at com.sun.jersey.api.client.WebResource$Builder.put(WebResource.java:529) at
Certificate should be fine since it is the same cert I used to make 2way SSL between service A and registry. I am also testing this on a real server with valid certificate.
Any clue on this?
Thanks in advance! Appreciate it
I found the root cause of my problem. I had this property as true
prefer-ip-address: true
but it should be false since my certificates have hostnames register, not IPs. So when it try to validate the certs it was comparing hostnames vs ip which are different and it was throwing bad_certificate exception.