fix: jwe-decrypt secret length restriction (#10928)
diff --git a/apisix/plugins/jwe-decrypt.lua b/apisix/plugins/jwe-decrypt.lua
index f163f40..0e4447e 100644
--- a/apisix/plugins/jwe-decrypt.lua
+++ b/apisix/plugins/jwe-decrypt.lua
@@ -47,7 +47,7 @@
type = "object",
properties = {
key = { type = "string" },
- secret = { type = "string", minLength = 32 },
+ secret = { type = "string" },
is_base64_encoded = { type = "boolean" },
},
required = { "key", "secret" },
@@ -66,7 +66,24 @@
function _M.check_schema(conf, schema_type)
if schema_type == core.schema.TYPE_CONSUMER then
- return core.schema.check(consumer_schema, conf)
+ local ok, err = core.schema.check(consumer_schema, conf)
+ if not ok then
+ return false, err
+ end
+
+ -- restrict the length of secret, we use A256GCM for encryption,
+ -- so the length should be 32 chars only
+ if conf.is_base64_encoded then
+ if #base64.decode_base64url(conf.secret) ~= 32 then
+ return false, "the secret length after base64 decode should be 32 chars"
+ end
+ else
+ if #conf.secret ~= 32 then
+ return false, "the secret length should be 32 chars"
+ end
+ end
+
+ return true
end
return core.schema.check(schema, conf)
end
diff --git a/docs/en/latest/plugins/jwe-decrypt.md b/docs/en/latest/plugins/jwe-decrypt.md
index 9969094..6da75d2 100644
--- a/docs/en/latest/plugins/jwe-decrypt.md
+++ b/docs/en/latest/plugins/jwe-decrypt.md
@@ -44,6 +44,12 @@
| secret | string | True | | | The decryption key. Must be 32 characters. The key could be saved in a secret manager using the [Secret](../terminology/secret.md) resource. |
| is_base64_encoded | boolean | False | false | | Set to true if the secret is base64 encoded. |
+:::note
+
+After enabling `is_base64_encoded`, your `secret` length may exceed 32 chars. You only need to make sure that the length after decoding is still 32 chars.
+
+:::
+
For Route:
| Name | Type | Required | Default | Description |
diff --git a/docs/zh/latest/plugins/jwe-decrypt.md b/docs/zh/latest/plugins/jwe-decrypt.md
index ce5c98f..cf7363e 100644
--- a/docs/zh/latest/plugins/jwe-decrypt.md
+++ b/docs/zh/latest/plugins/jwe-decrypt.md
@@ -44,6 +44,12 @@
| secret | string | True | | | 解密密钥,必须为 32 位。秘钥可以使用 [Secret](../terminology/secret.md) 资源保存在密钥管理服务中 |
| is_base64_encoded | boolean | False | false | | 如果密钥是 Base64 编码,则需要配置为 `true` |
+:::note
+
+注意,在启用 `is_base64_encoded` 后,你的 `secret` 长度可能会超过 32 位,你只需要保证在 Decode 后的长度仍然是 32 位即可。
+
+:::
+
Route 配置:
| 名称 | 类型 | 必选项 | 默认值 | 描述 |
diff --git a/t/plugin/jwe-decrypt.t b/t/plugin/jwe-decrypt.t
index 599fed2..e7fcf77 100644
--- a/t/plugin/jwe-decrypt.t
+++ b/t/plugin/jwe-decrypt.t
@@ -54,7 +54,7 @@
-=== TEST 2: wrong type of string
+=== TEST 2: wrong type of key
--- config
location /t {
content_by_lua_block {
@@ -74,13 +74,13 @@
-=== TEST 3: wrong type of string
+=== TEST 3: wrong type of secret
--- config
location /t {
content_by_lua_block {
local core = require("apisix.core")
local plugin = require("apisix.plugins.jwe-decrypt")
- local ok, err = plugin.check_schema({key = "123", secret = "123456"}, core.schema.TYPE_CONSUMER)
+ local ok, err = plugin.check_schema({key = "123", secret = 12345678901234567890123456789012}, core.schema.TYPE_CONSUMER)
if not ok then
ngx.say(err)
end
@@ -89,12 +89,52 @@
}
}
--- response_body
-property "secret" validation failed: string too short, expected at least 32, got 6
+property "secret" validation failed: wrong type: expected string, got number
done
-=== TEST 4: add consumer with username and plugins
+=== TEST 4: secret length too long
+--- config
+ location /t {
+ content_by_lua_block {
+ local core = require("apisix.core")
+ local plugin = require("apisix.plugins.jwe-decrypt")
+ local ok, err = plugin.check_schema({key = "123", secret = "123456789012345678901234567890123"}, core.schema.TYPE_CONSUMER)
+ if not ok then
+ ngx.say(err)
+ end
+
+ ngx.say("done")
+ }
+ }
+--- response_body
+the secret length should be 32 chars
+done
+
+
+
+=== TEST 5: secret length too long(base64 encode)
+--- config
+ location /t {
+ content_by_lua_block {
+ local core = require("apisix.core")
+ local plugin = require("apisix.plugins.jwe-decrypt")
+ local ok, err = plugin.check_schema({key = "123", secret = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmNkZWZn", is_base64_encoded = true}, core.schema.TYPE_CONSUMER)
+ if not ok then
+ ngx.say(err)
+ end
+
+ ngx.say("done")
+ }
+ }
+--- response_body
+the secret length after base64 decode should be 32 chars
+done
+
+
+
+=== TEST 6: add consumer with username and plugins
--- config
location /t {
content_by_lua_block {
@@ -123,7 +163,7 @@
-=== TEST 5: enable jwe-decrypt plugin using admin api
+=== TEST 7: enable jwe-decrypt plugin using admin api
--- config
location /t {
content_by_lua_block {
@@ -158,7 +198,7 @@
-=== TEST 6: create public API route (jwe-decrypt sign)
+=== TEST 8: create public API route (jwe-decrypt sign)
--- config
location /t {
content_by_lua_block {
@@ -184,7 +224,7 @@
-=== TEST 7: sign / verify in argument
+=== TEST 9: sign / verify in argument
--- config
location /t {
content_by_lua_block {
@@ -214,14 +254,14 @@
-=== TEST 8: test for unsupported method
+=== TEST 10: test for unsupported method
--- request
PATCH /apisix/plugin/jwe/encrypt?key=user-key
--- error_code: 404
-=== TEST 9: verify, missing token
+=== TEST 11: verify, missing token
--- request
GET /hello
--- error_code: 403
@@ -230,7 +270,7 @@
-=== TEST 10: verify: invalid JWE token
+=== TEST 12: verify: invalid JWE token
--- request
GET /hello
--- more_headers
@@ -241,7 +281,7 @@
-=== TEST 11: verify (in header)
+=== TEST 13: verify (in header)
--- request
GET /hello
--- more_headers
@@ -251,7 +291,7 @@
-=== TEST 12: verify (in header without Bearer)
+=== TEST 14: verify (in header without Bearer)
--- request
GET /hello
--- more_headers
@@ -261,7 +301,7 @@
-=== TEST 13: verify (header with bearer)
+=== TEST 15: verify (header with bearer)
--- request
GET /hello
--- more_headers
@@ -271,7 +311,7 @@
-=== TEST 14: verify (invalid bearer token)
+=== TEST 16: verify (invalid bearer token)
--- request
GET /hello
--- more_headers
@@ -282,7 +322,7 @@
-=== TEST 15: delete a exist consumer
+=== TEST 17: delete a exist consumer
--- config
location /t {
content_by_lua_block {
@@ -332,7 +372,7 @@
-=== TEST 16: add consumer with username and plugins with base64 secret
+=== TEST 18: add consumer with username and plugins with base64 secret
--- config
location /t {
content_by_lua_block {
@@ -362,7 +402,7 @@
-=== TEST 17: enable jwt decrypt plugin with base64 secret
+=== TEST 19: enable jwt decrypt plugin with base64 secret
--- config
location /t {
content_by_lua_block {
@@ -396,7 +436,7 @@
-=== TEST 18: create public API route (jwe-decrypt sign)
+=== TEST 20: create public API route (jwe-decrypt sign)
--- config
location /t {
content_by_lua_block {
@@ -422,7 +462,7 @@
-=== TEST 19: sign / verify in argument
+=== TEST 21: sign / verify in argument
--- config
location /t {
content_by_lua_block {
@@ -454,7 +494,7 @@
-=== TEST 20: verify (in header)
+=== TEST 22: verify (in header)
--- request
GET /hello
--- more_headers
@@ -464,7 +504,7 @@
-=== TEST 21: verify (in header without Bearer)
+=== TEST 23: verify (in header without Bearer)
--- request
GET /hello
--- more_headers
@@ -474,7 +514,7 @@
-=== TEST 22: enable jwt decrypt plugin with test upstream route
+=== TEST 24: enable jwt decrypt plugin with test upstream route
--- config
location /t {
content_by_lua_block {
@@ -508,7 +548,7 @@
-=== TEST 23: verify in upstream header
+=== TEST 25: verify in upstream header
--- request
GET /headers
--- more_headers