Skip to content

Commit

Permalink
feat(tls) add new methods set_upstream_ssl_trusted_store, `set_upst…
Browse files Browse the repository at this point in the history
…ream_ssl_verify` and `set_upstream_ssl_verify_depth` for dynamically overriding upstream TLS verification behavior of Nginx

This allows more flexibility when proxying to TLS enabled upstream servers in Nginx without sacrificing feature or performance.

Co-authored-by: Datong Sun <dndx@idndx.com>
  • Loading branch information
fffonion and dndx authored Feb 12, 2020
1 parent eff31f3 commit e4cc508
Show file tree
Hide file tree
Showing 6 changed files with 931 additions and 50 deletions.
3 changes: 3 additions & 0 deletions .ci/setup_env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,6 @@ nginx -V
resty -V
luarocks --version
openssl version

# Needed by tests of tls.set_upstream_trusted_store
luarocks install lua-resty-openssl
104 changes: 103 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ Table of Contents
* [resty.kong.tls.disable\_session\_reuse](#restykongtlsdisable_session_reuse)
* [resty.kong.tls.get\_full\_client\_certificate\_chain](#restykongtlsget_full_client_certificate_chain)
* [resty.kong.tls.set\_upstream\_cert\_and\_key](#restykongtlsset_upstream_cert_and_key)
* [resty.kong.tls.set\_upstream\_ssl\_trusted\_store](#restykongtlsset_upstream_ssl_trusted_store)
* [resty.kong.tls.set\_upstream\_ssl\_verify](#restykongtlsset_upstream_ssl_verify)
* [resty.kong.tls.set\_upstream\_ssl\_verify\_depth](#restykongtlsset_upstream_ssl_verify_depth)
* [resty.kong.tls.disable\_proxy\_ssl](#restykongtlsdisable_proxy_ssl)
* [License](#license)

Expand Down Expand Up @@ -134,6 +137,106 @@ previous ones.

[Back to TOC](#table-of-contents)

resty.kong.tls.set\_upstream\_ssl\_trusted\_store
--------------------------------------------
**syntax:** *ok, err = resty.kong.tls.set\_upstream\_ssl\_trusted\_store(store)*

**context:** *rewrite_by_lua&#42;, access_by_lua&#42;, balancer_by_lua&#42;*

**subsystems:** *http*

Set upstream ssl verification trusted store of current request. Global setting set by
`proxy_ssl_trusted_certificate` will be overwritten for the current request.

`store` is a `X509_STORE*` cdata that can be created by
[resty.openssl.x509.store.new](https://github.com/fffonion/lua-resty-openssl#storenew).

On success, this function returns `true` and future handshakes with upstream servers
will be verified with given store. Otherwise `nil` and a string describing the
error will be returned.

This function can be called multiple times in the same request. Later calls override
previous ones.

Example:
```lua
local x509 = require("resty.openssl.x509")
local crt, err = x509.new([[-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----]])
if err then
ngx.log(ngx.ERR, "failed to parse cert: ", err)
ngx.exit(500)
end
local store = require("resty.openssl.x509.store")
local st, err = store.new()
if err then
ngx.log(ngx.ERR, "failed to create store: ", err)
ngx.exit(500)
end
local ok, err = st:add(crt)
if err then
ngx.log(ngx.ERR, "failed to add cert to store: ", err)
ngx.exit(500)
end
-- st:add can be called multiple times, also accept a crl
-- st:add(another_crt)
-- st:add(crl)
-- OR
-- st:use_default() to load default CA bundle
local tls = require("resty.kong.tls")
local ok, err = tls.set_upstream_ssl_trusted_store(st.ctx)
if err then
ngx.log(ngx.ERR, "failed to set upstream trusted store: ", err)
ngx.exit(500)
end
local ok, err = tls.set_upstream_ssl_verify(true)
if err then
ngx.log(ngx.ERR, "failed to set upstream ssl verify: ", err)
ngx.exit(500)
end
```

[Back to TOC](#table-of-contents)

resty.kong.tls.set\_upstream\_ssl\_verify
--------------------------------------------
**syntax:** *ok, err = resty.kong.tls.set\_upstream\_ssl\_verify(verify)*

**context:** *rewrite_by_lua&#42;, access_by_lua&#42;, balancer_by_lua&#42;*

**subsystems:** *http*

Set upstream ssl verification enablement of current request to the given boolean
argument `verify`. Global setting set by `proxy_ssl_verify` will be overwritten.

On success, this function returns `true`. Otherwise `nil` and a string
describing the error will be returned.

This function can be called multiple times in the same request. Later calls override
previous ones.

[Back to TOC](#table-of-contents)

resty.kong.tls.set\_upstream\_ssl\_verify\_depth
--------------------------------------------
**syntax:** *ok, err = resty.kong.tls.set\_upstream\_ssl\_verify\_depth(depth)*

**context:** *rewrite_by_lua&#42;, access_by_lua&#42;, balancer_by_lua&#42;*

**subsystems:** *http*

Set upstream ssl verification depth of current request to the given non-negative integer
argument `depth`. Global setting set by `proxy_ssl_verify_depth` will be overwritten.

On success, this function returns `true`. Otherwise `nil` and a string
describing the error will be returned.

This function can be called multiple times in the same request. Later calls override
previous ones.

[Back to TOC](#table-of-contents)

resty.kong.tls.disable\_proxy\_ssl
----------------------------------
**syntax:** *ok, err = resty.kong.tls.disable_proxy_ssl()*
Expand Down Expand Up @@ -172,4 +275,3 @@ limitations under the License.
```

[Back to TOC](#table-of-contents)

82 changes: 82 additions & 0 deletions lualib/resty/kong/tls.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ if ngx.config.subsystem == "http" then
const char *ngx_http_lua_kong_ffi_disable_session_reuse(ngx_http_request_t *r);
int ngx_http_lua_kong_ffi_set_upstream_client_cert_and_key(ngx_http_request_t *r,
void *_chain, void *_key);
int ngx_http_lua_kong_ffi_set_upstream_ssl_trusted_store(ngx_http_request_t *r,
void *_store);
int ngx_http_lua_kong_ffi_set_upstream_ssl_verify(ngx_http_request_t *r,
int verify);
int ngx_http_lua_kong_ffi_set_upstream_ssl_verify_depth(ngx_http_request_t *r,
int depth);
]])

else
Expand Down Expand Up @@ -193,6 +199,82 @@ if ngx.config.subsystem == "http" then

error("unknown return code: " .. tostring(ret))
end

function _M.set_upstream_ssl_trusted_store(store)
if not ALLOWED_PHASES[get_phase()] then
error("API disabled in the current context", 2)
end

if type(store) ~= 'cdata' then
error("store expects a cdata object but found " .. type(store), 2)
end

local r = get_request()

local ret = C.ngx_http_lua_kong_ffi_set_upstream_ssl_trusted_store(
r, store)
if ret == NGX_OK then
return true
end

if ret == NGX_ERROR then
return nil, "error while setting upstream trusted store"
end

error("unknown return code: " .. tostring(ret))
end

function _M.set_upstream_ssl_verify(verify)
if not ALLOWED_PHASES[get_phase()] then
error("API disabled in the current context", 2)
end

if type(verify) ~= 'boolean' then
error("verify expects a boolean but found " .. type(verify), 2)
end

local r = get_request()

local ret = C.ngx_http_lua_kong_ffi_set_upstream_ssl_verify(
r, verify)
if ret == NGX_OK then
return true
end

if ret == NGX_ERROR then
return nil, "error while setting upstream ssl verify mode"
end

error("unknown return code: " .. tostring(ret))
end

function _M.set_upstream_ssl_verify_depth(depth)
if not ALLOWED_PHASES[get_phase()] then
error("API disabled in the current context", 2)
end

if type(depth) ~= 'number' then
error("depth expects a number but found " .. type(depth), 2)
end

if depth < 0 then
error("depth expects a non-negative integer but found " .. tostring(depth), 2)
end

local r = get_request()

local ret = C.ngx_http_lua_kong_ffi_set_upstream_ssl_verify_depth(
r, depth)
if ret == NGX_OK then
return true
end

if ret == NGX_ERROR then
return nil, "error while setting upstream ssl verify depth"
end

error("unknown return code: " .. tostring(ret))
end
end

else -- stream
Expand Down
Loading

0 comments on commit e4cc508

Please sign in to comment.