From 54ce30f4b8408b2c173f0bacb459da1d37569161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Hejman?= Date: Fri, 22 Nov 2024 14:33:12 +0100 Subject: [PATCH] Support auth against OpenSearch (#1030) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Little hackish, as it involves additional call to the backend (in order to decide whether use OpenSearch or Elasticsearch security endpoint) **but** given that we have auth header cache I think we might get away with that 😉 FWIW, Elasticsearch 7 uses the same [endpoint (`_security/_authenticate`)](https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-authenticate.html) as Elasticsearch 8 for auth (just verified :relieved:) --- quesma/elasticsearch/client.go | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/quesma/elasticsearch/client.go b/quesma/elasticsearch/client.go index d178adcd8..4568aab4a 100644 --- a/quesma/elasticsearch/client.go +++ b/quesma/elasticsearch/client.go @@ -13,7 +13,11 @@ import ( "time" ) -const esRequestTimeout = 5 * time.Second +const ( + esRequestTimeout = 5 * time.Second + elasticsearchSecurityEndpoint = "_security/_authenticate" + openSearchSecurityEndpoint = "_plugins/_security/api/account" +) type SimpleClient struct { client *http.Client @@ -41,7 +45,22 @@ func (es *SimpleClient) RequestWithHeaders(ctx context.Context, method, endpoint } func (es *SimpleClient) Authenticate(ctx context.Context, authHeader string) bool { - resp, err := es.doRequest(ctx, "GET", "_security/_authenticate", nil, http.Header{"Authorization": {authHeader}}) + var authEndpoint string + // This is really suboptimal, and we should find a better way to set this systematically (config perhaps?) + // OTOH, since we have auth cache in place, I am not concerned about this additional backend call - at least for the time being. + r, err := es.doRequest(ctx, "GET", "/", nil, http.Header{"Authorization": {authHeader}}) + if err != nil { + logger.ErrorWithCtx(ctx).Msgf("error sending request: %v", err) + return false + } + defer r.Body.Close() + + if isResponseFromElasticsearch(r) { + authEndpoint = elasticsearchSecurityEndpoint + } else { + authEndpoint = openSearchSecurityEndpoint + } + resp, err := es.doRequest(ctx, "GET", authEndpoint, nil, http.Header{"Authorization": {authHeader}}) if err != nil { logger.ErrorWithCtx(ctx).Msgf("error sending request: %v", err) return false @@ -66,3 +85,7 @@ func (es *SimpleClient) doRequest(ctx context.Context, method, endpoint string, } return es.client.Do(req) } + +func isResponseFromElasticsearch(resp *http.Response) bool { + return resp.Header.Get("X-Elastic-Product") != "" +}