加密通信

编辑

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

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

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);
        }
    });

以下是如何在 CA 证书可作为 PEM 编码文件提供时,设置客户端以信任已签署 Elasticsearch 使用的证书的 CA 的示例。

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

如果没有提供明确的配置,则将使用 系统默认配置