java - 如何使用 HTTPS 连接 'spring boot application (2.3.4.RELEASE) with elasticsearch 7.9.2'

标签 java spring spring-boot elasticsearch ssl

我是 spring-boot 和 Elasticsearch 技术堆栈的新手,我想建立安全的 HTTPS 连接
在我的 spring-boot 应用程序和本地运行的 Elasticsearch 服务器之间。
这些是我在 elasticsearch.yml 中所做的配置
为 Elasticsearch 服务器提供凭据
xpack.security.enabled:真
xpack.security.transport.ssl.enabled:真
用于 Elasticsearch 集群内的安全节点间连接
xpack.security.transport.ssl.verification_mode:证书
xpack.security.transport.ssl.keystore.path:弹性证书.p12
xpack.security.transport.ssl.truststore.path:弹性证书.p12
用于与客户端和 elasticsearch 集群的安全 Https 连接
xpack.security.http.ssl.enabled:真
xpack.security.http.ssl.keystore.path:弹性证书.p12
xpack.security.http.ssl.truststore.path:弹性证书.p12
xpack.security.http.ssl.client_authentication:可选
启用 PKI 身份验证
xpack.security.authc.realms.pki.pki1.order: 1
我已根据此链接生成由生成的 CA 签名的 CA 和客户端证书
https://www.elastic.co/blog/elasticsearch-security-configure-tls-ssl-pki-authentication
我已将 CA 添加到我的 java keystore 中。
这是我用来与 elasticsearch 服务器建立连接的 java 代码。
@配置
公共(public)类 RestClientConfig 扩展 AbstractElasticsearchConfiguration {

private static final Logger LOG = LoggerFactory.getLogger(RestClientConfig.class);

private static final String CERT_FILE = "client.p12";
private static final String CERT_PASSWORD = "";
private static final String USER_NAME = "elastic";
private static final String USER_PASS = "pwd";

@Override
@Bean
public RestHighLevelClient elasticsearchClient() {

    final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
            .connectedTo("localhost:9200")  // set the address of the Elasticsearch cluster
            .usingSsl(createSSLContext())  // use the SSLContext with the client cert
            .withBasicAuth(USER_NAME, USER_PASS)   // use the headers for authentication
            .build();
    return RestClients.create(clientConfiguration).rest();
}

private SSLContext createSSLContext() {
    try {
        SSLContext sslContext = SSLContext.getInstance("TLS");
        KeyManager[] keyManagers = getKeyManagers();
        sslContext.init(keyManagers, null, null);
        return sslContext;
    } catch (Exception e) {
        LOG.error("cannot create SSLContext", e);
    }
    return null;
}

private KeyManager[] getKeyManagers()
        throws KeyStoreException, NoSuchAlgorithmException, IOException, CertificateException, UnrecoverableKeyException {
    try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(CERT_FILE)) {
        KeyStore clientKeyStore = KeyStore.getInstance("PKCS12");
        clientKeyStore.load(inputStream, CERT_PASSWORD.toCharArray());
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(clientKeyStore, CERT_PASSWORD.toCharArray());
        return kmf.getKeyManagers();
    }
}
我的客户端证书名为“client.p12”,包含在 spring-boot 应用程序的资源文件夹中。在 Elasticsearch 方面,一切似乎都很好。
但是当我运行 spring-boot 应用程序时,它会给出这个警告和异常
无法创建索引:主机名“localhost”与对等方提供的证书主题不匹配(CN=instance);嵌套异常是 java.lang.RuntimeException:
主机名“localhost”与对等方提供的证书主题不匹配(CN=instance)
java.io.IOException:主机名“localhost”与对等方提供的证书主题不匹配(CN=instance)
原因:javax.net.ssl.SSLPeerUnverifiedException:主机名“localhost”与对等方提供的证书主题不匹配(CN=instance)
我这样做是因为我想稍后将 Elasticsearch 服务器迁移到另一个 VPS 托管。
这是我用于生成客户端证书的命令
bin/elasticsearch-certutil 证书 --ca
配置/弹性堆栈-ca.p12
-name "CN=something,OU=Consulting Team,DC=mydomain,DC=com"
进入
客户端.p12 ENTER
进入
在互联网上搜索此错误,我发现我的客户端证书存在问题。它与带有弹性节点的 SAN 名称有关。但我的知识很少
关于这些证书的东西。所以这对我来说真的很困惑。如果有人可以给我详细的解释为什么会发生这种情况并解决这个问题,我真的很感激并感激不尽。适当的链接也将有所帮助。这个问题
已经问过了
How to connect 'spring boot 2.1 with elasticsearch 6.6' with cluster node 'https'?
关联
但我没有运气。

最佳答案

您的问题与另一个问题相似,请参见此处:Certificate for <localhost> doesn't match any of the subject alternative names
因此,我假设如果您将 SAN 扩展 localhost 添加为 DNS,并将 localhost 的 ip 地址添加到 elasticsearch 证书,它应该可以工作。因此添加以下附加参数:--dns localhost --ip 127.0. 0.1 .你可以试试下面的命令并在这里分享你的结果吗?

bin/elasticsearch-certutil cert --ca config/elastic-stack-ca.p12 -name "CN=something,OU=Consulting Team,DC=mydomain,DC=com" --dns localhost --ip 127.0. 0.1
顺便说一下,您已将 Elasticsearch 配置为可选地请求客户端证书,但未标记为必需,请参阅:xpack.security.http.ssl.client_authentication: optional .所以它不是必需的,因此创建一个 KeyManager 并从中构造一个 sslcontext 是没有意义的。但我认为您需要导出 Elasticsearch 证书的公共(public)证书,并通过将其转换为 TrustManager 并从中创建 sslcontext 将其提供给您的 http 客户端。我在这里有一个工作示例:ElasticSearch RestHighLevelClient SSL example .

关于java - 如何使用 HTTPS 连接 'spring boot application (2.3.4.RELEASE) with elasticsearch 7.9.2',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67657426/

相关文章:

java - 如何为 Spring 服务创建 Java 客户端?

Java:用于保存不同类型基元的通用集合

java - Spring MVC : Failed to convert property value of type String to Integer

java - 创建一个猜谜游戏

spring - Spring 常规网站和移动网站是否应该分开?

tomcat - 使用独立 Tomcat 的 Spring Boot 容器身份验证

Java 变量赋值给 double。为什么该值会转换为 double ?

java - 如何使用 Spring security 2 和 Apache Tomcat 7 设置将 JSESSIONID cookie 设置为安全

java - 如何返回用户拥有的角色列表?

java - 整合Spring Boot和Reactor-Kafka的KafkaReceiver