You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by we...@apache.org on 2020/09/10 07:36:07 UTC
[apisix] branch master updated: improve: cache parsed certs and
pkeys to LRU cache (#2163)
This is an automated email from the ASF dual-hosted git repository.
wenming pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 1556cd0 improve: cache parsed certs and pkeys to LRU cache (#2163)
1556cd0 is described below
commit 1556cd0d7e763e085fc69bd9db859b6a57a7e883
Author: Alex Zhang <zc...@gmail.com>
AuthorDate: Thu Sep 10 15:35:55 2020 +0800
improve: cache parsed certs and pkeys to LRU cache (#2163)
---
apisix/http/router/radixtree_sni.lua | 60 ++++++++++++++++-------
t/router/radixtree-sni.t | 93 ++++++++++++++++++++++++++++++++++++
2 files changed, 136 insertions(+), 17 deletions(-)
diff --git a/apisix/http/router/radixtree_sni.lua b/apisix/http/router/radixtree_sni.lua
index 0663336..be24f52 100644
--- a/apisix/http/router/radixtree_sni.lua
+++ b/apisix/http/router/radixtree_sni.lua
@@ -31,6 +31,14 @@ local ssl_certificates
local radixtree_router
local radixtree_router_ver
+local cert_cache = core.lrucache.new {
+ ttl = 3600, count = 512,
+}
+
+local pkey_cache = core.lrucache.new {
+ ttl = 3600, count = 512,
+}
+
local _M = {
version = 0.1,
@@ -38,6 +46,22 @@ local _M = {
}
+local function parse_pem_cert(sni, cert)
+ core.log.debug("parsing cert for sni: ", sni)
+
+ local parsed, err = ngx_ssl.parse_pem_cert(cert)
+ return parsed, err
+end
+
+
+local function parse_pem_priv_key(sni, pkey)
+ core.log.debug("parsing priv key for sni: ", sni)
+
+ local parsed, err = ngx_ssl.parse_pem_priv_key(pkey)
+ return parsed, err
+end
+
+
local function create_router(ssl_items)
local ssl_items = ssl_items or {}
@@ -109,32 +133,33 @@ local function create_router(ssl_items)
end
-local function set_pem_ssl_key(cert, pkey)
+local function set_pem_ssl_key(sni, cert, pkey)
local r = get_request()
if r == nil then
return false, "no request found"
end
- local parse_cert, err = ngx_ssl.parse_pem_cert(cert)
- if parse_cert then
- local ok, err = ngx_ssl.set_cert(parse_cert)
- if not ok then
- return false, "failed to set PEM cert: " .. err
- end
- else
+ local parsed_cert, err = cert_cache(cert, nil, parse_pem_cert, sni, cert)
+ if not parsed_cert then
return false, "failed to parse PEM cert: " .. err
end
- local parse_pkey, err = ngx_ssl.parse_pem_priv_key(pkey)
- if parse_pkey then
- local ok, err = ngx_ssl.set_priv_key(parse_pkey)
- if not ok then
- return false, "failed to set PEM priv key: " .. err
- end
- else
+ local ok, err = ngx_ssl.set_cert(parsed_cert)
+ if not ok then
+ return false, "failed to set PEM cert: " .. err
+ end
+
+ local parsed_pkey, err = pkey_cache(pkey, nil, parse_pem_priv_key, sni,
+ pkey)
+ if not parsed_pkey then
return false, "failed to parse PEM priv key: " .. err
end
+ ok, err = ngx_ssl.set_priv_key(parsed_pkey)
+ if not ok then
+ return false, "failed to set PEM priv key: " .. err
+ end
+
return true
end
@@ -196,7 +221,8 @@ function _M.match_and_set(api_ctx)
ngx_ssl.clear_certs()
- ok, err = set_pem_ssl_key(matched_ssl.value.cert, matched_ssl.value.key)
+ ok, err = set_pem_ssl_key(sni, matched_ssl.value.cert,
+ matched_ssl.value.key)
if not ok then
return false, err
end
@@ -207,7 +233,7 @@ function _M.match_and_set(api_ctx)
local cert = matched_ssl.value.certs[i]
local key = matched_ssl.value.keys[i]
- ok, err = set_pem_ssl_key(cert, key)
+ ok, err = set_pem_ssl_key(sni, cert, key)
if not ok then
return false, err
end
diff --git a/t/router/radixtree-sni.t b/t/router/radixtree-sni.t
index 7a4eec1..5ef8dd1 100644
--- a/t/router/radixtree-sni.t
+++ b/t/router/radixtree-sni.t
@@ -1071,3 +1071,96 @@ GET /t
--- response_body
connected: 1
ssl handshake: userdata
+
+
+
+=== TEST 24: set ssl(sni: *.test2.com) once again
+--- config
+location /t {
+ content_by_lua_block {
+ local core = require("apisix.core")
+ local t = require("lib.test_admin")
+
+ local ssl_cert = t.read_file("conf/cert/test2.crt")
+ local ssl_key = t.read_file("conf/cert/test2.key")
+ local data = {cert = ssl_cert, key = ssl_key, sni = "*.test2.com"}
+
+ local code, body = t.test('/apisix/admin/ssl/1',
+ ngx.HTTP_PUT,
+ core.json.encode(data),
+ [[{
+ "node": {
+ "value": {
+ "sni": "*.test2.com"
+ },
+ "key": "/apisix/ssl/1"
+ },
+ "action": "set"
+ }]]
+ )
+
+ ngx.status = code
+ ngx.say(body)
+ }
+}
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 25: caching of parsed certs and pkeys
+--- config
+listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
+
+location /t {
+ content_by_lua_block {
+ -- etcd sync
+ ngx.sleep(0.2)
+
+ local work = function()
+ local sock = ngx.socket.tcp()
+
+ sock:settimeout(2000)
+
+ local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock")
+ if not ok then
+ ngx.say("failed to connect: ", err)
+ return
+ end
+
+ ngx.say("connected: ", ok)
+
+ local sess, err = sock:sslhandshake(nil, "www.test2.com", false)
+ if not sess then
+ ngx.say("failed to do SSL handshake: ", err)
+ return
+ end
+ ngx.say("ssl handshake: ", type(sess))
+ local ok, err = sock:close()
+ ngx.say("close: ", ok, " ", err)
+ end -- do
+
+ work()
+ work()
+
+ -- collectgarbage()
+ }
+}
+--- request
+GET /t
+--- response_body eval
+qr{connected: 1
+ssl handshake: userdata
+close: 1 nil
+connected: 1
+ssl handshake: userdata
+close: 1 nil}
+--- grep_error_log eval
+qr/parsing (cert|(priv key)) for sni: www.test2.com/
+--- grep_error_log_out
+parsing cert for sni: www.test2.com
+parsing priv key for sni: www.test2.com