0

I have a requirement to run a Eureka discovery server in secure https mode and to run a Spring Boot client microservice application (also in https mode) that registers with the Eureka server. All communication between client and server must use secure TLS encryption.

I created a self-signed SSL certificate and added it to a PKCS12 keystore. Then I added the keystore details to both of my application.properties files. When I run the eureka service, I can now access it over https. Same for the client microservice.

However, now my services aren't communicating. Before when I was running both in unsecure mode, the client had no problems registering with the Eureka service. Now it produces the following error:

2023-01-17 14:40:53,529 ERROR c.n.d.DiscoveryClient [DiscoveryClient-HeartbeatExecutor-0] DiscoveryClient_MY-MICROSERVICE/localhost:my-microservice:8079 - was unable to send heartbeat! com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server  
at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:112) ~[eureka-client-1.10.17.jar!/:1.10.17]    
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.sendHeartBeat(EurekaHttpClientDecorator.java:89) ~[eureka-client-1.10.17.jar!/:1.10.17]   
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$3.execute(EurekaHttpClientDecorator.java:92) ~[eureka-client-1.10.17.jar!/:1.10.17]   
at com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient.execute(SessionedEurekaHttpClient.java:77) ~[eureka-client-1.10.17.jar!/:1.10.17]     
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.sendHeartBeat(EurekaHttpClientDecorator.java:89) ~[eureka-client-1.10.17.jar!/:1.10.17]   
at com.netflix.discovery.DiscoveryClient.renew(DiscoveryClient.java:893) ~[eureka-client-1.10.17.jar!/:1.10.17]     
at com.netflix.discovery.DiscoveryClient$HeartbeatThread.run(DiscoveryClient.java:1457) ~[eureka-client-1.10.17.jar!/:1.10.17]  
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[?:?]   
at java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[?:?]  
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[?:?]   
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[?:?]   
at java.lang.Thread.run(Thread.java:833) ~[?:?]

I added my self-signed cert to my jdk-home\lib\security\cacerts file using the keytool. I also updated the eureka.client.serviceUrl.defaultZone property in my client app to use https protocol, but still it cannot register itself.

Here are my application.properties files for my eureka service and client app.

Eureka Service application.properties

server.port=8761
server.ssl.enabled: true
server.ssl.key-store: src/main/resources/springboot.p12
server.ssl.key-store-password: MyPassword
server.ssl.key-store-type: pkcs12
server.ssl.key-alias: springboot

security.require-ssl: true

spring.application.name=my-service-registry

eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.instance.nonSecurePortEnabled=false
eureka.instance.securePortEnabled=true
eureka.instance.securePort=${server.port}
eureka.dashboard.enabled=true

logging.level.com.netflix.eureka=OFF
logging.level.com.netflix.discovery=OFF

Client App application.properties

server.port = 8079
server.ssl.enabled: true
server.ssl.key-store: src/main/resources/springboot.p12
server.ssl.key-store-password: MyPassword
server.ssl.key-store-type: pkcs12
server.ssl.key-alias: springboot

security.require-ssl: true

spring.application.name=my-microservice
eureka.client.securePortEnabled = true
eureka.client.serviceUrl.defaultZone = https://localhost:8761/eureka
eureka.instance.prefer-ip-address = true
eureka.instance.securePortEnabled = true
eureka.instance.nonSecurePortEnabled = false

I am on windows with jdk-18.0.2.1.

In my pom.xml files I am using spring-cloud version 2021.0.3. The versions of springframework dependencies I'm using are below.

Eureka app dependencies

spring-cloud-starter-netflix-eureka-server 3.1.4
spring-boot-starter-tomcat 2.7.3
spring-boot-starter-web 2.7.3
spring-core 5.3.22
spring-boot-starter-test 2.7.0
spring-web 5.3.23
spring-security-crypto 5.7.5
spring-security-core 5.7.5
spring-security-web 5.7.5
spring-security-config 5.7.5
spring-boot-starter-security 2.7.5
spring-boot-starter 2.7.0
spring-boot-starter-log4j2 2.7.0

Client app dependencies

spring-boot-starter-web 2.7.0
spring-boot-starter-test 2.7.0
spring-boot-starter 2.7.0
spring-boot-starter-log4j2 2.7.0
spring-security-crypto 5.7.5

1 Answers1

0

Found the problem. Adding the self-signed cert to the truststore was not enough. The cert needs to include a subject alternative name or else the underlying apache SSLConnectionSocketFactory will refuse to validate it. This thread solved my problem. Certificate for <localhost> doesn't match any of the subject alternative names