加密通信编辑

可以使用 HttpClientConfigCallback 配置使用 TLS 的加密通信。作为参数接收的 org.apache.http.impl.nio.client.HttpAsyncClientBuilder 公开了多种方法来配置加密通信:setSSLContextsetSSLSessionStrategysetConnectionManager,按优先级从最低到最高排序。

当访问在 HTTP 层为 TLS 设置的 Elasticsearch 集群时,客户端需要信任 Elasticsearch 使用的证书。以下示例展示了如何设置客户端以信任已签署 Elasticsearch 使用的证书的 CA,前提是该 CA 证书在 PKCS#12 密钥库中可用。

Path trustStorePath = Paths.get("/path/to/truststore.p12");
KeyStore truststore = KeyStore.getInstance("pkcs12");
try (InputStream is = Files.newInputStream(trustStorePath)) {
    truststore.load(is, keyStorePass.toCharArray());
}
SSLContextBuilder sslBuilder = SSLContexts.custom()
    .loadTrustMaterial(truststore, null);
final SSLContext sslContext = sslBuilder.build();
RestClientBuilder builder = RestClient.builder(
    new HttpHost("localhost", 9200, "https"))
    .setHttpClientConfigCallback(new HttpClientConfigCallback() {
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(
                HttpAsyncClientBuilder httpClientBuilder) {
            return httpClientBuilder.setSSLContext(sslContext);
        }
    });

以下示例展示了如何设置客户端以信任已签署 Elasticsearch 使用的证书的 CA,前提是该 CA 证书以 PEM 编码文件形式可用。

Path caCertificatePath = Paths.get("/path/to/ca.crt");
CertificateFactory factory =
    CertificateFactory.getInstance("X.509");
Certificate trustedCa;
try (InputStream is = Files.newInputStream(caCertificatePath)) {
    trustedCa = factory.generateCertificate(is);
}
KeyStore trustStore = KeyStore.getInstance("pkcs12");
trustStore.load(null, null);
trustStore.setCertificateEntry("ca", trustedCa);
SSLContextBuilder sslContextBuilder = SSLContexts.custom()
    .loadTrustMaterial(trustStore, null);
final SSLContext sslContext = sslContextBuilder.build();
RestClient.builder(
    new HttpHost("localhost", 9200, "https"))
    .setHttpClientConfigCallback(new HttpClientConfigCallback() {
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(
            HttpAsyncClientBuilder httpClientBuilder) {
            return httpClientBuilder.setSSLContext(sslContext);
        }
    });

当 Elasticsearch 配置为要求客户端 TLS 身份验证时(例如,当配置 PKI 域时),客户端需要在 TLS 握手期间提供客户端证书以进行身份验证。以下示例展示了如何设置客户端以使用存储在 PKCS#12 密钥库中的证书和私钥进行 TLS 身份验证。

Path trustStorePath = Paths.get("/path/to/your/truststore.p12");
Path keyStorePath = Paths.get("/path/to/your/keystore.p12");
KeyStore trustStore = KeyStore.getInstance("pkcs12");
KeyStore keyStore = KeyStore.getInstance("pkcs12");
try (InputStream is = Files.newInputStream(trustStorePath)) {
    trustStore.load(is, trustStorePass.toCharArray());
}
try (InputStream is = Files.newInputStream(keyStorePath)) {
    keyStore.load(is, keyStorePass.toCharArray());
}
SSLContextBuilder sslBuilder = SSLContexts.custom()
    .loadTrustMaterial(trustStore, null)
    .loadKeyMaterial(keyStore, keyStorePass.toCharArray());
final SSLContext sslContext = sslBuilder.build();
RestClientBuilder builder = RestClient.builder(
    new HttpHost("localhost", 9200, "https"))
    .setHttpClientConfigCallback(new HttpClientConfigCallback() {
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(
            HttpAsyncClientBuilder httpClientBuilder) {
            return httpClientBuilder.setSSLContext(sslContext);
        }
    });

如果客户端证书和密钥不在密钥库中,而是以 PEM 编码文件形式提供,则无法直接使用它们来构建 SSLContext。您必须依赖外部库将 PEM 密钥解析为 PrivateKey 实例。或者,您可以使用外部工具从 PEM 文件构建密钥库,如以下示例所示。

openssl pkcs12 -export -in client.crt -inkey private_key.pem \
        -name "client" -out client.p12

如果没有提供显式配置,将使用 系统默认配置