193 lines
5.1 KiB
Lua
193 lines
5.1 KiB
Lua
-- SPDX-License-Identifier: GPL-3.0-or-later
|
|
-- check prerequisites
|
|
local has_http = pcall(require, 'kres_modules.http') and pcall(require, 'http.request')
|
|
if not has_http then
|
|
-- skipping http module test because its not installed
|
|
os.exit(77)
|
|
else
|
|
local request = require('http.request')
|
|
local openssl_ctx = require('openssl.ssl.context')
|
|
|
|
local function setup_module(desc, config)
|
|
if http then
|
|
modules.unload('http')
|
|
end
|
|
modules.load('http')
|
|
same(http.config(config), nil, desc .. ' can be configured')
|
|
|
|
local bound
|
|
for _ = 1,1000 do
|
|
bound, _err = pcall(net.listen, '127.0.0.1', math.random(1025,65535), { kind = 'webmgmt' })
|
|
if bound then
|
|
break
|
|
end
|
|
end
|
|
assert(bound, 'unable to bind a port for HTTP module (1000 attempts)')
|
|
|
|
local server_fd = next(http.servers)
|
|
assert(server_fd)
|
|
local server = http.servers[server_fd].server
|
|
ok(server ~= nil, 'creates server instance')
|
|
_, host, port = server:localname()
|
|
ok(host and port, 'binds to an interface')
|
|
return host, port
|
|
end
|
|
|
|
local function http_get(uri)
|
|
-- disable certificate verification in this test
|
|
local req = request.new_from_uri(uri)
|
|
local idxstart = string.find(uri, 'https://')
|
|
if idxstart == 1 then
|
|
req.ctx = openssl_ctx.new()
|
|
assert(req.ctx, 'OpenSSL cert verification must be disabled')
|
|
req.ctx:setVerify(openssl_ctx.VERIFY_NONE)
|
|
end
|
|
|
|
local headers = assert(req:go(16))
|
|
return tonumber(headers:get(':status'))
|
|
end
|
|
|
|
-- test whether http interface responds and binds
|
|
local function check_protocol(uri, description, ok_expected)
|
|
if ok_expected then
|
|
local code = http_get(uri)
|
|
same(code, 200, description)
|
|
else
|
|
boom(http_get, {uri}, description)
|
|
end
|
|
end
|
|
|
|
local function test_defaults()
|
|
local host, port = setup_module('HTTP module default config', nil)
|
|
|
|
local uri = string.format('http://%s:%d', host, port)
|
|
check_protocol(uri, 'HTTP is enabled by default', true)
|
|
uri = string.format('https://%s:%d', host, port)
|
|
check_protocol(uri, 'HTTPS is enabled by default', true)
|
|
|
|
modules.unload('http')
|
|
uri = string.format('http://%s:%d', host, port)
|
|
check_protocol(uri, 'HTTP stops working after module unload', false)
|
|
uri = string.format('https://%s:%d', host, port)
|
|
check_protocol(uri, 'HTTPS stops working after module unload', false)
|
|
|
|
end
|
|
|
|
local function test_http_only()
|
|
local desc = 'HTTP-only config'
|
|
local host, port = setup_module(desc,
|
|
{
|
|
tls = false,
|
|
})
|
|
|
|
local uri = string.format('http://%s:%d', host, port)
|
|
check_protocol(uri, 'HTTP works in ' .. desc, true)
|
|
uri = string.format('https://%s:%d', host, port)
|
|
check_protocol(uri, 'HTTPS does not work in ' .. desc, false)
|
|
end
|
|
|
|
local function test_https_only()
|
|
local desc = 'HTTPS-only config'
|
|
local host, port = setup_module(desc,
|
|
{
|
|
tls = true,
|
|
})
|
|
|
|
local uri = string.format('http://%s:%d', host, port)
|
|
check_protocol(uri, 'HTTP does not work in ' .. desc, false)
|
|
uri = string.format('https://%s:%d', host, port)
|
|
check_protocol(uri, 'HTTPS works in ' .. desc, true)
|
|
end
|
|
|
|
local function test_custom_cert()
|
|
desc = 'config with custom certificate'
|
|
local host, port = setup_module(desc, {{
|
|
cert = 'test.crt',
|
|
key = 'test.key'
|
|
}})
|
|
|
|
uri = string.format('https://%s:%d', host, port)
|
|
check_protocol(uri, 'HTTPS works for ' .. desc, true)
|
|
end
|
|
|
|
local function test_nonexistent_cert()
|
|
desc = 'config with non-existing certificate file'
|
|
boom(http.config, {{
|
|
cert = '/tmp/surely_nonexistent_cert_1532432095',
|
|
key = 'test.key'
|
|
}}, desc)
|
|
end
|
|
|
|
local function test_nonexistent_key()
|
|
desc = 'config with non-existing key file'
|
|
boom(http.config, {{
|
|
cert = 'test.crt',
|
|
key = '/tmp/surely_nonexistent_cert_1532432095'
|
|
}}, desc)
|
|
end
|
|
|
|
local function test_missing_key_param()
|
|
desc = 'config with missing key= param'
|
|
boom(http.config, {{
|
|
cert = 'test.crt'
|
|
}}, desc)
|
|
end
|
|
|
|
local function test_broken_cert()
|
|
desc = 'config with broken file in cert= param'
|
|
boom(http.config, {{
|
|
cert = 'broken.crt',
|
|
key = 'test.key'
|
|
}}, desc)
|
|
end
|
|
|
|
local function test_broken_key()
|
|
desc = 'config with broken file in key= param'
|
|
boom(http.config, {{
|
|
cert = 'test.crt',
|
|
key = 'broken.key'
|
|
}}, desc)
|
|
end
|
|
|
|
local function test_certificate_chain()
|
|
local desc = 'config with certificate chain (with intermediate CA cert)'
|
|
local host, port = setup_module(desc,
|
|
{
|
|
tls = true,
|
|
cert = 'chain.crt',
|
|
key = 'test.key',
|
|
})
|
|
local uri = string.format('https://%s:%d', host, port)
|
|
local req = request.new_from_uri(uri)
|
|
req.ctx = openssl_ctx.new()
|
|
|
|
if not req.ctx.setCertificateChain then
|
|
pass(string.format('SKIP (luaossl <= 20181207) - %s', desc))
|
|
else
|
|
local store = req.ctx:getStore()
|
|
store:add('ca.crt')
|
|
req.ctx:setVerify(openssl_ctx.VERIFY_PEER)
|
|
|
|
local headers = assert(req:go(16))
|
|
local code = tonumber(headers:get(':status'))
|
|
same(code, 200, desc)
|
|
end
|
|
end
|
|
|
|
|
|
-- plan tests
|
|
local tests = {
|
|
test_defaults,
|
|
test_http_only,
|
|
test_https_only,
|
|
test_custom_cert,
|
|
test_nonexistent_cert,
|
|
test_nonexistent_key,
|
|
test_missing_key_param,
|
|
test_broken_cert,
|
|
test_broken_key,
|
|
test_certificate_chain,
|
|
}
|
|
|
|
return tests
|
|
end
|