mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Merge commit '6c42ecd81d200e5626a2ede3ff2021b503d07ed7' into dev
This commit is contained in:
commit
7a6c62056c
6 changed files with 204 additions and 19 deletions
|
|
@ -20,6 +20,8 @@ jobs:
|
|||
openresty_version:
|
||||
- 1.17.8.2
|
||||
- 1.19.9.1
|
||||
- 1.21.4.3
|
||||
- 1.25.3.1
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
|
|
@ -49,7 +51,9 @@ jobs:
|
|||
run: cpanm -q -n Test::Nginx
|
||||
|
||||
- name: Install Luacov
|
||||
run: /usr/local/openresty/luajit/bin/luarocks install luacov
|
||||
run: |
|
||||
/usr/local/openresty/luajit/bin/luarocks install luacov
|
||||
/usr/local/openresty/luajit/bin/luarocks install lua-resty-openssl
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ end
|
|||
|
||||
|
||||
local _M = {
|
||||
_VERSION = '0.17.1',
|
||||
_VERSION = '0.17.2',
|
||||
}
|
||||
_M._USER_AGENT = "lua-resty-http/" .. _M._VERSION .. " (Lua) ngx_lua/" .. ngx.config.ngx_lua_version
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,26 @@
|
|||
local ffi = require "ffi"
|
||||
local ngx_re_gmatch = ngx.re.gmatch
|
||||
local ngx_re_sub = ngx.re.sub
|
||||
local ngx_re_find = ngx.re.find
|
||||
local ngx_log = ngx.log
|
||||
local ngx_WARN = ngx.WARN
|
||||
local ngx_DEBUG = ngx.DEBUG
|
||||
local to_hex = require("resty.string").to_hex
|
||||
local ffi_gc = ffi.gc
|
||||
local ffi_cast = ffi.cast
|
||||
local type = type
|
||||
|
||||
local lib_chain, lib_x509, lib_pkey
|
||||
local openssl_available, res = xpcall(function()
|
||||
lib_chain = require("resty.openssl.x509.chain")
|
||||
lib_x509 = require("resty.openssl.x509")
|
||||
lib_pkey = require("resty.openssl.pkey")
|
||||
end, debug.traceback)
|
||||
|
||||
if not openssl_available then
|
||||
ngx_log(ngx_WARN, "failed to load module `resty.openssl.*`, \z
|
||||
mTLS isn't supported without lua-resty-openssl:\n", res)
|
||||
end
|
||||
|
||||
--[[
|
||||
A connection function that incorporates:
|
||||
|
|
@ -148,7 +166,7 @@ local function connect(self, options)
|
|||
local proxy_uri_t
|
||||
proxy_uri_t, err = self:parse_uri(proxy_uri)
|
||||
if not proxy_uri_t then
|
||||
return nil, "uri parse error: ", err
|
||||
return nil, "uri parse error: " .. err
|
||||
end
|
||||
|
||||
local proxy_scheme = proxy_uri_t[1]
|
||||
|
|
@ -160,6 +178,61 @@ local function connect(self, options)
|
|||
proxy_port = proxy_uri_t[3]
|
||||
end
|
||||
|
||||
local cert_hash
|
||||
if ssl and ssl_client_cert and ssl_client_priv_key then
|
||||
local cert_type = type(ssl_client_cert)
|
||||
local key_type = type(ssl_client_priv_key)
|
||||
|
||||
if cert_type ~= "cdata" then
|
||||
return nil, "bad ssl_client_cert: cdata expected, got " .. cert_type
|
||||
end
|
||||
|
||||
if key_type ~= "cdata" then
|
||||
return nil, "bad ssl_client_priv_key: cdata expected, got " .. key_type
|
||||
end
|
||||
|
||||
if not openssl_available then
|
||||
return nil, "module `resty.openssl.*` not available, mTLS isn't supported without lua-resty-openssl"
|
||||
end
|
||||
|
||||
-- convert from `void*` to `OPENSSL_STACK*`
|
||||
local cert_chain, err = lib_chain.dup(ffi_cast("OPENSSL_STACK*", ssl_client_cert))
|
||||
if not cert_chain then
|
||||
return nil, "failed to dup the ssl_client_cert: " .. err
|
||||
end
|
||||
|
||||
if #cert_chain < 1 then
|
||||
return nil, "no cert in ssl_client_cert"
|
||||
end
|
||||
|
||||
local cert, err = lib_x509.dup(cert_chain[1].ctx)
|
||||
if not cert then
|
||||
return nil, "failed to dup the x509: " .. err
|
||||
end
|
||||
|
||||
-- convert from `void*` to `EVP_PKEY*`
|
||||
local key, err = lib_pkey.new(ffi_cast("EVP_PKEY*", ssl_client_priv_key))
|
||||
if not key then
|
||||
return nil, "failed to new the pkey: " .. err
|
||||
end
|
||||
|
||||
-- should not free the cdata passed in
|
||||
ffi_gc(key.ctx, nil)
|
||||
|
||||
-- check the private key in order to make sure the caller is indeed the holder of the cert
|
||||
ok, err = cert:check_private_key(key)
|
||||
if not ok then
|
||||
return nil, "the private key doesn't match the cert: " .. err
|
||||
end
|
||||
|
||||
cert_hash, err = cert:digest("sha256")
|
||||
if not cert_hash then
|
||||
return nil, "failed to calculate the digest of the cert: " .. err
|
||||
end
|
||||
|
||||
cert_hash = to_hex(cert_hash) -- convert to hex so that it's printable
|
||||
end
|
||||
|
||||
-- construct a poolname unique within proxy and ssl info
|
||||
if not poolname then
|
||||
poolname = (request_scheme or "")
|
||||
|
|
@ -170,12 +243,15 @@ local function connect(self, options)
|
|||
.. ":" .. tostring(ssl_verify)
|
||||
.. ":" .. (proxy_uri or "")
|
||||
.. ":" .. (request_scheme == "https" and proxy_authorization or "")
|
||||
.. ":" .. (cert_hash or "")
|
||||
-- in the above we only add the 'proxy_authorization' as part of the poolname
|
||||
-- when the request is https. Because in that case the CONNECT request (which
|
||||
-- carries the authorization header) is part of the connect procedure, whereas
|
||||
-- with a plain http request the authorization is part of the actual request.
|
||||
end
|
||||
|
||||
ngx_log(ngx_DEBUG, "poolname: ", poolname)
|
||||
|
||||
-- do TCP level connection
|
||||
local tcp_opts = { pool = poolname, pool_size = pool_size, backlog = backlog }
|
||||
if proxy then
|
||||
|
|
@ -184,7 +260,7 @@ local function connect(self, options)
|
|||
if not ok then
|
||||
return nil, "failed to connect to: " .. (proxy_host or "") ..
|
||||
":" .. (proxy_port or "") ..
|
||||
": ", err
|
||||
": " .. err
|
||||
end
|
||||
|
||||
if ssl and sock:getreusedtimes() == 0 then
|
||||
|
|
@ -204,7 +280,7 @@ local function connect(self, options)
|
|||
})
|
||||
|
||||
if not res then
|
||||
return nil, "failed to issue CONNECT to proxy:", err
|
||||
return nil, "failed to issue CONNECT to proxy: " .. err
|
||||
end
|
||||
|
||||
if res.status < 200 or res.status > 299 then
|
||||
|
|
@ -234,13 +310,13 @@ local function connect(self, options)
|
|||
-- Experimental mTLS support
|
||||
if ssl_client_cert and ssl_client_priv_key then
|
||||
if type(sock.setclientcert) ~= "function" then
|
||||
ngx_log(ngx_WARN, "cannot use SSL client cert and key without mTLS support")
|
||||
return nil, "cannot use SSL client cert and key without mTLS support"
|
||||
|
||||
else
|
||||
ok, err = sock:setclientcert(ssl_client_cert, ssl_client_priv_key)
|
||||
if not ok then
|
||||
ngx_log(ngx_WARN, "could not set client certificate: ", err)
|
||||
end
|
||||
ok, err = sock:setclientcert(ssl_client_cert, ssl_client_priv_key)
|
||||
if not ok then
|
||||
return nil, "could not set client certificate: " .. err
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ local rawget, rawset, setmetatable =
|
|||
local str_lower = string.lower
|
||||
|
||||
local _M = {
|
||||
_VERSION = '0.17.1',
|
||||
_VERSION = '0.17.2',
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package = "lua-resty-http"
|
||||
version = "0.17.1-0"
|
||||
version = "0.17.2-0"
|
||||
source = {
|
||||
url = "git://github.com/ledgetech/lua-resty-http",
|
||||
tag = "v0.17.1"
|
||||
tag = "v0.17.2"
|
||||
}
|
||||
description = {
|
||||
summary = "Lua HTTP client cosocket driver for OpenResty / ngx_lua.",
|
||||
117
src/deps/src/lua-resty-http/t/20-mtls.t
vendored
117
src/deps/src/lua-resty-http/t/20-mtls.t
vendored
|
|
@ -105,7 +105,6 @@ GET /t
|
|||
|
||||
=== TEST 2: Connection fails during handshake with not priv_key
|
||||
--- http_config eval: $::mtls_http_config
|
||||
--- SKIP
|
||||
--- config eval
|
||||
"
|
||||
lua_ssl_trusted_certificate $::HtmlDir/test.crt;
|
||||
|
|
@ -138,6 +137,9 @@ location /t {
|
|||
})
|
||||
|
||||
ngx.say(res:read_body())
|
||||
|
||||
else
|
||||
ngx.say('failed to connect: ' .. (err or ''))
|
||||
end
|
||||
|
||||
httpc:close()
|
||||
|
|
@ -148,13 +150,16 @@ location /t {
|
|||
--- request
|
||||
GET /t
|
||||
--- error_code: 200
|
||||
--- error_log
|
||||
could not set client certificate: bad client pkey type
|
||||
--- response_body_unlike: hello, CN=foo@example.com,O=OpenResty,ST=California,C=US
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
--- response_body
|
||||
failed to connect: bad ssl_client_priv_key: cdata expected, got string
|
||||
--- skip_nginx
|
||||
4: < 1.21.4
|
||||
|
||||
|
||||
=== TEST 3: Connection succeeds with client cert and key. SKIP'd for CI until feature is merged.
|
||||
--- SKIP
|
||||
=== TEST 3: Connection succeeds with client cert and key.
|
||||
--- http_config eval: $::mtls_http_config
|
||||
--- config eval
|
||||
"
|
||||
|
|
@ -208,4 +213,104 @@ GET /t
|
|||
[warn]
|
||||
--- response_body
|
||||
hello, CN=foo@example.com,O=OpenResty,ST=California,C=US
|
||||
--- skip_nginx
|
||||
4: < 1.21.4
|
||||
|
||||
=== TEST 4: users with different client certs should not share the same pool.
|
||||
--- http_config eval: $::mtls_http_config
|
||||
--- config eval
|
||||
"
|
||||
lua_ssl_trusted_certificate $::HtmlDir/test.crt;
|
||||
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local f = assert(io.open('$::HtmlDir/mtls_client.crt'))
|
||||
local cert_data = f:read('*a')
|
||||
f:close()
|
||||
|
||||
f = assert(io.open('$::HtmlDir/mtls_client.key'))
|
||||
local key_data = f:read('*a')
|
||||
f:close()
|
||||
|
||||
local ssl = require('ngx.ssl')
|
||||
|
||||
local cert = assert(ssl.parse_pem_cert(cert_data))
|
||||
local key = assert(ssl.parse_pem_priv_key(key_data))
|
||||
|
||||
f = assert(io.open('$::HtmlDir/test.crt'))
|
||||
local invalid_cert_data = f:read('*a')
|
||||
f:close()
|
||||
|
||||
f = assert(io.open('$::HtmlDir/test.key'))
|
||||
local invalid_key_data = f:read('*a')
|
||||
f:close()
|
||||
|
||||
local invalid_cert = assert(ssl.parse_pem_cert(invalid_cert_data))
|
||||
local invalid_key = assert(ssl.parse_pem_priv_key(invalid_key_data))
|
||||
|
||||
local httpc = assert(require('resty.http').new())
|
||||
|
||||
local ok, err = httpc:connect {
|
||||
scheme = 'https',
|
||||
host = 'unix:$::HtmlDir/mtls.sock',
|
||||
ssl_client_cert = cert,
|
||||
ssl_client_priv_key = key,
|
||||
}
|
||||
|
||||
if ok and not err then
|
||||
local res, err = assert(httpc:request {
|
||||
method = 'GET',
|
||||
path = '/',
|
||||
headers = {
|
||||
['Host'] = 'example.com',
|
||||
},
|
||||
})
|
||||
|
||||
ngx.say(res:read_body())
|
||||
end
|
||||
|
||||
httpc:set_keepalive()
|
||||
|
||||
local httpc = assert(require('resty.http').new())
|
||||
|
||||
local ok, err = httpc:connect {
|
||||
scheme = 'https',
|
||||
host = 'unix:$::HtmlDir/mtls.sock',
|
||||
ssl_client_cert = invalid_cert,
|
||||
ssl_client_priv_key = invalid_key,
|
||||
}
|
||||
|
||||
ngx.say(httpc:get_reused_times())
|
||||
ngx.say(ok)
|
||||
ngx.say(err)
|
||||
|
||||
if ok and not err then
|
||||
local res, err = assert(httpc:request {
|
||||
method = 'GET',
|
||||
path = '/',
|
||||
headers = {
|
||||
['Host'] = 'example.com',
|
||||
},
|
||||
})
|
||||
|
||||
ngx.say(res.status) -- expect 400
|
||||
end
|
||||
|
||||
httpc:close()
|
||||
}
|
||||
}
|
||||
"
|
||||
--- user_files eval: $::mtls_user_files
|
||||
--- request
|
||||
GET /t
|
||||
--- no_error_log
|
||||
[error]
|
||||
[warn]
|
||||
--- response_body
|
||||
hello, CN=foo@example.com,O=OpenResty,ST=California,C=US
|
||||
0
|
||||
true
|
||||
nil
|
||||
400
|
||||
--- skip_nginx
|
||||
4: < 1.21.4
|
||||
|
|
|
|||
Loading…
Reference in a new issue