From 99d844444232249a105eb99b190b123b8dca1b1c Mon Sep 17 00:00:00 2001 From: Abhishek Choudhary Date: Fri, 26 Jun 2026 11:36:39 +0545 Subject: [PATCH] feat(elasticsearch-logger): encrypt headers field at rest --- apisix/plugins/elasticsearch-logger.lua | 2 +- .../en/latest/plugins/elasticsearch-logger.md | 4 +- .../zh/latest/plugins/elasticsearch-logger.md | 4 +- t/plugin/elasticsearch-logger.t | 67 +++++++++++++++++++ 4 files changed, 72 insertions(+), 5 deletions(-) diff --git a/apisix/plugins/elasticsearch-logger.lua b/apisix/plugins/elasticsearch-logger.lua index 736b03219ae4..2d1dc7743397 100644 --- a/apisix/plugins/elasticsearch-logger.lua +++ b/apisix/plugins/elasticsearch-logger.lua @@ -111,7 +111,7 @@ local schema = { max_req_body_bytes = { type = "integer", minimum = 1, default = 524288 }, max_resp_body_bytes = { type = "integer", minimum = 1, default = 524288 }, }, - encrypt_fields = {"auth.password"}, + encrypt_fields = {"auth.password", "headers"}, oneOf = { {required = {"endpoint_addr", "field"}}, {required = {"endpoint_addrs", "field"}} diff --git a/docs/en/latest/plugins/elasticsearch-logger.md b/docs/en/latest/plugins/elasticsearch-logger.md index 58fd33119286..a6c15f14af7c 100644 --- a/docs/en/latest/plugins/elasticsearch-logger.md +++ b/docs/en/latest/plugins/elasticsearch-logger.md @@ -47,7 +47,7 @@ The `elasticsearch-logger` Plugin pushes request and response logs in batches to | auth | object | False | | | Elasticsearch [authentication](https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-up-authentication.html) configuration. | | auth.username | string | False | | | Elasticsearch [authentication](https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-up-authentication.html) username. Required if `auth` is configured. Must be provided together with `auth.password`. | | auth.password | string | False | | | Elasticsearch [authentication](https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-up-authentication.html) password. Required if `auth` is configured. Must be provided together with `auth.username`. The secret is encrypted with AES before being stored in etcd. | -| headers | object | False | | | Custom HTTP request headers to include in requests sent to Elasticsearch, as key-value pairs. Can be used as an alternative or complement to `auth` for authentication and other purposes. Available in APISIX from 3.16.0. | +| headers | object | False | | | Custom HTTP request headers to include in requests sent to Elasticsearch, as key-value pairs. Can be used as an alternative or complement to `auth` for authentication and other purposes. The values are encrypted with AES before being stored in etcd. Available in APISIX from 3.16.0. | | ssl_verify | boolean | False | true | | If true, perform SSL verification. | | timeout | integer | False | 10 | | Elasticsearch send data timeout in seconds. | | include_req_body | boolean | False | false | | If true, include the request body in the log. Note that if the request body is too big to be kept in the memory, it can not be logged due to NGINX's limitations. | @@ -57,7 +57,7 @@ The `elasticsearch-logger` Plugin pushes request and response logs in batches to | include_resp_body_expr | array[array] | False | | | An array of one or more conditions in the form of [lua-resty-expr](https://github.com/api7/lua-resty-expr). Used when the `include_resp_body` is true. Response body would only be logged when the expressions configured here evaluate to true. | | max_resp_body_bytes | integer | False | 524288 | >=1 | Response bodies within this size will be logged, if the size exceeds the configured value it will be truncated before logging. | -NOTE: `encrypt_fields = {"auth.password"}` is also defined in the schema, which means that the field will be stored encrypted in etcd. See [encrypted storage fields](../plugin-develop.md#encrypted-storage-fields). +NOTE: `encrypt_fields = {"auth.password", "headers"}` is also defined in the schema, which means that these fields will be stored encrypted in etcd. See [encrypted storage fields](../plugin-develop.md#encrypted-storage-fields). This Plugin supports using batch processors to aggregate and process entries (logs/data) in a batch. This avoids the need for frequently submitting the data. The batch processor submits data every `5` seconds or when the data in the queue reaches `1000`. See [Batch Processor](../batch-processor.md#configuration) for more information or setting your custom configuration. diff --git a/docs/zh/latest/plugins/elasticsearch-logger.md b/docs/zh/latest/plugins/elasticsearch-logger.md index 38c72ebeed2f..e7912512bfc0 100644 --- a/docs/zh/latest/plugins/elasticsearch-logger.md +++ b/docs/zh/latest/plugins/elasticsearch-logger.md @@ -47,7 +47,7 @@ description: elasticsearch-logger Plugin 将请求和响应日志批量推送到 | auth | object | 否 | | | Elasticsearch [身份验证](https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-up-authentication.html) 配置。 | | auth.username | string | 否 | | | Elasticsearch [身份验证](https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-up-authentication.html) 用户名​​。当配置 `auth` 时必填,需与 `auth.password` 成对配置。 | | auth.password | string | 否 | | | Elasticsearch [身份验证](https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-up-authentication.html) 密码。当配置 `auth` 时必填,需与 `auth.username` 成对配置。该密钥在存储到 etcd 之前会使用 AES 加密。 | -| headers | object | 否 | | | 自定义 HTTP 请求标头,以键值对形式包含在发送给 Elasticsearch 的请求中。可作为 `auth` 的替代或补充,用于身份验证和其他目的。在 APISIX 3.16.0 中可用。 | +| headers | object | 否 | | | 自定义 HTTP 请求标头,以键值对形式包含在发送给 Elasticsearch 的请求中。可作为 `auth` 的替代或补充,用于身份验证和其他目的。这些值在存储到 etcd 之前会使用 AES 加密。在 APISIX 3.16.0 中可用。 | | ssl_verify | boolean | 否 | true | | 如果为 true,则执行 SSL 验证。 | | timeout | integer | 否 | 10 | | Elasticsearch 发送数据超时(秒)。 | | include_req_body | boolean | 否 | false | | 如果为 true,则将请求主体包含在日志中。请注意,如果请求主体太大而无法保存在内存中,则由于 NGINX 的限制而无法记录。 | @@ -57,7 +57,7 @@ description: elasticsearch-logger Plugin 将请求和响应日志批量推送到 | include_resp_body_expr | array[array] | 否 | | | 一个或多个条件的数组,形式为 [lua-resty-expr](https://github.com/api7/lua-resty-expr)。在 `include_resp_body` 为 true 时使用。仅当此处配置的表达式计算结果为 true 时,才会记录响应主体。 | | max_resp_body_bytes | integer | 否 | 524288 | >=1 | 记录响应主体的最大字节数。如果响应主体超过此值,则会在记录前截断。在 APISIX 3.16.0 中可用。 | -注意:schema 中还定义了 `encrypt_fields = {"auth.password"}`,这意味着该字段将会被加密存储在 etcd 中。具体参考 [加密存储字段](../plugin-develop.md#加密存储字段)。 +注意:schema 中还定义了 `encrypt_fields = {"auth.password", "headers"}`,这意味着这些字段将会被加密存储在 etcd 中。具体参考 [加密存储字段](../plugin-develop.md#加密存储字段)。 本插件支持使用批处理器来聚合并批量处理条目(日志和数据)。这样可以避免插件频繁地提交数据,默认设置情况下批处理器会每 `5` 秒钟或队列中的数据达到 `1000` 条时提交数据,如需了解或自定义批处理器相关参数设置,请参考 [Batch-Processor](../batch-processor.md#配置) 配置部分。 diff --git a/t/plugin/elasticsearch-logger.t b/t/plugin/elasticsearch-logger.t index 64953d6a0fb6..34cdf7cb1f39 100644 --- a/t/plugin/elasticsearch-logger.t +++ b/t/plugin/elasticsearch-logger.t @@ -1014,3 +1014,70 @@ GET /hello hello world --- error_log Batch Processor[elasticsearch-logger] successfully processed the entries + + + +=== TEST 27: data encryption for headers +--- yaml_config +apisix: + data_encryption: + enable_encrypt_fields: true + keyring: + - edd1c9f0985e76a2 +--- config + location /t { + content_by_lua_block { + local json = require("toolkit.json") + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PUT, { + uri = "/hello", + upstream = { + type = "roundrobin", + nodes = { + ["127.0.0.1:1980"] = 1 + } + }, + plugins = { + ["elasticsearch-logger"] = { + endpoint_addr = "http://127.0.0.1:9201", + field = { + index = "services" + }, + headers = { + Authorization = "Basic ZWxhc3RpYzoxMjM0NTY=" + }, + batch_max_size = 1, + inactive_timeout = 1 + } + } + }) + + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + ngx.sleep(0.1) + + -- get plugin conf from admin api, header is decrypted + local code, message, res = t('/apisix/admin/routes/1', + ngx.HTTP_GET + ) + res = json.decode(res) + if code >= 300 then + ngx.status = code + ngx.say(message) + return + end + + ngx.say(res.value.plugins["elasticsearch-logger"].headers.Authorization) + + -- get plugin conf from etcd, header is encrypted + local etcd = require("apisix.core.etcd") + local res = assert(etcd.get('/routes/1')) + ngx.say(res.body.node.value.plugins["elasticsearch-logger"].headers.Authorization) + } + } +--- response_body +Basic ZWxhc3RpYzoxMjM0NTY= +8xFrqM3Y8W1eaQ5b6vIPlyOS+HvOyI4agcFeoe47abo=