Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(runloop): the sni cache isn't invalidated when a sni is updated #13165

Merged
merged 1 commit into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog/unreleased/kong/fix-sni-cache-invalidate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
message: |
Fixed an issue where the sni cache isn't invalidated when a sni is updated.
type: bugfix
scope: Core
23 changes: 16 additions & 7 deletions kong/runloop/events.lua
Original file line number Diff line number Diff line change
Expand Up @@ -258,24 +258,33 @@ local function crud_plugins_handler(data)
end


local function crud_snis_handler(data)
log(DEBUG, "[events] SNI updated, invalidating cached certificates")

local sni = data.old_entity or data.entity
local sni_name = sni.name
local function invalidate_snis(sni_name)
local sni_wild_pref, sni_wild_suf = certificate.produce_wild_snis(sni_name)
core_cache:invalidate("snis:" .. sni_name)

if sni_wild_pref then
if sni_wild_pref and sni_wild_pref ~= sni_name then
core_cache:invalidate("snis:" .. sni_wild_pref)
end

if sni_wild_suf then
if sni_wild_suf and sni_wild_suf ~= sni_name then
core_cache:invalidate("snis:" .. sni_wild_suf)
end
end


local function crud_snis_handler(data)
log(DEBUG, "[events] SNI updated, invalidating cached certificates")

local new_name = data.entity.name
local old_name = data.old_entity and data.old_entity.name

invalidate_snis(new_name)
if old_name and old_name ~= new_name then
invalidate_snis(old_name)
end
end


local function crud_consumers_handler(data)
workspaces.set_workspace(data.workspace)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,12 @@ for _, strategy in helpers.each_strategy() do
end)

it("on certificate delete+re-creation", function()
-- populate cache
get_cert(8443, "ssl-example.com")
get_cert(8443, "new-ssl-example.com")
get_cert(9443, "ssl-example.com")
get_cert(9443, "new-ssl-example.com")

-- TODO: PATCH update are currently not possible
-- with the admin API because snis have their name as their
-- primary key and the DAO has limited support for such updates.
Expand Down Expand Up @@ -514,6 +520,10 @@ for _, strategy in helpers.each_strategy() do
end)

it("on certificate update", function()
-- populate cache
get_cert(8443, "new-ssl-example.com")
get_cert(9443, "new-ssl-example.com")

-- update our certificate *without* updating the
-- attached sni

Expand Down Expand Up @@ -548,6 +558,12 @@ for _, strategy in helpers.each_strategy() do
end)

it("on sni update via id", function()
-- populate cache
get_cert(8443, "new-ssl-example.com")
get_cert(8443, "updated-sn-via-id.com")
get_cert(9443, "new-ssl-example.com")
get_cert(9443, "updated-sn-via-id.com")

local admin_res = admin_client_1:get("/snis")
local body = assert.res_status(200, admin_res)
local sni = assert(cjson.decode(body).data[1])
Expand Down Expand Up @@ -579,6 +595,12 @@ for _, strategy in helpers.each_strategy() do
end)

it("on sni update via name", function()
-- populate cache
get_cert(8443, "updated-sn-via-id.com")
get_cert(8443, "updated-sn.com")
get_cert(9443, "updated-sn-via-id.com")
get_cert(9443, "updated-sn.com")

local admin_res = admin_client_1:patch("/snis/updated-sn-via-id.com", {
body = { name = "updated-sn.com" },
headers = { ["Content-Type"] = "application/json" },
Expand Down Expand Up @@ -606,6 +628,10 @@ for _, strategy in helpers.each_strategy() do
end)

it("on certificate delete", function()
-- populate cache
get_cert(8443, "updated-sn.com")
get_cert(9443, "updated-sn.com")

-- delete our certificate

local admin_res = admin_client_1:delete("/certificates/updated-sn.com")
Expand All @@ -630,6 +656,14 @@ for _, strategy in helpers.each_strategy() do

describe("wildcard snis", function()
it("on create", function()
-- populate cache
get_cert(8443, "test.wildcard.com")
get_cert(8443, "test2.wildcard.com")
get_cert(8443, "wildcard.com")
get_cert(9443, "test.wildcard.com")
get_cert(9443, "test2.wildcard.com")
get_cert(9443, "wildcard.com")

local admin_res = admin_client_1:post("/certificates", {
body = {
cert = ssl_fixtures.cert_alt,
Expand Down Expand Up @@ -680,6 +714,12 @@ for _, strategy in helpers.each_strategy() do
end)

it("on certificate update", function()
-- populate cache
get_cert(8443, "test.wildcard.com")
get_cert(8443, "test2.wildcard.com")
get_cert(9443, "test.wildcard.com")
get_cert(9443, "test2.wildcard.com")

-- update our certificate *without* updating the
-- attached sni

Expand Down Expand Up @@ -723,6 +763,14 @@ for _, strategy in helpers.each_strategy() do
end)

it("on sni update via id", function()
-- populate cache
get_cert(8443, "test.wildcard.com")
get_cert(8443, "test2.wildcard.com")
get_cert(8443, "test.wildcard_updated.com")
get_cert(9443, "test.wildcard.com")
get_cert(9443, "test2.wildcard.com")
get_cert(9443, "test.wildcard_updated.com")

local admin_res = admin_client_1:get("/snis/%2A.wildcard.com")
local body = assert.res_status(200, admin_res)
local sni = assert(cjson.decode(body))
Expand Down Expand Up @@ -762,6 +810,14 @@ for _, strategy in helpers.each_strategy() do
end)

it("on sni update via name", function()
-- populate cache
get_cert(8443, "test.wildcard.org")
get_cert(8443, "test2.wildcard.org")
get_cert(8443, "test.wildcard_updated.com")
get_cert(9443, "test.wildcard.org")
get_cert(9443, "test2.wildcard.org")
get_cert(9443, "test.wildcard_updated.com")

local admin_res = admin_client_1:patch("/snis/%2A.wildcard_updated.com", {
body = { name = "*.wildcard.org" },
headers = { ["Content-Type"] = "application/json" },
Expand Down Expand Up @@ -797,6 +853,12 @@ for _, strategy in helpers.each_strategy() do
end)

it("on certificate delete", function()
-- populate cache
get_cert(8443, "test.wildcard.org")
get_cert(8443, "test2.wildcard.org")
get_cert(9443, "test.wildcard.org")
get_cert(9443, "test2.wildcard.org")

-- delete our certificate

local admin_res = admin_client_1:delete("/certificates/%2A.wildcard.org")
Expand Down
Loading