From 7d61f87fad98c5da01e4b51ac7d5d54e62a0a1ab Mon Sep 17 00:00:00 2001 From: sriram22 Date: Fri, 17 Jan 2025 00:16:49 -0600 Subject: [PATCH 1/2] changes to include apikey configuration for elastic search rest client --- .../lowlevel/runtime/ElasticsearchConfig.java | 10 ++++++++++ .../lowlevel/runtime/RestClientBuilderHelper.java | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/ElasticsearchConfig.java b/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/ElasticsearchConfig.java index 6b4ccf0fc04dd..290c5031862b7 100644 --- a/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/ElasticsearchConfig.java +++ b/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/ElasticsearchConfig.java @@ -28,6 +28,16 @@ public interface ElasticsearchConfig { @WithDefault("http") String protocol(); + /** + * The API Key ID for Elasticsearch authentication. + */ + Optional apiKeyId(); + + /** + * The API Key Secret for Elasticsearch authentication. + */ + Optional apiKeySecret(); + /** * The username for basic HTTP authentication. */ diff --git a/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/RestClientBuilderHelper.java b/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/RestClientBuilderHelper.java index f17e348c1ea81..3bd3dfd3af223 100644 --- a/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/RestClientBuilderHelper.java +++ b/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/RestClientBuilderHelper.java @@ -1,9 +1,13 @@ package io.quarkus.elasticsearch.restclient.lowlevel.runtime; import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Base64; import java.util.List; +import org.apache.http.Header; +import org.apache.http.HttpHeaders; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; @@ -12,6 +16,7 @@ import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; import org.apache.http.impl.nio.reactor.IOReactorConfig; +import org.apache.http.message.BasicHeader; import org.apache.http.nio.conn.NoopIOSessionStrategy; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; @@ -63,6 +68,15 @@ public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpCli credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(config.username().get(), config.password().orElse(null))); httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + } else if (config.apiKeyId().isPresent() && config.apiKeySecret().isPresent()) { + String apiKeyId = config.apiKeyId().get(); + String apiKeySecret = config.apiKeySecret().get(); + + String apiKeyAuth = Base64.getEncoder().encodeToString( + (apiKeyId + ":" + apiKeySecret).getBytes(StandardCharsets.UTF_8)); + Header apiKeyHeader = new BasicHeader(HttpHeaders.AUTHORIZATION, "ApiKey " + apiKeyAuth); + builder.setDefaultHeaders(new Header[] { apiKeyHeader }); + LOG.info("API Key authentication is enabled."); } if (config.ioThreadCounts().isPresent()) { From 953cbf29ddb921893d335257032d62ae85a4dad1 Mon Sep 17 00:00:00 2001 From: sriram22 Date: Fri, 17 Jan 2025 00:16:49 -0600 Subject: [PATCH 2/2] changes to include apikey configuration for elastic search rest client --- .../lowlevel/runtime/ElasticsearchConfig.java | 16 +++- .../runtime/RestClientBuilderHelper.java | 80 ++++++++++++++----- 2 files changed, 71 insertions(+), 25 deletions(-) diff --git a/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/ElasticsearchConfig.java b/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/ElasticsearchConfig.java index 290c5031862b7..54f1bd8128d80 100644 --- a/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/ElasticsearchConfig.java +++ b/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/ElasticsearchConfig.java @@ -10,6 +10,7 @@ import io.quarkus.runtime.annotations.ConfigRoot; import io.smallrye.config.ConfigMapping; import io.smallrye.config.WithDefault; +import io.smallrye.config.WithParentName; @ConfigMapping(prefix = "quarkus.elasticsearch") @ConfigRoot(phase = ConfigPhase.RUN_TIME) @@ -29,14 +30,21 @@ public interface ElasticsearchConfig { String protocol(); /** - * The API Key ID for Elasticsearch authentication. + * Retrieves the Configuration for API Key Authentication */ - Optional apiKeyId(); + @WithParentName + Optional esApiKeyAuth(); /** - * The API Key Secret for Elasticsearch authentication. + * Represents the API Key authentication details for Elasticsearch */ - Optional apiKeySecret(); + interface EsApiKeyAuth { + + /** + * Retrieves the API key used for authentication. + */ + String apiKey(); + } /** * The username for basic HTTP authentication. diff --git a/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/RestClientBuilderHelper.java b/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/RestClientBuilderHelper.java index 3bd3dfd3af223..95d16c73dec91 100644 --- a/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/RestClientBuilderHelper.java +++ b/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/RestClientBuilderHelper.java @@ -1,9 +1,8 @@ package io.quarkus.elasticsearch.restclient.lowlevel.runtime; import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Base64; +import java.util.Collections; import java.util.List; import org.apache.http.Header; @@ -59,25 +58,9 @@ public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder reques builder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { @Override public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { - if (config.username().isPresent()) { - if (!"https".equalsIgnoreCase(config.protocol())) { - LOG.warn("Using Basic authentication in HTTP implies sending plain text passwords over the wire, " + - "use the HTTPS protocol instead."); - } - CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, - new UsernamePasswordCredentials(config.username().get(), config.password().orElse(null))); - httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); - } else if (config.apiKeyId().isPresent() && config.apiKeySecret().isPresent()) { - String apiKeyId = config.apiKeyId().get(); - String apiKeySecret = config.apiKeySecret().get(); - - String apiKeyAuth = Base64.getEncoder().encodeToString( - (apiKeyId + ":" + apiKeySecret).getBytes(StandardCharsets.UTF_8)); - Header apiKeyHeader = new BasicHeader(HttpHeaders.AUTHORIZATION, "ApiKey " + apiKeyAuth); - builder.setDefaultHeaders(new Header[] { apiKeyHeader }); - LOG.info("API Key authentication is enabled."); - } + + EsAuth authMethod = checkAuthMethod(config); + authMethod.apply(httpClientBuilder, config); if (config.ioThreadCounts().isPresent()) { IOReactorConfig ioReactorConfig = IOReactorConfig.custom() @@ -106,6 +89,7 @@ public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpCli } return result; } + }); return builder; @@ -126,4 +110,58 @@ public static Sniffer createSniffer(RestClient client, ElasticsearchConfig confi return builder.build(); } + + public enum EsAuth { + NONE { + @Override + public void apply(HttpAsyncClientBuilder httpClientBuilder, ElasticsearchConfig config) { + // No authentication needed + } + }, + + BASIC { + @Override + public void apply(HttpAsyncClientBuilder httpClientBuilder, ElasticsearchConfig config) { + if (config.username().isPresent()) { + if (!"https".equalsIgnoreCase(config.protocol())) { + LOG.warn("Using Basic authentication in HTTP implies sending plain text passwords over the wire, " + + "use the HTTPS protocol instead."); + } + + CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(AuthScope.ANY, + new UsernamePasswordCredentials(config.username().get(), + config.password().orElse(null))); + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + } + } + }, + + API_KEY { + @Override + public void apply(HttpAsyncClientBuilder httpClientBuilder, ElasticsearchConfig config) { + if (config.esApiKeyAuth().isPresent()) { + ElasticsearchConfig.EsApiKeyAuth auth = config.esApiKeyAuth().get(); + Header apiKeyHeader = new BasicHeader(HttpHeaders.AUTHORIZATION, + "ApiKey " + auth.apiKey()); + httpClientBuilder.setDefaultHeaders(Collections.singleton(apiKeyHeader)); + LOG.info("API Key authentication is enabled."); + } + } + }; + + public abstract void apply(HttpAsyncClientBuilder httpClientBuilder, ElasticsearchConfig config); + } + + private static EsAuth checkAuthMethod(ElasticsearchConfig config) { + boolean hasBasic = config.username().isPresent(); + boolean hasApiKey = config.esApiKeyAuth().isPresent(); + + if (hasBasic && hasApiKey) { + LOG.warn("Multiple authentication methods configured. Defaulting to Basic Authentication."); + return EsAuth.BASIC; + } + + return hasApiKey ? EsAuth.API_KEY : hasBasic ? EsAuth.BASIC : EsAuth.NONE; + } }