From aeac79145c5bfc772bfbd01178cfda1f672e42a6 Mon Sep 17 00:00:00 2001 From: Max Leske <250711+theseion@users.noreply.github.com> Date: Sat, 7 Dec 2024 10:07:48 +0100 Subject: [PATCH] feat: add VirtualHostMode setting refs https://github.com/coreruleset/go-ftw/issues/361 --- spec/v2.1.1/ftw.md | 2247 +++++++++++++++++ .../waf-platform-overrides-schema-v2.1.1.json | 1 + spec/v2.1.1/waf-tests-schema-v2.1.1.json | 1 + types/types.go | 33 +- 4 files changed, 2278 insertions(+), 4 deletions(-) create mode 100644 spec/v2.1.1/ftw.md create mode 100755 spec/v2.1.1/waf-platform-overrides-schema-v2.1.1.json create mode 100755 spec/v2.1.1/waf-tests-schema-v2.1.1.json diff --git a/spec/v2.1.1/ftw.md b/spec/v2.1.1/ftw.md new file mode 100644 index 0000000..df33bbc --- /dev/null +++ b/spec/v2.1.1/ftw.md @@ -0,0 +1,2247 @@ +## FTWTest +Welcome to the FTW YAMLFormat documentation. + In this document we will explain all the possible options that can be used within the YAML format. + Generally this is the preferred format for writing tests in as they don't require any programming skills + in order to understand and change. If you find a bug in this format please open an issue. + + + FTWTest is the base type used when unmarshaling YAML tests files + + + + + + +
+ +
+ +meta FTWTestMeta + +
+
+ +Meta describes the metadata information of this yaml test file + +
+ +
+ +
+ +rule_id uint + +
+
+ +RuleId is the ID of the rule this test targets. + + + +Examples: + + +```yaml +# RuleId +rule_id: 123456 +``` + + +
+ +
+ +
+ +tests []Test + +
+
+ +Tests is a list of FTW tests + + + +Examples: + + +```yaml +tests: + - test_title: 123456-1 + ruleid: 0 + test_id: 0 + desc: Unix RCE using `time` + stages: + - description: Get cookie from server + input: + dest_addr: 192.168.0.1 + port: 8080 + protocol: http + uri: /test + version: HTTP/1.1 + method: REPORT + headers: + Accept: '*/*' + Host: localhost + User-Agent: CRS Tests + save_cookie: false + stop_magic: true + autocomplete_headers: false + encoded_request: TXkgRGF0YQo= + output: + status: 200 + response_contains: HTTP/1.1 + log_contains: nothing + no_log_contains: everything + log: + expect_ids: + - 123456 + no_expect_ids: + - 123456 + match_regex: id[:\s"]*123456 + no_match_regex: id[:\s"]*123456 + expect_error: true +``` + + +
+ +
+ + + + + +## FTWTestMeta + +Appears in: + + +- FTWTest.meta + + + + + +
+ +
+ +author string + +
+
+ +Author is the list of authors that added content to this file + + + +Examples: + + +```yaml +# Author +author: Felipe Zipitria +``` + + +
+ +
+ +
+ +enabled bool + +
+
+ +Enabled indicates if the tests are enabled to be run by the engine or not. + + + +Examples: + + +```yaml +# Enabled +enabled: false +``` + + +
+ +
+ +
+ +name string + +
+
+ +Name is the name of the tests contained in this file. + + + +Examples: + + +```yaml +# Name +name: test01 +``` + + +
+ +
+ +
+ +description string + +
+
+ +Description is a textual description of the tests contained in this file. + + + +Examples: + + +```yaml +# Description +description: The tests here target SQL injection. +``` + + +
+ +
+ +
+ +version string + +
+
+ +Version is the version of the YAML Schema. + + + +Examples: + + +```yaml +# Version +version: v1 +``` + + +
+ +
+ +
+ +tags []string + +
+
+ +description: | + Tags is list of strings that can be used for arbitrary grouping of tests. + examples: + - name: Tags + value: ["PHP", "bug-123"] + +
+ +
+ + + + + +## Test + +Appears in: + + +- FTWTest.tests + + +```yaml +- test_title: 123456-1 + ruleid: 0 + test_id: 0 + desc: Unix RCE using `time` + stages: + - description: Get cookie from server + input: + dest_addr: 192.168.0.1 + port: 8080 + protocol: http + uri: /test + version: HTTP/1.1 + method: REPORT + headers: + Accept: '*/*' + Host: localhost + User-Agent: CRS Tests + save_cookie: false + stop_magic: true + autocomplete_headers: false + encoded_request: TXkgRGF0YQo= + output: + status: 200 + response_contains: HTTP/1.1 + log_contains: nothing + no_log_contains: everything + log: + expect_ids: + - 123456 + no_expect_ids: + - 123456 + match_regex: id[:\s"]*123456 + no_match_regex: id[:\s"]*123456 + expect_error: true +``` + + + +
+ +
+ +test_title string + +
+
+ +TestTitle is the title of this particular types. It is used for inclusion/exclusion of each run by the tool. + + + +Examples: + + +```yaml +test_title: 123456-1 +``` + + +
+ +
+ +
+ +test_id uint + +
+
+ +TestId is the ID of the test, in relation to `rule_id`. + +When this field is not set, the ID will be inferred from the +position. + + + +Examples: + + +```yaml +# TestId +test_id: 4 +``` + + +
+ +
+ +
+ +desc string + +
+
+ +TestDescription is the description for this particular test. + +Should be used to describe the internals of the specific things this test is targeting. + + + +Examples: + + +```yaml +desc: Unix RCE using `time` +``` + + +
+ +
+ +
+ +stages []Stage + +
+
+ +Stages is the list of all the stages to perform this test. + + + +Examples: + + +```yaml +stages: + - description: Get cookie from server + input: + dest_addr: 192.168.0.1 + port: 8080 + protocol: http + uri: /test + version: HTTP/1.1 + method: REPORT + headers: + Accept: '*/*' + Host: localhost + User-Agent: CRS Tests + save_cookie: false + stop_magic: true + autocomplete_headers: false + encoded_request: TXkgRGF0YQo= + output: + status: 200 + response_contains: HTTP/1.1 + log_contains: nothing + no_log_contains: everything + log: + expect_ids: + - 123456 + no_expect_ids: + - 123456 + match_regex: id[:\s"]*123456 + no_match_regex: id[:\s"]*123456 + expect_error: true +``` + + +
+ +
+ +
+ +tags []string + +
+
+ +description: | + Tags is list of strings that can be used for arbitrary grouping of tests. + examples: + - name: Tags + value: ["PHP", "bug-123"] + +
+ +
+ + + + + +## Stage + +Appears in: + + +- Test.stages + + +```yaml +- description: Get cookie from server + input: + dest_addr: 192.168.0.1 + port: 8080 + protocol: http + uri: /test + version: HTTP/1.1 + method: REPORT + headers: + Accept: '*/*' + Host: localhost + User-Agent: CRS Tests + save_cookie: false + stop_magic: true + autocomplete_headers: false + encoded_request: TXkgRGF0YQo= + output: + status: 200 + response_contains: HTTP/1.1 + log_contains: nothing + no_log_contains: everything + log: + expect_ids: + - 123456 + no_expect_ids: + - 123456 + match_regex: id[:\s"]*123456 + no_match_regex: id[:\s"]*123456 + expect_error: true +``` + + + +
+ +
+ +description string + +
+
+ +Describes the purpose of this stage. + + + +Examples: + + +```yaml +description: Get cookie from server +``` + + +
+ +
+ +
+ +input Input + +
+
+ +Input is the data that is passed to the test + + + +Examples: + + +```yaml +# Input +input: + dest_addr: 192.168.0.1 + port: 8080 + protocol: http + uri: /test + version: HTTP/1.1 + method: REPORT + headers: + Accept: '*/*' + Host: localhost + User-Agent: CRS Tests + save_cookie: false + stop_magic: true + autocomplete_headers: false + encoded_request: TXkgRGF0YQo= +``` + + +
+ +
+ +
+ +output Output + +
+
+ +Output is the data that is returned from the test + + + +Examples: + + +```yaml +# Output +output: + status: 200 + response_contains: HTTP/1.1 + log_contains: nothing + no_log_contains: everything + log: + expect_ids: + - 123456 + no_expect_ids: + - 123456 + match_regex: id[:\s"]*123456 + no_match_regex: id[:\s"]*123456 + expect_error: true +``` + + +
+ +
+ + + + + +## Input + +Appears in: + + +- Stage.input + + +```yaml +# Input +dest_addr: 192.168.0.1 +port: 8080 +protocol: http +uri: /test +version: HTTP/1.1 +method: REPORT +headers: + Accept: '*/*' + Host: localhost + User-Agent: CRS Tests +save_cookie: false +stop_magic: true +autocomplete_headers: false +encoded_request: TXkgRGF0YQo= +``` + + + +
+ +
+ +dest_addr string + +
+
+ +DestAddr is the IP of the destination host that the test will send the message to. + + + +Examples: + + +```yaml +# DestAddr +dest_addr: 127.0.0.1 +``` + + +
+ +
+ +
+ +port int + +
+
+ +Port allows you to declare which port on the destination host the test should connect to. + + + +Examples: + + +```yaml +# Port +port: 80 +``` + + +
+ +
+ +
+ +protocol string + +
+
+ +Protocol allows you to declare which protocol the test should use when sending the request. + + + +Examples: + + +```yaml +# Protocol +protocol: http +``` + + +
+ +
+ +
+ +uri string + +
+
+ +URI allows you to declare the URI the test should use as part of the request line. + + + +Examples: + + +```yaml +# URI +uri: /get?hello=world +``` + + +
+ +
+ +
+ +follow_redirect bool + +
+
+ +FollowRedirect will expect the previous stage of the same test to have received a +redirect response, it will fail the test otherwise. The redirect location will be used +to send the request for the current stage and any settings for port, protocol, address, +or URI will be ignored. + + + +Examples: + + +```yaml +# follow_redirect +follow_redirect: true +``` + + +
+ +
+ +
+ +version string + +
+
+ +Version allows you to declare the HTTP version the test should use as part of the request line. + + + +Examples: + + +```yaml +# Version +version: "1.1" +``` + + +
+ +
+ +
+ +method string + +
+
+ +Method allows you to declare the HTTP method the test should use as part of the request line. + + + +Examples: + + +```yaml +# Method +method: GET +``` + + +
+ +
+ +
+ +headers map[string]string + +
+
+ +Headers allows you to declare headers that the test should send. + + + +Examples: + + +```yaml +# Headers +headers: + Accept: '*/*' + Host: localhost + User-Agent: CRS Tests +``` + + +
+ +
+ +
+ +data string + +
+
+ +Data allows you to declare the payload that the test should in the request body. + + + +Examples: + + +```yaml +# Data +data: Bibitti bopi +``` + + +
+ +
+ +
+ +encoded_data string + +
+
+ +EncodedData allows you to declare the payload as a base64 encoded string, which +will be decoded into bytes and sent verbatimt to the server. This allows for complex +payloads that include invisible characters or invalid Unicode byte sequences. + + + +Examples: + + +```yaml +# encoded_data +encoded_data: c29tZXRoaW5nIHdpdGgKbmV3bGluZQo= +``` + + +
+ +
+ +
+ +save_cookie bool + +
+
+ +SaveCookie allows you to automatically provide cookies if there are multiple stages and save cookie is set + + + +Examples: + + +```yaml +# SaveCookie +save_cookie: 80 +``` + + +
+ +
+ +
+ +stop_magic bool + +
+
+ +StopMagic is deprecated. + + + +Examples: + + +```yaml +# StopMagic +stop_magic: false +``` + + +
+ +
+ +
+ +autocomplete_headers bool + +
+
+ +AutocompleteHeaders allows the test framework to automatically fill the request with Content-Type and Connection headers. + +Defaults: `true`. + + + +Examples: + + +```yaml +# StopMagic +autocomplete_headers: false +``` + + +
+ +
+ +
+ +encoded_request string + +
+
+ +EncodedRequest will take a base64 encoded string that will be decoded and sent through as the request. + +It will override all other settings + + + +Examples: + + +```yaml +# EncodedRequest +encoded_request: a +``` + + +
+ +
+ +
+ +raw_request string + +
+
+ +RAWRequest is deprecated. + + + +Examples: + + +```yaml +# RAWRequest +raw_request: TXkgRGF0YQo= +``` + + +
+ +
+ +
+ +response Response + +
+
+ +Response describes a response from the web server that a WAF is expected to analyse. + +Note: This functionality requires a backend that can send the specified request to the + reverse proxy. Currently, only Albedo (https://github.com/coreruleset/albedo) is supported. + +
+ +
+ +
+ +virtual_host_mode bool + +
+
+ +VirtualHostMode determines the value of the `Host` header for internal requests (e.g., the +requests used to insert markers into the web server log). This is useful for running tests +against a virtual host, as the log entries for all requests must end up in the same log file, +and often, log files are segregated by virtual host. + +If `true`, internal requests will use the same value for the `Host` header as the test request. + +If `false`, the value for the `Host` header of internal requests will be `localhost`. + +Default: `false`. + +
+ +
+ + + + + +## Response + +Appears in: + + +- Input.response + + + + + +
+ +
+ +headers map[string]string + +
+
+ +Headers defines the headers the response will carry. + + + +Examples: + + +```yaml +# Headers +headers: + Accept: '*/*' + Host: localhost + User-Agent: CRS Tests +``` + + +
+ +
+ +
+ +status int + +
+
+ +Status describes the HTTP status code of the response. + +Default: `200` if omitted. + + + +Examples: + + +```yaml +# Status +status: 302 +``` + + +
+ +
+ +
+ +body string + +
+
+ +Body defines the body of the response as a plain string. + + + +Examples: + + +```yaml +# Body +body: | + {"aJsonDocument": ["in the response"]} +``` + + +
+ +
+ +
+ +encoded_body string + +
+
+ +EncodedBody defines the body of the response as a base64 encoded string. This is useful if the response +needs to contain non-printable characters. + + + +Examples: + + +```yaml +# EncodedBody +encoded_body: eyJhSnNvbkRvY3VtZW50IjogWyJpbiB0aGUgcmVzcG9uc2UiXX0= +``` + + +
+ +
+ +
+ +log_message string + +
+
+ +LogMessage specifies a message to be printed in the log of the backend server that sends the response. +This can be helpful when debugging, to match resopnses sent by the backend to test executions. + + + +Examples: + + +```yaml +# LogMessage +log_message: Response splitting test 1 +``` + + +
+ +
+ + + + + +## Output + +Appears in: + + +- Stage.output + + +```yaml +# Output +status: 200 +response_contains: HTTP/1.1 +log_contains: nothing +no_log_contains: everything +log: + expect_ids: + - 123456 + no_expect_ids: + - 123456 + match_regex: id[:\s"]*123456 + no_match_regex: id[:\s"]*123456 +expect_error: true +``` + + + +
+ +
+ +status int + +
+
+ +Status describes the HTTP status code expected in the response. + + + +Examples: + + +```yaml +# Status +status: 200 +``` + + +
+ +
+ +
+ +response_contains string + +
+
+ +ResponseContains describes the text that should be contained in the HTTP response. + + + +Examples: + + +```yaml +# ResponseContains +response_contains: Hello, World +``` + + +
+ +
+ +
+ +log_contains string + +
+
+ +LogContains describes the text that should be contained in the WAF logs. + + + +Examples: + + +```yaml +# LogContains +log_contains: id 920100 +``` + + +
+ +
+ +
+ +no_log_contains string + +
+
+ +NoLogContains describes the text that should not be contained in the WAF logs. + + + +Examples: + + +```yaml +# NoLogContains +no_log_contains: id 920100 +``` + + +
+ +
+ +
+ +log Log + +
+
+ +Log is used to configure expectations about the log contents. + + + +Examples: + + +```yaml +log: + expect_ids: + - 123456 + no_expect_ids: + - 123456 + match_regex: id[:\s"]*123456 + no_match_regex: id[:\s"]*123456 +``` + + +
+ +
+ +
+ +expect_error bool + +
+
+ +When `ExpectError` is true, we don't expect an answer from the WAF, just an error. + + + +Examples: + + +```yaml +# ExpectError +expect_error: false +``` + + +
+ +
+ +
+ +retry_once bool + +
+
+ +When `RetryOnce` is true, the test run will be retried once upon failures. This options +primary purpose is to work around a race condition in phase 5, where the log entry for +a phase 5 rule may appear after the end marker of the previous test. + +
+ +
+ +
+ +isolated bool + +
+
+ +Isolated specifies that the test is expected to trigger a single rule only. +If the rule triggers any other rule than the (single) one specified in +expect_ids, the test fill be considered a failure. + +Default: `false` + + + +Examples: + + +```yaml +# Isolated +isolated: true +``` + + +
+ +
+ + + + + +## Log + +Appears in: + + +- Output.log + + +```yaml +expect_ids: + - 123456 +no_expect_ids: + - 123456 +match_regex: id[:\s"]*123456 +no_match_regex: id[:\s"]*123456 +``` + + + +
+ +
+ +expect_ids []uint + +
+
+ +description: | + Expect the given IDs to be contained in the log output. + examples: + -value: ExampleLog.ExpectIds + +
+ +
+ +
+ +no_expect_ids []uint + +
+
+ +Expect the given IDs _not_ to be contained in the log output. + + + +Examples: + + +```yaml +no_expect_ids: + - 123456 +``` + + +
+ +
+ +
+ +match_regex string + +
+
+ +Expect the regular expression to match log content for the current types. + + + +Examples: + + +```yaml +match_regex: id[:\s"]*123456 +``` + + +
+ +
+ +
+ +no_match_regex string + +
+
+ +Expect the regular expression to _not_ match log content for the current types. + + + +Examples: + + +```yaml +no_match_regex: id[:\s"]*123456 +``` + + +
+ +
+ + + + + + + + +## FTWOverrides +FTWOverrides describes platform specific overrides for tests + + + + + + +
+ +
+ +version string + +
+
+ +The version field designates the version of the schema that validates this file + + + +Examples: + + +```yaml +version: v0.1.0 +``` + + +
+ +
+ +
+ +meta FTWOverridesMeta + +
+
+ +Meta describes the metadata information + + + +Examples: + + +```yaml +meta: + engine: libmodsecurity3 + platform: nginx + annotations: + os: Debian Bullseye + purpose: L7ASR test suite +``` + + +
+ +
+ +
+ +test_overrides []TestOverride + +
+
+ +List of test override specifications + + + +Examples: + + +```yaml +test_overrides: + - rule_id: 920100 + test_ids: [4, 6] + reason: |- + nginx returns 400 when `Content-Length` header is sent in a + `Transfer-Encoding: chunked` request. + output: + status: 200 + response_contains: HTTP/1.1 + log_contains: nothing + no_log_contains: everything + log: + expect_ids: + - 123456 + no_expect_ids: + - 123456 + match_regex: id[:\s"]*123456 + no_match_regex: id[:\s"]*123456 + expect_error: true +``` + + +
+ +
+ + + + + +## FTWOverridesMeta + +Appears in: + + +- FTWOverrides.meta + + +```yaml +engine: libmodsecurity3 +platform: nginx +annotations: + os: Debian Bullseye + purpose: L7ASR test suite +``` + + + +
+ +
+ +engine string + +
+
+ +The name of the WAF engine the tests are expected to run against + + + +Examples: + + +```yaml +engine: coraza +``` + + +
+ +
+ +
+ +platform string + +
+
+ +The name of the platform (e.g., web server) the tests are expected to run against + + + +Examples: + + +```yaml +platform: nginx +``` + + +
+ +
+ +
+ +annotations map[string]string + +
+
+ +Custom annotations; can be used to add additional meta information + + + +Examples: + + +```yaml +annotations: + os: Debian Bullseye + purpose: L7ASR test suite +``` + + +
+ +
+ + + + + +## TestOverride + +Appears in: + + +- FTWOverrides.test_overrides + + +```yaml +- rule_id: 920100 + test_ids: [4, 6] + reason: |- + nginx returns 400 when `Content-Length` header is sent in a + `Transfer-Encoding: chunked` request. + output: + status: 200 + response_contains: HTTP/1.1 + log_contains: nothing + no_log_contains: everything + log: + expect_ids: + - 123456 + no_expect_ids: + - 123456 + match_regex: id[:\s"]*123456 + no_match_regex: id[:\s"]*123456 + expect_error: true +``` + + + +
+ +
+ +rule_id uint + +
+
+ +ID of the rule this test targets. + + + +Examples: + + +```yaml +rule_id: 920100 +``` + + +
+ +
+ +
+ +test_ids []uint + +
+
+ +IDs of the tests for rule_id that overrides should be applied to. +If this field is not set, the overrides will be applied to all tests of rule_id. + + + +Examples: + + +```yaml +test_ids: + - 4 + - 6 +``` + + +
+ +
+ +
+ +stage_ids []uint + +
+
+ +IDs of the stages to which overrides should be applied. +Stage IDs listed will be overridden for all test IDs listed in `TestIds`. +If this field is not set, the overrides will be applied to all stages. + +
+ +
+ +
+ +reason string + +
+
+ +Describes why this override is necessary. + + + +Examples: + + +```yaml +reason: |- + nginx returns 400 when `Content-Length` header is sent in a + `Transfer-Encoding: chunked` request. +``` + + +
+ +
+ +
+ +retry_once bool + +
+
+ +Whether a stage should be retried once in case of failure. +This option is primarily a workaround for a race condition in phase 5, +where the log entry of a rule may be flushed after the test end marker. + + + +Examples: + + +```yaml +retry_once: true +``` + + +
+ +
+ +
+ +output types.Output + +
+
+ +Specifies overrides on the test output. +This definition *replaces* the output definition of the test. + + + +Examples: + + +```yaml +output: + status: 200 + response_contains: HTTP/1.1 + log_contains: nothing + no_log_contains: everything + log: + expect_ids: + - 123456 + no_expect_ids: + - 123456 + match_regex: id[:\s"]*123456 + no_match_regex: id[:\s"]*123456 + expect_error: true +``` + + +
+ +
+ + + + + +## types.Output +Output defines the expectations of a test + +Appears in: + + +- TestOverride.output + + +```yaml +status: 200 +response_contains: HTTP/1.1 +log_contains: nothing +no_log_contains: everything +log: + expect_ids: + - 123456 + no_expect_ids: + - 123456 + match_regex: id[:\s"]*123456 + no_match_regex: id[:\s"]*123456 +expect_error: true +``` + + + +
+ +
+ +status int + +
+
+ +Status describes the HTTP status code expected in the response. + + + +Examples: + + +```yaml +# Status +status: 200 +``` + + +
+ +
+ +
+ +response_contains string + +
+
+ +ResponseContains describes the text that should be contained in the HTTP response. + + + +Examples: + + +```yaml +# ResponseContains +response_contains: Hello, World +``` + + +
+ +
+ +
+ +log_contains string + +
+
+ +LogContains describes the text that should be contained in the WAF logs. + + + +Examples: + + +```yaml +# LogContains +log_contains: id 920100 +``` + + +
+ +
+ +
+ +no_log_contains string + +
+
+ +NoLogContains describes the text that should not be contained in the WAF logs. + + + +Examples: + + +```yaml +# NoLogContains +no_log_contains: id 920100 +``` + + +
+ +
+ +
+ +log Log + +
+
+ +Log is used to configure expectations about the log contents. + + + +Examples: + + +```yaml +log: + expect_ids: + - 123456 + no_expect_ids: + - 123456 + match_regex: id[:\s"]*123456 + no_match_regex: id[:\s"]*123456 +``` + + +
+ +
+ +
+ +expect_error types.bool + +
+
+ +When `ExpectError` is true, we don't expect an answer from the WAF, just an error. + + + +Examples: + + +```yaml +# ExpectError +expect_error: false +``` + + +
+ +
+ +
+ +retry_once types.bool + +
+
+ +When `RetryOnce` is true, the test run will be retried once upon failures. This options +primary purpose is to work around a race condition in phase 5, where the log entry for +a phase 5 rule may appear after the end marker of the previous test. + +
+ +
+ +
+ +isolated bool + +
+
+ +Isolated specifies that the test is expected to trigger a single rule only. +If the rule triggers any other rule than the (single) one specified in +expect_ids, the test fill be considered a failure. + +Default: `false` + + + +Examples: + + +```yaml +# Isolated +isolated: true +``` + + +
+ +
+ + + + + +## types.Log + + + + + + +
+ +
+ +expect_ids []uint + +
+
+ +description: | + Expect the given IDs to be contained in the log output. + examples: + -value: ExampleLog.ExpectIds + +
+ +
+ +
+ +no_expect_ids []uint + +
+
+ +Expect the given IDs _not_ to be contained in the log output. + + + +Examples: + + +```yaml +no_expect_ids: + - 123456 +``` + + +
+ +
+ +
+ +match_regex string + +
+
+ +Expect the regular expression to match log content for the current types. + + + +Examples: + + +```yaml +match_regex: id[:\s"]*123456 +``` + + +
+ +
+ +
+ +no_match_regex string + +
+
+ +Expect the regular expression to _not_ match log content for the current types. + + + +Examples: + + +```yaml +no_match_regex: id[:\s"]*123456 +``` + + +
+ +
+ + + + diff --git a/spec/v2.1.1/waf-platform-overrides-schema-v2.1.1.json b/spec/v2.1.1/waf-platform-overrides-schema-v2.1.1.json new file mode 100755 index 0000000..138a705 --- /dev/null +++ b/spec/v2.1.1/waf-platform-overrides-schema-v2.1.1.json @@ -0,0 +1 @@ +{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://github.com/coreruleset/ftw-tests-schema/v2/types/overrides/ftw-overrides","$ref":"#/$defs/FTWOverrides","$defs":{"FTWOverrides":{"properties":{"version":{"type":"string"},"meta":{"$ref":"#/$defs/FTWOverridesMeta"},"test_overrides":{"items":{"$ref":"#/$defs/TestOverride"},"type":"array"}},"additionalProperties":false,"type":"object","required":["version","meta","test_overrides"]},"FTWOverridesMeta":{"properties":{"engine":{"type":"string"},"platform":{"type":"string"},"annotations":{"additionalProperties":{"type":"string"},"type":"array"}},"additionalProperties":false,"type":"object","required":["engine","platform","annotations"]},"Log":{"properties":{"expect_ids":{"items":{"type":"integer"},"type":"array"},"no_expect_ids":{"items":{"type":"integer"},"type":"array"},"match_regex":{"type":"string"},"no_match_regex":{"type":"string"}},"additionalProperties":false,"type":"object"},"Output":{"properties":{"status":{"type":"integer"},"response_contains":{"type":"string"},"log_contains":{"type":"string"},"no_log_contains":{"type":"string"},"log":{"$ref":"#/$defs/Log"},"expect_error":{"type":"boolean"},"retry_once":{"type":"boolean"},"isolated":{"type":"boolean"}},"additionalProperties":false,"type":"object"},"TestOverride":{"properties":{"rule_id":{"type":"integer"},"test_ids":{"items":{"type":"integer"},"type":"array"},"stage_ids":{"items":{"type":"integer"},"type":"array"},"reason":{"type":"string"},"retry_once":{"type":"boolean"},"output":{"$ref":"#/$defs/Output"}},"additionalProperties":false,"type":"object","required":["rule_id","reason","output"]}}} \ No newline at end of file diff --git a/spec/v2.1.1/waf-tests-schema-v2.1.1.json b/spec/v2.1.1/waf-tests-schema-v2.1.1.json new file mode 100755 index 0000000..d692d6b --- /dev/null +++ b/spec/v2.1.1/waf-tests-schema-v2.1.1.json @@ -0,0 +1 @@ +{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://github.com/coreruleset/ftw-tests-schema/v2/types/ftw-test","$ref":"#/$defs/FTWTest","$defs":{"FTWTest":{"properties":{"meta":{"$ref":"#/$defs/FTWTestMeta"},"rule_id":{"type":"integer"},"tests":{"items":{"$ref":"#/$defs/Test"},"type":"array"}},"additionalProperties":false,"type":"object","required":["meta","rule_id","tests"]},"FTWTestMeta":{"properties":{"author":{"type":"string"},"enabled":{"type":"boolean"},"name":{"type":"string"},"description":{"type":"string"},"version":{"type":"string"},"tags":{"items":{"type":"string"},"type":"array"}},"additionalProperties":false,"type":"object"},"Input":{"properties":{"dest_addr":{"type":"string"},"port":{"type":"integer"},"protocol":{"type":"string"},"uri":{"type":"string"},"follow_redirect":{"type":"boolean"},"version":{"type":"string"},"method":{"type":"string"},"headers":{"additionalProperties":{"type":"string"},"type":"object"},"data":{"type":"string"},"encoded_data":{"type":"string"},"save_cookie":{"type":"boolean"},"stop_magic":{"type":"boolean"},"autocomplete_headers":{"type":"boolean"},"encoded_request":{"type":"string"},"raw_request":{"type":"string"},"response":{"$ref":"#/$defs/Response"},"virtual_host_mode":{"type":"boolean"}},"additionalProperties":false,"type":"object"},"Log":{"properties":{"expect_ids":{"items":{"type":"integer"},"type":"array"},"no_expect_ids":{"items":{"type":"integer"},"type":"array"},"match_regex":{"type":"string"},"no_match_regex":{"type":"string"}},"additionalProperties":false,"type":"object"},"Output":{"properties":{"status":{"type":"integer"},"response_contains":{"type":"string"},"log_contains":{"type":"string"},"no_log_contains":{"type":"string"},"log":{"$ref":"#/$defs/Log"},"expect_error":{"type":"boolean"},"retry_once":{"type":"boolean"},"isolated":{"type":"boolean"}},"additionalProperties":false,"type":"object"},"Response":{"properties":{"headers":{"additionalProperties":{"type":"string"},"type":"object"},"status":{"type":"integer"},"body":{"type":"string"},"encoded_body":{"type":"string"},"log_message":{"type":"string"}},"additionalProperties":false,"type":"object"},"Stage":{"properties":{"description":{"type":"string"},"input":{"$ref":"#/$defs/Input"},"output":{"$ref":"#/$defs/Output"}},"additionalProperties":false,"type":"object","required":["input","output"]},"Test":{"properties":{"test_title":{"type":"string"},"test_id":{"type":"integer"},"desc":{"type":"string"},"stages":{"items":{"$ref":"#/$defs/Stage"},"type":"array"},"tags":{"items":{"type":"string"},"type":"array"}},"additionalProperties":false,"type":"object","required":["test_id","stages"]}}} \ No newline at end of file diff --git a/types/types.go b/types/types.go index 81f22c0..c6fef4c 100644 --- a/types/types.go +++ b/types/types.go @@ -91,6 +91,7 @@ type Test struct { // description: | // RuleId is the ID of the rule this test targets. + // // This field is for internal use and not exposed via YAML. // examples: // - name: RuleId @@ -99,6 +100,7 @@ type Test struct { // description: | // TestId is the ID of the test, in relation to `rule_id`. + // // When this field is not set, the ID will be inferred from the // position. // examples: @@ -108,6 +110,7 @@ type Test struct { // description: | // TestDescription is the description for this particular test. + // // Should be used to describe the internals of the specific things this test is targeting. // examples: // - value: ExampleTest.TestDescription @@ -271,7 +274,8 @@ type Input struct { // description: | // AutocompleteHeaders allows the test framework to automatically fill the request with Content-Type and Connection headers. - // Defaults to true. + // + // Defaults: `true`. // examples: // - name: StopMagic // value: false @@ -279,6 +283,7 @@ type Input struct { // description: | // EncodedRequest will take a base64 encoded string that will be decoded and sent through as the request. + // // It will override all other settings // examples: // - name: EncodedRequest @@ -296,12 +301,29 @@ type Input struct { // description: | // Response describes a response from the web server that a WAF is expected to analyse. + // // Note: This functionality requires a backend that can send the specified request to the // reverse proxy. Currently, only Albedo (https://github.com/coreruleset/albedo) is supported. // example: - // - name Response + // - name: Response // value: ExampleResponse Response Response `yaml:"response,omitempty" json:"response,omitempty" koanf:"response,omitempty"` + + // description: | + // VirtualHostMode determines the value of the `Host` header for internal requests (e.g., the + // requests used to insert markers into the web server log). This is useful for running tests + // against a virtual host, as the log entries for all requests must end up in the same log file, + // and often, log files are segregated by virtual host. + // + // If `true`, internal requests will use the same value for the `Host` header as the test request. + // + // If `false`, the value for the `Host` header of internal requests will be `localhost`. + // + // Default: `false`. + // example: + // - name: VirtualHostMode + // value: true + VirtualHostMode bool `yaml:"virtual_host_mode,omitempty" json:"virtual_host_mode,omitempty" koanf:"virtual_host_mode,omitempty"` } type Response struct { @@ -313,7 +335,9 @@ type Response struct { Headers map[string]string `yaml:"headers,omitempty" json:"headers,omitempty" koanf:"headers,omitempty"` // description: | - // Status describes the HTTP status code of the response. Defaults to `200` if omitted. + // Status describes the HTTP status code of the response. + // + // Default: `200` if omitted. // examples: // - name: Status // value: 302 @@ -400,7 +424,8 @@ type Output struct { // Isolated specifies that the test is expected to trigger a single rule only. // If the rule triggers any other rule than the (single) one specified in // expect_ids, the test fill be considered a failure. - // Default: false + // + // Default: `false` // examples: // - name: Isolated // value: true