feat(waf): CRS-App-Exclusion-Plugins (Nextcloud/WordPress/Drupal) pro Domain — v1.3.12
Statt manueller SecRuleRemoveById-IDs kann man pro Domain offizielle OWASP-CRS- Exclusion-Plugins aktivieren — pfad-genaue, upstream-gepflegte App-Ausnahmen. - Migration 0046: waf_configs.crs_plugins text[]. - Engine (engine.go): je gewähltem Plugin werden config/before VOR den CRS-Rules und after DANACH inkludiert (exakt nach OWASP-CRS-Plugin-Spec); nur die für DIESE Domain gewählten, nur wenn die Datei existiert. Whitelist KnownCRSPlugins. - Handler: crs_plugins im Upsert-Body + Whitelist-Validierung (Include-Pfad- Injection-Schutz). - Packaging (postinst): lädt die Plugins (coreruleset/<name>-plugin) nach <crs>/plugins/ — self-healing auf jedem configure, nur fehlende. - UI: Multi-Select „App-Profile (CRS-Plugins)" im WAF-Config-Drawer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ import (
|
||||
"git.netcell-it.de/projekte/edgeguard-native/internal/models"
|
||||
"git.netcell-it.de/projekte/edgeguard-native/internal/services/audit"
|
||||
wafsvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/waf"
|
||||
intwaf "git.netcell-it.de/projekte/edgeguard-native/internal/waf"
|
||||
)
|
||||
|
||||
// wafRuleIDRe erlaubt nur einzelne CRS-Rule-IDs oder Ranges ("942100" /
|
||||
@@ -80,13 +81,14 @@ func (h *WafHandler) Get(c *gin.Context) {
|
||||
|
||||
// upsertBody is the accepted JSON for PUT /waf/configs/:domain_id.
|
||||
type upsertBody struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Mode string `json:"mode"`
|
||||
ParanoiaLevel int `json:"paranoia_level"`
|
||||
RuleExclusions []string `json:"rule_exclusions"`
|
||||
ExclusionNotes map[string]string `json:"exclusion_notes"`
|
||||
TrustedProxies []string `json:"trusted_proxies"`
|
||||
CustomRules string `json:"custom_rules"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Mode string `json:"mode"`
|
||||
ParanoiaLevel int `json:"paranoia_level"`
|
||||
RuleExclusions []string `json:"rule_exclusions"`
|
||||
CRSPlugins []string `json:"crs_plugins"`
|
||||
ExclusionNotes map[string]string `json:"exclusion_notes"`
|
||||
TrustedProxies []string `json:"trusted_proxies"`
|
||||
CustomRules string `json:"custom_rules"`
|
||||
}
|
||||
|
||||
// Upsert creates or updates the WAF config for a domain.
|
||||
@@ -110,9 +112,20 @@ func (h *WafHandler) Upsert(c *gin.Context) {
|
||||
if body.RuleExclusions == nil {
|
||||
body.RuleExclusions = []string{}
|
||||
}
|
||||
if body.CRSPlugins == nil {
|
||||
body.CRSPlugins = []string{}
|
||||
}
|
||||
if body.TrustedProxies == nil {
|
||||
body.TrustedProxies = []string{}
|
||||
}
|
||||
// CRS-Plugins müssen aus der bekannten Whitelist stammen — sie werden zu
|
||||
// Include-Pfaden, ein unbekannter Name wäre Pfad-Injection.
|
||||
for _, p := range body.CRSPlugins {
|
||||
if _, ok := intwaf.KnownCRSPlugins[strings.TrimSpace(p)]; !ok {
|
||||
response.BadRequest(c, errors.New("unbekanntes CRS-Plugin: "+p))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if body.ExclusionNotes == nil {
|
||||
body.ExclusionNotes = map[string]string{}
|
||||
@@ -144,6 +157,7 @@ func (h *WafHandler) Upsert(c *gin.Context) {
|
||||
Mode: body.Mode,
|
||||
ParanoiaLevel: body.ParanoiaLevel,
|
||||
RuleExclusions: body.RuleExclusions,
|
||||
CRSPlugins: body.CRSPlugins,
|
||||
ExclusionNotes: body.ExclusionNotes,
|
||||
TrustedProxies: body.TrustedProxies,
|
||||
CustomRules: body.CustomRules,
|
||||
|
||||
Reference in New Issue
Block a user