From 9c2c7b3053f1e21b5dbcd36c0d77946ab42218e4 Mon Sep 17 00:00:00 2001 From: chronolaw Date: Mon, 4 Mar 2024 12:08:23 +0800 Subject: [PATCH] refactor(router/atc): ensure to validate possible routes fields fix is_empty_field add protocols for stream tests tests for tls_passthrough fix-snis-tls-passthrough-in-trad-compat.yml style lint --- ...ix-snis-tls-passthrough-in-trad-compat.yml | 5 ++ kong/db/schema/entities/routes.lua | 21 +++++- kong/router/transform.lua | 4 +- spec/01-unit/08-router_spec.lua | 66 +++++++++++++++++++ 4 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 changelog/unreleased/kong/fix-snis-tls-passthrough-in-trad-compat.yml diff --git a/changelog/unreleased/kong/fix-snis-tls-passthrough-in-trad-compat.yml b/changelog/unreleased/kong/fix-snis-tls-passthrough-in-trad-compat.yml new file mode 100644 index 000000000000..bd3f49e4f265 --- /dev/null +++ b/changelog/unreleased/kong/fix-snis-tls-passthrough-in-trad-compat.yml @@ -0,0 +1,5 @@ +message: | + fix an issue where SNI-based routing does not work + using tls_passthrough and the traditional_compatible router flavor +type: bugfix +scope: Core diff --git a/kong/db/schema/entities/routes.lua b/kong/db/schema/entities/routes.lua index 148a2b8aab21..d166c70d29fa 100644 --- a/kong/db/schema/entities/routes.lua +++ b/kong/db/schema/entities/routes.lua @@ -130,10 +130,29 @@ else } if kong_router_flavor == "traditional_compatible" then + local is_empty_field = require("kong.router.transform").is_empty_field + table.insert(entity_checks, { custom_entity_check = { + field_sources = { "id", "protocols", + "snis", "sources", "destinations", + "methods", "hosts", "paths", "headers", + }, run_with_missing_fields = true, - fn = validate_route, + fn = function(entity) + if is_empty_field(entity.snis) and + is_empty_field(entity.sources) and + is_empty_field(entity.destinations) and + is_empty_field(entity.methods) and + is_empty_field(entity.hosts) and + is_empty_field(entity.paths) and + is_empty_field(entity.headers) + then + return true + end + + return validate_route(entity) + end, }} ) end diff --git a/kong/router/transform.lua b/kong/router/transform.lua index 141525e1ec50..2933bc1c32a6 100644 --- a/kong/router/transform.lua +++ b/kong/router/transform.lua @@ -524,9 +524,7 @@ local function get_priority(route) -- stream expression - if not is_empty_field(srcs) or - not is_empty_field(dsts) - then + if is_stream_route(route) then return stream_get_priority(snis, srcs, dsts) end diff --git a/spec/01-unit/08-router_spec.lua b/spec/01-unit/08-router_spec.lua index 3078c907f82c..9e7a9e2cba12 100644 --- a/spec/01-unit/08-router_spec.lua +++ b/spec/01-unit/08-router_spec.lua @@ -4307,6 +4307,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8101", + protocols = { "tcp", }, sources = { { ip = "127.0.0.1" }, { ip = "127.0.0.2" }, @@ -4317,6 +4318,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8102", + protocols = { "tcp", }, sources = { { port = 65001 }, { port = 65002 }, @@ -4328,6 +4330,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8103", + protocols = { "tcp", }, sources = { { ip = "127.168.0.0/8" }, } @@ -4338,6 +4341,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8104", + protocols = { "tcp", }, sources = { { ip = "127.0.0.1", port = 65001 }, } @@ -4347,6 +4351,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8105", + protocols = { "tcp", }, sources = { { ip = "127.0.0.2", port = 65300 }, { ip = "127.168.0.0/16", port = 65301 }, @@ -4416,6 +4421,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8101", + protocols = { "tcp", }, destinations = { { ip = "127.0.0.1" }, { ip = "127.0.0.2" }, @@ -4426,6 +4432,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8102", + protocols = { "tcp", }, destinations = { { port = 65001 }, { port = 65002 }, @@ -4437,6 +4444,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8103", + protocols = { "tcp", }, destinations = { { ip = "127.168.0.0/8" }, } @@ -4447,6 +4455,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8104", + protocols = { "tcp", }, destinations = { { ip = "127.0.0.1", port = 65001 }, } @@ -4456,6 +4465,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8105", + protocols = { "tcp", }, destinations = { { ip = "127.0.0.2", port = 65300 }, { ip = "127.168.0.0/16", port = 65301 }, @@ -4613,6 +4623,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8101", + protocols = { "tls", }, snis = { "www.example.org" }, } }, @@ -4620,6 +4631,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8102", + protocols = { "tls", }, sources = { { ip = "127.0.0.1" }, } @@ -4629,6 +4641,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8103", + protocols = { "tls", }, destinations = { { ip = "172.168.0.1" }, } @@ -4655,6 +4668,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8101", + protocols = { "tls", }, snis = { "www.example.org" }, } }, @@ -4662,6 +4676,7 @@ for _, flavor in ipairs({ "traditional", "traditional_compatible", "expressions" service = service, route = { id = "e8fb37f1-102d-461e-9c51-6608a6bb8102", + protocols = { "tls", }, sources = { { ip = "127.0.0.1" }, }, @@ -5033,6 +5048,57 @@ do assert.same("/bar", match_t.upstream_uri) end) end) + + describe("Router (flavor = " .. flavor .. ")", function() + reload_router(flavor, "stream") + + it("[#stream SNI-based routing does work using tls_passthrough]", function() + local use_case = { + { + service = service, + route = { + id = "e8fb37f1-102d-461e-9c51-6608a6bb8101", + protocols = { "tls_passthrough", }, + snis = { "www.example.com" }, + preserve_host = true, + }, + }, + { + service = service, + route = { + id = "e8fb37f1-102d-461e-9c51-6608a6bb8102", + protocols = { "tls_passthrough", }, + snis = { "www.example.org" }, + preserve_host = true, + }, + }, + } + + local router = assert(new_router(use_case)) + + local _ngx = { + var = { + ssl_preread_server_name = "www.example.com", + }, + } + router._set_ngx(_ngx) + local match_t = router:exec() + + assert.truthy(match_t) + assert.same(use_case[1].route, match_t.route) + + local _ngx = { + var = { + ssl_preread_server_name = "www.example.org", + }, + } + router._set_ngx(_ngx) + local match_t = router:exec() + + assert.truthy(match_t) + assert.same(use_case[2].route, match_t.route) + end) + end) end -- local flavor = "traditional_compatible" do