我正在尝试配置 SpringVault,由于某种原因,我需要禁用 SSL 验证。有没有已知的方法来配置 Spring Vault 以忽略 SSL?
正如该项目的 github 页面所述 - 无法在 Spring Vault 中禁用 SSL 验证。请参考项目github问题。或者如果有人有答案,请随时发帖
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.http.URIScheme;
import org.apache.hc.core5.http.config.Registry;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.vault.authentication.ClientAuthentication;
import org.springframework.vault.authentication.SessionManager;
import org.springframework.vault.authentication.TokenAuthentication;
import org.springframework.vault.client.RestTemplateBuilder;
import org.springframework.vault.client.RestTemplateFactory;
import org.springframework.vault.client.VaultEndpoint;
import org.springframework.vault.config.AbstractVaultConfiguration;
import org.springframework.vault.core.VaultTemplate;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.function.Consumer;
import java.util.function.Function;
@Configuration
@ConfigurationProperties(prefix = "spring.cloud.config.server.vault")
public class VaultConfigurationImpl extends AbstractVaultConfiguration {
private String host;
private int port;
private String scheme;
private String token;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getScheme() {
return scheme;
}
public void setScheme(String scheme) {
this.scheme = scheme;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
@Override
@NonNull
public VaultEndpoint vaultEndpoint() {
VaultEndpoint vaultEndpoint = new VaultEndpoint();
vaultEndpoint.setHost(getHost());
vaultEndpoint.setPort(getPort());
vaultEndpoint.setScheme(getScheme());
return vaultEndpoint;
}
// implement method based on the login mechanism ex-Token,AppRole,Certificate,etc
@Override
@NonNull
public ClientAuthentication clientAuthentication() {
return new TokenAuthentication(getToken());
}
@Bean
@ConditionalOnProperty(name = "spring.cloud.config.server.vault.skip-ssl-validation", havingValue = "true")
@NonNull
public RestTemplateFactory restTemplateFactory(ClientFactoryWrapper requestFactoryWrapper) {
return new DefaultRestTemplateFactory(requestFactoryWrapper.getClientHttpRequestFactory(),
it -> restTemplateBuilder(vaultEndpointProvider(), it));
}
@Bean
@ConditionalOnProperty(name = "spring.cloud.config.server.vault.skip-ssl-validation", havingValue = "true")
@NonNull
public VaultTemplate vaultTemplate() {
return new VaultTemplate(
restTemplateBuilder(vaultEndpointProvider(), getClientFactoryWrapper().getClientHttpRequestFactory()),
getBeanFactory().getBean("sessionManager", SessionManager.class));
}
@Bean
@ConditionalOnProperty(name = "spring.cloud.config.server.vault.skip-ssl-validation", havingValue = "true")
@NonNull
public ClientFactoryWrapper clientHttpRequestFactoryWrapper() {
return new ClientFactoryWrapper(disableSSlHttpClient5());
}
private ClientFactoryWrapper getClientFactoryWrapper() {
return getBeanFactory().getBean("clientHttpRequestFactoryWrapper", ClientFactoryWrapper.class);
}
private HttpComponentsClientHttpRequestFactory disableSSlHttpClient5() {
SSLContext sslContext;
try {
sslContext = SSLContextBuilder.create()
.loadTrustMaterial((X509Certificate[] _, String _) -> true)
.build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
throw new RuntimeException(e);
}
Registry<ConnectionSocketFactory> socketRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register(URIScheme.HTTPS.getId(), new SSLConnectionSocketFactory(sslContext))
.register(URIScheme.HTTP.getId(), new PlainConnectionSocketFactory())
.build();
CloseableHttpClient httpClient = HttpClientBuilder.create()
.setConnectionManager(new PoolingHttpClientConnectionManager(socketRegistry))
.setConnectionManagerShared(true)
.build();
return new HttpComponentsClientHttpRequestFactory(httpClient);
}
}
class DefaultRestTemplateFactory implements RestTemplateFactory {
private final ClientHttpRequestFactory requestFactory;
private final Function<ClientHttpRequestFactory, RestTemplateBuilder> builderFunction;
public DefaultRestTemplateFactory(ClientHttpRequestFactory requestFactory,
Function<ClientHttpRequestFactory, RestTemplateBuilder> builderFunction) {
this.requestFactory = requestFactory;
this.builderFunction = builderFunction;
}
@Override
@NonNull
public RestTemplate create(@Nullable Consumer<RestTemplateBuilder> customizer) {
RestTemplateBuilder builder = this.builderFunction.apply(this.requestFactory);
if (customizer != null) {
customizer.accept(builder);
}
return builder.build();
}
}
虽然已经晚了,但我还是会发布答案并希望对某人有所帮助。基于Vault跳过ssl验证属性,我们可以覆盖并创建bean(ClientFactoryWrapper是主要的)并扩展AbstractVaultConfiguration,它负责为Spring Vault自动配置ClientFactoryWrapper。这里使用了 spring.cloud.config.server.vault 的属性,但如果需要,可以无缝更改为 spring.cloud.vault。