From 01b3aaeb3219de2b3029cd298bb937a249d6ee7e Mon Sep 17 00:00:00 2001 From: mikyll Date: Mon, 20 Apr 2026 17:59:37 +0200 Subject: [PATCH 1/7] feat(ai-rag): resolve secrets reference from env var and secret managers --- apisix/plugins/ai-rag.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apisix/plugins/ai-rag.lua b/apisix/plugins/ai-rag.lua index 0acd5f1a1306..8a382efc43db 100644 --- a/apisix/plugins/ai-rag.lua +++ b/apisix/plugins/ai-rag.lua @@ -24,6 +24,8 @@ local core = require("apisix.core") local azure_openai_embeddings = require("apisix.plugins.ai-rag.embeddings.azure_openai").schema local azure_ai_search_schema = require("apisix.plugins.ai-rag.vector-search.azure_ai_search").schema +local fetch_secrets = require("apisix.secret").fetch_secrets + local HTTP_INTERNAL_SERVER_ERROR = ngx.HTTP_INTERNAL_SERVER_ERROR local HTTP_BAD_REQUEST = ngx.HTTP_BAD_REQUEST @@ -102,6 +104,9 @@ function _M.access(conf, ctx) local vector_search_driver = require("apisix.plugins.ai-rag.vector-search." .. vector_search_provider) + embeddings_provider_conf = fetch_secrets(embeddings_provider_conf, true) + vector_search_provider_conf = fetch_secrets(vector_search_provider_conf, true) + local vs_req_schema = vector_search_driver.request_schema local emb_req_schema = embeddings_driver.request_schema From 31087734b6ca7166e5c6894d1d25a8062178555d Mon Sep 17 00:00:00 2001 From: mikyll Date: Mon, 20 Apr 2026 18:00:54 +0200 Subject: [PATCH 2/7] test(ai-rag): add test case to verify env var resolution in api_key config field --- t/plugin/ai-rag.t | 63 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/t/plugin/ai-rag.t b/t/plugin/ai-rag.t index 86b0c6440586..f8613935463c 100644 --- a/t/plugin/ai-rag.t +++ b/t/plugin/ai-rag.t @@ -36,6 +36,12 @@ add_block_preprocessor(sub { $block->set_value("request", "GET /t"); } + my $main_config = $block->main_config // <<_EOC_; + env AI_RAG_APIKEY=apikey; +_EOC_ + + $block->set_value("main_config", $main_config); + my $http_config = $block->http_config // <<_EOC_; server { listen 3623; @@ -390,3 +396,60 @@ POST /echo --- error_code: 200 --- response_body eval qr/\{"messages":\[\{"content":"passed","role":"user"\}\]\}|\{"messages":\[\{"role":"user","content":"passed"\}\]\}/ + + + +=== TEST 13: configure plugin with api_key via nginx env directive secret reference +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "uri": "/echo", + "plugins": { + "ai-rag": { + "embeddings_provider": { + "azure_openai": { + "endpoint": "http://localhost:3623/embeddings", + "api_key": "$ENV://AI_RAG_APIKEY" + } + }, + "vector_search_provider": { + "azure_ai_search": { + "endpoint": "http://localhost:3623/search", + "api_key": "$ENV://AI_RAG_APIKEY" + } + } + } + }, + "upstream": { + "type": "roundrobin", + "nodes": { + "127.0.0.1:1980": 1 + }, + "scheme": "http", + "pass_host": "node" + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- response_body +passed + + + +=== TEST 14: send request with api_key resolved from environment variable +--- request +POST /echo +{"ai_rag":{"vector_search":{"fields":"something"},"embeddings":{"input":"which service is good for devops"}}} +--- error_code: 200 +--- response_body eval +qr/\{"messages":\[\{"content":"passed","role":"user"\}\]\}|\{"messages":\[\{"role":"user","content":"passed"\}\]\}/ From 3d1ada8affb2939d5a7629335bd31bcd660f64a2 Mon Sep 17 00:00:00 2001 From: mikyll Date: Mon, 20 Apr 2026 18:04:30 +0200 Subject: [PATCH 3/7] docs(ai-rag): add secret resolution to ai-rag documentation --- docs/en/latest/plugins/ai-rag.md | 25 +++++++++++++++++++++++-- docs/zh/latest/plugins/ai-rag.md | 25 +++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/docs/en/latest/plugins/ai-rag.md b/docs/en/latest/plugins/ai-rag.md index 844b3078e368..42e85fdf3f4b 100644 --- a/docs/en/latest/plugins/ai-rag.md +++ b/docs/en/latest/plugins/ai-rag.md @@ -48,11 +48,11 @@ The Plugin supports using [Azure OpenAI](https://azure.microsoft.com/en-us/produ | embeddings_provider | True | object | Configurations of the embedding models provider. | | embeddings_provider.azure_openai | True | object | Configurations of [Azure OpenAI](https://azure.microsoft.com/en-us/products/ai-services/openai-service) as the embedding models provider. | | embeddings_provider.azure_openai.endpoint | True | string | Azure OpenAI embedding model endpoint. | -| embeddings_provider.azure_openai.api_key | True | string | Azure OpenAI API key. | +| embeddings_provider.azure_openai.api_key | True | string | Azure OpenAI API key. Supports [secret references](../terminology/secret.md) via environment variables (e.g. `$ENV://AI_RAG_APIKEY`) and secret managers. | | vector_search_provider | True | object | Configuration for the vector search provider. | | vector_search_provider.azure_ai_search | True | object | Configuration for Azure AI Search. | | vector_search_provider.azure_ai_search.endpoint | True | string | Azure AI Search endpoint. | -| vector_search_provider.azure_ai_search.api_key | True | string | Azure AI Search API key. | +| vector_search_provider.azure_ai_search.api_key | True | string | Azure AI Search API key. Supports [secret references](../terminology/secret.md) via environment variables (e.g. `$ENV://AI_RAG_APIKEY`) and secret managers. | ## Request Body Format @@ -233,3 +233,24 @@ You should receive an `HTTP/1.1 200 OK` response similar to the following: } } ``` + +## Secret References + +The `api_key` fields support APISIX secret resolution, via environment variable and secret manager. For secret reference formats and setup, see [APISIX Secret](../terminology/secret.md). Example: + +```json +{ + "embeddings_provider": { + "azure_openai": { + "endpoint": "'"$AZ_EMBEDDINGS_ENDPOINT"'", + "api_key": "$ENV://AI_RAG_APIKEY" + } + }, + "vector_search_provider": { + "azure_ai_search": { + "endpoint": "'"$AZ_AI_SEARCH_ENDPOINT"'", + "api_key": "$ENV://AI_RAG_APIKEY" + } + } +} +``` diff --git a/docs/zh/latest/plugins/ai-rag.md b/docs/zh/latest/plugins/ai-rag.md index da4e0672de9a..7b927d413764 100644 --- a/docs/zh/latest/plugins/ai-rag.md +++ b/docs/zh/latest/plugins/ai-rag.md @@ -48,11 +48,11 @@ description: ai-rag 插件通过检索增强生成(RAG)增强 LLM 输出, | embeddings_provider | 是 | object | 嵌入模型提供商的配置。 | | embeddings_provider.azure_openai | 是 | object | [Azure OpenAI](https://azure.microsoft.com/en-us/products/ai-services/openai-service) 作为嵌入模型提供商的配置。 | | embeddings_provider.azure_openai.endpoint | 是 | string | Azure OpenAI 嵌入模型端点。 | -| embeddings_provider.azure_openai.api_key | 是 | string | Azure OpenAI API 密钥。 | +| embeddings_provider.azure_openai.api_key | 是 | string | Azure OpenAI API 密钥。 支持通过环境变量(如 `$ENV://AI_RAG_APIKEY`)和密钥管理器进行[密钥引用](../terminology/secret.md)。 | | vector_search_provider | 是 | object | 向量搜索提供商的配置。 | | vector_search_provider.azure_ai_search | 是 | object | Azure AI Search 的配置。 | | vector_search_provider.azure_ai_search.endpoint | 是 | string | Azure AI Search 端点。 | -| vector_search_provider.azure_ai_search.api_key | 是 | string | Azure AI Search API 密钥。 | +| vector_search_provider.azure_ai_search.api_key | 是 | string | Azure AI Search API 密钥。 支持通过环境变量(如 `$ENV://AI_RAG_APIKEY`)和密钥管理器进行[密钥引用](../terminology/secret.md)。 | ## 请求体格式 @@ -233,3 +233,24 @@ curl "http://127.0.0.1:9080/rag" -X POST \ } } ``` + +## 密钥引用 + +`api_key` 字段支持通过环境变量和密钥管理器进行 APISIX 密钥解析。有关密钥引用格式和设置,请参阅 [APISIX 密钥](../terminology/secret.md)。示例: + +```json +{ + "embeddings_provider": { + "azure_openai": { + "endpoint": "'"$AZ_EMBEDDINGS_ENDPOINT"'", + "api_key": "$ENV://AI_RAG_APIKEY" + } + }, + "vector_search_provider": { + "azure_ai_search": { + "endpoint": "'"$AZ_AI_SEARCH_ENDPOINT"'", + "api_key": "$ENV://AI_RAG_APIKEY" + } + } +} +``` From 593cebeba6521e3bca331aad34b2b8099cead2c4 Mon Sep 17 00:00:00 2001 From: mikyll Date: Mon, 20 Apr 2026 18:20:29 +0200 Subject: [PATCH 4/7] test(ai-rag): add secret resolution test case --- t/plugin/ai-rag.t | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/t/plugin/ai-rag.t b/t/plugin/ai-rag.t index 24ec59673275..cd6bcd22383e 100644 --- a/t/plugin/ai-rag.t +++ b/t/plugin/ai-rag.t @@ -649,3 +649,13 @@ ai_rag ssl_verify: false } --- response_body passed + + + +=== TEST 19: send request with api_key resolved from environment variable +--- request +POST /echo +{"ai_rag":{"vector_search":{"fields":"something"},"embeddings":{"input":"which service is good for devops"}}} +--- error_code: 200 +--- response_body eval +qr/\{"messages":\[\{"content":"passed","role":"user"\}\]\}|\{"messages":\[\{"role":"user","content":"passed"\}\]\}/ From 22a580705a124dd18d0cc0cf0a467340698915d5 Mon Sep 17 00:00:00 2001 From: mikyll Date: Tue, 21 Apr 2026 10:35:07 +0200 Subject: [PATCH 5/7] docs(ai-rag): update secret references example --- docs/en/latest/plugins/ai-rag.md | 4 ++-- docs/zh/latest/plugins/ai-rag.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/en/latest/plugins/ai-rag.md b/docs/en/latest/plugins/ai-rag.md index 165362e0b99d..828eb56d5848 100644 --- a/docs/en/latest/plugins/ai-rag.md +++ b/docs/en/latest/plugins/ai-rag.md @@ -400,13 +400,13 @@ The `api_key` fields support APISIX secret resolution, via environment variable "embeddings_provider": { "azure_openai": { "endpoint": "'"$AZ_EMBEDDINGS_ENDPOINT"'", - "api_key": "$ENV://AI_RAG_APIKEY" + "api_key": "$ENV://API_KEY" } }, "vector_search_provider": { "azure_ai_search": { "endpoint": "'"$AZ_AI_SEARCH_ENDPOINT"'", - "api_key": "$ENV://AI_RAG_APIKEY" + "api_key": "$secret://$manager/$id/$secret_name/$key" } } } diff --git a/docs/zh/latest/plugins/ai-rag.md b/docs/zh/latest/plugins/ai-rag.md index 32df38886e0e..6434e51f031d 100644 --- a/docs/zh/latest/plugins/ai-rag.md +++ b/docs/zh/latest/plugins/ai-rag.md @@ -400,13 +400,13 @@ curl "http://127.0.0.1:9080/rag" -X POST \ "embeddings_provider": { "azure_openai": { "endpoint": "'"$AZ_EMBEDDINGS_ENDPOINT"'", - "api_key": "$ENV://AI_RAG_APIKEY" + "api_key": "$ENV://API_KEY" } }, "vector_search_provider": { "azure_ai_search": { "endpoint": "'"$AZ_AI_SEARCH_ENDPOINT"'", - "api_key": "$ENV://AI_RAG_APIKEY" + "api_key": "$secret://$manager/$id/$secret_name/$key" } } } From 50824a2ff1ccb4e09613abb991b06d582de64d19 Mon Sep 17 00:00:00 2001 From: mikyll Date: Wed, 22 Apr 2026 10:39:45 +0200 Subject: [PATCH 6/7] test(ai-rag): fix wrong apikey in env example --- t/plugin/ai-rag.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/plugin/ai-rag.t b/t/plugin/ai-rag.t index cd6bcd22383e..b23cbcbbda10 100644 --- a/t/plugin/ai-rag.t +++ b/t/plugin/ai-rag.t @@ -42,7 +42,7 @@ add_block_preprocessor(sub { } my $main_config = $block->main_config // <<_EOC_; - env AI_RAG_APIKEY=apikey; + env AI_RAG_APIKEY=key; _EOC_ $block->set_value("main_config", $main_config); From 5f8852bfc5731c1fddfd59bf8c1d010237e9a62a Mon Sep 17 00:00:00 2001 From: mikyll Date: Thu, 23 Apr 2026 09:39:17 +0200 Subject: [PATCH 7/7] docs(ai-rag): lint chinese docs for azure ai search --- docs/zh/latest/plugins/ai-rag.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/latest/plugins/ai-rag.md b/docs/zh/latest/plugins/ai-rag.md index 6434e51f031d..72a29facc82a 100644 --- a/docs/zh/latest/plugins/ai-rag.md +++ b/docs/zh/latest/plugins/ai-rag.md @@ -53,7 +53,7 @@ import TabItem from '@theme/TabItem'; | `vector_search_provider` | object | 是 | | | 向量搜索提供商的配置。 | | `vector_search_provider.azure_ai_search` | object | 是 | | | [Azure AI Search](https://azure.microsoft.com/en-us/products/ai-services/ai-search) 的配置。 | | `vector_search_provider.azure_ai_search.endpoint` | string | 是 | | | Azure AI Search 端点。 | -| `vector_search_provider.azure_ai_search.api_key` | string | 是 | | | Azure AI Search API 密钥。 支持通过环境变量(如 `$ENV://AI_RAG_APIKEY`)和密钥管理器进行[密钥引用](../terminology/secret.md)。 | +| `vector_search_provider.azure_ai_search.api_key` | string | 是 | | | Azure AI Search API 密钥。支持通过环境变量(如 `$ENV://AI_RAG_APIKEY`)和密钥管理器进行[密钥引用](../terminology/secret.md)。 | ## 请求体格式