Java 弹簧靴+;尤里卡+;SSL环境中的CloudConfig
我需要以下microservice环境的加密设置。一个支持SSL的Eureka服务器,具有云配置服务和多个微服务,只需连接到发现服务、读取配置并运行其内容。一切都通过HTTPS和身份验证 所以…我所做的: 在/config上包含云配置服务的Eureka Discovery服务器/* 服务器正在向Eureka服务器注册,Eureka仪表板将显示该实例。此服务在启用SSL和用户身份验证的端口9001上运行。服务照常进行 然后我创建了一个新的SpringBoot服务,它连接到Eureka并注册到它。由于自签名证书,我在本文中编写了一个小的SSLConfiguration类:将我的个人信任库提供给底层的EurekaClient。 我们的所有服务都配置了application.yml:Java 弹簧靴+;尤里卡+;SSL环境中的CloudConfig,java,spring,spring-boot,tomcat,ssl,Java,Spring,Spring Boot,Tomcat,Ssl,我需要以下microservice环境的加密设置。一个支持SSL的Eureka服务器,具有云配置服务和多个微服务,只需连接到发现服务、读取配置并运行其内容。一切都通过HTTPS和身份验证 所以…我所做的: 在/config上包含云配置服务的Eureka Discovery服务器/* 服务器正在向Eureka服务器注册,Eureka仪表板将显示该实例。此服务在启用SSL和用户身份验证的端口9001上运行。服务照常进行 然后我创建了一个新的SpringBoot服务,它连接到Eureka并注册到它。由
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
客户端可以完美地连接和注册
现在我希望SpringBoot服务注册到Eureka服务器,并在引导过程中从配置服务器加载配置。因此,我将spring、http和eureka设置移到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
如果服务启动,它将在引导过程中尝试连接到Eureka服务器。这不起作用,因为它不信任来自Eureka服务器的自签名证书。我不能使用@Configure或@Bean,因为我在引导中(至少我发现没有任何东西起作用)。上述SSLConfiguration解决方案也不起作用
好的,然后我用javax.net.ssl.trustStore等将JVM参数设置为我的个人信任库
bootRun {
jvmArgs = [
"-Djavax.net.ssl.trustStore=/absolute/path/to/keystore.p12",
"-Djavax.net.ssl.trustStorePassword=changeit",
"-Djavax.net.ssl.trustStoreType=PKCS12",
]
}
服务启动,Eureka客户端开始与Eureka服务器通信,找到云配置实例并加载属性文件,然后创建Spring上下文。该属性仅包含一些测试属性
但是,错误是:
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
好的,坏的,但是好的。因为我们提供了JVM参数,所以不应该再使用SSLConfiguration。删除
现在-一切似乎都正常,服务应该启动嵌入式Tomcat。但这不起作用,因为另一个异常是,配置的密钥库为空(“trustAnchors参数必须为非空”表示密钥库存在,但不包含任何别名证书)。我认为,JVM参数用于嵌入式Tomcat中,它试图使用信任库来获取某种ClientCertificates之类的证书。我不知道
如果我禁用云配置,嵌入式Tomcat仍然会有相同的错误。如果我也删除了JVM参数,服务就会出现
所以-我不知道,我需要做什么,在引导过程中进行加密通信,而不为Eureka客户机定义JVM参数,或者给嵌入式tomcat一个信任库(他不需要) 有趣的事情-如果我使用嵌入式Undertow而不是嵌入式Tomcat,它会工作-但这就是解决方案吗
dependencies {
compile("org.springframework.boot:spring-boot-starter") {
exclude module: "tomcat-embed-el"
}
compile("org.springframework.boot:spring-boot-starter-web") {
exclude module: "spring-boot-starter-tomcat"
}
compile('org.springframework.boot:spring-boot-starter-undertow')
...
}
定义META-INF/spring.factories并添加org.springframework.cloud.bootstrap.bootstrap配置=。。。线 课程可以是:
@Configuration
@BootstrapConfiguration
public class SslConfiguration {
@Value("${http.client.ssl.trust-store}")
private URL trustStore;
@Value("${http.client.ssl.trust-store-password}")
private String trustStorePassword;
@Bean
public DiscoveryClient.DiscoveryClientOptionalArgs getTrustStoredEurekaClient(SSLContext sslContext) {
DiscoveryClient.DiscoveryClientOptionalArgs args = new DiscoveryClient.DiscoveryClientOptionalArgs();
args.setSSLContext(sslContext);
return args;
}
@Bean
public SSLContext sslContext() throws Exception {
return new SSLContextBuilder().loadTrustMaterial(trustStore, trustStorePassword.toCharArray()).build();
}
}
由于DiscoveryClientOptionalArgs现在定义了两次,因此添加另一个类,该类在Spring上下文启动后加载
@Configuration
public class DiscoveryServiceConfiguration {
@Bean
public static BeanFactoryPostProcessor registerPostProcessor() {
return (ConfigurableListableBeanFactory beanFactory) -> {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
for (String beanDefinitionName : registry.getBeanDefinitionNames()) {
if (beanDefinitionName.equalsIgnoreCase("discoveryClientOptionalArgs")) {
BeanDefinition beanDefinition = registry.containsBeanDefinition(beanDefinitionName) ? registry.getBeanDefinition(beanDefinitionName) : null;
if (beanDefinition != null) {
if (registry.containsBeanDefinition(beanDefinitionName)) {
registry.removeBeanDefinition(beanDefinitionName);
}
}
}
}
};
}
}
那也行。您不再需要定义JVM参数