This is an automated email from the ASF dual-hosted git repository.

membphis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new e598e6f  bugfix: wrong counter was used, resulting in only one 
certificate working fine. (#1818)
e598e6f is described below

commit e598e6fa6aa71fcdfab99aff8eb24acce37d257a
Author: nic-chen <33000667+nic-c...@users.noreply.github.com>
AuthorDate: Fri Jul 10 18:39:08 2020 +0800

    bugfix: wrong counter was used, resulting in only one certificate working 
fine. (#1818)
    
    Fix #1817
---
 apisix/http/router/radixtree_sni.lua |  23 ++-
 t/node/invalid-service.t             |   2 +-
 t/node/invalid-upstream.t            |   2 +-
 t/router/multi-ssl-certs.t           | 360 +++++++++++++++++++++++++++++++++++
 t/router/radixtree-sni.t             |   7 +-
 5 files changed, 381 insertions(+), 13 deletions(-)

diff --git a/apisix/http/router/radixtree_sni.lua 
b/apisix/http/router/radixtree_sni.lua
index 1eb7aa5..d042aee 100644
--- a/apisix/http/router/radixtree_sni.lua
+++ b/apisix/http/router/radixtree_sni.lua
@@ -25,6 +25,7 @@ local error            = error
 local str_find         = string.find
 local aes              = require "resty.aes"
 local assert           = assert
+local str_gsub         = string.gsub
 local ngx_decode_base64 = ngx.decode_base64
 local ssl_certificates
 local radixtree_router
@@ -80,7 +81,6 @@ local function create_router(ssl_items)
                 end
             end
 
-            local
             idx = idx + 1
             route_items[idx] = {
                 paths = sni,
@@ -96,6 +96,10 @@ local function create_router(ssl_items)
     end
 
     core.log.info("route items: ", core.json.delay_encode(route_items, true))
+    -- for testing
+    if #route_items > 1 then
+        core.log.info("we have more than 1 ssl certs now")
+    end
     local router, err = radixtree_new(route_items)
     if not router then
         return nil, err
@@ -151,7 +155,7 @@ function _M.match_and_set(api_ctx)
     local sni
     sni, err = ngx_ssl.server_name()
     if type(sni) ~= "string" then
-        return false, "failed to fetch SNI: " .. (err or "not found")
+        return false, "failed to fetch SSL certificate: " .. (err or "not 
found")
     end
 
     core.log.debug("sni: ", sni)
@@ -159,7 +163,7 @@ function _M.match_and_set(api_ctx)
     local sni_rev = sni:reverse()
     local ok = radixtree_router:dispatch(sni_rev, nil, api_ctx)
     if not ok then
-        core.log.warn("not found any valid sni configuration")
+        core.log.warn("failed to find any SSL certificate by SNI: ", sni)
         return false
     end
 
@@ -172,14 +176,19 @@ function _M.match_and_set(api_ctx)
             end
         end
         if not matched then
-            core.log.warn("not found any valid sni configuration, matched sni: 
",
-                          core.json.delay_encode(api_ctx.matched_sni, true), " 
current sni: ", sni)
+            local log_snis = core.json.encode(api_ctx.matched_sni, true)
+            if log_snis ~= nil then
+                log_snis = str_gsub(log_snis:reverse(), "%[", "%]")
+                log_snis = str_gsub(log_snis, "%]", "%[", 1)
+            end
+            core.log.warn("failed to find any SSL certificate by SNI: ",
+                          sni, " matched SNIs: ", log_snis)
             return false
         end
     else
         if str_find(sni_rev, ".", #api_ctx.matched_sni, true) then
-            core.log.warn("not found any valid sni configuration, matched sni: 
",
-                          api_ctx.matched_sni:reverse(), " current sni: ", sni)
+            core.log.warn("failed to find any SSL certificate by SNI: ",
+                          sni, " matched SNI: ", api_ctx.matched_sni:reverse())
             return false
         end
     end
diff --git a/t/node/invalid-service.t b/t/node/invalid-service.t
index 4a6af13..0b74232 100644
--- a/t/node/invalid-service.t
+++ b/t/node/invalid-service.t
@@ -39,7 +39,7 @@ __DATA__
             end
 
             ngx.print(core.json.encode(res.body))
-            ngx.sleep(0.5)
+            ngx.sleep(1)
         }
     }
 --- request
diff --git a/t/node/invalid-upstream.t b/t/node/invalid-upstream.t
index b6138ab..1d83e9e 100644
--- a/t/node/invalid-upstream.t
+++ b/t/node/invalid-upstream.t
@@ -38,7 +38,7 @@ __DATA__
             end
 
             ngx.print(core.json.encode(res.body))
-            ngx.sleep(0.5)
+            ngx.sleep(1)
         }
     }
 --- request
diff --git a/t/router/multi-ssl-certs.t b/t/router/multi-ssl-certs.t
new file mode 100644
index 0000000..61fe22a
--- /dev/null
+++ b/t/router/multi-ssl-certs.t
@@ -0,0 +1,360 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+use t::APISIX 'no_plan';
+
+log_level('debug');
+no_root_location();
+
+$ENV{TEST_NGINX_HTML_DIR} ||= html_dir();
+
+run_tests;
+
+__DATA__
+
+=== TEST 1: set ssl(sni: www.test.com)
+--- 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/apisix.crt")
+        local ssl_key =  t.read_file("conf/cert/apisix.key")
+        local data = {cert = ssl_cert, key = ssl_key, sni = "www.test.com"}
+
+        local code, body = t.test('/apisix/admin/ssl/1',
+            ngx.HTTP_PUT,
+            core.json.encode(data),
+            [[{
+                "node": {
+                    "value": {
+                        "sni": "www.test.com"
+                    },
+                    "key": "/apisix/ssl/1"
+                },
+                "action": "set"
+            }]]
+            )
+
+        ngx.status = code
+        ngx.say(body)
+    }
+}
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 2: set route(id: 1)
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/routes/1',
+                 ngx.HTTP_PUT,
+                 [[{
+                        "upstream": {
+                            "nodes": {
+                                "127.0.0.1:1980": 1
+                            },
+                            "type": "roundrobin"
+                        },
+                        "uri": "/hello"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 3: client request
+--- config
+listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
+
+location /t {
+    content_by_lua_block {
+        -- etcd sync
+        ngx.sleep(0.2)
+
+        do
+            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.test.com", true)
+            if not sess then
+                ngx.say("failed to do SSL handshake: ", err)
+                return
+            end
+
+            ngx.say("ssl handshake: ", type(sess))
+
+            local req = "GET /hello HTTP/1.0\r\nHost: 
www.test.com\r\nConnection: close\r\n\r\n"
+            local bytes, err = sock:send(req)
+            if not bytes then
+                ngx.say("failed to send http request: ", err)
+                return
+            end
+
+            ngx.say("sent http request: ", bytes, " bytes.")
+
+            while true do
+                local line, err = sock:receive()
+                if not line then
+                    -- ngx.say("failed to receive response status line: ", err)
+                    break
+                end
+
+                ngx.say("received: ", line)
+            end
+
+            local ok, err = sock:close()
+            ngx.say("close: ", ok, " ", err)
+        end  -- do
+        -- collectgarbage()
+    }
+}
+--- request
+GET /t
+--- response_body eval
+qr{connected: 1
+ssl handshake: userdata
+sent http request: 62 bytes.
+received: HTTP/1.1 200 OK
+received: Content-Type: text/plain
+received: Connection: close
+received: Server: \w+
+received: \nreceived: hello world
+close: 1 nil}
+--- error_log
+lua ssl server name: "www.test.com"
+--- no_error_log
+[error]
+[alert]
+
+
+
+=== TEST 4: set second ssl(sni: *.test2.com)
+--- 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/2',
+            ngx.HTTP_PUT,
+            core.json.encode(data),
+            [[{
+                "node": {
+                    "value": {
+                        "sni": "*.test2.com"
+                    },
+                    "key": "/apisix/ssl/2"
+                },
+                "action": "set"
+            }]]
+            )
+
+        ngx.status = code
+        ngx.say(body)
+    }
+}
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 5: client request: www.test2.com
+--- config
+listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
+
+location /t {
+    content_by_lua_block {
+        -- etcd sync
+        ngx.sleep(0.2)
+
+        do
+            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", true)
+            if not sess then
+                ngx.say("failed to do SSL handshake: ", err)
+                return
+            end
+
+            ngx.say("ssl handshake: ", type(sess))
+        end  -- do
+        -- collectgarbage()
+    }
+}
+--- request
+GET /t
+--- response_body
+connected: 1
+failed to do SSL handshake: 18: self signed certificate
+--- error_log
+lua ssl server name: "www.test2.com"
+we have more than 1 ssl certs now
+--- no_error_log
+[error]
+[alert]
+
+
+
+=== TEST 6: set third ssl(sni: apisix.dev)
+--- 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/apisix_admin_ssl.crt")
+        local ssl_key =  t.read_file("conf/cert/apisix_admin_ssl.key")
+        local data = {cert = ssl_cert, key = ssl_key, sni = "apisix.dev"}
+
+        local code, body = t.test('/apisix/admin/ssl/3',
+            ngx.HTTP_PUT,
+            core.json.encode(data),
+            [[{
+                "node": {
+                    "value": {
+                        "sni": "apisix.dev"
+                    },
+                    "key": "/apisix/ssl/3"
+                },
+                "action": "set"
+            }]]
+            )
+
+        ngx.status = code
+        ngx.say(body)
+    }
+}
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 7: client request: apisix.dev
+--- config
+listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
+
+location /t {
+    content_by_lua_block {
+        -- etcd sync
+        ngx.sleep(0.2)
+
+        do
+            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, "apisix.dev", true)
+            if not sess then
+                ngx.say("failed to do SSL handshake: ", err)
+                return
+            end
+
+            ngx.say("ssl handshake: ", type(sess))
+        end  -- do
+        -- collectgarbage()
+    }
+}
+--- request
+GET /t
+--- response_body
+connected: 1
+failed to do SSL handshake: 18: self signed certificate
+--- error_log
+lua ssl server name: "apisix.dev"
+we have more than 1 ssl certs now
+--- no_error_log
+[error]
+[alert]
+
+
+
+=== TEST 19: remove test ssl certs 
+--- config
+location /t {
+    content_by_lua_block {
+        local core = require("apisix.core")
+        local t = require("lib.test_admin")
+
+        t.test('/apisix/admin/ssl/1', ngx.HTTP_DELETE)
+        t.test('/apisix/admin/ssl/2', ngx.HTTP_DELETE)
+        t.test('/apisix/admin/ssl/3', ngx.HTTP_DELETE)
+
+    }
+}
+--- request
+GET /t
+--- no_error_log
+[error]
diff --git a/t/router/radixtree-sni.t b/t/router/radixtree-sni.t
index 86724e0..06388a7 100644
--- a/t/router/radixtree-sni.t
+++ b/t/router/radixtree-sni.t
@@ -207,7 +207,7 @@ GET /t
 connected: 1
 failed to do SSL handshake: certificate host mismatch
 --- error_log
-not found any valid sni configuration
+failed to find any SSL certificate by SNI
 
 
 
@@ -561,7 +561,7 @@ connected: 1
 failed to do SSL handshake: certificate host mismatch
 --- error_log
 lua ssl server name: "aa.bb.test2.com"
-not found any valid sni configuration, matched sni: *.test2.com current sni: 
aa.bb.test2.com
+failed to find any SSL certificate by SNI: aa.bb.test2.com matched SNI: 
*.test2.com
 --- no_error_log
 [error]
 [alert]
@@ -856,7 +856,7 @@ connected: 1
 failed to do SSL handshake: certificate host mismatch
 --- error_log
 lua ssl server name: "aa.bb.test2.com"
-not found any valid sni configuration, matched sni: 
["moc.2tset","moc.2tset.*"] current sni: aa.bb.test2.com
+failed to find any SSL certificate by SNI: aa.bb.test2.com matched SNIs: 
["*.test2.com","test2.com"]
 --- no_error_log
 [error]
 [alert]
@@ -904,7 +904,6 @@ passed
 === TEST 20: client request: test2.com
 --- config
 listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
-
 location /t {
     content_by_lua_block {
         -- etcd sync

Reply via email to