I want the following encrypted setup for a microservice environment. A SSL enabled Eureka Server with Cloud Configuration Service and multiple microservices that only need to connect to the Discovery service, read the configuration and run their stuff. Everything via HTTPS and with authentication.
So...what I did:
A Eureka Discovery Server including a Cloud Configuration Service on /config/* The Server is registering itself to the Eureka server and the Eureka Dashboard shows the instance. This service runs on port 9001 with SSL enabled and user-authentication. The service works as usual.
Then I've created a new SpringBoot service, that connects to Eureka and registered itself to it. Because of the self signed certificate, I wrote a small SSLConfguration Class from this post: How to override Spring Cloud Eureka default discovery client default ssl context? to give my personal truststore to the underlying EurekaClient. All our services are configured with application.yml:
spring:
application:
name: mark2
server:
port: 9998
ssl:
enabled: true
key-store: classpath:keystore.p12
key-store-password: changeit
key-store-type: PKCS12
keyAlias: mark2
http:
client:
ssl:
trust-store: classpath:keystore.p12
trust-store-password: changeit
eureka:
client:
serviceUrl:
defaultZone: https://user:pass@localhost:9001/eureka
The client connects and registers perfectly.
Now I want the SpringBoot service to register to the Eureka Server and load the configuration from the Config Server - during bootstrap. So I've moved the spring, http and eureka settings to bootstrap.yml
spring:
application:
name: mark2
cloud:
config:
username: user
password: password
discovery:
enabled: true
serviceId: EUREKA-DISCOVERY-SERVICE
failFast: true
name: my
profile: settings
# label: v1
http:
client:
ssl:
trust-store: classpath:keystore.p12
trust-store-password: changeit
eureka:
client:
serviceUrl:
defaultZone: https://user:password@localhost:9001/eureka
instance:
metadataMap:
user: user
password: password
configPath: /config
If the service starts, it tries to connect during bootstrap to the Eureka server. This doesn't work, because it isn't trusting the self signed certificate from the Eureka server. I cannot use @Configure or @Bean because I'm in the bootstrap (at least nothing that I found worked). The above solution with the SSLConfiguration isn't working too.
Ok, then I set the JVM args with javax.net.ssl.trustStore etc. to my personal truststore.
bootRun {
jvmArgs = [
"-Djavax.net.ssl.trustStore=/absolute/path/to/keystore.p12",
"-Djavax.net.ssl.trustStorePassword=changeit",
"-Djavax.net.ssl.trustStoreType=PKCS12",
]
}
The service starts and the Eureka client starts to communicate with the Eureka server, finds a Cloud Configuration instance and loads a property file and the Spring context is created. The property contains only some test properties.
But then - error:
Field optionalArgs in org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration$RefreshableEurekaClientConfiguration required a single bean, but 2 were found:
- getTrustStoredEurekaClient: defined by method 'getTrustStoredEurekaClient' in class path resource [de/mark2/SslConfiguration.class]
- discoveryClientOptionalArgs: defined by method 'discoveryClientOptionalArgs' in org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration
Ok, bad but ok. Because we gave the JVM args, we should not use SSLConfiguration any more. Removed.
Now - everything seems ok and the service should start the embedded Tomcat. But this doesn't work because of another Exception that says, that the configured keystore is empty ("the trustAnchors parameter must be non-empty" means the keystore exists but doesn't contain any alias certs). I think, the JVM args are used in the embedded Tomcat and it tries to use the truststore for some kind of ClientCertificates or so. I don't know.
If I disable the cloud configuration - the embedded Tomcat still has the same error. If I then remove the JVM args too - the service comes up.
So - I don't have an idea, what I need to do, to communicate encrypted during bootstrap without defining the JVM args for the Eureka Client or give the embedded tomcat a Truststore (which he doesn't need).