Skip to main content

working-with-filters

Use when creating, editing, debugging, or deploying UTMStack event-processor filters (the YAML pipelines under filters/ that normalize vendor logs into the go-sdk Event/Side schema), or when a filter field is missing, a rule cannot match a value, actionResult is wrong, or a dropped op needs to be kept. Typical prompts are edit the o365 filter, add a rename or cast step, why is event.Parameters not matching, deploy the filter, or the filter reverted after a restart. Not for correlation rules, use working-with-rules for those.

소스 정보

저장소
utmstack/UTMStack
최근 소스 활동
2026년 10월 7일 15:33
감지된 SKILL.md 언어
영어
스타
592
포크
83

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
4 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
working-with-filters
description
Use when creating, editing, debugging, or deploying UTMStack event-processor filters (the YAML pipelines under filters/ that normalize vendor logs into the go-sdk Event/Side schema), or when a filter field is missing, a rule cannot match a value, actionResult is wrong, or a dropped op needs to be kept. Typical prompts are edit the o365 filter, add a rename or cast step, why is event.Parameters not matching, deploy the filter, or the filter reverted after a restart. Not for correlation rules, use working-with-rules for those.
# Working with UTMStack Filters Filters are YAML in `filters/<vendor>/<name>.yml` — a `pipeline` of ordered `steps` that turn a vendor's raw log into the canonical `Event` + `Side` (origin/target) shape. Rules then match the **normalized** field, never the raw one. **The single most important mental model:** a filter field only exists if (1) it is a valid go-sdk proto path AND (2) a preceding step actually populates it. Unknown top-level paths are **silently dropped** at proto conversion — no error, the field just never appears. ## Core workflow (always this order) 1. **Read the raw shape first.** Before writing a step, query the live index to see the exact fields a real event carries and their JSON types (string vs array vs int). See `references/deploy-and-durability.md` for the no-JWT query snippet. Guessing field names is how filters go dead. 2. **Edit** `filters/<vendor>/<name>.yml`. 3. **Validate with PyYAML, never the LSP.** The LSP throws false `All sequence items must start at the same column` / `Implicit map key` errors on these files. The source of truth: `python -c "import yaml; d=yaml.safe_load(open('filters/office365/o365.yml',encoding='utf-8')); print(len(d['pipeline'][0]['steps']))"` (use the utmstack venv python, set `PYTHONIOENCODING=utf-8`). 4. **Deploy to all three layers** or it reverts on restart. See `references/deploy-and-durability.md`. 5. **Verify the engine** actually reloaded it (`/workdir/pipeline/filters/<id>.yaml`), not just the DB. ## Critical gotchas (the ones that cause dead detections) - **CEL is scalar-only.** `contains()` / `startsWith` / `endsWith` require the gjson value to be a *String*; `equals`/`oneOf` compare scalars. Array/object fields (`event.Parameters`, `event.Members`, `Target`) return **false**. If a rule must `contains` one of them, add a `cast: {fields:[...], to: string}` step — but `cast` on an array stringifies it, so `contains` then works. Confirm in `go-sdk .../plugins/cel_overloads.go`. - **`action` is a RENAME, not a raw field.** In O365, `event.Operation → action`. A `drop`/`rename` keys on `action` only work *after* that rename; key on `event.Operation` if you move them before it. Renames are lossy — the source is deleted. - **`actionResult` is ADDED by the filter**, derived from `event.ResultStatus`. Order of `add` steps matters (later `add` wins for a matching event), and some vendors lie (AAD reports `ResultStatus: Success` on a *failed* login → force-override to `failed`). - **`drop` is a performance lever.** Put the `drop` step as early as possible (right after `json`) keyed on the raw op field, so dropped events skip all renames/`add`s and the geolocation `dynamic` plugin call. Reorder is safe iff the match set is identical. - **Schema is proto-gated.** `Side` has `host`, not `hostname`; `Event` has no `system.*`. Writing `origin.hostname` silently produces nothing. ## Read these when you need them - `references/cel-semantics.md` — every CEL function + its exact type requirement (from go-sdk). - `references/deploy-and-durability.md` — the 3-layer deploy, container re-lookup, restart-revert trap, filter-ID renumbering, no-JWT queries. - `references/known-mistakes.md` — error classes from past campaigns + the `docs/rvald26-draft-prs-review.md` findings, so you don't repeat them. **Cross-reference:** the rule that consumes a field is the one to check when a filter change lands — see the `working-with-rules` skill.
GitHub에서 보기