]> git.kaiwu.me - haproxy.git/commitdiff
REGTESTS: http-rules: test the HTTP authentication action, fetches and ACL
authorWilly Tarreau <w@1wt.eu>
Mon, 21 Sep 2026 20:29:01 +0000 (20:29 +0000)
committerWilly Tarreau <w@1wt.eu>
Wed, 30 Sep 2026 14:55:57 +0000 (16:55 +0200)
Neither the "auth" action nor the http_auth_user, http_auth_pass,
http_auth_type and http_auth_group fetches were covered, and the
userlist section was only exercised through the stats.

The test declares a userlist with two users, one of them in a group,
and checks that the credentials are readable before being validated,
that http_auth() only matches with the right password, that
http_auth_group() only matches for the member of the group, and that
the "auth" action emits a 401 carrying the requested realm until valid
credentials are presented.

reg-tests/http-rules/http_auth.vtc [new file with mode: 0644]

diff --git a/reg-tests/http-rules/http_auth.vtc b/reg-tests/http-rules/http_auth.vtc
new file mode 100644 (file)
index 0000000..9efaa1b
--- /dev/null
@@ -0,0 +1,106 @@
+varnishtest "Test the HTTP authentication action, fetches and ACL"
+
+# Neither the "auth" action nor the http_auth_user, http_auth_pass,
+# http_auth_type and http_auth_group fetches were covered, and the
+# userlist section itself was only used by the stats. The test checks a
+# successful and a failed authentication, the group membership, and the
+# 401 response emitted by the "auth" action with its realm.
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+    global
+    .if feature(THREAD)
+        thread-groups 1
+    .endif
+        chroot /
+
+    defaults
+       mode http
+       timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+       timeout client  "${HAPROXY_TEST_TIMEOUT-5s}"
+       timeout server  "${HAPROXY_TEST_TIMEOUT-5s}"
+
+    userlist ul
+       group admins
+       user u1 insecure-password pass1 groups admins
+       user u2 insecure-password pass2
+
+    frontend fe
+       bind "fd@${fe}"
+
+       acl auth_ok  http_auth(ul)
+       acl is_admin http_auth_group(ul) admins
+
+       # the credentials are readable even before they are validated
+       http-request set-var(txn.user)  http_auth_user
+       http-request set-var(txn.pass)  http_auth_pass
+       http-request set-var(txn.type)  http_auth_type
+       http-request set-var(txn.ok)    str(yes) if auth_ok
+       http-request set-var(txn.admin) str(yes) if is_admin
+
+       http-request auth realm "protected area" if { path /private } !auth_ok
+       http-request return status 200
+
+       http-after-response set-header x-user  "%[var(txn.user)]"
+       http-after-response set-header x-pass  "%[var(txn.pass)]"
+       http-after-response set-header x-type  "%[var(txn.type)]"
+       http-after-response set-header x-ok    "%[var(txn.ok)]"
+       http-after-response set-header x-admin "%[var(txn.admin)]"
+} -start
+
+client c1 -connect ${h1_fe_sock} {
+       # no credentials at all
+       txreq -url "/public"
+       rxresp
+       expect resp.status == 200
+       expect resp.http.x-user  == ""
+       expect resp.http.x-pass  == ""
+       expect resp.http.x-type  == ""
+       expect resp.http.x-ok    == ""
+       expect resp.http.x-admin == ""
+
+       # valid credentials of a user belonging to the group
+       txreq -url "/public" -hdr "authorization: Basic dTE6cGFzczE="
+       rxresp
+       expect resp.status == 200
+       expect resp.http.x-user  == "u1"
+       expect resp.http.x-pass  == "pass1"
+       expect resp.http.x-type  == "Basic"
+       expect resp.http.x-ok    == "yes"
+       expect resp.http.x-admin == "yes"
+
+       # valid credentials of a user outside of the group
+       txreq -url "/public" -hdr "authorization: Basic dTI6cGFzczI="
+       rxresp
+       expect resp.status == 200
+       expect resp.http.x-user  == "u2"
+       expect resp.http.x-pass  == "pass2"
+       expect resp.http.x-ok    == "yes"
+       expect resp.http.x-admin == ""
+
+       # the user exists but the password is wrong
+       txreq -url "/public" -hdr "authorization: Basic dTE6d3Jvbmc="
+       rxresp
+       expect resp.status == 200
+       expect resp.http.x-user  == "u1"
+       expect resp.http.x-pass  == "wrong"
+       expect resp.http.x-ok    == ""
+} -run
+
+client c2 -connect ${h1_fe_sock} {
+       # the protected path triggers the "auth" action
+       txreq -url "/private"
+       rxresp
+       expect resp.status == 401
+       expect resp.http.www-authenticate == {Basic realm="protected area"}
+
+       txreq -url "/private" -hdr "authorization: Basic dTE6d3Jvbmc="
+       rxresp
+       expect resp.status == 401
+
+       txreq -url "/private" -hdr "authorization: Basic dTE6cGFzczE="
+       rxresp
+       expect resp.status == 200
+       expect resp.http.x-user == "u1"
+} -run