From d7dfdde2737b4205e9d9ed982f2f061b7b68da4c Mon Sep 17 00:00:00 2001 From: Todd Kennedy <95242064+tkennedy1-godaddy@users.noreply.github.com> Date: Wed, 11 Jun 2025 15:54:59 -0700 Subject: [PATCH] out_es: add apikey to available auth types Allow for using an API key as an authentication type to elastic. Signed-off-by: Todd Kennedy <95242064+tkennedy1-godaddy@users.noreply.github.com> --- plugins/out_es/es.c | 26 ++++++++++++- plugins/out_es/es.h | 1 + tests/runtime/out_elasticsearch.c | 61 +++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/plugins/out_es/es.c b/plugins/out_es/es.c index 4e653e7e349..5d8a8da3eab 100644 --- a/plugins/out_es/es.c +++ b/plugins/out_es/es.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include @@ -822,6 +824,7 @@ static void cb_es_flush(struct flb_event_chunk *event_chunk, struct flb_http_client *c; flb_sds_t signature = NULL; int compressed = FLB_FALSE; + flb_sds_t header_line = NULL; /* Get upstream connection */ u_conn = flb_upstream_conn_get(ctx->u); @@ -885,6 +888,23 @@ static void cb_es_flush(struct flb_event_chunk *event_chunk, else if (ctx->cloud_user && ctx->cloud_passwd) { flb_http_basic_auth(c, ctx->cloud_user, ctx->cloud_passwd); } + else if (ctx->http_api_key) { + header_line = flb_sds_printf(NULL, "ApiKey %s", ctx->http_api_key); + if (header_line == NULL) { + flb_plg_error(ctx->ins, "failed to format API key auth header"); + goto retry; + } + + if (flb_http_add_header(c, + FLB_HTTP_HEADER_AUTH, strlen(FLB_HTTP_HEADER_AUTH), + header_line, flb_sds_len(header_line)) != 0) { + flb_plg_error(ctx->ins, "failed to add API key auth header"); + flb_sds_destroy(header_line); + goto retry; + } + + flb_sds_destroy(header_line); + } #ifdef FLB_HAVE_AWS if (ctx->has_aws_auth == FLB_TRUE) { @@ -1099,6 +1119,11 @@ static struct flb_config_map config_map[] = { 0, FLB_TRUE, offsetof(struct flb_elasticsearch, http_passwd), "Password for user defined in HTTP_User" }, + { + FLB_CONFIG_MAP_STR, "http_api_key", NULL, + 0, FLB_TRUE, offsetof(struct flb_elasticsearch, http_api_key), + "Base-64 encoded API key credential for Elasticsearch" + }, /* HTTP Compression */ { @@ -1288,7 +1313,6 @@ static struct flb_config_map config_map[] = { 0, FLB_TRUE, offsetof(struct flb_elasticsearch, trace_error), "When enabled print the Elasticsearch exception to stderr (for diag only)" }, - /* EOF */ {0} }; diff --git a/plugins/out_es/es.h b/plugins/out_es/es.h index b6512ebc2a0..04e603c8e59 100644 --- a/plugins/out_es/es.h +++ b/plugins/out_es/es.h @@ -54,6 +54,7 @@ struct flb_elasticsearch { /* HTTP Auth */ char *http_user; char *http_passwd; + char *http_api_key; /* Elastic Cloud Auth */ char *cloud_user; diff --git a/tests/runtime/out_elasticsearch.c b/tests/runtime/out_elasticsearch.c index 3b67d56d432..bd34dc27412 100644 --- a/tests/runtime/out_elasticsearch.c +++ b/tests/runtime/out_elasticsearch.c @@ -7,6 +7,21 @@ #include "data/es/json_es.h" /* JSON_ES */ +static void cb_check_http_api_key(void *ctx, int ffd, + int res_ret, void *res_data, + size_t res_size, void *data) +{ + char *api_key = data; + + TEST_CHECK(api_key != NULL); + TEST_CHECK(strlen(api_key) > 0); + + TEST_CHECK(strcmp(api_key, "my-api-key-for-elasticsearch") == 0); + + flb_free(res_data); +} + + static void cb_check_write_op_index(void *ctx, int ffd, int res_ret, void *res_data, size_t res_size, void *data) @@ -722,6 +737,51 @@ void flb_test_div0() flb_destroy(ctx); } +void flb_test_http_api_key() +{ + int ret; + int size = sizeof(JSON_ES) - 1; + flb_ctx_t *ctx; + int in_ffd; + int out_ffd; + char *api_key = "my-api-key-for-elasticsearch"; + + /* Create context, flush every second (some checks omitted here) */ + ctx = flb_create(); + flb_service_set(ctx, "flush", "1", "grace", "1", NULL); + + /* Lib input mode */ + in_ffd = flb_input(ctx, (char *) "lib", NULL); + flb_input_set(ctx, in_ffd, "tag", "test", NULL); + + /* Elasticsearch output */ + out_ffd = flb_output(ctx, (char *) "es", NULL); + flb_output_set(ctx, out_ffd, + "match", "test", + NULL); + + /* Configure http_api_key */ + flb_output_set(ctx, out_ffd, + "http_api_key", api_key, + NULL); + + /* Enable test mode */ + ret = flb_output_set_test(ctx, out_ffd, "formatter", + cb_check_http_api_key, + api_key, NULL); + + /* Start */ + ret = flb_start(ctx); + TEST_CHECK(ret == 0); + + /* Ingest data sample */ + flb_lib_push(ctx, in_ffd, (char *) JSON_ES, size); + + sleep(2); + flb_stop(ctx); + flb_destroy(ctx); +} + static void cb_check_long_index(void *ctx, int ffd, int res_ret, void *res_data, size_t res_size, @@ -1012,6 +1072,7 @@ TEST_LIST = { {"tag_key" , flb_test_tag_key }, {"replace_dots" , flb_test_replace_dots }, {"id_key" , flb_test_id_key }, + {"http_api_key" , flb_test_http_api_key }, {"logstash_prefix_separator" , flb_test_logstash_prefix_separator }, {"response_success" , flb_test_response_success }, {"response_successes", flb_test_response_successes },