Skip to content

Instantly share code, notes, and snippets.

@AlrikG
Created July 19, 2023 08:08
Show Gist options
  • Save AlrikG/823f83c309e1cd63256e68522af7a38a to your computer and use it in GitHub Desktop.
Save AlrikG/823f83c309e1cd63256e68522af7a38a to your computer and use it in GitHub Desktop.
Elasticsearch SSL Client
package de.osp.adapter.elasticsearch;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
import de.osp.adapter.Config;
@Getter
@Setter
@EqualsAndHashCode
@Log4j2
public final class ElasticsearchClient implements Closeable
{
private static final boolean GENERATE_TRUSTSTORE = true;
private static final boolean SAVE_GENERATED_TRUSTSTORE = false;
private static final SSLContext SSL_CONTEXT;
private final CloseableHttpClient httpClient;
private final HttpHost httpHost;
private ElasticsearchClient(CloseableHttpClient httpClient, HttpHost httpHost)
{
this.httpClient = httpClient;
this.httpHost = httpHost;
}
static
{
SSL_CONTEXT = GENERATE_TRUSTSTORE ? createTruststore(Config.ES_CERT, Config.CERTIFICATE_ALIAS, Config.TRUSTSTORE_PASSWORD) : loadTruststore(Config.TRUSTSTORE_FILE, Config.TRUSTSTORE_PASSWORD);
}
private static SSLContext loadTruststore(String truststoreFile, String truststorePassword)
{
// generation: keytool -import -file es01.crt -alias elastic -keystore truststore.jks
try
{
return SSLContextBuilder.create().loadTrustMaterial(new File(truststoreFile), truststorePassword.toCharArray()).build();
}
catch (Exception e)
{
log.error("Could not create truststore", e);
throw new RuntimeException("Could not create truststore", e);
}
}
private static SSLContext createTruststore(String pemFile, String certificateAlias, String truststorePassword)
{
// Load the PEM certificate
try (InputStream inputStream = new ByteArrayInputStream(pemFile.getBytes(StandardCharsets.UTF_8)))
{
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate) cf.generateCertificate(inputStream);
// Create a new KeyStore
KeyStore truststore = KeyStore.getInstance(KeyStore.getDefaultType());
truststore.load(null, truststorePassword.toCharArray());
// Add the certificate to the truststore
truststore.setCertificateEntry(certificateAlias, certificate);
// Save the truststore to a file
if (SAVE_GENERATED_TRUSTSTORE)
{
String truststoreFile = "truststore_generated.jks";
try (FileOutputStream outputStream = new FileOutputStream(truststoreFile))
{
truststore.store(outputStream, truststorePassword.toCharArray());
}
}
log.info("Truststore created successfully!");
return SSLContextBuilder.create().loadTrustMaterial(truststore, TrustSelfSignedStrategy.INSTANCE).build();
}
catch (Exception e)
{
log.error("Could not create truststore", e);
throw new RuntimeException("Could not create truststore", e);
}
}
private static CloseableHttpClient https()
{
// Create the credentials provider
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(Config.ES_USER, Config.ES_PASSWORD));
// Create the SSLContext with the truststore
return HttpClients.custom().setMaxConnPerRoute(100).setMaxConnTotal(100).setDefaultCredentialsProvider(credentialsProvider).setSSLContext(SSL_CONTEXT).build();
}
private static CloseableHttpClient http()
{
return HttpClients.custom().setMaxConnPerRoute(100).setMaxConnTotal(100).build();
}
public static ElasticsearchClient build()
{
CloseableHttpClient httpClient = "https".equals(Config.ES_SCHEME) ? https() : http();
HttpHost httpHost = new HttpHost(Config.ES_HOST, Config.ES_PORT, Config.ES_SCHEME);
return new ElasticsearchClient(httpClient, httpHost);
}
@Override
public void close() throws IOException
{
httpClient.close();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment