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

membphis pushed a commit to branch feat/ssl-session-ticket-takeover
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to 
refs/heads/feat/ssl-session-ticket-takeover by this push:
     new 57c36ab6a5 fix(ssl-session-ticket): record the first round of a worker 
from a timer
57c36ab6a5 is described below

commit 57c36ab6a5e9cfe8ab649ed2b419b170ee5f2ce4
Author: Yuansheng Wang <[email protected]>
AuthorDate: Thu Oct 29 10:20:03 2026 +0800

    fix(ssl-session-ticket): record the first round of a worker from a timer
    
    init_worker cannot sleep: when every process of a reload writes its worker
    record at once, the first write only spun on the lock of the state and could
    time out ("failed to lock shared dict 'tls-session-ticket': timeout"). A
    worker still applies the target at once, then records it from a timer.
    
    t/stream-node/mtls.t replays a saved session under another SNI to check that
    a resumed session cannot bypass the client verification. TEST 8 and 9 keep
    the session cache of the previous Stream listener; TEST 10 to 12 replay a
    ticket of the shared keys, the only way a Stream session resumes with a
    runtime that takes over the keys: it is rejected the same way.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 apisix/ssl/session_ticket.lua | 16 ++++++++++--
 t/stream-node/mtls.t          | 59 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/apisix/ssl/session_ticket.lua b/apisix/ssl/session_ticket.lua
index fcc52b7f7c..de9ce9f568 100644
--- a/apisix/ssl/session_ticket.lua
+++ b/apisix/ssl/session_ticket.lua
@@ -316,10 +316,22 @@ function _M.init_worker()
         return
     end
 
-    tick()
+    -- Apply at once. Writing the record takes the lock of the state, which
+    -- may have to wait for the other processes, e.g. all of them during a
+    -- reload: init_worker cannot sleep, so in a timer.
+    _M.reconcile()
+    local ok, err = ngx.timer.at(0, function(premature)
+        if not premature then
+            tick()
+        end
+    end)
+    if not ok then
+        core.log.error("failed to create the first round of the TLS session 
ticket keys: ",
+                       err)
+    end
     timers.register_timer(TIMER_NAME, tick)
 
-    local ok, err = ngx.timer.every(EXIT_HOOK_INTERVAL, on_exit_hook)
+    ok, err = ngx.timer.every(EXIT_HOOK_INTERVAL, on_exit_hook)
     if not ok then
         core.log.error("failed to create the exit hook of the TLS session 
ticket keys: ", err)
     end
diff --git a/t/stream-node/mtls.t b/t/stream-node/mtls.t
index 9e1f2c9349..97d98d2fab 100644
--- a/t/stream-node/mtls.t
+++ b/t/stream-node/mtls.t
@@ -316,6 +316,9 @@ GET /t
 
 
 === TEST 8: request localhost and save tls session to reuse
+The session cache of the Stream listener, see TEST 10 for the shared
+session ticket keys.
+--- legacy_ssl_session_tickets
 --- stream_enable
 --- max_size: 1048576
 --- exec
@@ -326,6 +329,7 @@ echo "" | timeout 1 openssl s_client -ign_eof -connect 
127.0.0.1:2005 \
 
 
 === TEST 9: request test.com with saved tls session
+--- legacy_ssl_session_tickets
 --- stream_enable
 --- max_size: 1048576
 --- exec
@@ -333,3 +337,58 @@ echo "" | openssl s_client -connect 127.0.0.1:2005 
-servername test.com \
     -sess_in session.dat
 --- error_log
 sni in client hello mismatch hostname of ssl session, sni: test.com, hostname: 
localhost
+
+
+
+=== TEST 10: share the session ticket keys
+--- extra_yaml_config
+plugin_attr:
+  ssl-session-ticket:
+    enabled: true
+    key_source: external
+--- config
+    location /t {
+        content_by_lua_block {
+            local h = require("lib.ssl_session_ticket")
+            local code = h.put_keys(1)
+            h.wait_state(function(s) return s.keys[1] == h.key(1) end)
+            ngx.say(code < 300)
+        }
+    }
+--- request
+GET /t
+--- response_body
+true
+
+
+
+=== TEST 11: request localhost and save the tls session, a ticket of the 
shared keys
+With a runtime that takes over the keys, the Stream listener resumes sessions
+with them only.
+--- extra_yaml_config
+plugin_attr:
+  ssl-session-ticket:
+    enabled: true
+    key_source: external
+--- stream_enable
+--- max_size: 1048576
+--- exec
+sleep 2; echo "" | timeout 1 openssl s_client -ign_eof -connect 127.0.0.1:2005 
\
+    -servername localhost -cert t/certs/mtls_client.crt -key 
t/certs/mtls_client.key \
+    -sess_out session.dat
+
+
+
+=== TEST 12: a shared ticket of another SNI does not bypass the client 
verification
+--- extra_yaml_config
+plugin_attr:
+  ssl-session-ticket:
+    enabled: true
+    key_source: external
+--- stream_enable
+--- max_size: 1048576
+--- exec
+sleep 2; echo "" | openssl s_client -connect 127.0.0.1:2005 -servername 
test.com \
+    -sess_in session.dat
+--- error_log
+sni in client hello mismatch hostname of ssl session, sni: test.com, hostname: 
localhost

Reply via email to