From dabfe2a175c0ab0617b60135b584e8e686e40bf6 Mon Sep 17 00:00:00 2001 From: Abhishek Choudhary Date: Tue, 7 Jul 2026 17:13:23 +0800 Subject: [PATCH 1/2] fix: invalidate secret LRU cache on /secrets changes The secret resolver passed a constant "" version to the secret LRU cache, so core.lrucache never detected staleness: a deleted secret kept resolving to its cached value indefinitely, and updates were only picked up after the TTL window. With refresh_stale = true an expired entry is served while a background refresh retries, so once a secret is deleted the refresh fails forever and the stale value is served forever. Pass the real secrets conf_version (already exposed via _M.secrets) so a change to /secrets re-resolves the entry on the next access, matching how route/service caches behave. $env:// shares this cache; env values are static, so dropping them on a /secrets bump is harmless. Signed-off-by: Abhishek Choudhary --- apisix/secret.lua | 4 ++- t/secret/secret_lru.t | 72 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/apisix/secret.lua b/apisix/secret.lua index d64851115daa..f25daa647c9d 100644 --- a/apisix/secret.lua +++ b/apisix/secret.lua @@ -233,7 +233,9 @@ local function fetch(uri, use_cache) return val end - return secrets_cache(uri, "", fetch_by_uri, uri) + -- pass the secrets conf_version so the cache re-resolves when /secrets changes + local version = secrets and secrets.conf_version or "" + return secrets_cache(uri, version, fetch_by_uri, uri) end local function retrieve_refs(refs, use_cache) diff --git a/t/secret/secret_lru.t b/t/secret/secret_lru.t index 3ff3386fcf15..d9c8348b2f6f 100644 --- a/t/secret/secret_lru.t +++ b/t/secret/secret_lru.t @@ -96,3 +96,75 @@ GET /t } --- response_body nil + + + +=== TEST 2: store secret into vault +--- exec +VAULT_TOKEN='root' VAULT_ADDR='http://0.0.0.0:8200' vault kv put kv/apisix/lru-key/jack key=value +--- response_body +Success! Data written to: kv/apisix/lru-key/jack + + + +=== TEST 3: deleted secret is evicted from the LRU cache +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local secret = require("apisix.secret") + + -- configure the vault secret manager + local code, body = t('/apisix/admin/secrets/vault/lru', + ngx.HTTP_PUT, + [[{ + "uri": "http://127.0.0.1:8200", + "prefix": "kv/apisix", + "token": "root" + }]] + ) + if code >= 300 then + ngx.status = code + return ngx.say(body) + end + + local ref = { key = "$secret://vault/lru/lru-key/jack/key" } + + -- resolve through the cache once the manager config is synced + local resolved + for _ = 1, 50 do + resolved = secret.fetch_secrets(ref, true) + if resolved.key == "value" then + break + end + ngx.sleep(0.1) + end + ngx.say(resolved.key) + + local _, ver = secret.secrets() + + code, body = t('/apisix/admin/secrets/vault/lru', ngx.HTTP_DELETE) + if code >= 300 then + ngx.status = code + return ngx.say(body) + end + + -- wait for the /secrets config version to bump + for _ = 1, 50 do + local _, new_ver = secret.secrets() + if new_ver ~= ver then + break + end + ngx.sleep(0.1) + end + + -- cache must re-resolve: the manager is gone, so it falls back to the literal ref + resolved = secret.fetch_secrets(ref, true) + ngx.say(resolved.key) + } + } +--- request +GET /t +--- response_body +value +$secret://vault/lru/lru-key/jack/key From 6b848963e6ff9339fea7cbde1fe17b8b6855caf5 Mon Sep 17 00:00:00 2001 From: Abhishek Choudhary Date: Wed, 8 Jul 2026 15:27:14 +0800 Subject: [PATCH 2/2] test: raise TEST 3 client timeout to avoid flakiness TEST 3 polls for the /secrets version bump after the delete, which can take a couple of seconds on a loaded runner. Give the request a 20s ceiling so a slow poll fails on the assertion, not a client timeout. Signed-off-by: Abhishek Choudhary --- t/secret/secret_lru.t | 1 + 1 file changed, 1 insertion(+) diff --git a/t/secret/secret_lru.t b/t/secret/secret_lru.t index d9c8348b2f6f..670bf03b5154 100644 --- a/t/secret/secret_lru.t +++ b/t/secret/secret_lru.t @@ -165,6 +165,7 @@ Success! Data written to: kv/apisix/lru-key/jack } --- request GET /t +--- timeout: 20 --- response_body value $secret://vault/lru/lru-key/jack/key