Skip to content

Changes to include apikey configuration for elastic search rest client #45688

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

sriram22
Copy link

@sriram22 sriram22 commented Jan 17, 2025

Adding support for apikey to elasticsearch low level rest client
Fixes #45490

Copy link

quarkus-bot bot commented Jan 17, 2025

Thanks for your pull request!

Your pull request does not follow our editorial rules. Could you have a look?

  • title should preferably start with an uppercase character (if it makes sense!)
  • description should not be empty, describe your intent or provide links to the issues this PR is fixing (using Fixes #NNNNN) or changelogs

This message is automatically generated by a bot.

Copy link

quarkus-bot bot commented Jan 17, 2025

/cc @gsmet (elasticsearch), @loicmathieu (elasticsearch), @marko-bekhta (elasticsearch)

Copy link
Contributor

@marko-bekhta marko-bekhta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @sriram22,

Thanks for the PR. I've added a comment inline and you might also want to take a look at that message from the quarkus bot 😉😃.

@@ -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()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should add a bit more validation... e.g. we should check that only one auth method is configured, and if there are both, we should let the user know (since we'd only apply one). And we probably would want to check that outside of the customize method 🤔

Also, maybe it's worth creating a small enum with auth methods, e.g. NONE, BASIC, API_KEY where you'd have a method that applies required transformations and here in the customizer you'd just make a call authMethod.apply(builder, config )

@sriram22 sriram22 changed the title changes to include apikey configuration for elastic search rest client Changes to include apikey configuration for elastic search rest client Jan 17, 2025
/**
* The API Key ID for Elasticsearch authentication.
*/
Optional<String> apiKeyId();
Copy link
Contributor

@manofthepeace manofthepeace Jan 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since both apiKeyId and apiKeySecret are needed or not I think this should be in a nested interface like this;

@WithParentName
Optional<EsAuth> esAuth()

interface EsAuth {
    String apiKeyId
    String apiKeySecret
}

This way the code can just check for esAuth.isPresent()

esAuth is a quick name just as an example. WithParentName only if you do not want to have an extra level to the config.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

used this as reference for configuration https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/_other_authentication_methods.html#_elasticsearch_api_keys but looks like the apikey generated from elastic search already has base64 encoded apikeyid and secret. nevertheless i have made updates

@sriram22 sriram22 force-pushed the elasticsearchrest/apikeyconfig branch from 9f6366e to 953cbf2 Compare January 25, 2025 05:24
Copy link
Contributor

@marko-bekhta marko-bekhta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updated PR! 🎉
I've added a few questions inline 😃.

BASIC {
@Override
public void apply(HttpAsyncClientBuilder httpClientBuilder, ElasticsearchConfig config) {
if (config.username().isPresent()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since you are returning an auth type after you've checked the presence of the properties these very outer ifs aren't necessary anymore, right?

Header apiKeyHeader = new BasicHeader(HttpHeaders.AUTHORIZATION,
"ApiKey " + auth.apiKey());
httpClientBuilder.setDefaultHeaders(Collections.singleton(apiKeyHeader));
LOG.info("API Key authentication is enabled.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
LOG.info("API Key authentication is enabled.");

I'd say let's be consistent here, since we aren't logging at info for the basic auth, we shouldn't log here too.

Comment on lines +160 to +163
if (hasBasic && hasApiKey) {
LOG.warn("Multiple authentication methods configured. Defaulting to Basic Authentication.");
return EsAuth.BASIC;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd still say it's better to throw an exception here instead of logging a warning since this is a "misconfiguration", and a user would want to be precise about the auth methods.

Comment on lines +32 to +48
/**
* Retrieves the Configuration for API Key Authentication
*/
@WithParentName
Optional<EsApiKeyAuth> esApiKeyAuth();

/**
* Represents the API Key authentication details for Elasticsearch
*/
interface EsApiKeyAuth {

/**
* Retrieves the API key used for authentication.
*/
String apiKey();
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since it's a single property.. do we want to wrap it in the interface? This would probably make more sense for the basic auth where there's a pair of properties... if we want to have auth grouped somehow maybe we can consider going with something like:

# basic
quarkus.elasticsearch.auth.basic.username=foo
quarkus.elasticsearch.auth.basic.password=bar
# or API key:
quarkus.elasticsearch.auth.api-key=foobar

but that would mean deprecating existing username/password properties and creating new alternatives for them too. @yrodiere do you think it's worth doing ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the way it's done is fine, if unnecessarily complex. @WithParentName means the interface is basically ignored, and the effective property key is quarkus.elasticsearch.api-key, which is fine by me.

So... no change needed here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

add apikey authentication support to quarkus-elasticsearch-rest-client
4 participants