diff --git a/doc/admin-guide/configuration/hrw4u.en.rst b/doc/admin-guide/configuration/hrw4u.en.rst index 4a0fb3f6961..02bded4ebec 100644 --- a/doc/admin-guide/configuration/hrw4u.en.rst +++ b/doc/admin-guide/configuration/hrw4u.en.rst @@ -326,6 +326,7 @@ rm-destination QUERY ... [I] keep_query("foo,bar") Keep only specif run-plugin foo.so "args" run-plugin("foo.so", "arg1", ...) Run an external remap plugin set-body "foo" inbound.resp.body = "foo" Set the response body set-body-from "\https://..." set-body-from("\https://...") Set the response body from a URL +set-body-from-file "/tmp/b" set-body-from-file("/tmp/b") Set the response body from a local file set-config 12 set-config("name", 17) Set a configuration variable to a value set-conn-dscp 8 inbound.conn.dscp = 8 Set the DSCP value for the connection set-conn-mark 17 inbound.conn.mark = 17 Set the MARK value for the connection @@ -717,24 +718,34 @@ validated. Functions --------- -The ``functions`` list accepts any of the statement-function names used in -HRW4U source. The complete set of deniable functions is: +The ``functions`` list accepts any of the function names used in HRW4U source, +both statement functions and the functions that produce a value in an +expression. The complete set of deniable functions is: ====================== ============================================= Function Description ====================== ============================================= +``access`` File accessibility check ``add-header`` Add a header (``+=`` operator equivalent) +``cache`` Cache lookup result status +``cidr`` Masked client IP address match ``counter`` Increment an ATS statistics counter +``internal`` Internally generated transaction check ``keep_query`` Keep only specified query parameters ``no-op`` Explicit no-op statement +``random`` Random number in the given range ``remove_query`` Remove specified query parameters ``run-plugin`` Invoke an external remap plugin +``set-body`` Set the response body ``set-body-from`` Set response body from a URL +``set-body-from-file`` Set response body from a local file ``set-config`` Override an ATS configuration variable ``set-debug`` Enable per-transaction ATS debug logging ``set-plugin-cntl`` Set a plugin control flag ``set-redirect`` Issue an HTTP redirect response ``skip-remap`` Skip remap processing (open proxy) +``ssn-txn-count`` Transaction count on server connection +``txn-count`` Transaction count on client connection ====================== ============================================= Conditions and Operators diff --git a/tools/hrw4u/schema/sandbox.schema.json b/tools/hrw4u/schema/sandbox.schema.json index 0e106dc4401..b458ffa6443 100644 --- a/tools/hrw4u/schema/sandbox.schema.json +++ b/tools/hrw4u/schema/sandbox.schema.json @@ -52,14 +52,19 @@ }, "functions": { "type": "array", - "description": "Statement function names.", + "description": "Function names, both statement functions and functions used as values in expressions.", "items": { "type": "string", "enum": [ + "access", "add-header", + "cache", + "cidr", "counter", + "internal", "keep_query", "no-op", + "random", "remove_query", "run-plugin", "set-body", @@ -69,7 +74,9 @@ "set-debug", "set-plugin-cntl", "set-redirect", - "skip-remap" + "skip-remap", + "ssn-txn-count", + "txn-count" ] }, "uniqueItems": true diff --git a/tools/hrw4u/src/symbols.py b/tools/hrw4u/src/symbols.py index a57c6f27041..3dc66fee983 100644 --- a/tools/hrw4u/src/symbols.py +++ b/tools/hrw4u/src/symbols.py @@ -181,6 +181,8 @@ def resolve_condition(self, name: str, section: SectionType | None = None) -> tu def resolve_function(self, func_name: str, args: list[str], strip_quotes: bool = False) -> str: with self.debug_context("resolve_function", func_name, args): + self._collect_warning(self._sandbox.check_function(func_name)) + if params := self._lookup_function_cached(func_name): tag = params.target validator = params.validate diff --git a/tools/hrw4u/tests/data/sandbox/denied-value-function.ast.txt b/tools/hrw4u/tests/data/sandbox/denied-value-function.ast.txt new file mode 100644 index 00000000000..619ebb87be3 --- /dev/null +++ b/tools/hrw4u/tests/data/sandbox/denied-value-function.ast.txt @@ -0,0 +1 @@ +(program (programItem (section REMAP { (sectionBody (conditional (ifStatement if (condition (expression (term (factor (functionCall access ( (argumentList (value "/tmp/hrw4u-probe")) )))))) (block { (blockItem (statement inbound.req.X-Probe = (value "yes") ;)) })))) (sectionBody (statement inbound.req.X-Txn-Count = (value "{txn-count()}") ;)) })) ) diff --git a/tools/hrw4u/tests/data/sandbox/denied-value-function.error.txt b/tools/hrw4u/tests/data/sandbox/denied-value-function.error.txt new file mode 100644 index 00000000000..3cf46508ffe --- /dev/null +++ b/tools/hrw4u/tests/data/sandbox/denied-value-function.error.txt @@ -0,0 +1,3 @@ +'access' is denied by sandbox policy (function) +'txn-count' is denied by sandbox policy (function) +Feature denied by sandbox policy. Contact platform team. diff --git a/tools/hrw4u/tests/data/sandbox/denied-value-function.input.txt b/tools/hrw4u/tests/data/sandbox/denied-value-function.input.txt new file mode 100644 index 00000000000..2f88b18ddfb --- /dev/null +++ b/tools/hrw4u/tests/data/sandbox/denied-value-function.input.txt @@ -0,0 +1,7 @@ +REMAP { + if access("/tmp/hrw4u-probe") { + inbound.req.X-Probe = "yes"; + } + + inbound.req.X-Txn-Count = "{txn-count()}"; +} diff --git a/tools/hrw4u/tests/data/sandbox/denied-value-function.sandbox.yaml b/tools/hrw4u/tests/data/sandbox/denied-value-function.sandbox.yaml new file mode 100644 index 00000000000..923045b668a --- /dev/null +++ b/tools/hrw4u/tests/data/sandbox/denied-value-function.sandbox.yaml @@ -0,0 +1,7 @@ +sandbox: + message: "Feature denied by sandbox policy. Contact platform team." + + deny: + functions: + - access + - txn-count diff --git a/tools/hrw4u/tests/data/sandbox/warned-value-function.ast.txt b/tools/hrw4u/tests/data/sandbox/warned-value-function.ast.txt new file mode 100644 index 00000000000..eeab10ba62e --- /dev/null +++ b/tools/hrw4u/tests/data/sandbox/warned-value-function.ast.txt @@ -0,0 +1 @@ +(program (programItem (section REMAP { (sectionBody (conditional (ifStatement if (condition (expression (term (factor (comparison (comparable (functionCall cidr ( (argumentList (value 24) , (value 48)) ))) == (value "10.0.0.0")))))) (block { (blockItem (statement inbound.req.X-Net = (value "matched") ;)) })))) })) ) diff --git a/tools/hrw4u/tests/data/sandbox/warned-value-function.input.txt b/tools/hrw4u/tests/data/sandbox/warned-value-function.input.txt new file mode 100644 index 00000000000..30650f52988 --- /dev/null +++ b/tools/hrw4u/tests/data/sandbox/warned-value-function.input.txt @@ -0,0 +1,5 @@ +REMAP { + if cidr(24, 48) == "10.0.0.0" { + inbound.req.X-Net = "matched"; + } +} diff --git a/tools/hrw4u/tests/data/sandbox/warned-value-function.output.txt b/tools/hrw4u/tests/data/sandbox/warned-value-function.output.txt new file mode 100644 index 00000000000..feeedd3db29 --- /dev/null +++ b/tools/hrw4u/tests/data/sandbox/warned-value-function.output.txt @@ -0,0 +1,3 @@ +cond %{REMAP_PSEUDO_HOOK} [AND] +cond %{CIDR:24,48} ="10.0.0.0" + set-header X-Net "matched" diff --git a/tools/hrw4u/tests/data/sandbox/warned-value-function.sandbox.yaml b/tools/hrw4u/tests/data/sandbox/warned-value-function.sandbox.yaml new file mode 100644 index 00000000000..3709f31dc49 --- /dev/null +++ b/tools/hrw4u/tests/data/sandbox/warned-value-function.sandbox.yaml @@ -0,0 +1,6 @@ +sandbox: + message: "This feature will be denied in a future release. Contact platform team." + + warn: + functions: + - cidr diff --git a/tools/hrw4u/tests/data/sandbox/warned-value-function.warning.txt b/tools/hrw4u/tests/data/sandbox/warned-value-function.warning.txt new file mode 100644 index 00000000000..9c1a45ce251 --- /dev/null +++ b/tools/hrw4u/tests/data/sandbox/warned-value-function.warning.txt @@ -0,0 +1,2 @@ +'cidr' is warned by sandbox policy (function) +This feature will be denied in a future release. Contact platform team.