From 262a3122c057bd38381ad5025bb5f3b0901a2a1c Mon Sep 17 00:00:00 2001 From: jeremyjpj0916 <31913027+jeremyjpj0916@users.noreply.github.com> Date: Tue, 13 Dec 2022 05:41:53 -0500 Subject: [PATCH 1/6] Update connection.lua --- .../plugins/scalable-rate-limiter/policies/connection.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kong/plugins/scalable-rate-limiter/policies/connection.lua b/kong/plugins/scalable-rate-limiter/policies/connection.lua index f7cad8b..7a898f0 100644 --- a/kong/plugins/scalable-rate-limiter/policies/connection.lua +++ b/kong/plugins/scalable-rate-limiter/policies/connection.lua @@ -3,6 +3,8 @@ local redis_cluster = require "resty.rediscluster" local resty_lock = require "resty.lock" local worker = ngx.worker local inspect = require "inspect" +local dns_client = require "kong.resty.dns.client" +local ip = require "resty.mediador.ip" local _M = {} local data = { @@ -10,6 +12,12 @@ local data = { } local function get_redis_config(source_config) + -- If not ipv4 and not ipv6 adress then we need to resolve hostname to ip + if not ip.isv4(source_config.redis_host) and not ip.isv6(source_config.redis_host) then + dns_client = require("kong.tools.dns")(kong.configuration) -- configure DNS client + source_config.redis_host = dns_client.toip(source_config.redis_host) + end + return { name = "d11-redis-cluster", serv_list = { From 2a1626484c6e767b945ca33448f114e0f238f4b2 Mon Sep 17 00:00:00 2001 From: jeremyjpj0916 <31913027+jeremyjpj0916@users.noreply.github.com> Date: Tue, 13 Dec 2022 12:08:21 -0500 Subject: [PATCH 2/6] Update connection.lua --- kong/plugins/scalable-rate-limiter/policies/connection.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kong/plugins/scalable-rate-limiter/policies/connection.lua b/kong/plugins/scalable-rate-limiter/policies/connection.lua index 7a898f0..145f1f9 100644 --- a/kong/plugins/scalable-rate-limiter/policies/connection.lua +++ b/kong/plugins/scalable-rate-limiter/policies/connection.lua @@ -4,7 +4,7 @@ local resty_lock = require "resty.lock" local worker = ngx.worker local inspect = require "inspect" local dns_client = require "kong.resty.dns.client" -local ip = require "resty.mediador.ip" +local ipmatcher = require "resty.ipmatcher" local _M = {} local data = { @@ -13,7 +13,7 @@ local data = { local function get_redis_config(source_config) -- If not ipv4 and not ipv6 adress then we need to resolve hostname to ip - if not ip.isv4(source_config.redis_host) and not ip.isv6(source_config.redis_host) then + if not ipmatcher.parse_ipv4(source_config.redis_host) and not ipmatcher.parse_ipv6(source_config.redis_host) then dns_client = require("kong.tools.dns")(kong.configuration) -- configure DNS client source_config.redis_host = dns_client.toip(source_config.redis_host) end From 12340c932721d0804ed9b45973076d6fa8633680 Mon Sep 17 00:00:00 2001 From: jeremyjpj0916 <31913027+jeremyjpj0916@users.noreply.github.com> Date: Tue, 13 Dec 2022 12:11:18 -0500 Subject: [PATCH 3/6] Update kong-scalable-rate-limiter-1.1.0-1.rockspec --- kong-scalable-rate-limiter-1.1.0-1.rockspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kong-scalable-rate-limiter-1.1.0-1.rockspec b/kong-scalable-rate-limiter-1.1.0-1.rockspec index 558ebf1..2f48288 100644 --- a/kong-scalable-rate-limiter-1.1.0-1.rockspec +++ b/kong-scalable-rate-limiter-1.1.0-1.rockspec @@ -14,7 +14,7 @@ description = { } dependencies = { - + "lua-resty-ipmatcher == 0.6.1-0", } build = { From 56a2fa634dfd2ba7a5b23c13b06c584622a23a1b Mon Sep 17 00:00:00 2001 From: jeremyjpj0916 <31913027+jeremyjpj0916@users.noreply.github.com> Date: Tue, 13 Dec 2022 12:13:16 -0500 Subject: [PATCH 4/6] Update kong-scalable-rate-limiter-1.1.0-1.rockspec --- kong-scalable-rate-limiter-1.1.0-1.rockspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kong-scalable-rate-limiter-1.1.0-1.rockspec b/kong-scalable-rate-limiter-1.1.0-1.rockspec index 2f48288..88a7ca2 100644 --- a/kong-scalable-rate-limiter-1.1.0-1.rockspec +++ b/kong-scalable-rate-limiter-1.1.0-1.rockspec @@ -14,7 +14,7 @@ description = { } dependencies = { - "lua-resty-ipmatcher == 0.6.1-0", + "lua-resty-ipmatcher == 0.6.1", } build = { From eb7c23f099dfddef7a6439620e58e683f10554e6 Mon Sep 17 00:00:00 2001 From: jeremyjpj0916 <31913027+jeremyjpj0916@users.noreply.github.com> Date: Thu, 5 Jan 2023 01:22:08 -0500 Subject: [PATCH 5/6] Update redis-cluster.yml --- .pongo/redis-cluster.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pongo/redis-cluster.yml b/.pongo/redis-cluster.yml index 5d9e482..1ec6209 100644 --- a/.pongo/redis-cluster.yml +++ b/.pongo/redis-cluster.yml @@ -9,6 +9,7 @@ networks: services: redis-cluster: image: redis:latest + hostname: pongo-test-network command: redis-cli -p 7101 --cluster create 172.18.55.1:7101 172.18.55.2:7102 172.18.55.3:7103 --cluster-yes depends_on: - redis-1 From 028dc4480adbd2dca8cd813eb93daa34e016eb27 Mon Sep 17 00:00:00 2001 From: jeremyjpj0916 <31913027+jeremyjpj0916@users.noreply.github.com> Date: Thu, 5 Jan 2023 01:27:10 -0500 Subject: [PATCH 6/6] Update 01-access_spec.lua --- spec/scalable-rate-limiter/01-access_spec.lua | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/spec/scalable-rate-limiter/01-access_spec.lua b/spec/scalable-rate-limiter/01-access_spec.lua index eba1b08..5a15b4b 100644 --- a/spec/scalable-rate-limiter/01-access_spec.lua +++ b/spec/scalable-rate-limiter/01-access_spec.lua @@ -3,6 +3,7 @@ local cjson = require "cjson" -- REDIS_HOST and REDIS_PORT taken from .pongo/redis-cluster.yml local REDIS_HOST = "172.18.55.1" +local REDIS_HOSTNAME = "pongo-test-network" local REDIS_PORT = 7101 local REDIS_PASSWORD = "" local REDIS_DATABASE = 1 @@ -75,6 +76,15 @@ for _, strategy in helpers.each_strategy() do limit_by = "service", batch_size = 2, } + + local limit_by_service_config_hostname = { + policy = policy, + minute = per_minute_limit, + redis_host = REDIS_HOSTNAME, + redis_port = REDIS_PORT, + limit_by = "service", + batch_size = 2, + } local limit_by_header_config = { policy = policy, @@ -206,6 +216,127 @@ for _, strategy in helpers.each_strategy() do end end) end) + + describe("global level plugin limit by service using redis hostname", function() + lazy_setup(function() + helpers.kill_all() + + bp, db = helpers.get_db_utils(strategy, nil, {"scalable-rate-limiter"}) + + -- Add request termination plugin at global level to return 200 response for all api calls + bp.plugins:insert { + name = "request-termination", + config = { + status_code = 200, + }, + } + + -- Global level Rate limiting plugin limit by service + bp.plugins:insert { + name = "scalable-rate-limiter", + config = limit_by_service_config_hostname, + } + + local service_1 = bp.services:insert { + protocol = "http", + host = mock_host, + port = mock_port, + name = "service_1", + } + + bp.routes:insert { + methods = {"GET"}, + protocols = {"http"}, + paths = {"/service_1_route_1"}, + strip_path = false, + preserve_host = true, + service = service_1, + } + + local service_2 = bp.services:insert { + protocol = "http", + host = mock_host, + port = mock_port, + name = "service_2", + } + + bp.routes:insert { + methods = {"GET"}, + protocols = {"http"}, + paths = {"/service_2_route_1"}, + strip_path = false, + preserve_host = true, + service = service_2, + } + + local service_3 = bp.services:insert { + protocol = "http", + host = mock_host, + port = mock_port, + name = "service_3", + } + + bp.routes:insert { + methods = {"GET"}, + protocols = {"http"}, + paths = {"/service_3_route_1"}, + strip_path = false, + preserve_host = true, + service = service_3, + } + + bp.routes:insert { + methods = {"GET"}, + protocols = {"http"}, + paths = {"/service_3_route_2"}, + strip_path = false, + preserve_host = true, + service = service_3, + } + + assert(helpers.start_kong({ + database = strategy, + nginx_conf = "spec/fixtures/custom_nginx.template", + plugins = "bundled,scalable-rate-limiter", + })) + end) + + lazy_teardown(function() + helpers.stop_kong() + assert(db:truncate()) + end) + + it_with_retry("blocks requests over limit on same service", function() + for i = 1, per_minute_limit do + local res = GET("/service_1_route_1", nil, 200) + end + + local res = GET("/service_1_route_1", nil, 429) + end) + + it_with_retry("blocks requests over limit on same service with multiple routes", function() + for i = 1, per_minute_limit/2 do + local res = GET("/service_3_route_1", nil, 200) + end + + for i = 1, per_minute_limit/2 do + local res = GET("/service_3_route_2", nil, 200) + end + + local res = GET("/service_3_route_1", nil, 429) + local res = GET("/service_3_route_2", nil, 429) + end) + + it_with_retry("allows requests upto limit on each different service", function() + for i = 1, per_minute_limit do + local res = GET("/service_1_route_1", nil, 200) + end + + for i = 1, per_minute_limit do + local res = GET("/service_2_route_1", nil, 200) + end + end) + end) describe("global level plugin limit by header", function() lazy_setup(function()