Add remove whitelist action to WAF logs

This commit is contained in:
root
2026-01-30 22:12:43 +02:00
parent 7a09449d60
commit 3ea4378bd3

View File

@@ -295,6 +295,46 @@ class Waf extends Page implements HasForms, HasTable
return false; return false;
} }
protected function ruleMatchesEntry(array $rule, array $entry): bool
{
if (!is_array($rule)) {
return false;
}
if (isset($rule['enabled']) && !$rule['enabled']) {
return false;
}
$ruleId = (string) ($entry['rule_id'] ?? '');
$uri = (string) ($entry['uri'] ?? '');
$host = (string) ($entry['host'] ?? '');
$ip = (string) ($entry['remote_ip'] ?? '');
$idsRaw = (string) ($rule['rule_ids'] ?? '');
$ids = preg_split('/[,\s]+/', $idsRaw, -1, PREG_SPLIT_NO_EMPTY) ?: [];
$ids = array_map('trim', $ids);
if ($ruleId !== '' && !empty($ids) && !in_array($ruleId, $ids, true)) {
return false;
}
$matchType = (string) ($rule['match_type'] ?? '');
$matchValue = (string) ($rule['match_value'] ?? '');
if ($matchType === 'ip' && $matchValue !== '' && $this->ipMatches($ip, $matchValue)) {
return true;
}
if ($matchType === 'uri_exact' && $matchValue !== '' && $uri === $matchValue) {
return true;
}
if ($matchType === 'uri_prefix' && $matchValue !== '' && str_starts_with($uri, $matchValue)) {
return true;
}
if ($matchType === 'host' && $matchValue !== '' && $host === $matchValue) {
return true;
}
return false;
}
protected function ipMatches(string $ip, string $rule): bool protected function ipMatches(string $ip, string $rule): bool
{ {
if ($ip === '' || $rule === '') { if ($ip === '' || $rule === '') {
@@ -376,6 +416,50 @@ class Waf extends Page implements HasForms, HasTable
->send(); ->send();
} }
public function removeWhitelistEntry(array $record): void
{
$rules = $this->getWhitelistRules();
$beforeCount = count($rules);
$rules = array_values(array_filter($rules, function (array $rule) use ($record): bool {
return ! $this->ruleMatchesEntry($rule, $record);
}));
if (count($rules) === $beforeCount) {
Notification::make()
->title(__('No matching whitelist rule found'))
->warning()
->send();
return;
}
Setting::set('waf_whitelist_rules', json_encode(array_values($rules), JSON_UNESCAPED_SLASHES));
$this->wafFormData['whitelist_rules'] = $rules;
try {
$agent = new AgentClient;
$agent->wafApplySettings(
Setting::get('waf_enabled', '0') === '1',
(string) Setting::get('waf_paranoia', '1'),
Setting::get('waf_audit_log', '1') === '1',
$rules
);
} catch (Exception $e) {
Notification::make()
->title(__('Whitelist updated, but apply failed'))
->body($e->getMessage())
->warning()
->send();
}
$this->auditEntries = $this->markWhitelisted($this->auditEntries);
Notification::make()
->title(__('Whitelist removed'))
->success()
->send();
}
public function table(Table $table): Table public function table(Table $table): Table
{ {
return $table return $table
@@ -435,6 +519,13 @@ class Waf extends Page implements HasForms, HasTable
->color('primary') ->color('primary')
->visible(fn (array $record): bool => empty($record['whitelisted'])) ->visible(fn (array $record): bool => empty($record['whitelisted']))
->action(fn (array $record) => $this->whitelistEntry($record)), ->action(fn (array $record) => $this->whitelistEntry($record)),
\Filament\Actions\Action::make('removeWhitelist')
->label(__('Remove whitelist'))
->icon('heroicon-o-x-mark')
->color('danger')
->visible(fn (array $record): bool => !empty($record['whitelisted']))
->requiresConfirmation()
->action(fn (array $record) => $this->removeWhitelistEntry($record)),
]) ])
->emptyStateHeading(__('No blocked rules found')) ->emptyStateHeading(__('No blocked rules found'))
->emptyStateDescription(__('No ModSecurity denials found in the audit log.')) ->emptyStateDescription(__('No ModSecurity denials found in the audit log.'))