Add HLRC docs for AuthN and TLS (#51355) (#51551)

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:
Ioannis Kakavas 2020-01-29 08:14:38 +02:00 committed by GitHub
parent 46166b9b40
commit 81e7d926f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 145 additions and 5 deletions

View File

@ -51,10 +51,14 @@ import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
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.concurrent.CountDownLatch;
@ -379,11 +383,11 @@ public class RestClientDocumentation {
//end::rest-client-config-disable-preemptive-auth
}
{
Path keyStorePath = Paths.get("");
String keyStorePass = "";
//tag::rest-client-config-encrypted-communication
KeyStore truststore = KeyStore.getInstance("jks");
try (InputStream is = Files.newInputStream(keyStorePath)) {
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()
@ -400,5 +404,87 @@ public class RestClientDocumentation {
});
//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
}
}
}

View File

@ -64,21 +64,75 @@ include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-config-disa
--------------------------------------------------
<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 can also be configured through the
Encrypted communication using TLS can also be configured through 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`]
received as an argument exposes multiple methods to configure encrypted
communication: `setSSLContext`, `setSSLSessionStrategy` and
`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"]
--------------------------------------------------
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]
will be used.