kong--kong
1138 行
32 KiB
Lua
1138 行
32 KiB
Lua
local helpers = require "spec.helpers"
|
|
local cjson = require "cjson"
|
|
|
|
local MESSAGE = "echo, ping, pong. echo, ping, pong. echo, ping, pong.\n"
|
|
|
|
for _, strategy in helpers.each_strategy() do
|
|
describe("Plugin: ip-restriction (access) [#" .. strategy .. "]", function()
|
|
local plugin
|
|
local proxy_client
|
|
local admin_client
|
|
local db
|
|
|
|
lazy_setup(function()
|
|
local bp
|
|
bp, db = helpers.get_db_utils(strategy, {
|
|
"routes",
|
|
"services",
|
|
"plugins",
|
|
})
|
|
|
|
local route1 = bp.routes:insert {
|
|
hosts = { "ip-restriction1.test" },
|
|
}
|
|
|
|
local route2 = bp.routes:insert {
|
|
hosts = { "ip-restriction2.test" },
|
|
}
|
|
|
|
local route3 = bp.routes:insert {
|
|
hosts = { "ip-restriction3.test" },
|
|
}
|
|
|
|
local route4 = bp.routes:insert {
|
|
hosts = { "ip-restriction4.test" },
|
|
}
|
|
|
|
local route5 = bp.routes:insert {
|
|
hosts = { "ip-restriction5.test" },
|
|
}
|
|
|
|
local route6 = bp.routes:insert {
|
|
hosts = { "ip-restriction6.test" },
|
|
}
|
|
|
|
local route7 = bp.routes:insert {
|
|
hosts = { "ip-restriction7.test" },
|
|
}
|
|
|
|
local route8 = bp.routes:insert {
|
|
hosts = { "ip-restriction8.test" },
|
|
}
|
|
|
|
local route9 = bp.routes:insert {
|
|
hosts = { "ip-restriction9.test" },
|
|
}
|
|
|
|
local route10 = bp.routes:insert {
|
|
hosts = { "ip-restriction10.test" },
|
|
}
|
|
|
|
local route11 = bp.routes:insert {
|
|
hosts = { "ip-restriction11.test" },
|
|
}
|
|
|
|
local route12 = bp.routes:insert {
|
|
hosts = { "ip-restriction12.test" },
|
|
}
|
|
|
|
local grpc_service = bp.services:insert {
|
|
name = "grpc1",
|
|
url = helpers.grpcbin_url,
|
|
}
|
|
|
|
local route_grpc_deny = assert(bp.routes:insert {
|
|
protocols = { "grpc" },
|
|
paths = { "/hello.HelloService/" },
|
|
hosts = { "ip-restriction-grpc1.test" },
|
|
service = grpc_service,
|
|
})
|
|
|
|
local route_grpc_allow = assert(bp.routes:insert {
|
|
protocols = { "grpc" },
|
|
paths = { "/hello.HelloService/" },
|
|
hosts = { "ip-restriction-grpc2.test" },
|
|
service = grpc_service,
|
|
})
|
|
|
|
local route_grpc_xforwarded_deny = assert(bp.routes:insert {
|
|
protocols = { "grpc" },
|
|
paths = { "/hello.HelloService/" },
|
|
hosts = { "ip-restriction-grpc3.test" },
|
|
service = grpc_service,
|
|
})
|
|
|
|
-- tcp services/routes
|
|
local tcp_srv = bp.services:insert({
|
|
name = "tcp",
|
|
host = helpers.mock_upstream_host,
|
|
port = helpers.mock_upstream_stream_port,
|
|
protocol = "tcp"
|
|
})
|
|
|
|
local tls_srv = bp.services:insert({
|
|
name = "tls",
|
|
host = helpers.mock_upstream_host,
|
|
port = helpers.mock_upstream_stream_ssl_port,
|
|
protocol = "tls"
|
|
})
|
|
|
|
local route_tcp_allow = bp.routes:insert {
|
|
destinations = {
|
|
{
|
|
port = 19000,
|
|
},
|
|
},
|
|
protocols = {
|
|
"tcp",
|
|
},
|
|
service = tcp_srv,
|
|
}
|
|
|
|
local route_tcp_deny = bp.routes:insert {
|
|
destinations = {
|
|
{
|
|
port = 19443,
|
|
},
|
|
},
|
|
protocols = {
|
|
"tls",
|
|
},
|
|
service = tls_srv,
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route1.id },
|
|
config = {
|
|
deny = { "127.0.0.1", "127.0.0.2" }
|
|
},
|
|
}
|
|
|
|
plugin = assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route2.id },
|
|
config = {
|
|
deny = { "127.0.0.2" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route3.id },
|
|
config = {
|
|
allow = { "127.0.0.2" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route4.id },
|
|
config = {
|
|
allow = { "127.0.0.1" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route5.id },
|
|
config = {
|
|
deny = { "127.0.0.0/24" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route6.id },
|
|
config = {
|
|
allow = { "127.0.0.4" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route7.id },
|
|
config = {
|
|
deny = { "127.0.0.4" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route8.id },
|
|
config = {
|
|
allow = { "0.0.0.0/0" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route9.id },
|
|
config = {
|
|
allow = { "127.0.0.1" },
|
|
deny = { "127.0.0.1" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route10.id },
|
|
config = {
|
|
allow = { "127.0.0.0/24" },
|
|
deny = { "127.0.0.1" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route11.id },
|
|
config = {
|
|
allow = { "127.0.0.0/24" },
|
|
deny = { "127.0.0.0/24" },
|
|
},
|
|
})
|
|
|
|
bp.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route12.id },
|
|
config = {
|
|
deny = { "127.0.0.0/24" },
|
|
status = 401,
|
|
message = "Forbidden"
|
|
},
|
|
}
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route_tcp_allow.id },
|
|
config = {
|
|
allow = { "127.0.0.0/24" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route_tcp_deny.id },
|
|
config = {
|
|
deny = { "127.0.0.0/24" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route_grpc_deny.id },
|
|
config = {
|
|
deny = { "127.0.0.0/24" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route_grpc_allow.id },
|
|
config = {
|
|
deny = { "127.0.0.2/32" }
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route_grpc_xforwarded_deny.id },
|
|
config = {
|
|
allow = { "127.0.0.4/32" },
|
|
},
|
|
})
|
|
|
|
assert(helpers.start_kong {
|
|
database = strategy,
|
|
real_ip_header = "X-Forwarded-For",
|
|
real_ip_recursive = "on",
|
|
trusted_ips = "0.0.0.0/0, ::/0",
|
|
nginx_conf = "spec/fixtures/custom_nginx.template",
|
|
stream_listen = helpers.get_proxy_ip(false) .. ":19000," ..
|
|
helpers.get_proxy_ip(false) .. ":19443 ssl"
|
|
})
|
|
|
|
proxy_client = helpers.proxy_client()
|
|
admin_client = helpers.admin_client()
|
|
end)
|
|
|
|
lazy_teardown(function()
|
|
if proxy_client and admin_client then
|
|
proxy_client:close()
|
|
admin_client:close()
|
|
end
|
|
|
|
helpers.stop_kong()
|
|
end)
|
|
|
|
describe("deny", function()
|
|
it("blocks a request when the IP is denied", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction1.test"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
|
|
it("blocks a request when the IP is denied with status/message", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction12.test"
|
|
}
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
local json = cjson.decode(body)
|
|
|
|
assert.not_nil(json)
|
|
assert.matches("Forbidden", json.message)
|
|
end)
|
|
|
|
it("blocks a request when the IP is denied #grpc", function()
|
|
local ok, err = helpers.proxy_client_grpc(){
|
|
service = "hello.HelloService.SayHello",
|
|
opts = {
|
|
["-authority"] = "ip-restriction-grpc1.test",
|
|
["-v"] = true,
|
|
},
|
|
}
|
|
assert.falsy(ok)
|
|
assert.matches("Code: PermissionDenied", err)
|
|
end)
|
|
|
|
it("blocks a request when the IP is denied #tcp", function()
|
|
local tcp = ngx.socket.tcp()
|
|
assert(tcp:connect(helpers.get_proxy_ip(true), 19443))
|
|
assert(tcp:sslhandshake(nil, nil, false))
|
|
assert(tcp:send(MESSAGE))
|
|
assert(tcp:receive("*a"))
|
|
tcp:close()
|
|
|
|
assert.logfile().has.line("IP address not allowed", true)
|
|
-- Ensure no preread phase errors occur (regression test for #14749)
|
|
assert.logfile().has.no.line("[error]", true)
|
|
assert.logfile().has.no.line("traceback", true)
|
|
assert.logfile().has.no.line("function cannot be called in preread phase", true)
|
|
end)
|
|
|
|
it("allows a request when the IP is not denied", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "ip-restriction2.test"
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("127.0.0.1", json.vars.remote_addr)
|
|
end)
|
|
|
|
it("allows a request when the IP is not denied #grpc", function()
|
|
local ok = helpers.proxy_client_grpc(){
|
|
service = "hello.HelloService.SayHello",
|
|
opts = {
|
|
["-authority"] = "ip-restriction-grpc2.test",
|
|
["-v"] = true,
|
|
},
|
|
}
|
|
assert.truthy(ok)
|
|
end)
|
|
|
|
it("allows a request when the IP is not denied #tcp", function()
|
|
local tcp = ngx.socket.tcp()
|
|
local ip = helpers.get_proxy_ip(false)
|
|
assert(tcp:connect(ip, 19000))
|
|
assert(tcp:send(MESSAGE))
|
|
local body = assert(tcp:receive("*a"))
|
|
assert.equal(MESSAGE, body)
|
|
tcp:close()
|
|
|
|
-- Ensure no preread phase errors occur (regression test for #14749)
|
|
assert.logfile().has.no.line("[error]", true)
|
|
assert.logfile().has.no.line("traceback", true)
|
|
assert.logfile().has.no.line("function cannot be called in preread phase", true)
|
|
end)
|
|
|
|
it("blocks IP with CIDR", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction5.test"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("blocks an IP on a allowed CIDR range", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction10.test"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("takes precedence over an allowed IP", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction9.test"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("takes precedence over an allowed CIDR range", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction11.test"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
|
|
describe("X-Forwarded-For", function()
|
|
it("allows without any X-Forwarded-For and allowed IP", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "ip-restriction7.test"
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("127.0.0.1", json.vars.remote_addr)
|
|
end)
|
|
it("allows with allowed X-Forwarded-For header", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "ip-restriction7.test",
|
|
["X-Forwarded-For"] = "127.0.0.3"
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("127.0.0.3", json.vars.remote_addr)
|
|
end)
|
|
it("blocks with not allowed X-Forwarded-For header", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction7.test",
|
|
["X-Forwarded-For"] = "127.0.0.4"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
end)
|
|
end)
|
|
|
|
describe("allow", function()
|
|
it("blocks a request when the IP is not allowed", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction3.test"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("allows a allowed IP", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction4.test"
|
|
}
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
describe("X-Forwarded-For", function()
|
|
it("blocks without any X-Forwarded-For and not allowed IP", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction6.test"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("block with not allowed X-Forwarded-For header", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction6.test",
|
|
["X-Forwarded-For"] = "127.0.0.3"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("block with not allowed X-Forwarded-For header #grpc", function()
|
|
local ok, err = helpers.proxy_client_grpc(){
|
|
service = "hello.HelloService.SayHello",
|
|
opts = {
|
|
["-authority"] = "ip-restriction-grpc3.test",
|
|
["-v"] = true,
|
|
},
|
|
}
|
|
assert.falsy(ok)
|
|
assert.matches("Code: PermissionDenied", err)
|
|
end)
|
|
it("allows with allowed X-Forwarded-For header", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction6.test",
|
|
["X-Forwarded-For"] = "127.0.0.4"
|
|
}
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
it("allows with allowed X-Forwarded-For header #grpc", function()
|
|
assert.truthy(helpers.proxy_client_grpc(){
|
|
service = "hello.HelloService.SayHello",
|
|
opts = {
|
|
["-authority"] = "ip-restriction-grpc3.test",
|
|
["-v"] = true,
|
|
["-H"] = "'X-Forwarded-For: 127.0.0.4'",
|
|
},
|
|
})
|
|
end)
|
|
it("allows with allowed complex X-Forwarded-For header", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction6.test",
|
|
["X-Forwarded-For"] = "127.0.0.4, 127.0.0.3"
|
|
}
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
end)
|
|
end)
|
|
|
|
it("supports config changes without restarting", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "ip-restriction2.test"
|
|
}
|
|
})
|
|
assert.res_status(200, res)
|
|
|
|
res = assert(admin_client:send {
|
|
method = "PATCH",
|
|
path = "/plugins/" .. plugin.id,
|
|
body = {
|
|
config = { deny = { "127.0.0.1", "127.0.0.2" } },
|
|
},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
assert.res_status(200, res)
|
|
|
|
helpers.pwait_until(function()
|
|
res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "ip-restriction2.test"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
|
|
res = assert(admin_client:send {
|
|
method = "PATCH",
|
|
path = "/plugins/" .. plugin.id,
|
|
body = {
|
|
config = { deny = { "127.0.0.2", "127.0.0.3" } },
|
|
},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
assert.res_status(200, res)
|
|
|
|
helpers.pwait_until(function()
|
|
res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "ip-restriction2.test"
|
|
}
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
end)
|
|
|
|
describe("#regression", function()
|
|
it("handles a CIDR entry with 0.0.0.0/0", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction8.test"
|
|
}
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
end)
|
|
end)
|
|
|
|
describe("Plugin: ip-restriction (access) [#" .. strategy .. "]", function()
|
|
local plugin
|
|
local proxy_client
|
|
local admin_client
|
|
local db
|
|
|
|
lazy_setup(function()
|
|
local bp
|
|
bp, db = helpers.get_db_utils(strategy, {
|
|
"routes",
|
|
"services",
|
|
"plugins",
|
|
})
|
|
|
|
local route1 = bp.routes:insert {
|
|
hosts = { "ip-restriction1.test" },
|
|
}
|
|
|
|
local route2 = bp.routes:insert {
|
|
hosts = { "ip-restriction2.test" },
|
|
}
|
|
|
|
local route3 = bp.routes:insert {
|
|
hosts = { "ip-restriction3.test" },
|
|
}
|
|
|
|
local route4 = bp.routes:insert {
|
|
hosts = { "ip-restriction4.test" },
|
|
}
|
|
|
|
local route5 = bp.routes:insert {
|
|
hosts = { "ip-restriction5.test" },
|
|
}
|
|
|
|
local route6 = bp.routes:insert {
|
|
hosts = { "ip-restriction6.test" },
|
|
}
|
|
|
|
local route7 = bp.routes:insert {
|
|
hosts = { "ip-restriction7.test" },
|
|
}
|
|
|
|
local route8 = bp.routes:insert {
|
|
hosts = { "ip-restriction8.test" },
|
|
}
|
|
|
|
local route9 = bp.routes:insert {
|
|
hosts = { "ip-restriction9.test" },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route1.id },
|
|
config = {
|
|
deny = { "::1", "::2" }
|
|
},
|
|
}
|
|
|
|
plugin = assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route2.id },
|
|
config = {
|
|
deny = { "::2" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route3.id },
|
|
config = {
|
|
deny = { "fe80::/8" },
|
|
},
|
|
})
|
|
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route4.id },
|
|
config = {
|
|
allow = { "::2" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route5.id },
|
|
config = {
|
|
allow = { "::1" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route6.id },
|
|
config = {
|
|
allow = { "::/0" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route7.id },
|
|
config = {
|
|
allow = { "::1" },
|
|
deny = { "::1" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route8.id },
|
|
config = {
|
|
allow = { "::1/128" },
|
|
deny = { "::1" },
|
|
},
|
|
})
|
|
|
|
assert(db.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route9.id },
|
|
config = {
|
|
allow = { "::1/128" },
|
|
deny = { "::1/128" },
|
|
},
|
|
})
|
|
|
|
assert(helpers.start_kong {
|
|
database = strategy,
|
|
real_ip_recursive = "on",
|
|
trusted_ips = "0.0.0.0/0, ::/0",
|
|
nginx_conf = "spec/fixtures/custom_nginx.template",
|
|
})
|
|
|
|
proxy_client = helpers.proxy_client()
|
|
admin_client = helpers.admin_client()
|
|
end)
|
|
|
|
lazy_teardown(function()
|
|
if proxy_client and admin_client then
|
|
proxy_client:close()
|
|
admin_client:close()
|
|
end
|
|
|
|
helpers.stop_kong()
|
|
end)
|
|
|
|
describe("deny", function()
|
|
it("blocks a request when the IPv6 is denied", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction1.test",
|
|
["X-Real-IP"] = "::1",
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("allows a request when the IPv6 is not denied", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "ip-restriction2.test",
|
|
["X-Real-IP"] = "::1",
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("::1", json.vars.remote_addr)
|
|
end)
|
|
it("blocks the IPv6 with CIDR", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction3.test",
|
|
["X-Real-IP"] = "fe80::1",
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("blocks an IPv6 on a allowed IPv6 CIDR range", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction8.test",
|
|
["X-Real-IP"] = "::1",
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("takes precedence over an allowed IPv6", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction7.test",
|
|
["X-Real-IP"] = "::1",
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("takes precedence over an allowed IPv6 CIDR range", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction9.test"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
end)
|
|
|
|
describe("allow", function()
|
|
it("blocks a request when the IPv6 is not allowed", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction4.test",
|
|
["X-Real-IP"] = "::1",
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("allows a allowed IPv6", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction5.test",
|
|
["X-Real-IP"] = "::1",
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("::1", json.vars.remote_addr)
|
|
end)
|
|
end)
|
|
|
|
it("supports config changes without restarting", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "ip-restriction2.test",
|
|
["X-Real-IP"] = "::1",
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("::1", json.vars.remote_addr)
|
|
|
|
res = assert(admin_client:send {
|
|
method = "PATCH",
|
|
path = "/plugins/" .. plugin.id,
|
|
body = {
|
|
config = { deny = { "::1", "::2" } },
|
|
},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
assert.res_status(200, res)
|
|
|
|
helpers.wait_for_all_config_update()
|
|
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "ip-restriction2.test",
|
|
["X-Real-IP"] = "::1",
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
|
|
res = assert(admin_client:send {
|
|
method = "PATCH",
|
|
path = "/plugins/" .. plugin.id,
|
|
body = {
|
|
config = { deny = { "::2", "::3" } },
|
|
},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
assert.res_status(200, res)
|
|
|
|
helpers.wait_for_all_config_update()
|
|
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "ip-restriction2.test",
|
|
["X-Real-IP"] = "::1",
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("::1", json.vars.remote_addr)
|
|
end)
|
|
|
|
describe("#regression", function()
|
|
it("handles a CIDR entry with ::/0", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction6.test",
|
|
["X-Real-IP"] = "::1",
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("::1", json.vars.remote_addr)
|
|
end)
|
|
end)
|
|
end)
|
|
|
|
describe("Plugin: ip-restriction (access) [#" .. strategy .. "]", function()
|
|
local proxy_client
|
|
local admin_client
|
|
|
|
lazy_setup(function()
|
|
local bp
|
|
bp = helpers.get_db_utils(strategy, {
|
|
"routes",
|
|
"services",
|
|
"plugins",
|
|
})
|
|
|
|
local route1 = bp.routes:insert {
|
|
hosts = { "ip-restriction1.test" },
|
|
}
|
|
|
|
local route2 = bp.routes:insert {
|
|
hosts = { "ip-restriction2.test" },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route1.id },
|
|
config = {
|
|
deny = { "::4" }
|
|
},
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "ip-restriction",
|
|
route = { id = route2.id },
|
|
config = {
|
|
allow = { "::4" }
|
|
},
|
|
}
|
|
|
|
assert(helpers.start_kong {
|
|
database = strategy,
|
|
real_ip_header = "X-Forwarded-For",
|
|
real_ip_recursive = "on",
|
|
trusted_ips = "0.0.0.0/0, ::/0",
|
|
nginx_conf = "spec/fixtures/custom_nginx.template",
|
|
})
|
|
|
|
proxy_client = helpers.proxy_client()
|
|
admin_client = helpers.admin_client()
|
|
end)
|
|
|
|
lazy_teardown(function()
|
|
if proxy_client and admin_client then
|
|
proxy_client:close()
|
|
admin_client:close()
|
|
end
|
|
|
|
helpers.stop_kong()
|
|
end)
|
|
|
|
describe("deny", function()
|
|
it("allows with allowed X-Forwarded-For header", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "ip-restriction1.test",
|
|
["X-Forwarded-For"] = "::3",
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("::3", json.vars.remote_addr)
|
|
end)
|
|
it("blocks with not allowed X-Forwarded-For header", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction1.test",
|
|
["X-Forwarded-For"] = "::4"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("blocks with blocked complex X-Forwarded-For header", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction1.test",
|
|
["X-Forwarded-For"] = "::4, ::3"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("allows with allowed complex X-Forwarded-For header", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction1.test",
|
|
["X-Forwarded-For"] = "::3, ::4"
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("::3", json.vars.remote_addr)
|
|
end)
|
|
end)
|
|
|
|
describe("allow", function()
|
|
it("block with not allowed X-Forwarded-For header", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction2.test",
|
|
["X-Forwarded-For"] = "::3"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
it("allows with allowed X-Forwarded-For header", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction2.test",
|
|
["X-Forwarded-For"] = "::4"
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("::4", json.vars.remote_addr)
|
|
end)
|
|
it("allows with allowed complex X-Forwarded-For header", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction2.test",
|
|
["X-Forwarded-For"] = "::4, ::3"
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("::4", json.vars.remote_addr)
|
|
end)
|
|
it("blocks with blocked complex X-Forwarded-For header", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/status/200",
|
|
headers = {
|
|
["Host"] = "ip-restriction2.test",
|
|
["X-Forwarded-For"] = "::3, ::4"
|
|
}
|
|
})
|
|
local body = assert.res_status(403, res)
|
|
assert.matches("IP address not allowed", body)
|
|
end)
|
|
end)
|
|
end)
|
|
end
|