Add remove whitelist action to WAF logs
This commit is contained in:
@@ -295,6 +295,46 @@ class Waf extends Page implements HasForms, HasTable
|
||||
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
|
||||
{
|
||||
if ($ip === '' || $rule === '') {
|
||||
@@ -376,6 +416,50 @@ class Waf extends Page implements HasForms, HasTable
|
||||
->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
|
||||
{
|
||||
return $table
|
||||
@@ -435,6 +519,13 @@ class Waf extends Page implements HasForms, HasTable
|
||||
->color('primary')
|
||||
->visible(fn (array $record): bool => empty($record['whitelisted']))
|
||||
->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'))
|
||||
->emptyStateDescription(__('No ModSecurity denials found in the audit log.'))
|
||||
|
||||
Reference in New Issue
Block a user