Skip to content

Commit

Permalink
fix(cache): make acl entities group cache warmup (#11414)
Browse files Browse the repository at this point in the history
kong acl plugin will need to get all consumer groups by customer id (because consumer group and acl plugin config some complex connection), these entities can not be warmed up by Kong, The "warm up" mechanism mainly ensures that all entities are loaded into the cache and enables more precise SQL queries (based on cache key definitions) https://github.com/Kong/kong/blob/master/kong/plugins/acl/daos.lua#L8. However, for scenarios where it is necessary to iterate through all entities under a consumer ID, caching is not possible. https://github.com/Kong/kong/blob/master/kong/plugins/acl/groups.lua#L45

So this PR tries a patch warmup mechanism to support acls entities config.

FTI-5275
  • Loading branch information
oowl authored and windmgc committed Mar 7, 2024
1 parent f8e23b2 commit af322f9
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 0 deletions.
5 changes: 5 additions & 0 deletions changelog/unreleased/kong/acl_cache_warmup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
message: Fix cache warmup mechanism not working in `acls` plugin groups config entity scenario.
type: bugfix
scope: Core
prs:
- 11414
12 changes: 12 additions & 0 deletions kong/cache/warmup.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
local utils = require "kong.tools.utils"
local constants = require "kong.constants"
local buffer = require "string.buffer"
local acl_groups
if utils.load_module_if_exists("kong.plugins.acl.groups") then
acl_groups = require "kong.plugins.acl.groups"
end


local cache_warmup = {}
Expand Down Expand Up @@ -136,6 +140,14 @@ function cache_warmup.single_dao(dao)
if not ok then
return nil, err
end

if entity_name == "acls" and acl_groups ~= nil then
log(NOTICE, "warmup acl groups cache for consumer id: ", entity.consumer.id , "...")
local _, err = acl_groups.warmup_groups_cache(entity.consumer.id)
if err then
log(NOTICE, "warmup acl groups cache for consumer id: ", entity.consumer.id , " err: ", err)
end
end
end

if entity_name == "services" and host_count > 0 then
Expand Down
11 changes: 11 additions & 0 deletions kong/plugins/acl/groups.lua
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,22 @@ local function group_in_groups(groups_to_check, groups)
end
end

local function warmup_groups_cache(consumer_id)
local cache_key = kong.db.acls:cache_key(consumer_id)
local _, err = kong.cache:get(cache_key, nil,
load_groups_into_memory,
{ id = consumer_id })
if err then
return nil, err
end
end


return {
get_current_consumer_id = get_current_consumer_id,
get_consumer_groups = get_consumer_groups,
get_authenticated_groups = get_authenticated_groups,
consumer_in_groups = consumer_in_groups,
group_in_groups = group_in_groups,
warmup_groups_cache = warmup_groups_cache,
}
49 changes: 49 additions & 0 deletions spec/03-plugins/18-acl/02-access_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -711,10 +711,39 @@ for _, strategy in helpers.each_strategy() do
}
}

local route14 = bp.routes:insert({
hosts = { "acl14.com" }
})

local acl_prefunction_code = " local consumer_id = \"" .. tostring(consumer2.id) .. "\"\n" .. [[
local cache_key = kong.db.acls:cache_key(consumer_id)
-- we must use shadict to get the cache, because the `kong.cache` was hooked by `kong.plugins.pre-function`
local raw_groups, err = ngx.shared.kong_db_cache:get("kong_db_cache"..cache_key)
if raw_groups then
ngx.exit(200)
else
ngx.log(ngx.ERR, "failed to get cache: ", err)
ngx.exit(500)
end
]]

bp.plugins:insert {
route = { id = route14.id },
name = "pre-function",
config = {
access = {
acl_prefunction_code,
},
}
}

assert(helpers.start_kong({
plugins = "bundled, ctx-checker",
database = strategy,
nginx_conf = "spec/fixtures/custom_nginx.template",
db_cache_warmup_entities = "keyauth_credentials,consumers,acls",
}))
end)

Expand Down Expand Up @@ -1332,6 +1361,26 @@ for _, strategy in helpers.each_strategy() do
assert.matches("You cannot consume this service", json.message)
end)
end)

describe("cache warmup acls group", function()
it("cache warmup acls group", function()
assert(helpers.restart_kong {
plugins = "bundled, ctx-checker",
database = strategy,
nginx_conf = "spec/fixtures/custom_nginx.template",
db_cache_warmup_entities = "keyauth_credentials,consumers,acls",
})

proxy_client = helpers.proxy_client()
local res = assert(proxy_client:get("/request", {
headers = {
["Host"] = "acl14.com"
}
}))
assert.res_status(200, res)
end)
end)

end)

describe("Plugin: ACL (access) [#" .. strategy .. "] anonymous", function()
Expand Down

0 comments on commit af322f9

Please sign in to comment.