Add filter write/create/delete and jail-filter assign endpoints (Task 2.2)
- PUT /api/config/filters/{name}: updates failregex/ignoreregex/datepattern/
journalmatch in filter.d/{name}.local; validates regex via re.compile();
supports ?reload=true
- POST /api/config/filters: creates filter.d/{name}.local from FilterCreateRequest;
returns 409 if file already exists
- DELETE /api/config/filters/{name}: deletes .local only; returns 409 for
conf-only (readonly) filters
- POST /api/config/jails/{name}/filter: assigns filter to jail by writing
'filter = {name}' to jail.d/{jail}.local; supports ?reload=true
- New models: FilterUpdateRequest, FilterCreateRequest, AssignFilterRequest
- New service helpers: _safe_filter_name, _validate_regex_patterns,
_write_filter_local_sync, _set_jail_local_key_sync
- Fixed .local-only filter discovery in _parse_filters_sync (5-tuple return)
- Fixed get_filter extension stripping (.local is 6 chars not 5)
- Renamed file_config.py raw-write routes to /raw suffix
(PUT /filters/{name}/raw, POST /filters/raw) to avoid routing conflicts
- Full service + router tests; all 930 tests pass
This commit is contained in:
@@ -370,6 +370,79 @@ class FilterConfigUpdate(BaseModel):
|
||||
journalmatch: str | None = Field(default=None)
|
||||
|
||||
|
||||
class FilterUpdateRequest(BaseModel):
|
||||
"""Payload for ``PUT /api/config/filters/{name}``.
|
||||
|
||||
Accepts only the user-editable ``[Definition]`` fields. Fields left as
|
||||
``None`` are not changed; the existing value from the merged conf/local is
|
||||
preserved.
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(strict=True)
|
||||
|
||||
failregex: list[str] | None = Field(
|
||||
default=None,
|
||||
description="Updated failure-detection regex patterns. ``None`` = keep existing.",
|
||||
)
|
||||
ignoreregex: list[str] | None = Field(
|
||||
default=None,
|
||||
description="Updated bypass-ban regex patterns. ``None`` = keep existing.",
|
||||
)
|
||||
datepattern: str | None = Field(
|
||||
default=None,
|
||||
description="Custom date-parsing pattern. ``None`` = keep existing.",
|
||||
)
|
||||
journalmatch: str | None = Field(
|
||||
default=None,
|
||||
description="Systemd journal match expression. ``None`` = keep existing.",
|
||||
)
|
||||
|
||||
|
||||
class FilterCreateRequest(BaseModel):
|
||||
"""Payload for ``POST /api/config/filters``.
|
||||
|
||||
Creates a new user-defined filter at ``filter.d/{name}.local``.
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(strict=True)
|
||||
|
||||
name: str = Field(
|
||||
...,
|
||||
description="Filter base name (e.g. ``my-custom-filter``). Must not already exist in ``filter.d/``.",
|
||||
)
|
||||
failregex: list[str] = Field(
|
||||
default_factory=list,
|
||||
description="Failure-detection regex patterns.",
|
||||
)
|
||||
ignoreregex: list[str] = Field(
|
||||
default_factory=list,
|
||||
description="Regex patterns that bypass ban logic.",
|
||||
)
|
||||
prefregex: str | None = Field(
|
||||
default=None,
|
||||
description="Prefix regex prepended to every failregex.",
|
||||
)
|
||||
datepattern: str | None = Field(
|
||||
default=None,
|
||||
description="Custom date-parsing pattern.",
|
||||
)
|
||||
journalmatch: str | None = Field(
|
||||
default=None,
|
||||
description="Systemd journal match expression.",
|
||||
)
|
||||
|
||||
|
||||
class AssignFilterRequest(BaseModel):
|
||||
"""Payload for ``POST /api/config/jails/{jail_name}/filter``."""
|
||||
|
||||
model_config = ConfigDict(strict=True)
|
||||
|
||||
filter_name: str = Field(
|
||||
...,
|
||||
description="Filter base name to assign to the jail (e.g. ``sshd``).",
|
||||
)
|
||||
|
||||
|
||||
class FilterListResponse(BaseModel):
|
||||
"""Response for ``GET /api/config/filters``."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user