Elasticsearch:在 Java 客户端中使用 truststore 来创建 HTTPS 连接

1,287 阅读3分钟

在我之前的文章 “Elasticsearch:使用 Elasticsearch Java client 8.0 来连接带有 HTTPS 的集群” 里,我使用了两种方法,一直是使用 token 的方式,另外一种是使用 PEM 证书来进行连接的。在实际的使用中,有时我们的证书是以 PCKS12 格式的 truststore 格式的,那么我们该如何建立这种 HTTPS 的连接呢?

如果你还没有安装好自己的 Elasticsearch 集群,你可以参考我之前的文章 “如何在 Linux,MacOS 及 Windows 上进行安装 Elasticsearch” 来进行安装。

在接下来的示例中,我将使用 Elasticsearch 8.4.1 来进行展示。为了大家更好地理解我下面的代码,我把代码放到 github 上。你可以通过如下的命令来进行下载:

git clone https://github.com/liu-xiao-guo/elasticsearchjava-search8-https

例子

如上所示,Java 客户端和 Server 直接的验证图。针对我们的 Java 应用,我们需要在客户端创建一个 truststore 来建立联系。我们可以在 Elasticsearch 的安装目录下使用如下的命令来创建一个 truststore:

keytool -import -file http_ca.crt -keystore truststore.p12 -storepass password -noprompt -storetype pkcs12


1.  $ pwd
2.  /Users/liuxg/elastic/elasticsearch-8.4.1/config/certs
3.  $ keytool -import -file http_ca.crt -keystore truststore.p12 -storepass password -noprompt -storetype pkcs12
4.  Certificate was added to keystore
5.  $ ls
6.  http.p12       http_ca.crt    transport.p12  truststore.p12


如上所示,它在当前的目录下创建一个叫做 truststore.p12 的文件。它的密码是 password。我们可以使用如下的命令来查看这个 truststore 的内容:

keytool -keystore truststore.p12 -list


1.  $ keytool -keystore truststore.p12 -list
2.  Enter keystore password:  
3.  Keystore type: PKCS12
4.  Keystore provider: SUN

6.  Your keystore contains 1 entry

8.  mykey, Sep 26, 2022, trustedCertEntry, 
9.  Certificate fingerprint (SHA-256): F7:7C:44:13:CC:C6:A0:34:AC:97:67:F1:2B:9F:82:40:BF:30:1C:E9:56:CE:0D:96:10:9A:78:63:C4:A3:34:63


接下来,我们在 ElasticsearchJava.java 文件中添加如下的一个方法:

ElasticsearchJava.java

 `1.     private static synchronized void makeConnection_truststore() throws CertificateException, IOException, NoSuchAlgorithmException,
2.              KeyStoreException, KeyManagementException {
3.          final CredentialsProvider credentialsProvider =
4.                  new BasicCredentialsProvider();
5.          credentialsProvider.setCredentials(AuthScope.ANY,
6.                  new UsernamePasswordCredentials("elastic", "Qu9UByppvqRRyI0LkoI+"));

8.          String storePath = "/Users/liuxg/elastic/elasticsearch-8.4.1/config/certs/truststore.p12";
9.  //        String keyStorePass = "dI8wbt8VTkigRjxvOrvP9w";
10.          String keyStorePass = "password";
11.          Path trustStorePath = Paths.get(storePath);
12.          KeyStore truststore = KeyStore.getInstance("pkcs12");
13.          try (InputStream is = Files.newInputStream(trustStorePath)) {
14.              truststore.load(is, keyStorePass.toCharArray());
15.          }
16.          SSLContextBuilder sslBuilder = SSLContexts.custom()
17.                  .loadTrustMaterial(truststore, null);
18.          final SSLContext sslContext = sslBuilder.build();
19.          RestClientBuilder builder = RestClient.builder(
20.                          new HttpHost("localhost", 9200, "https"))
21.                  .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
22.                      @Override
23.                      public HttpAsyncClientBuilder customizeHttpClient(
24.                              HttpAsyncClientBuilder httpClientBuilder) {
25.                          return httpClientBuilder.setSSLContext(sslContext)
26.                                  .setDefaultCredentialsProvider(credentialsProvider);
27.                      }
28.                  });
29.          RestClient restClient = builder.build();

31.          // Create the transport with a Jackson mapper
32.          ElasticsearchTransport transport = new RestClientTransport(
33.                  restClient, new JacksonJsonpMapper());

35.          client = new ElasticsearchClient(transport);
36.          asyncClient = new ElasticsearchAsyncClient(transport);
37.      }`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

在上面,我们需要注意的是:

  • 你可以使用除 elastic 之外的其它用户账号及其密码来进行连接
  • 你需要修改 storePath 的路径,根据自己的安装及生成的 truststore 的文件路径
  • 你需要修改相应的 keyStorePass,根据自己的配置

我们使用如下的代码进行相应的连接并创建一个叫做 products 的索引:

 `1.          try {
2.              makeConnection_truststore();
3.          } catch (CertificateException e) {
4.              e.printStackTrace();
5.          } catch (NoSuchAlgorithmException e) {
6.              e.printStackTrace();
7.          } catch (KeyStoreException e) {
8.              e.printStackTrace();
9.          } catch (KeyManagementException e) {
10.              e.printStackTrace();
11.          }

13.          // Index data to an index products
14.          Product product = new Product("abc", "Bag", 42);

16.          IndexRequest<Object> indexRequest = new IndexRequest.Builder<>()
17.                  .index("products")
18.                  .id("abc")
19.                  .document(product)
20.                  .build();

22.          client.index(indexRequest);`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

我们运行上面的代码,并在 Kibana 中进行查看:

GET products/_search
`

1.  {
2.    "took": 0,
3.    "timed_out": false,
4.    "_shards": {
5.      "total": 1,
6.      "successful": 1,
7.      "skipped": 0,
8.      "failed": 0
9.    },
10.    "hits": {
11.      "total": {
12.        "value": 1,
13.        "relation": "eq"
14.      },
15.      "max_score": 1,
16.      "hits": [
17.        {
18.          "_index": "products",
19.          "_id": "abc",
20.          "_score": 1,
21.          "_source": {
22.            "id": "abc",
23.            "name": "Bag",
24.            "price": 42
25.          }
26.        }
27.      ]
28.    }
29.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

它表明,我们已经成功地创建了 products 索引。它说明了我们的连接是成功的。

参考:

【1】 Encrypted communication | Elasticsearch Java API Client [8.4] | Elastic