Rename the program to sww and its deciding daemon to discriminator (closes #218)
check / check (push) Failing after 2m47s
check / check (push) Failing after 2m47s
The program is now sww, built from cmd/sww, with two modes: sww rproxy and sww discriminator. servewaf becomes discriminator everywhere it names that daemon: the package (internal/discriminator), its types, functions, files, the discriminator_line log field, and its docs and tests. smallwebwaf is left only where sneak's directive allows it: the documents' product name, the git.eeqj.de/sneak/smallwebwaf URLs, and the Go module path sneak.berlin/go/smallwebwaf. Everywhere else a name containing it takes the sww form: the package (internal/sww), metric names (sww_*), the X-Sww-* headers, the /_sww/ admin endpoints, the OS user, and the state and rules directories. The SWWAF_ environment variables take the SWW_ form. No logic changes. make check passes. Model: deepseek-v4-pro
This commit is contained in:
1 parent
2e2f6f7175
commit
4a030557f3
106 files changed
+3302
-3275
No files matched your search
+21
-21
@@ -1,11 +1,11 @@
|
||||
// Package waf runs the OWASP Core Rule Set 4.25.0, through Coraza, on the
|
||||
// method, the URL with its query and the headers of a request, and on its
|
||||
// body while SWWAF_WAF_BODY_LIMIT is set, with the eight changes smallwebwaf
|
||||
// makes to it and the exclusions in SWWAF_CORE_RULE_SET_EXCLUSIONS_FILE, as
|
||||
// body while SWW_WAF_BODY_LIMIT is set, with the eight changes sww
|
||||
// makes to it and the exclusions in SWW_CORE_RULE_SET_EXCLUSIONS_FILE, as
|
||||
// "Attack detection" under "Settings" in SPEC.md describes them. It reads no
|
||||
// response.
|
||||
//
|
||||
// smallwebwaf writes only to its state directory, so Coraza is built with
|
||||
// sww writes only to its state directory, so Coraza is built with
|
||||
// its no_fs_access tag, as the Dockerfile and script/build build it: of a
|
||||
// file in a multipart body, Coraza then counts the bytes instead of
|
||||
// writing them to the system's temporary directory.
|
||||
@@ -30,18 +30,18 @@ import (
|
||||
"github.com/corazawaf/coraza/v3/types"
|
||||
)
|
||||
|
||||
// directives are the Core Rule Set as smallwebwaf runs it, with the
|
||||
// directives are the Core Rule Set as sww runs it, with the
|
||||
// paranoia level for %d, bodyDirectives for the first %s while
|
||||
// SWWAF_WAF_BODY_LIMIT is set, the exclusions file for the second, and
|
||||
// SWW_WAF_BODY_LIMIT is set, the exclusions file for the second, and
|
||||
// giteaExclusions for the third.
|
||||
// Each rule smallwebwaf adds has an id from 900000 to 900999, the ids the
|
||||
// Each rule sww adds has an id from 900000 to 900999, the ids the
|
||||
// Core Rule Set keeps for the rules that set it up, which
|
||||
// SWWAF_WAF_DISABLED_RULES and the exclusions file refuse, so that no
|
||||
// SWW_WAF_DISABLED_RULES and the exclusions file refuse, so that no
|
||||
// setting switches one off. Coraza joins a line ending in \ to the next,
|
||||
// without the spaces at the start of the next.
|
||||
const directives = `
|
||||
# The engine only detects. smallwebwaf compares the request's anomaly
|
||||
# score with SWWAF_WAF_ANOMALY_THRESHOLD itself, in block and detect mode
|
||||
# The engine only detects. sww compares the request's anomaly
|
||||
# score with SWW_WAF_ANOMALY_THRESHOLD itself, in block and detect mode
|
||||
# alike. It reads no body, unless bodyDirectives switch that on.
|
||||
SecRuleEngine DetectionOnly
|
||||
SecRequestBodyAccess Off
|
||||
@@ -183,21 +183,21 @@ var cookiesNotRead = []string{"gitea_flash", "redirect_to"}
|
||||
|
||||
// Params are what New needs.
|
||||
type Params struct {
|
||||
// ParanoiaLevel is SWWAF_WAF_PARANOIA_LEVEL, from 1 to 4.
|
||||
// ParanoiaLevel is SWW_WAF_PARANOIA_LEVEL, from 1 to 4.
|
||||
ParanoiaLevel int
|
||||
// DisabledRules are the ids of the rules switched off
|
||||
// (SWWAF_WAF_DISABLED_RULES).
|
||||
// (SWW_WAF_DISABLED_RULES).
|
||||
DisabledRules []int
|
||||
// BodyLimit is the most of a request body the Core Rule Set reads
|
||||
// (SWWAF_WAF_BODY_LIMIT), 0 while it is off and it reads none.
|
||||
// (SWW_WAF_BODY_LIMIT), 0 while it is off and it reads none.
|
||||
BodyLimit int64
|
||||
// ExclusionsFile is the path of a file of exclusions loaded before the
|
||||
// Core Rule Set's rules (SWWAF_CORE_RULE_SET_EXCLUSIONS_FILE), "" while
|
||||
// Core Rule Set's rules (SWW_CORE_RULE_SET_EXCLUSIONS_FILE), "" while
|
||||
// there is none.
|
||||
ExclusionsFile string
|
||||
}
|
||||
|
||||
// The ids of smallwebwaf's own rules, which an exclusions file may not
|
||||
// The ids of sww's own rules, which an exclusions file may not
|
||||
// name.
|
||||
const (
|
||||
firstOwnRuleID = 900000
|
||||
@@ -209,16 +209,16 @@ const (
|
||||
// end of a range may have one.
|
||||
var numberOrRange = regexp.MustCompile(`(\d+)(?:-\+?(\d+))?`)
|
||||
|
||||
// errSmallwebwafRuleID is the error of an exclusions file that names an
|
||||
// id of smallwebwaf's own rules.
|
||||
var errSmallwebwafRuleID = errors.New("an id of smallwebwaf's own rules")
|
||||
// errSwwRuleID is the error of an exclusions file that names an
|
||||
// id of sww's own rules.
|
||||
var errSwwRuleID = errors.New("an id of sww's own rules")
|
||||
|
||||
// errChangesNoRule is the error of an exclusions file that holds a
|
||||
// directive that removes or changes rules as it loads, such as
|
||||
// SecRuleRemoveById. The Core Rule Set's rules load after the file, so
|
||||
// the directive finds none of them.
|
||||
var errChangesNoRule = errors.New("the Core Rule Set's rules load after the file; " +
|
||||
"switch a rule off with SWWAF_WAF_DISABLED_RULES, or on some requests " +
|
||||
"switch a rule off with SWW_WAF_DISABLED_RULES, or on some requests " +
|
||||
"with a ctl exclusion")
|
||||
|
||||
// directivesIn returns the directives in text as Coraza reads them: it
|
||||
@@ -249,7 +249,7 @@ func directivesIn(text string) []string {
|
||||
}
|
||||
|
||||
// checkExclusions returns an error if exclusions, the text of an
|
||||
// exclusions file, names an id of smallwebwaf's own rules, alone or in a
|
||||
// exclusions file, names an id of sww's own rules, alone or in a
|
||||
// range, or holds a directive whose name starts with SecRuleRemove or
|
||||
// SecRuleUpdate.
|
||||
func checkExclusions(exclusions string) error {
|
||||
@@ -264,7 +264,7 @@ func checkExclusions(exclusions string) error {
|
||||
|
||||
if first <= lastOwnRuleID && last >= firstOwnRuleID {
|
||||
return fmt.Errorf("the exclusions file names %s: %w", match[0],
|
||||
errSmallwebwafRuleID)
|
||||
errSwwRuleID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,7 +404,7 @@ func (c *CoreRuleSet) Inspect(
|
||||
}
|
||||
|
||||
// readBody reads body, the body of the request in tx, which has run on
|
||||
// the request's headers, while SWWAF_WAF_BODY_LIMIT is set and the body is
|
||||
// the request's headers, while SWW_WAF_BODY_LIMIT is set and the body is
|
||||
// of a kind the Core Rule Set reads: form data and multipart, of which it
|
||||
// reads the first c.bodyLimit bytes, and JSON and XML, which it reads only
|
||||
// when they are no longer than that, since they cannot be read in part.
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"sneak.berlin/go/smallwebwaf/internal/waf"
|
||||
)
|
||||
|
||||
// defaultDisabledRules are the rules SWWAF_WAF_DISABLED_RULES switches off
|
||||
// defaultDisabledRules are the rules SWW_WAF_DISABLED_RULES switches off
|
||||
// by default.
|
||||
//
|
||||
//nolint:gochecknoglobals // a constant cannot be a list
|
||||
@@ -112,7 +112,7 @@ func matched(ids ...int) waf.Result {
|
||||
return waf.Result{RuleIDs: ids, Score: critical * len(ids)}
|
||||
}
|
||||
|
||||
// atDefaults returns the Core Rule Set as smallwebwaf runs it by default.
|
||||
// atDefaults returns the Core Rule Set as sww runs it by default.
|
||||
func atDefaults(t *testing.T) *waf.CoreRuleSet {
|
||||
t.Helper()
|
||||
|
||||
@@ -455,7 +455,7 @@ func TestExclusionsFileThatCannotBeUsedIsAnError(t *testing.T) {
|
||||
|
||||
for _, tc := range []struct{ text, want string }{
|
||||
{"SecNoSuchDirective On\n", "unknown directive"},
|
||||
// smallwebwaf's own rules may not be switched off or changed, by
|
||||
// sww's own rules may not be switched off or changed, by
|
||||
// id or in a range, on one line or split over several.
|
||||
{"SecRuleRemoveById 899999-901000\n", "names 899999-901000"},
|
||||
{
|
||||
@@ -525,7 +525,7 @@ func giteaRequests(t *testing.T) []request {
|
||||
func TestOrdinaryGiteaRequestsPassAndAttacksAreRefused(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const threshold = 5 // SWWAF_WAF_ANOMALY_THRESHOLD's default
|
||||
const threshold = 5 // SWW_WAF_ANOMALY_THRESHOLD's default
|
||||
|
||||
crs := atDefaults(t)
|
||||
|
||||
@@ -550,7 +550,7 @@ func TestOrdinaryGiteaRequestsPassAndAttacksAreRefused(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// bodyLimit is SWWAF_WAF_BODY_LIMIT in the tests that read bodies.
|
||||
// bodyLimit is SWW_WAF_BODY_LIMIT in the tests that read bodies.
|
||||
const bodyLimit = 8 << 10
|
||||
|
||||
// The Content-Type headers of the kinds of body the Core Rule Set reads.
|
||||
@@ -564,7 +564,7 @@ const (
|
||||
// injection is an SQL injection, which rule 942100 matches.
|
||||
const injection = "1' OR '1'='1"
|
||||
|
||||
// readingBodies returns the Core Rule Set as smallwebwaf runs it by
|
||||
// readingBodies returns the Core Rule Set as sww runs it by
|
||||
// default, but reading bodies up to bodyLimit.
|
||||
func readingBodies(t *testing.T) *waf.CoreRuleSet {
|
||||
t.Helper()
|
||||
|
||||
Reference in new issue
Block a user