kong/spec/01-unit/04-prefix_handler_spec.lua (954 lines of code) (raw):
local helpers = require "spec.helpers"
local conf_loader = require "kong.conf_loader"
local prefix_handler = require "kong.cmd.utils.prefix_handler"
local ffi = require "ffi"
local exists = helpers.path.exists
local join = helpers.path.join
local C = ffi.C
ffi.cdef([[
struct group *getgrnam(const char *name);
struct passwd *getpwnam(const char *name);
]])
local function kong_user_group_exists()
if C.getpwnam("kong") == nil or C.getgrnam("kong") == nil then
return false
else
return true
end
end
describe("NGINX conf compiler", function()
describe("gen_default_ssl_cert()", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
prefix = "ssl_tmp",
ssl_cert = "spec/fixtures/kong_spec.crt",
ssl_cert_key = "spec/fixtures/kong_spec.key",
admin_ssl_cert = "spec/fixtures/kong_spec.crt",
admin_ssl_cert_key = "spec/fixtures/kong_spec.key",
status_cert = "spec/fixtures/kong_spec.crt",
status_cert_key = "spec/fixtures/kong_spec.key",
}))
before_each(function()
helpers.dir.makepath("ssl_tmp")
end)
after_each(function()
pcall(helpers.dir.rmtree, "ssl_tmp")
end)
describe("proxy", function()
it("auto-generates SSL certificate and key", function()
assert(prefix_handler.gen_default_ssl_cert(conf))
for _, suffix in ipairs({ "", "_ecdsa" }) do
assert(exists(conf["ssl_cert_default" .. suffix]))
assert(exists(conf["ssl_cert_key_default" .. suffix]))
end
end)
it("does not re-generate if they already exist", function()
assert(prefix_handler.gen_default_ssl_cert(conf))
for _, suffix in ipairs({ "", "_ecdsa" }) do
local cer = helpers.file.read(conf["ssl_cert_default" .. suffix])
local key = helpers.file.read(conf["ssl_cert_key_default" .. suffix])
assert(prefix_handler.gen_default_ssl_cert(conf))
assert.equal(cer, helpers.file.read(conf["ssl_cert_default" .. suffix]))
assert.equal(key, helpers.file.read(conf["ssl_cert_key_default" .. suffix]))
end
end)
end)
describe("admin", function()
it("auto-generates SSL certificate and key", function()
assert(prefix_handler.gen_default_ssl_cert(conf, "admin"))
for _, suffix in ipairs({ "", "_ecdsa" }) do
assert(exists(conf["admin_ssl_cert_default" .. suffix]))
assert(exists(conf["admin_ssl_cert_key_default" .. suffix]))
end
end)
it("does not re-generate if they already exist", function()
assert(prefix_handler.gen_default_ssl_cert(conf, "admin"))
for _, suffix in ipairs({ "", "_ecdsa" }) do
local cer = helpers.file.read(conf["admin_ssl_cert_default" .. suffix])
local key = helpers.file.read(conf["admin_ssl_cert_key_default" .. suffix])
assert(prefix_handler.gen_default_ssl_cert(conf, "admin"))
assert.equal(cer, helpers.file.read(conf["admin_ssl_cert_default" .. suffix]))
assert.equal(key, helpers.file.read(conf["admin_ssl_cert_key_default" .. suffix]))
end
end)
end)
describe("status", function()
it("auto-generates SSL certificate and key", function()
assert(prefix_handler.gen_default_ssl_cert(conf, "status"))
for _, suffix in ipairs({ "", "_ecdsa" }) do
assert(exists(conf["status_ssl_cert_default" .. suffix]))
assert(exists(conf["status_ssl_cert_key_default" .. suffix]))
end
end)
it("does not re-generate if they already exist", function()
assert(prefix_handler.gen_default_ssl_cert(conf, "status"))
for _, suffix in ipairs({ "", "_ecdsa" }) do
local cer = helpers.file.read(conf["status_ssl_cert_default" .. suffix])
local key = helpers.file.read(conf["status_ssl_cert_key_default" .. suffix])
assert(prefix_handler.gen_default_ssl_cert(conf, "status"))
assert.equal(cer, helpers.file.read(conf["status_ssl_cert_default" .. suffix]))
assert.equal(key, helpers.file.read(conf["status_ssl_cert_key_default" .. suffix]))
end
end)
end)
end)
describe("compile_kong_conf()", function()
it("compiles the Kong NGINX conf chunk", function()
local kong_nginx_conf = prefix_handler.compile_kong_conf(helpers.test_conf)
assert.matches("lua_package_path%s+'%./spec/fixtures/custom_plugins/%?%.lua;.+'", kong_nginx_conf)
assert.matches("listen%s+0%.0%.0%.0:9000;", kong_nginx_conf)
assert.matches("listen%s+127%.0%.0%.1:9001;", kong_nginx_conf)
assert.matches("server_name%s+kong;", kong_nginx_conf)
assert.matches("server_name%s+kong_admin;", kong_nginx_conf)
assert.matches("lua_ssl_trusted_certificate.+;", kong_nginx_conf)
end)
it("compiles with custom conf", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
mem_cache_size = "128k",
proxy_listen = "0.0.0.0:80",
admin_listen = "127.0.0.1:8001"
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("lua_shared_dict%s+kong_db_cache%s+128k;", kong_nginx_conf)
assert.matches("listen%s+0%.0%.0%.0:80;", kong_nginx_conf)
assert.matches("listen%s+127%.0%.0%.1:8001;", kong_nginx_conf)
end)
it("enables HTTP/2", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "0.0.0.0:9000, 0.0.0.0:9443 http2 ssl",
admin_listen = "127.0.0.1:9001, 127.0.0.1:9444 http2 ssl",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("listen%s+0%.0%.0%.0:9000;", kong_nginx_conf)
assert.matches("listen%s+0%.0%.0%.0:9443 ssl http2;", kong_nginx_conf)
assert.matches("listen%s+127%.0%.0%.1:9001;", kong_nginx_conf)
assert.matches("listen%s+127%.0%.0%.1:9444 ssl http2;", kong_nginx_conf)
conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "0.0.0.0:9000, 0.0.0.0:9443 http2 ssl",
admin_listen = "127.0.0.1:9001, 127.0.0.1:8444 ssl",
}))
kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("listen%s+0%.0%.0%.0:9000;", kong_nginx_conf)
assert.matches("listen%s+0%.0%.0%.0:9443 ssl http2;", kong_nginx_conf)
assert.matches("listen%s+127%.0%.0%.1:9001;", kong_nginx_conf)
assert.matches("listen%s+127%.0%.0%.1:8444 ssl;", kong_nginx_conf)
conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "0.0.0.0:9000, 0.0.0.0:9443 ssl",
admin_listen = "127.0.0.1:9001, 127.0.0.1:8444 http2 ssl",
}))
kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("listen%s+0%.0%.0%.0:9000;", kong_nginx_conf)
assert.matches("listen%s+0%.0%.0%.0:9443 ssl;", kong_nginx_conf)
assert.matches("listen%s+127%.0%.0%.1:9001;", kong_nginx_conf)
assert.matches("listen%s+127%.0%.0%.1:8444 ssl http2;", kong_nginx_conf)
end)
it("enables proxy_protocol", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "0.0.0.0:9000 proxy_protocol",
nginx_proxy_real_ip_header = "proxy_protocol",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("listen%s+0%.0%.0%.0:9000 proxy_protocol;", kong_nginx_conf)
assert.matches("real_ip_header%s+proxy_protocol;", kong_nginx_conf)
end)
it("enables proxy_protocol", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "0.0.0.0:9000 proxy_protocol",
real_ip_header = "proxy_protocol",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("listen%s+0%.0%.0%.0:9000 proxy_protocol;", kong_nginx_conf)
assert.matches("real_ip_header%s+proxy_protocol;", kong_nginx_conf)
end)
it("enables deferred", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "0.0.0.0:9000 deferred",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("listen%s+0%.0%.0%.0:9000 deferred;", kong_nginx_conf)
end)
it("enables bind", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "0.0.0.0:9000 bind",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("listen%s+0%.0%.0%.0:9000 bind;", kong_nginx_conf)
end)
it("enables reuseport", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "0.0.0.0:9000 reuseport",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("listen%s+0%.0%.0%.0:9000 reuseport;", kong_nginx_conf)
end)
it("enables ipv6only", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "[::1]:9000 ipv6only=on",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("listen%s+%[0000:0000:0000:0000:0000:0000:0000:0001%]:9000 ipv6only=on;", kong_nginx_conf)
end)
it("disables ipv6only", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "0.0.0.0:9000 ipv6only=off",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("listen%s+0%.0%.0%.0:9000 ipv6only=off;", kong_nginx_conf)
end)
it("enables so_keepalive", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "0.0.0.0:9000 so_keepalive=on",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("listen%s+0%.0%.0%.0:9000 so_keepalive=on;", kong_nginx_conf)
end)
it("disables so_keepalive", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "0.0.0.0:9000 so_keepalive=off",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("listen%s+0%.0%.0%.0:9000 so_keepalive=off;", kong_nginx_conf)
end)
it("configures so_keepalive", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "0.0.0.0:9000 so_keepalive=30m::10",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("listen%s+0%.0%.0%.0:9000 so_keepalive=30m::10;", kong_nginx_conf)
end)
it("disables SSL", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
proxy_listen = "127.0.0.1:8000",
admin_listen = "127.0.0.1:8001",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.not_matches("listen%s+%d+%.%d+%.%d+%.%d+:%d+ ssl;", kong_nginx_conf)
assert.not_matches("ssl_certificate", kong_nginx_conf)
assert.not_matches("ssl_certificate_key", kong_nginx_conf)
assert.not_matches("ssl_certificate_by_lua_block", kong_nginx_conf)
assert.not_matches("ssl_dhparam", kong_nginx_conf)
end)
describe("handles client_ssl", function()
it("on", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
client_ssl = true,
client_ssl_cert = "spec/fixtures/kong_spec.crt",
client_ssl_cert_key = "spec/fixtures/kong_spec.key",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("proxy_ssl_certificate%s+.*spec/fixtures/kong_spec%.crt", kong_nginx_conf)
assert.matches("proxy_ssl_certificate_key%s+.*spec/fixtures/kong_spec%.key", kong_nginx_conf)
end)
it("off", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
client_ssl = false,
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.not_matches("proxy_ssl_certificate%s+.*spec/fixtures/kong_spec%.crt", kong_nginx_conf)
assert.not_matches("proxy_ssl_certificate_key%s+.*spec/fixtures/kong_spec%.key", kong_nginx_conf)
end)
end)
it("sets lua_ssl_verify_depth", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
lua_ssl_verify_depth = "2"
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("lua_ssl_verify_depth%s+2;", kong_nginx_conf)
end)
it("includes default lua_ssl_verify_depth", function()
local conf = assert(conf_loader(helpers.test_conf_path))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("lua_ssl_verify_depth%s+1;", kong_nginx_conf)
end)
it("includes default lua_ssl_trusted_certificate", function()
local conf = assert(conf_loader(helpers.test_conf_path))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("lua_ssl_trusted_certificate.+;", kong_nginx_conf)
end)
it("sets lua_ssl_trusted_certificate to a combined file (single entry)", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
lua_ssl_trusted_certificate = "spec/fixtures/kong_spec.crt",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("lua_ssl_trusted_certificate%s+.*ca_combined", kong_nginx_conf)
end)
it("sets lua_ssl_trusted_certificate to a combined file (multiple entries)", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
lua_ssl_trusted_certificate = "spec/fixtures/kong_clustering_ca.crt,spec/fixtures/kong_clustering.crt",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("lua_ssl_trusted_certificate%s+.*ca_combined", kong_nginx_conf)
end)
it("writes the client_max_body_size as defined", function()
local conf = assert(conf_loader(nil, {
nginx_http_client_max_body_size = "1m",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("client_max_body_size%s+1m", nginx_conf)
end)
it("writes the client_max_body_size as defined (admin)", function()
local conf = assert(conf_loader(nil, {
nginx_admin_client_max_body_size = "50m",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("client_max_body_size%s+50m", nginx_conf)
end)
it("writes the client_body_buffer_size directive as defined", function()
local conf = assert(conf_loader(nil, {
nginx_http_client_body_buffer_size = "128k",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("client_body_buffer_size%s+128k", nginx_conf)
end)
it("writes the client_body_buffer_size directive as defined (admin)", function()
local conf = assert(conf_loader(nil, {
nginx_admin_client_body_buffer_size = "50m",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("client_body_buffer_size%s+50m", nginx_conf)
end)
it("writes kong_cassandra shm if using Cassandra", function()
local conf = assert(conf_loader(nil, {
database = "cassandra",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("lua_shared_dict%s+kong_cassandra", nginx_conf)
end)
it("does not write kong_cassandra shm if not using Cassandra", function()
local conf = assert(conf_loader(nil, {
database = "postgres",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.not_matches("lua_shared_dict%s+kong_cassandra", nginx_conf)
end)
describe("user directive", function()
it("is included by default if the kong user/group exist", function()
local conf = assert(conf_loader(helpers.test_conf_path))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
if kong_user_group_exists() == true then
assert.matches("user kong kong;", nginx_conf)
else
assert.not_matches("user%s+[^;]*;", nginx_conf)
end
end)
it("is not included when 'nobody'", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
nginx_main_user = "nobody"
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.not_matches("user%s+[^;]*;", nginx_conf)
end)
it("is not included when 'nobody nobody'", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
nginx_main_user = "nobody nobody"
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.not_matches("user%s+[^;]*;", nginx_conf)
end)
it("is included when otherwise", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
nginx_main_user = "www_data www_data"
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("user%s+www_data www_data;", nginx_conf)
end)
end)
describe("user directive (alias)", function()
it("is not included when 'nobody'", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
nginx_user = "nobody"
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.not_matches("user%s+[^;]*;", nginx_conf)
end)
it("is not included when 'nobody nobody'", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
nginx_user = "nobody nobody"
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.not_matches("user%s+[^;]*;", nginx_conf)
end)
it("is included when otherwise", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
nginx_user = "www_data www_data"
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("user%s+www_data www_data;", nginx_conf)
end)
end)
describe("ngx_http_realip_module settings", function()
it("defaults", function()
local conf = assert(conf_loader())
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("real_ip_header%s+X%-Real%-IP;", nginx_conf)
assert.matches("real_ip_recursive%s+off;", nginx_conf)
assert.not_matches("set_real_ip_from", nginx_conf)
end)
it("real_ip_recursive on", function()
local conf = assert(conf_loader(nil, {
nginx_proxy_real_ip_recursive = true,
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("real_ip_recursive%s+on;", nginx_conf)
end)
it("real_ip_recursive on", function()
local conf = assert(conf_loader(nil, {
real_ip_recursive = true,
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("real_ip_recursive%s+on;", nginx_conf)
end)
it("real_ip_recursive off", function()
local conf = assert(conf_loader(nil, {
nginx_proxy_real_ip_recursive = false,
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("real_ip_recursive%s+off;", nginx_conf)
end)
it("real_ip_recursive off", function()
local conf = assert(conf_loader(nil, {
real_ip_recursive = false,
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("real_ip_recursive%s+off;", nginx_conf)
end)
it("set_real_ip_from", function()
local conf = assert(conf_loader(nil, {
trusted_ips = "192.168.1.0/24,192.168.2.1,2001:0db8::/32"
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("set_real_ip_from%s+192%.168%.1%.0/24", nginx_conf)
assert.matches("set_real_ip_from%s+192%.168%.1%.0", nginx_conf)
assert.matches("set_real_ip_from%s+2001:0db8::/32", nginx_conf)
end)
it("set_real_ip_from (stream proxy)", function()
local conf = assert(conf_loader(nil, {
trusted_ips = "192.168.1.0/24,192.168.2.1,2001:0db8::/32",
stream_listen = "127.0.0.1:8888",
proxy_listen = "off",
admin_listen = "off",
status_listen = "off",
}))
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("set_real_ip_from%s+192%.168%.1%.0/24", nginx_conf)
assert.matches("set_real_ip_from%s+192%.168%.1%.0", nginx_conf)
assert.matches("set_real_ip_from%s+2001:0db8::/32", nginx_conf)
end)
it("proxy_protocol", function()
local conf = assert(conf_loader(nil, {
proxy_listen = "0.0.0.0:8000 proxy_protocol, 0.0.0.0:8443 ssl",
nginx_proxy_real_ip_header = "proxy_protocol",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("real_ip_header%s+proxy_protocol", nginx_conf)
assert.matches("listen%s0%.0%.0%.0:8000 proxy_protocol;", nginx_conf)
assert.matches("listen%s0%.0%.0%.0:8443 ssl;", nginx_conf)
end)
it("proxy_protocol", function()
local conf = assert(conf_loader(nil, {
proxy_listen = "0.0.0.0:8000 proxy_protocol, 0.0.0.0:8443 ssl",
real_ip_header = "proxy_protocol",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("real_ip_header%s+proxy_protocol", nginx_conf)
assert.matches("listen%s0%.0%.0%.0:8000 proxy_protocol;", nginx_conf)
assert.matches("listen%s0%.0%.0%.0:8443 ssl;", nginx_conf)
end)
end)
describe("injected NGINX directives", function()
it("injects proxy_access_log directive", function()
local conf = assert(conf_loader(nil, {
proxy_access_log = "/dev/stdout",
stream_listen = "0.0.0.0:9100",
nginx_stream_tcp_nodelay = "on",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("access_log%s/dev/stdout;", nginx_conf)
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("access_log%slogs/access.log%sbasic;", nginx_conf)
local conf = assert(conf_loader(nil, {
proxy_stream_access_log = "/dev/stdout custom",
stream_listen = "0.0.0.0:9100",
nginx_stream_tcp_nodelay = "on",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("access_log%slogs/access.log;", nginx_conf)
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("access_log%s/dev/stdout%scustom;", nginx_conf)
end)
it("injects proxy_error_log directive", function()
local conf = assert(conf_loader(nil, {
proxy_error_log = "/dev/stdout",
stream_listen = "0.0.0.0:9100",
nginx_stream_tcp_nodelay = "on",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("error_log%s/dev/stdout%snotice;", nginx_conf)
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("error_log%slogs/error.log%snotice;", nginx_conf)
local conf = assert(conf_loader(nil, {
proxy_stream_error_log = "/dev/stdout",
stream_listen = "0.0.0.0:9100",
nginx_stream_tcp_nodelay = "on",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("error_log%slogs/error.log%snotice;", nginx_conf)
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("error_log%s/dev/stdout%snotice;", nginx_conf)
end)
it("injects nginx_main_* directives", function()
local conf = assert(conf_loader(nil, {
nginx_main_pcre_jit = "on",
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("pcre_jit%s+on;", nginx_conf)
local conf = assert(conf_loader(nil, {
nginx_main_pcre_jit = true,
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("pcre_jit%s+on;", nginx_conf)
local conf = assert(conf_loader(nil, {
nginx_main_pcre_jit = "off",
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("pcre_jit%s+off;", nginx_conf)
local conf = assert(conf_loader(nil, {
nginx_main_pcre_jit = false,
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("pcre_jit%s+off;", nginx_conf)
end)
it("injects nginx_events_* directives", function()
local conf = assert(conf_loader(nil, {
nginx_events_accept_mutex = "on",
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("accept_mutex%s+on;", nginx_conf)
local conf = assert(conf_loader(nil, {
nginx_events_accept_mutex = true,
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("accept_mutex%s+on;", nginx_conf)
local conf = assert(conf_loader(nil, {
nginx_events_accept_mutex = "off",
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("accept_mutex%s+off;", nginx_conf)
local conf = assert(conf_loader(nil, {
nginx_events_accept_mutex = false,
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("accept_mutex%s+off;", nginx_conf)
end)
it("injects nginx_http_* directives", function()
local conf = assert(conf_loader(nil, {
nginx_http_large_client_header_buffers = "8 24k",
nginx_http_log_format = "custom_fmt '$connection $request_time'"
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("large_client_header_buffers%s+8 24k;", nginx_conf)
assert.matches("log_format%s+custom_fmt '$connection $request_time';", nginx_conf)
end)
it("injects nginx_proxy_* directives", function()
local conf = assert(conf_loader(nil, {
nginx_proxy_large_client_header_buffers = "16 24k",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("large_client_header_buffers%s+16 24k;", nginx_conf)
end)
it("injects nginx_admin_* directives", function()
local conf = assert(conf_loader(nil, {
nginx_admin_large_client_header_buffers = "4 24k",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("large_client_header_buffers%s+4 24k;", nginx_conf)
end)
it("injects nginx_status_* directives", function()
local conf = assert(conf_loader(nil, {
status_listen = "0.0.0.0:8005",
nginx_status_large_client_header_buffers = "4 24k",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("large_client_header_buffers%s+4 24k;", nginx_conf)
end)
it("injects nginx_upstream_* directives", function()
local conf = assert(conf_loader(nil, {
nginx_upstream_keepalive = "120",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("keepalive%s+120;", nginx_conf)
end)
it("injects nginx_stream_* directives", function()
local conf = assert(conf_loader(nil, {
stream_listen = "0.0.0.0:9100",
nginx_stream_tcp_nodelay = "on",
}))
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("tcp_nodelay%s+on;", nginx_conf)
local conf = assert(conf_loader(nil, {
nginx_stream_tcp_nodelay = true,
}))
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("tcp_nodelay%s+on;", nginx_conf)
local conf = assert(conf_loader(nil, {
stream_listen = "0.0.0.0:9100",
nginx_stream_tcp_nodelay = "off",
}))
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("tcp_nodelay%s+off;", nginx_conf)
local conf = assert(conf_loader(nil, {
stream_listen = "0.0.0.0:9100",
nginx_stream_tcp_nodelay = false,
}))
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("tcp_nodelay%s+off;", nginx_conf)
end)
it("injects nginx_sproxy_* directives", function()
local conf = assert(conf_loader(nil, {
stream_listen = "0.0.0.0:9100",
nginx_sproxy_tcp_nodelay = "on",
}))
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("tcp_nodelay%s+on;", nginx_conf)
local conf = assert(conf_loader(nil, {
stream_listen = "0.0.0.0:9100",
nginx_sproxy_tcp_nodelay = true,
}))
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("tcp_nodelay%s+on;", nginx_conf)
local conf = assert(conf_loader(nil, {
stream_listen = "0.0.0.0:9100",
nginx_sproxy_tcp_nodelay = "off",
}))
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("tcp_nodelay%s+off;", nginx_conf)
local conf = assert(conf_loader(nil, {
stream_listen = "0.0.0.0:9100",
nginx_sproxy_tcp_nodelay = false,
}))
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("tcp_nodelay%s+off;", nginx_conf)
end)
it("injects nginx_supstream_* directives", function()
local conf = assert(conf_loader(nil, {
nginx_supstream_keepalive = "120",
}))
local nginx_conf = prefix_handler.compile_kong_stream_conf(conf)
assert.matches("keepalive%s120;", nginx_conf)
end)
it("does not inject directives if value is 'NONE'", function()
local conf = assert(conf_loader(nil, {
nginx_upstream_keepalive = "NONE",
}))
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.not_matches("keepalive%s+%d+;", nginx_conf)
end)
describe("default injected NGINX directives", function()
it("configures default body buffering directives", function()
local conf = assert(conf_loader())
local nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("client_max_body_size%s+0;", nginx_conf)
assert.matches("client_body_buffer_size%s+8k;", nginx_conf)
-- Admin API Defaults:
assert.matches("client_max_body_size%s+10m;", nginx_conf)
assert.matches("client_body_buffer_size%s+10m;", nginx_conf)
end)
end)
end)
end)
describe("compile_nginx_conf()", function()
it("compiles a main NGINX conf", function()
local nginx_conf = prefix_handler.compile_nginx_conf(helpers.test_conf)
assert.matches("worker_processes%s+1;", nginx_conf)
assert.matches("daemon%s+on;", nginx_conf)
end)
it("compiles with custom conf", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
nginx_main_daemon = "off"
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("daemon%s+off;", nginx_conf)
end)
it("compiles with custom conf (alias)", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
nginx_daemon = "off"
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("daemon%s+off;", nginx_conf)
end)
it("compiles without opinionated nginx optimizations", function()
local conf = assert(conf_loader(nil, {
nginx_main_worker_rlimit_nofile = "NONE",
nginx_events_worker_connections = "NONE",
nginx_events_multi_accept = "NONE",
}))
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.not_matches("worker_rlimit_nofile%s+%d+;", nginx_conf)
assert.not_matches("worker_connections%s+%d+;", nginx_conf)
assert.not_matches("multi_accept%s+on;", nginx_conf)
end)
it("compiles with opinionated nginx optimizations", function()
local conf = assert(conf_loader())
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("worker_rlimit_nofile%s+%d+;", nginx_conf)
assert.matches("worker_connections%s+%d+;", nginx_conf)
assert.matches("multi_accept%s+on;", nginx_conf)
end)
it("compiles with correct auto values", function()
local conf = assert(conf_loader(nil, {
nginx_main_worker_rlimit_nofile = "auto",
nginx_events_worker_connections = "auto",
}))
local ulimit = prefix_handler.get_ulimit()
ulimit = math.min(ulimit, 16384)
ulimit = math.max(ulimit, 1024)
local nginx_conf = prefix_handler.compile_nginx_conf(conf)
assert.matches("worker_rlimit_nofile%s+" .. ulimit .. ";", nginx_conf)
assert.matches("worker_connections%s+" .. ulimit .. ";", nginx_conf)
end)
it("converts dns_resolver to string", function()
local nginx_conf = prefix_handler.compile_nginx_conf({
dns_resolver = { "8.8.8.8", "8.8.4.4" }
}, [[
"resolver ${{DNS_RESOLVER}} ipv6=off;"
]])
assert.matches("resolver%s+8%.8%.8%.8 8%.8%.4%.4 ipv6=off;", nginx_conf)
end)
end)
describe("prepare_prefix()", function()
local tmp_config = conf_loader(helpers.test_conf_path, {
prefix = "servroot_tmp"
})
before_each(function()
pcall(helpers.dir.rmtree, tmp_config.prefix)
helpers.dir.makepath(tmp_config.prefix)
end)
after_each(function()
pcall(helpers.dir.rmtree, tmp_config.prefix)
end)
it("creates inexistent prefix", function()
finally(function()
pcall(helpers.dir.rmtree, "inexistent")
end)
local config = assert(conf_loader(helpers.test_conf_path, {
prefix = "inexistent"
}))
assert(prefix_handler.prepare_prefix(config))
assert.truthy(exists("inexistent"))
end)
it("ensures prefix is a directory", function()
local tmp = os.tmpname()
finally(function()
os.remove(tmp)
end)
local config = assert(conf_loader(helpers.test_conf_path, {
prefix = tmp
}))
local ok, err = prefix_handler.prepare_prefix(config)
assert.equal(tmp .. " is not a directory", err)
assert.is_nil(ok)
end)
it("creates pids folder", function()
assert(prefix_handler.prepare_prefix(tmp_config))
assert.truthy(exists(join(tmp_config.prefix, "pids")))
end)
it("creates NGINX conf and log files", function()
assert(prefix_handler.prepare_prefix(tmp_config))
assert.truthy(exists(tmp_config.kong_env))
assert.truthy(exists(tmp_config.nginx_kong_conf))
assert.truthy(exists(tmp_config.nginx_err_logs))
assert.truthy(exists(tmp_config.nginx_acc_logs))
assert.truthy(exists(tmp_config.admin_acc_logs))
end)
it("dumps Kong conf", function()
assert(prefix_handler.prepare_prefix(tmp_config))
local in_prefix_kong_conf = assert(conf_loader(tmp_config.kong_env))
assert.same(tmp_config, in_prefix_kong_conf)
end)
it("dump Kong conf (custom conf)", function()
local conf = assert(conf_loader(nil, {
pg_database = "foobar",
pg_schema = "foo",
prefix = tmp_config.prefix,
nginx_main_worker_rlimit_nofile = 65536,
nginx_events_worker_connections = 65536,
}))
assert.equal("foobar", conf.pg_database)
assert.equal("foo", conf.pg_schema)
assert(prefix_handler.prepare_prefix(conf))
local in_prefix_kong_conf = assert(conf_loader(tmp_config.kong_env, {
pg_database = "foobar",
pg_schema = "foo",
prefix = tmp_config.prefix,
}))
assert.same(conf, in_prefix_kong_conf)
end)
it("writes custom plugins in Kong conf", function()
local conf = assert(conf_loader(nil, {
plugins = { "foo", "bar" },
prefix = tmp_config.prefix
}))
assert(prefix_handler.prepare_prefix(conf))
local in_prefix_kong_conf = assert(conf_loader(tmp_config.kong_env))
assert.True(in_prefix_kong_conf.loaded_plugins.foo)
assert.True(in_prefix_kong_conf.loaded_plugins.bar)
end)
describe("vault references", function()
it("are kept as references in .kong_env", function()
finally(function()
helpers.unsetenv("PG_DATABASE")
end)
helpers.setenv("PG_DATABASE", "resolved-kong-database")
local conf = assert(conf_loader(nil, {
prefix = tmp_config.prefix,
pg_database = "{vault://env/pg-database}",
}))
assert.equal("resolved-kong-database", conf.pg_database)
assert.equal("{vault://env/pg-database}", conf["$refs"].pg_database)
assert(prefix_handler.prepare_prefix(conf))
local contents = helpers.file.read(tmp_config.kong_env)
assert.matches("pg_database = {vault://env/pg-database}", contents, nil, true)
assert.not_matches("resolved-kong-database", contents, nil, true)
end)
end)
describe("ssl", function()
it("does not create SSL dir if disabled", function()
local conf = conf_loader(nil, {
prefix = tmp_config.prefix,
proxy_listen = "127.0.0.1:8000",
admin_listen = "127.0.0.1:8001",
})
assert(prefix_handler.prepare_prefix(conf))
assert.falsy(exists(join(conf.prefix, "ssl")))
end)
it("does not create SSL dir if using custom cert", function()
local conf = conf_loader(nil, {
prefix = tmp_config.prefix,
proxy_listen = "127.0.0.1:8000 ssl",
admin_listen = "127.0.0.1:8001 ssl",
status_listen = "127.0.0.1:8002 ssl",
ssl_cipher_suite = "custom",
ssl_cert = "spec/fixtures/kong_spec.crt",
ssl_cert_key = "spec/fixtures/kong_spec.key",
admin_ssl_cert = "spec/fixtures/kong_spec.crt",
admin_ssl_cert_key = "spec/fixtures/kong_spec.key",
status_ssl_cert = "spec/fixtures/kong_spec.crt",
status_ssl_cert_key = "spec/fixtures/kong_spec.key",
})
assert(prefix_handler.prepare_prefix(conf))
assert.falsy(exists(join(conf.prefix, "ssl")))
end)
it("generates default SSL cert", function()
local conf = conf_loader(nil, {
prefix = tmp_config.prefix,
proxy_listen = "127.0.0.1:8000 ssl",
admin_listen = "127.0.0.1:8001 ssl",
status_listen = "127.0.0.1:8002 ssl",
})
assert(prefix_handler.prepare_prefix(conf))
assert.truthy(exists(join(conf.prefix, "ssl")))
for _, suffix in ipairs({ "", "_ecdsa" }) do
assert.truthy(exists(conf["ssl_cert_default" .. suffix]))
assert.truthy(exists(conf["ssl_cert_key_default" .. suffix]))
assert.truthy(exists(conf["admin_ssl_cert_default" .. suffix]))
assert.truthy(exists(conf["admin_ssl_cert_key_default" .. suffix]))
assert.truthy(exists(conf["status_ssl_cert_default" .. suffix]))
assert.truthy(exists(conf["status_ssl_cert_key_default" .. suffix]))
end
end)
it("generates default SSL certs with correct permissions", function()
local conf = conf_loader(nil, {
prefix = tmp_config.prefix,
proxy_listen = "127.0.0.1:8000 ssl",
admin_listen = "127.0.0.1:8001 ssl",
status_listen = "127.0.0.1:8002 ssl",
})
assert(prefix_handler.prepare_prefix(conf))
for _, prefix in ipairs({ "", "status_", "admin_" }) do
for _, suffix in ipairs({ "", "_ecdsa" }) do
local handle = io.popen("ls -l " .. conf[prefix .. "ssl_cert_default" .. suffix])
local result = handle:read("*a")
handle:close()
assert.matches("%-rw%-r[-w]%-r%-%-", result, nil, false)
handle = io.popen("ls -l " .. conf[prefix .. "ssl_cert_key_default" .. suffix])
result = handle:read("*a")
handle:close()
assert.matches("-rw-------", result, nil, true)
end
end
end)
it("generates default SSL DH params", function()
local conf = conf_loader(nil, {
prefix = tmp_config.prefix,
proxy_listen = "127.0.0.1:8000 ssl",
admin_listen = "127.0.0.1:8001 ssl",
status_listen = "127.0.0.1:8002 ssl",
stream_listen = "127.0.0.1:7000 ssl",
})
assert(prefix_handler.prepare_prefix(conf))
assert.truthy(exists(join(conf.prefix, "ssl")))
assert.truthy(exists(join(conf.prefix, "ssl", conf.ssl_dhparam .. ".pem")))
assert.truthy(exists(join(conf.prefix, "ssl", conf.nginx_http_ssl_dhparam .. ".pem")))
assert.truthy(exists(join(conf.prefix, "ssl", conf.nginx_stream_ssl_dhparam .. ".pem")))
end)
end)
describe("custom template", function()
local templ_fixture = "spec/fixtures/custom_nginx.template"
lazy_setup(function()
pcall(helpers.dir.rmtree, "/tmp/not-a-file")
assert(helpers.dir.makepath("/tmp/not-a-file"))
end)
lazy_teardown(function()
pcall(helpers.dir.rmtree, "/tmp/not-a-file")
end)
it("accepts a custom NGINX conf template", function()
assert(prefix_handler.prepare_prefix(tmp_config, templ_fixture))
assert.truthy(exists(tmp_config.nginx_conf))
local contents = helpers.file.read(tmp_config.nginx_conf)
assert.matches("# This is a custom nginx configuration template for Kong specs", contents, nil, true)
assert.matches("daemon%s+on;", contents)
assert.matches("listen%s+0%.0%.0%.0:9000;", contents)
end)
it("errors on non-existing file", function()
local ok, err = prefix_handler.prepare_prefix(tmp_config, "spec/fixtures/inexistent.template")
assert.is_nil(ok)
assert.equal("no such file: spec/fixtures/inexistent.template", err)
end)
it("errors on file read failures", function()
local ok, err = prefix_handler.prepare_prefix(tmp_config, "/tmp/not-a-file")
assert.is_nil(ok)
assert.matches("failed reading custom nginx template file: /tmp/not-a-file", err, nil, true)
end)
it("reports Penlight templating errors", function()
local u = helpers.unindent
local tmp = os.tmpname()
helpers.file.write(tmp, u[[
> if t.hello then
> end
]])
finally(function()
helpers.file.delete(tmp)
end)
local ok, err = prefix_handler.prepare_prefix(helpers.test_conf, tmp)
assert.is_nil(ok)
assert.matches("failed to compile nginx config template: .* " ..
"attempt to index global 't' %(a nil value%)", err)
end)
end)
describe("nginx_* injected directives aliases", function()
-- Aliases maintained for pre-established Nginx directives specified
-- as Kong config properties
describe("'upstream_keepalive'", function()
describe("1.2 Nginx template", function()
local templ_fixture = "spec/fixtures/1.2_custom_nginx.template"
it("compiles", function()
assert(prefix_handler.prepare_prefix(tmp_config, templ_fixture))
assert.truthy(exists(tmp_config.nginx_conf))
local contents = helpers.file.read(tmp_config.nginx_conf)
assert.matches("# This is the Kong 1.2 default template", contents,
nil, true)
assert.matches("daemon on;", contents, nil, true)
assert.matches("listen 0.0.0.0:9000;", contents, nil, true)
assert.not_matches("keepalive", contents, nil, true)
end)
end)
end)
end)
end)
end)