This is an automated email from the ASF dual-hosted git repository.
Yilialinn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new f94b3c765 docs: clarify JWE and RAG plugin guidance (#13873)
f94b3c765 is described below
commit f94b3c76567574ffd11981cad2a8b025a0af3f4f
Author: Yilia Lin <[email protected]>
AuthorDate: Mon Aug 31 10:13:19 2026 +0800
docs: clarify JWE and RAG plugin guidance (#13873)
---
docs/en/latest/plugins/ai-rag.md | 26 +++++++++---------
docs/en/latest/plugins/jwe-decrypt.md | 50 +++++++++++++++++++++++------------
2 files changed, 46 insertions(+), 30 deletions(-)
diff --git a/docs/en/latest/plugins/ai-rag.md b/docs/en/latest/plugins/ai-rag.md
index fe1130ddf..113ee2bb2 100644
--- a/docs/en/latest/plugins/ai-rag.md
+++ b/docs/en/latest/plugins/ai-rag.md
@@ -7,7 +7,7 @@ keywords:
- ai-rag
- AI
- LLM
-description: The ai-rag Plugin enhances LLM outputs with Retrieval-Augmented
Generation (RAG), efficiently retrieving relevant documents to improve accuracy
and contextual relevance in responses.
+description: The ai-rag Plugin retrieves context with Azure OpenAI embeddings
and Azure AI Search before an LLM request is proxied.
---
<!--
@@ -38,9 +38,9 @@ import TabItem from '@theme/TabItem';
## Description
-The `ai-rag` Plugin provides Retrieval-Augmented Generation (RAG) capabilities
with LLMs. It facilitates the efficient retrieval of relevant documents or
information from external data sources, which are used to enhance the LLM
responses, thereby improving the accuracy and contextual relevance of the
generated outputs.
+The `ai-rag` Plugin implements the retrieval step of a Retrieval-Augmented
Generation (RAG) request flow. It generates an embedding from the request,
performs a vector search, adds the retrieved content to the protocol-specific
LLM request input, and removes the `ai_rag` request object before the request
is proxied.
-The Plugin supports using [Azure
OpenAI](https://azure.microsoft.com/en-us/products/ai-services/openai-service)
and [Azure AI
Search](https://azure.microsoft.com/en-us/products/ai-services/ai-search)
services for generating embeddings and performing vector search. PRs for
introducing support for other service providers are welcomed.
+The current implementation supports [Azure
OpenAI](https://azure.microsoft.com/en-us/products/ai-services/openai-service)
for embeddings and [Azure AI
Search](https://azure.microsoft.com/en-us/products/ai-services/ai-search) for
vector search. Use the [`ai-proxy`](./ai-proxy.md) Plugin in the same request
flow to proxy the augmented request to the LLM provider. The Plugin does not
create or populate a search index; prepare the index and its content before
sending requests through APISIX.
## Plugin Attributes
@@ -115,14 +115,14 @@ Save the API keys and endpoints to environment variables:
```shell
# replace with your values
-AZ_OPENAI_DOMAIN=https://ai-plugin-developer.openai.azure.com
-AZ_OPENAI_API_KEY=9m7VYroxITMDEqKKEnpOknn1rV7QNQT7DrIBApcwMLYJQQJ99ALACYeBjFXJ3w3AAABACOGXGcd
+AZ_OPENAI_DOMAIN=https://your-openai-resource.openai.azure.com
+AZ_OPENAI_API_KEY=your-azure-openai-api-key
AZ_CHAT_ENDPOINT=${AZ_OPENAI_DOMAIN}/openai/deployments/gpt-4o/chat/completions?api-version=2024-02-15-preview
AZ_EMBEDDING_MODEL=text-embedding-3-large
AZ_EMBEDDINGS_ENDPOINT=${AZ_OPENAI_DOMAIN}/openai/deployments/${AZ_EMBEDDING_MODEL}/embeddings?api-version=2023-05-15
-AZ_AI_SEARCH_SVC_DOMAIN=https://ai-plugin-developer.search.windows.net
-AZ_AI_SEARCH_KEY=IFZBp3fKVdq7loEVe9LdwMvVdZrad9A4lPH90AzSeC06SlR
+AZ_AI_SEARCH_SVC_DOMAIN=https://your-search-service.search.windows.net
+AZ_AI_SEARCH_KEY=your-azure-ai-search-api-key
AZ_AI_SEARCH_INDEX=vectest
AZ_AI_SEARCH_ENDPOINT=${AZ_AI_SEARCH_SVC_DOMAIN}/indexes/${AZ_AI_SEARCH_INDEX}/docs/search?api-version=2024-07-01
```
@@ -243,17 +243,17 @@ spec:
embeddings_provider:
azure_openai:
endpoint:
"https://your-openai-resource.openai.azure.com/openai/deployments/text-embedding-3-large/embeddings?api-version=2023-05-15"
- api_key: "Bearer your-api-key"
+ api_key: "your-azure-openai-api-key"
vector_search_provider:
azure_ai_search:
endpoint:
"https://your-search-service.search.windows.net/indexes/vectest/docs/search?api-version=2024-07-01"
- api_key: "Bearer your-api-key"
+ api_key: "your-azure-ai-search-api-key"
- name: ai-proxy
config:
provider: openai
auth:
header:
- api-key: "Bearer your-api-key"
+ api-key: "your-azure-openai-api-key"
model: gpt-4o
override:
endpoint:
"https://your-openai-resource.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2024-02-15-preview"
@@ -307,18 +307,18 @@ spec:
embeddings_provider:
azure_openai:
endpoint:
"https://your-openai-resource.openai.azure.com/openai/deployments/text-embedding-3-large/embeddings?api-version=2023-05-15"
- api_key: "Bearer your-api-key"
+ api_key: "your-azure-openai-api-key"
vector_search_provider:
azure_ai_search:
endpoint:
"https://your-search-service.search.windows.net/indexes/vectest/docs/search?api-version=2024-07-01"
- api_key: "Bearer your-api-key"
+ api_key: "your-azure-ai-search-api-key"
- name: ai-proxy
enable: true
config:
provider: openai
auth:
header:
- api-key: "Bearer your-api-key"
+ api-key: "your-azure-openai-api-key"
model: gpt-4o
override:
endpoint:
"https://your-openai-resource.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2024-02-15-preview"
diff --git a/docs/en/latest/plugins/jwe-decrypt.md
b/docs/en/latest/plugins/jwe-decrypt.md
index 02dafc736..78a8947b3 100644
--- a/docs/en/latest/plugins/jwe-decrypt.md
+++ b/docs/en/latest/plugins/jwe-decrypt.md
@@ -6,7 +6,7 @@ keywords:
- Plugin
- JWE Decrypt
- jwe-decrypt
-description: The jwe-decrypt Plugin decrypts JWE authorization headers in
requests directed to Routes or Services, enhancing API security.
+description: The jwe-decrypt Plugin decrypts its supported five-part compact
token format and forwards the plaintext in a configured request header.
---
<!--
@@ -37,19 +37,31 @@ import TabItem from '@theme/TabItem';
## Description
-The `jwe-decrypt` Plugin decrypts
[JWE](https://datatracker.ietf.org/doc/html/rfc7516) authorization headers in
requests sent to APISIX [Routes](../terminology/route.md) or
[Services](../terminology/service.md).
+The `jwe-decrypt` Plugin reads a five-part compact token from a request
header, selects a [Consumer](../terminology/consumer.md) by the token's `kid`,
decrypts the ciphertext with AES-256-GCM, and writes the plaintext to a
configured header before proxying the request. You can enable the Plugin on
APISIX [Routes](../terminology/route.md) or
[Services](../terminology/service.md).
-The decryption key should be configured in
[Consumer](../terminology/consumer.md).
+The token resembles [JWE Compact
Serialization](https://datatracker.ietf.org/doc/html/rfc7516#section-3.1), but
the current Plugin uses a Plugin-specific format. Configure a 32-byte
decryption secret on the Consumer.
+
+:::warning
+
+The current implementation reads `kid` from the decoded header but does not
validate the `alg` or `enc` fields and does not use the protected-header
segment as AES-GCM additional authenticated data (AAD). Standard RFC 7516 JWE
libraries are therefore not directly interoperable. Generate tokens with the
exact format described below, use a fixed trusted token generator, and do not
treat header fields as authenticated.
+
+:::
+
+:::caution
+
+The decrypted plaintext is forwarded in a request header. For sensitive
plaintext, do not rely on an HTTPS Upstream alone: APISIX does not verify
server certificates for standard HTTP Upstreams. Send the request over an
authenticated, protected network path, such as through a proxy or service mesh
that validates the upstream server's identity. Restrict access to the upstream
and avoid logging the configured forwarding header.
+
+:::
## Attributes
### Consumer
-| Name | Type | Required | Default | Valid values |
Description
|
-| ----------------- | ------- | -------- | ------- | -------------- |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-| key | string | True | | | A unique
key that identifies the Credential for a Consumer.
|
-| secret | string | True | | 32 characters | The
shared symmetric encryption/decryption key. You can also store it in an
environment variable and reference it using the `env://` prefix, or in a secret
manager such as HashiCorp Vault's KV secrets engine, and reference it using the
`secret://` prefix. |
-| is_base64_encoded | boolean | False | false | | Set to
true if the secret is base64 encoded. Note that after enabling
`is_base64_encoded`, the `secret` length may exceed 32 characters. You only
need to make sure the decoded length is still 32 characters.
|
+| Name | Type | Required | Default | Valid values |
Description
|
+| ----------------- | ------- | -------- | ------- | -------------- |
----------------------------------------------------------------------------------------------------------------------------------------
|
+| key | string | True | | | A unique
key that identifies the Credential for a Consumer.
|
+| secret | string | True | | 32 bytes | A shared
symmetric key. Use a [secret reference](../terminology/secret.md), such as
`$env://...` or `$secret://...`. |
+| is_base64_encoded | boolean | False | false | | Set to
true if the secret is base64url encoded. The decoded secret must still be 32
bytes. |
### Route or Service
@@ -57,7 +69,7 @@ The decryption key should be configured in
[Consumer](../terminology/consumer.md
| -------------- | ------- | -------- | ------------- | ------------ |
---------------------------------------------------------------------------------------------------------------------------------
|
| header | string | True | Authorization | | The
header to get the token from.
|
| forward_header | string | True | Authorization | | Name of
the header that passes the plaintext to the Upstream.
|
-| strict | boolean | False | true | | If
true, throw a 403 error if JWE token is missing from the request. If false, do
not throw an error when JWE token is not found. |
+| strict | boolean | False | true | | If
true, return a 403 error when the encrypted plugin token is missing. If false,
continue when the token is not found. |
## Examples
@@ -75,7 +87,7 @@ admin_key=$(yq '.deployment.admin.admin_key[0].key'
conf/config.yaml | sed 's/"/
### Create a Consumer with the Decryption Key
-The following example demonstrates how to create a Consumer with the
decryption key and generate a JWE token for it.
+The following example demonstrates how to create a Consumer with the
decryption key and generate an encrypted plugin token for it.
Create a Consumer with `jwe-decrypt` and configure the decryption key:
@@ -160,13 +172,13 @@ kubectl apply -f jwe-consumer-ic.yaml
</TabItem>
</Tabs>
-To generate a JWE token for the Consumer, encrypt the payload offline with any
AES-256-GCM library, using the Consumer secret as the key. The token structure
is:
+To generate a token for the Consumer, encrypt the payload offline with
AES-256-GCM without protected-header AAD, using the Consumer secret as the key.
Standard RFC 7516 libraries normally authenticate the protected header as AAD
and are not directly interoperable with this Plugin. Use the following exact
token structure:
```text
base64url(header).<empty>.base64url(iv).base64url(ciphertext).base64url(tag)
```
-where the header is `{"alg":"dir","enc":"A256GCM","kid":"<consumer-key>"}`.
The IV must be unique and randomly generated for every token; never reuse an IV
with the same key.
+where the header is `{"alg":"dir","enc":"A256GCM","kid":"<consumer-key>"}`.
The fields describe the intended algorithm and identify the Consumer, but the
current Plugin does not authenticate or validate them. The IV must be unique
and randomly generated for every token; never reuse an IV with the same key.
For example, the following token encrypts the payload
`{"uid":10000,"uname":"test"}` for the Consumer key `jack-key` with the secret
configured above:
@@ -174,9 +186,9 @@ For example, the following token encrypts the payload
`{"uid":10000,"uname":"tes
eyJraWQiOiJqYWNrLWtleSIsImFsZyI6ImRpciIsImVuYyI6IkEyNTZHQ00ifQ..vi29KBCQKcVmPwTT.VToyPMFbq-ZY05MIpntP1N3AmYeq3zELQ0B6iQ.vuTPG2ODc-DjUTjNCzfA2A
```
-### Decrypt Data with JWE
+### Decrypt Data from the Plugin Token
-The following example demonstrates how to decrypt the JWE token generated
above.
+The following example demonstrates how to decrypt the plugin token generated
above.
Create a Route with `jwe-decrypt` to decrypt the authorization header:
@@ -197,8 +209,9 @@ curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
},
"upstream": {
"type": "roundrobin",
+ "scheme": "https",
"nodes": {
- "httpbin.org:80": 1
+ "httpbin.org:443": 1
}
}
}'
@@ -221,9 +234,10 @@ services:
forward_header: Authorization
upstream:
type: roundrobin
+ scheme: https
nodes:
- host: httpbin.org
- port: 80
+ port: 443
weight: 1
```
@@ -240,6 +254,8 @@ adc sync -f adc.yaml
<Tabs groupId="k8s-api">
<TabItem value="gateway-api" label="Gateway API">
+The following Gateway API configuration uses public HTTPBin only with the
non-sensitive demonstration payload shown on this page. Before forwarding real
decrypted data, replace it with a controlled upstream and use an authenticated,
protected network path. An APISIX HTTPS Upstream does not validate the upstream
server certificate by itself; use a proxy or service mesh that validates the
upstream server's identity.
+
```yaml title="jwe-decrypt-ic.yaml"
apiVersion: v1
kind: Service
@@ -304,7 +320,7 @@ kubectl apply -f jwe-decrypt-ic.yaml
</TabItem>
</Tabs>
-Send a request to the Route with the JWE encrypted data in the `Authorization`
header:
+Send a request to the Route with the encrypted plugin token in the
`Authorization` header:
```shell
curl "http://127.0.0.1:9080/anything/jwe" -H 'Authorization:
eyJraWQiOiJqYWNrLWtleSIsImFsZyI6ImRpciIsImVuYyI6IkEyNTZHQ00ifQ..vi29KBCQKcVmPwTT.VToyPMFbq-ZY05MIpntP1N3AmYeq3zELQ0B6iQ.vuTPG2ODc-DjUTjNCzfA2A'