]> git.kaiwu.me - haproxy.git/commitdiff
REGTESTS: cli: test the privilege levels of the CLI
authorWilly Tarreau <w@1wt.eu>
Tue, 22 Sep 2026 03:44:08 +0000 (03:44 +0000)
committerWilly Tarreau <w@1wt.eu>
Wed, 30 Sep 2026 15:19:30 +0000 (17:19 +0200)
The "operator" and "user" commands, which drop the privileges of the
current connection, had no coverage, and "show cli level" was only
reported by the smoke test.

The test walks down the three levels and checks both what each of them
still allows and what it refuses: reading the statistics and the
process information is allowed everywhere, clearing the counters
requires operator, and changing a global setting, a server state,
an ACL or entering the expert or experimental modes requires admin. It
also verifies that the levels only go down, and that a refused command
really left the setting untouched.

Each case chains the level change and the command it affects on a
single line because the level only applies to the connection it was set
on, and vtest opens a new connection for every "send".

reg-tests/cli/levels.vtc [new file with mode: 0644]

diff --git a/reg-tests/cli/levels.vtc b/reg-tests/cli/levels.vtc
new file mode 100644 (file)
index 0000000..1e25183
--- /dev/null
@@ -0,0 +1,86 @@
+varnishtest "Test the privilege levels of the CLI"
+
+# The "operator" and "user" CLI commands, which drop the privileges of
+# the current connection, had no coverage, and "show cli level" was only
+# reported by the smoke test. This test walks down the three levels and
+# checks both what each of them still allows and what it refuses.
+#
+# The levels only apply to the connection they were set on, and vtest
+# opens a new connection for every "send", so each case chains the
+# level change and the command it is meant to affect in a single line.
+
+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}"
+
+    frontend fe
+       bind "fd@${fe}"
+       http-request return status 200
+
+    backend be
+       server s1 127.0.0.1:1 disabled
+} -start
+
+haproxy h1 -cli {
+       # the socket declared by the test harness is an admin one
+       send "show cli level"
+       expect ~ "^admin"
+
+       # dropping to operator, then to user
+       send "operator; show cli level"
+       expect ~ "\noperator"
+       send "user; show cli level"
+       expect ~ "\nuser"
+       # the levels only go down, an operator cannot become admin again
+       send "operator; user; show cli level"
+       expect ~ "\nuser"
+
+       # reading the statistics is allowed at every level
+       send "operator; show stat"
+       expect ~ "\n# pxname,svname,qcur"
+       send "user; show stat"
+       expect ~ "\n# pxname,svname,qcur"
+       send "user; show info"
+       expect ~ "Name: HAProxy"
+
+       # changing a global setting requires admin
+       send "set maxconn global 1234; show info"
+       expect ~ "\nMaxconn: 1234\n"
+       send "operator; set maxconn global 4321"
+       expect ~ "Permission denied"
+       send "user; set maxconn global 4321"
+       expect ~ "Permission denied"
+       # and it was really left untouched
+       send "show info"
+       expect ~ "\nMaxconn: 1234\n"
+
+       # so does entering the expert or experimental modes
+       send "user; expert-mode on"
+       expect ~ "Permission denied"
+       send "operator; experimental-mode on"
+       expect ~ "Permission denied"
+
+       # and so does modifying an ACL or a map
+       send "operator; add acl virt@nosuchacl foo"
+       expect ~ "Permission denied"
+
+       # clearing the counters is what an operator is allowed to do, while
+       # changing a server state turns out to require admin as well
+       send "operator; clear counters"
+       expect !~ "Permission denied"
+       send "user; clear counters"
+       expect ~ "Permission denied"
+       send "operator; set server be/s1 state ready"
+       expect ~ "Permission denied"
+}