From 1218b57bc5a237dcaa450acdf2cb7a1fa98c85bc Mon Sep 17 00:00:00 2001 From: root Date: Sat, 31 Jan 2026 00:31:05 +0200 Subject: [PATCH] Simplify WAF whitelist rules --- app/Filament/Admin/Pages/Waf.php | 85 +++++++++++++++++++++++++------- bin/jabali-agent | 4 -- 2 files changed, 68 insertions(+), 21 deletions(-) diff --git a/app/Filament/Admin/Pages/Waf.php b/app/Filament/Admin/Pages/Waf.php index 7de7fc8..1191af0 100644 --- a/app/Filament/Admin/Pages/Waf.php +++ b/app/Filament/Admin/Pages/Waf.php @@ -125,15 +125,78 @@ class Waf extends Page implements HasForms, HasTable ->columns(2), Section::make(__('Whitelist Rules')) ->description(__('Exclude trusted traffic from specific ModSecurity rule IDs.')) + ->headerActions([ + \Filament\Actions\Action::make('addWhitelistRule') + ->label(__('Add Custom Rule')) + ->icon('heroicon-o-plus') + ->modalHeading(__('Add Whitelist Rule')) + ->form([ + TextInput::make('label') + ->label(__('Name')) + ->placeholder(__('Example: Admin API allowlist')) + ->maxLength(80), + Select::make('match_type') + ->label(__('Match Type')) + ->options([ + 'ip' => __('IP Address or CIDR'), + 'uri_exact' => __('Exact URI'), + 'uri_prefix' => __('URI Prefix'), + 'host' => __('Host Header'), + ]) + ->required(), + TextInput::make('match_value') + ->label(__('Match Value')) + ->placeholder(__('Example: 203.0.113.10 or /wp-admin/admin-ajax.php')) + ->required(), + TextInput::make('rule_ids') + ->label(__('Rule IDs')) + ->placeholder(__('Example: 942100,949110')) + ->helperText(__('Comma-separated ModSecurity rule IDs to disable for matches.')) + ->required(), + ]) + ->action(function (array $data): void { + $rules = $this->getWhitelistRules(); + + $rules[] = [ + 'label' => $data['label'] ?? null, + 'match_type' => $data['match_type'] ?? '', + 'match_value' => $data['match_value'] ?? '', + 'rule_ids' => $data['rule_ids'] ?? '', + ]; + + 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 saved, but apply failed')) + ->body($e->getMessage()) + ->warning() + ->send(); + } + + Notification::make() + ->title(__('Whitelist rule added')) + ->success() + ->send(); + }), + ]) ->schema([ Repeater::make('whitelist_rules') ->label(__('Whitelist Entries')) ->table([ - RepeaterTableColumn::make(__('Name'))->width('18%'), + RepeaterTableColumn::make(__('Name'))->width('22%'), RepeaterTableColumn::make(__('Match Type'))->width('16%'), - RepeaterTableColumn::make(__('Match Value'))->width('28%'), - RepeaterTableColumn::make(__('Rule IDs'))->width('26%'), - RepeaterTableColumn::make(__('Enabled'))->width('12%')->alignCenter(), + RepeaterTableColumn::make(__('Match Value'))->width('32%'), + RepeaterTableColumn::make(__('Rule IDs'))->width('30%'), ]) ->schema([ TextInput::make('label') @@ -158,13 +221,8 @@ class Waf extends Page implements HasForms, HasTable ->placeholder(__('Example: 942100,949110')) ->helperText(__('Comma-separated ModSecurity rule IDs to disable for matches.')) ->required(), - Toggle::make('enabled') - ->label(__('Enabled')) - ->default(true), ]) - ->itemLabel(fn (array $state): ?string => $state['label'] ?? $state['match_value'] ?? null) ->addActionLabel(__('Add Whitelist Rule')) - ->collapsible() ->columns(['default' => 2, 'md' => 2]), ]) ->columns(1), @@ -275,9 +333,6 @@ class Waf extends Page implements HasForms, HasTable if (!is_array($rule)) { continue; } - if (isset($rule['enabled']) && !$rule['enabled']) { - continue; - } $idsRaw = (string) ($rule['rule_ids'] ?? ''); $ids = preg_split('/[,\s]+/', $idsRaw, -1, PREG_SPLIT_NO_EMPTY) ?: []; @@ -311,9 +366,6 @@ class Waf extends Page implements HasForms, HasTable if (!is_array($rule)) { return false; } - if (isset($rule['enabled']) && !$rule['enabled']) { - return false; - } $ruleId = (string) ($entry['rule_id'] ?? ''); $uri = (string) ($entry['uri'] ?? ''); @@ -407,11 +459,10 @@ class Waf extends Page implements HasForms, HasTable } $rules[] = [ - 'label' => __('Whitelist rule {rule}', ['rule' => $record['rule_id'] ?? '']), + 'label' => __('Whitelist rule :rule', ['rule' => $record['rule_id'] ?? '']), 'match_type' => $matchType, 'match_value' => $matchValue, 'rule_ids' => $record['rule_id'] ?? '', - 'enabled' => true, ]; Setting::set('waf_whitelist_rules', json_encode(array_values($rules), JSON_UNESCAPED_SLASHES)); diff --git a/bin/jabali-agent b/bin/jabali-agent index c464dbd..48a48f1 100755 --- a/bin/jabali-agent +++ b/bin/jabali-agent @@ -3382,10 +3382,6 @@ function buildWafWhitelistRules(array $rules): array continue; } - if (isset($rule['enabled']) && !$rule['enabled']) { - continue; - } - $matchType = (string) ($rule['match_type'] ?? ''); $matchValue = trim((string) ($rule['match_value'] ?? '')); $idsRaw = (string) ($rule['rule_ids'] ?? '');