]> git.kaiwu.me - haproxy.git/commitdiff
REGTEST: ocsp: make the ocsp_client_check test fast
authorWilly Tarreau <w@1wt.eu>
Tue, 10 Nov 2026 09:11:07 +0000 (10:11 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 10 Nov 2026 10:02:23 +0000 (11:02 +0100)
The last part of the test, which checks what happens when the OCSP
responder is not running anymore, used to take about 3 seconds: the
connection to the responder is refused, and the httpclient performs its
retries with the usual 1 second delay before reporting the responder as
unreachable.

A previous attempt tried to split the test in two but it failed due to
the need to hard-code the listening port which appears in the certificate,
preventing the tests from running in parallel, so everything must remain
in the same file to remain sequential.

In addition, setting a shorter timeout in HAPROXY_TEST_TIMEOUT (e.g. 400)
made it systematically fail with a 504: the 'do-ocsp-request' action limits
the OCSP check to the http-request timeout, which it arms when the rule is
evaluated, while the server timeout of the clear listener which forwards
the client's request was started earlier. Both being set to the same value,
the listener always gave up first.

Let's perform this last check through a dedicated SSL frontend whose
http-request timeout is set to a fixed 50ms, which is the timeout being
tested and remains well below the clear listener's server timeout. The
other checks keep using HAPROXY_TEST_TIMEOUT, so that a real OCSP round
trip is never limited to 50ms. The whole check now reports a timeout,
whose code and reason are verified, and the whole test takes about 700ms
in multiple tests of 250ms each, instead of around 3.2s.

reg-tests/ssl/ocsp_client_check.vtci

index 737dccff46b2478a5df0a50ac16228984d8c974a..eed1be99458f1962887728b30924e8fa1721048f 100644 (file)
@@ -54,6 +54,10 @@ haproxy h1 -conf {
         bind "fd@${clear_good_tcp}"
         server s1 "${VTC_SOCK_TYPE}+${h1_ssl_tcp_sock}" ssl verify none crt client_good.pem
 
+    listen clear-good-timeout-lst
+        bind "fd@${clear_good_timeout}"
+        server s1 "${VTC_SOCK_TYPE}+${h1_ssl_to_sock}" ssl verify none crt client_good.pem
+
     # The action never denies the request by itself, the OCSP status and error
     # reason are only exposed through variables. It is up to the configuration
     # to decide what to do with them.
@@ -71,6 +75,23 @@ haproxy h1 -conf {
         http-after-response set-header x-ocsp-error "%[var(txn.ocsp_reason)]"
         http-after-response set-header x-ocsp-reason "%[var(txn.ocsp_reason),ocsp_check_err_str]"
 
+    # Same check with a short http-request timeout, used once the responder
+    # is stopped. The 'do-ocsp-request' action arms this timeout when the
+    # rule is evaluated, so it must remain well below the server timeout of
+    # clear-good-timeout-lst, which started earlier, otherwise the latter would
+    # expire first and return a 504. It is the timeout being tested, so it
+    # does not depend on HAPROXY_TEST_TIMEOUT.
+    frontend ssl-to-fe
+        bind "${VTC_SOCK_TYPE}+fd@${ssl_to}" ssl crt server.pem ca-file "${testdir}/certs/ocsp_client_check/ca/ocsp_client_check_ca.crt" verify optional
+        timeout http-request 50ms
+
+        http-request do-ocsp-request status-var txn.ocsp_status reason-var txn.ocsp_reason
+        http-request return status 200
+
+        http-after-response set-header x-ocsp-status "%[var(txn.ocsp_status)]"
+        http-after-response set-header x-ocsp-error "%[var(txn.ocsp_reason)]"
+        http-after-response set-header x-ocsp-reason "%[var(txn.ocsp_reason),ocsp_check_err_str]"
+
     # Same check, performed by a "tcp-request content" rule instead.
     frontend ssl-tcp-fe
         bind "${VTC_SOCK_TYPE}+fd@${ssl_tcp}" ssl crt server.pem ca-file "${testdir}/certs/ocsp_client_check/ca/ocsp_client_check_ca.crt" verify optional
@@ -138,16 +159,16 @@ client c1 -connect ${h1_clear_good_tcp_sock} {
 # The responder should have answered all the expected requests by now.
 process p1 -wait -expect-exit 0
 
-# The OCSP responder is not running anymore, the check cannot be performed. The
-# request is still not denied but the status is not "good", the error code is
-# non-zero and the converted reason is filled.
-client c1 -connect ${h1_clear_good_sock} {
+# The OCSP responder is not running anymore, the check cannot be performed and
+# times out. The request is still not denied but the status is not "good", the
+# error code is non-zero and the converted reason is filled.
+client c1 -connect ${h1_clear_good_timeout_sock} {
     txreq
     rxresp
     expect resp.status == 200
     expect resp.http.x-ocsp-status == "unknown"
-    expect resp.http.x-ocsp-error ~ "^[1-9][0-9]*$"
-    expect resp.http.x-ocsp-reason != ""
+    expect resp.http.x-ocsp-error == "11"
+    expect resp.http.x-ocsp-reason == "Timeout"
 } -run
 
 haproxy h1 -wait