This commit adds examples in our documentation for - An HLRC instance authenticating to an elasticsearch cluster using an elasticsearch token service access token or an API key - An HLRC instance connecting to an elasticsearch cluster that is setup for TLS on the HTTP layer when the CA certificate of the cluster is available either as a PEM file or a keystore - An HLRC instance connecting to an elasticsearch cluster that requires client authentication where the client key and certificate are available in a keystore Co-Authored-By: Lisa Cawley <lcawley@elastic.co>
This commit is contained in:
parent
46166b9b40
commit
81e7d926f6
|
@ -51,10 +51,14 @@ import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
|
import java.security.cert.Certificate;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
@ -379,11 +383,11 @@ public class RestClientDocumentation {
|
||||||
//end::rest-client-config-disable-preemptive-auth
|
//end::rest-client-config-disable-preemptive-auth
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Path keyStorePath = Paths.get("");
|
|
||||||
String keyStorePass = "";
|
String keyStorePass = "";
|
||||||
//tag::rest-client-config-encrypted-communication
|
//tag::rest-client-config-encrypted-communication
|
||||||
KeyStore truststore = KeyStore.getInstance("jks");
|
Path trustStorePath = Paths.get("/path/to/truststore.p12");
|
||||||
try (InputStream is = Files.newInputStream(keyStorePath)) {
|
KeyStore truststore = KeyStore.getInstance("pkcs12");
|
||||||
|
try (InputStream is = Files.newInputStream(trustStorePath)) {
|
||||||
truststore.load(is, keyStorePass.toCharArray());
|
truststore.load(is, keyStorePass.toCharArray());
|
||||||
}
|
}
|
||||||
SSLContextBuilder sslBuilder = SSLContexts.custom()
|
SSLContextBuilder sslBuilder = SSLContexts.custom()
|
||||||
|
@ -400,5 +404,87 @@ public class RestClientDocumentation {
|
||||||
});
|
});
|
||||||
//end::rest-client-config-encrypted-communication
|
//end::rest-client-config-encrypted-communication
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
//tag::rest-client-config-trust-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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//end::rest-client-config-trust-ca-pem
|
||||||
|
}
|
||||||
|
{
|
||||||
|
String trustStorePass = "";
|
||||||
|
String keyStorePass = "";
|
||||||
|
//tag::rest-client-config-mutual-tls-authentication
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//end::rest-client-config-mutual-tls-authentication
|
||||||
|
}
|
||||||
|
{
|
||||||
|
//tag::rest-client-auth-bearer-token
|
||||||
|
RestClientBuilder builder = RestClient.builder(
|
||||||
|
new HttpHost("localhost", 9200, "http"));
|
||||||
|
Header[] defaultHeaders =
|
||||||
|
new Header[]{new BasicHeader("Authorization",
|
||||||
|
"Bearer u6iuAxZ0RG1Kcm5jVFI4eU4tZU9aVFEwT2F3")};
|
||||||
|
builder.setDefaultHeaders(defaultHeaders);
|
||||||
|
//end::rest-client-auth-bearer-token
|
||||||
|
}
|
||||||
|
{
|
||||||
|
//tag::rest-client-auth-api-key
|
||||||
|
String apiKeyId = "uqlEyn8B_gQ_jlvwDIvM";
|
||||||
|
String apiKeySecret = "HxHWk2m4RN-V_qg9cDpuX";
|
||||||
|
String apiKeyAuth =
|
||||||
|
Base64.getEncoder().encodeToString(
|
||||||
|
(apiKeyId + ":" + apiKeySecret)
|
||||||
|
.getBytes(StandardCharsets.UTF_8));
|
||||||
|
RestClientBuilder builder = RestClient.builder(
|
||||||
|
new HttpHost("localhost", 9200, "http"));
|
||||||
|
Header[] defaultHeaders =
|
||||||
|
new Header[]{new BasicHeader("Authorization",
|
||||||
|
"ApiKey " + apiKeyAuth)};
|
||||||
|
builder.setDefaultHeaders(defaultHeaders);
|
||||||
|
//end::rest-client-auth-api-key
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,21 +64,75 @@ include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-config-disa
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
<1> Disable preemptive authentication
|
<1> Disable preemptive authentication
|
||||||
|
|
||||||
|
=== Other authentication methods
|
||||||
|
|
||||||
|
==== Elasticsearch Token Service tokens
|
||||||
|
|
||||||
|
If you want the client to authenticate with an Elasticsearch access token, set the relevant HTTP request header.
|
||||||
|
If the client makes requests on behalf of a single user only, you can set the necessary `Authorization` header as a default header as shown
|
||||||
|
in the following example:
|
||||||
|
|
||||||
|
["source","java",subs="attributes,callouts,macros"]
|
||||||
|
--------------------------------------------------
|
||||||
|
include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-auth-bearer-token]
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
==== Elasticsearch API keys
|
||||||
|
|
||||||
|
If you want the client to authenticate with an Elasticsearch API key, set the relevant HTTP request header.
|
||||||
|
If the client makes requests on behalf of a single user only, you can set the necessary `Authorization` header as a default header as shown
|
||||||
|
in the following example:
|
||||||
|
|
||||||
|
["source","java",subs="attributes,callouts,macros"]
|
||||||
|
--------------------------------------------------
|
||||||
|
include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-auth-api-key]
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
=== Encrypted communication
|
=== Encrypted communication
|
||||||
|
|
||||||
Encrypted communication can also be configured through the
|
Encrypted communication using TLS can also be configured through the
|
||||||
`HttpClientConfigCallback`. The
|
`HttpClientConfigCallback`. The
|
||||||
https://hc.apache.org/httpcomponents-asyncclient-dev/httpasyncclient/apidocs/org/apache/http/impl/nio/client/HttpAsyncClientBuilder.html[`org.apache.http.impl.nio.client.HttpAsyncClientBuilder`]
|
https://hc.apache.org/httpcomponents-asyncclient-dev/httpasyncclient/apidocs/org/apache/http/impl/nio/client/HttpAsyncClientBuilder.html[`org.apache.http.impl.nio.client.HttpAsyncClientBuilder`]
|
||||||
received as an argument exposes multiple methods to configure encrypted
|
received as an argument exposes multiple methods to configure encrypted
|
||||||
communication: `setSSLContext`, `setSSLSessionStrategy` and
|
communication: `setSSLContext`, `setSSLSessionStrategy` and
|
||||||
`setConnectionManager`, in order of precedence from the least important.
|
`setConnectionManager`, in order of precedence from the least important.
|
||||||
The following is an example:
|
|
||||||
|
When accessing an Elasticsearch cluster that is setup for TLS on the HTTP layer, the client needs to trust the certificate that
|
||||||
|
Elasticsearch is using.
|
||||||
|
The following is an example of setting up the client to trust the CA that has signed the certificate that Elasticsearch is using, when
|
||||||
|
that CA certificate is available in a PKCS#12 keystore:
|
||||||
|
|
||||||
["source","java",subs="attributes,callouts,macros"]
|
["source","java",subs="attributes,callouts,macros"]
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-config-encrypted-communication]
|
include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-config-encrypted-communication]
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
|
The following is an example of setting up the client to trust the CA that has signed the certificate that Elasticsearch is using, when
|
||||||
|
that CA certificate is available as a PEM encoded file.
|
||||||
|
|
||||||
|
["source","java",subs="attributes,callouts,macros"]
|
||||||
|
--------------------------------------------------
|
||||||
|
include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-config-trust-ca-pem]
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
When Elasticsearch is configured to require client TLS authentication, for example when a PKI realm is configured, the client needs to provide
|
||||||
|
a client certificate during the TLS handshake in order to authenticate. The following is an example of setting up the client for TLS
|
||||||
|
authentication with a certificate and a private key that are stored in a PKCS#12 keystore.
|
||||||
|
|
||||||
|
["source","java",subs="attributes,callouts,macros"]
|
||||||
|
--------------------------------------------------
|
||||||
|
include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-config-mutual-tls-authentication]
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
If the client certificate and key are not available in a keystore but rather as PEM encoded files, you cannot use them
|
||||||
|
directly to build an SSLContext. You must rely on external libraries to parse the PEM key into a PrivateKey instance. Alternatively, you
|
||||||
|
can use external tools to build a keystore from your PEM files, as shown in the following example:
|
||||||
|
|
||||||
|
```
|
||||||
|
openssl pkcs12 -export -in client.crt -inkey private_key.pem \
|
||||||
|
-name "client" -out client.p12
|
||||||
|
```
|
||||||
|
|
||||||
If no explicit configuration is provided, the http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#CustomizingStores[system default configuration]
|
If no explicit configuration is provided, the http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#CustomizingStores[system default configuration]
|
||||||
will be used.
|
will be used.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue