pysigma-backend-parseable 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pysigma_backend_parseable-0.1.0/.github/workflows/ci.yml +108 -0
- pysigma_backend_parseable-0.1.0/.gitignore +10 -0
- pysigma_backend_parseable-0.1.0/CHANGELOG.md +29 -0
- pysigma_backend_parseable-0.1.0/LICENSE +21 -0
- pysigma_backend_parseable-0.1.0/PKG-INFO +327 -0
- pysigma_backend_parseable-0.1.0/README.md +308 -0
- pysigma_backend_parseable-0.1.0/examples/placeholder-pipeline.yml +24 -0
- pysigma_backend_parseable-0.1.0/examples/placeholder-rule.yml +11 -0
- pysigma_backend_parseable-0.1.0/examples/powershell.yml +14 -0
- pysigma_backend_parseable-0.1.0/pyproject.toml +42 -0
- pysigma_backend_parseable-0.1.0/reports/corpus-baseline.json +14 -0
- pysigma_backend_parseable-0.1.0/reports/corpus-report.md +75 -0
- pysigma_backend_parseable-0.1.0/scripts/corpus_sweep.py +365 -0
- pysigma_backend_parseable-0.1.0/sigma/backends/parseable/__init__.py +3 -0
- pysigma_backend_parseable-0.1.0/sigma/backends/parseable/parseable.py +342 -0
- pysigma_backend_parseable-0.1.0/sigma/pipelines/parseable/__init__.py +17 -0
- pysigma_backend_parseable-0.1.0/sigma/pipelines/parseable/ecs.py +123 -0
- pysigma_backend_parseable-0.1.0/sigma/pipelines/parseable/otlp.py +114 -0
- pysigma_backend_parseable-0.1.0/sigma/pipelines/parseable/sysmon.py +61 -0
- pysigma_backend_parseable-0.1.0/tests/integration/fixtures/cidr-events.json +12 -0
- pysigma_backend_parseable-0.1.0/tests/integration/fixtures/events.json +131 -0
- pysigma_backend_parseable-0.1.0/tests/integration/fixtures/numeric-keyword-events.json +6 -0
- pysigma_backend_parseable-0.1.0/tests/integration/fixtures/pipeline-events.json +24 -0
- pysigma_backend_parseable-0.1.0/tests/integration/test_parseable.py +158 -0
- pysigma_backend_parseable-0.1.0/tests/integration/test_pipeline_semantics.py +75 -0
- pysigma_backend_parseable-0.1.0/tests/test_backend.py +153 -0
- pysigma_backend_parseable-0.1.0/tests/test_cidr.py +26 -0
- pysigma_backend_parseable-0.1.0/tests/test_corpus_sweep.py +39 -0
- pysigma_backend_parseable-0.1.0/tests/test_extended_backend.py +263 -0
- pysigma_backend_parseable-0.1.0/tests/test_pipelines.py +173 -0
- pysigma_backend_parseable-0.1.0/tests/test_unsupported.py +55 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
release:
|
|
7
|
+
types: [published]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
test:
|
|
15
|
+
name: Python ${{ matrix.python-version }}
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
- uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: ${{ matrix.python-version }}
|
|
27
|
+
cache: pip
|
|
28
|
+
cache-dependency-path: pyproject.toml
|
|
29
|
+
- name: Install test dependencies
|
|
30
|
+
run: python -m pip install --upgrade pip && python -m pip install -e '.[test]' sigma-cli build
|
|
31
|
+
- name: Lint
|
|
32
|
+
run: ruff check .
|
|
33
|
+
- name: Unit tests
|
|
34
|
+
run: pytest tests -m 'not integration' --cov=sigma.backends.parseable --cov=sigma.pipelines.parseable --cov-report=term-missing
|
|
35
|
+
- name: Sigma CLI discovery and conversion
|
|
36
|
+
run: |
|
|
37
|
+
sigma list targets
|
|
38
|
+
sigma list pipelines parseable
|
|
39
|
+
sigma convert -t parseable -O dataset=windows-events examples/powershell.yml > /tmp/parseable-query.sql
|
|
40
|
+
sigma convert -t parseable -p parseable_otlp -O dataset=otel-events examples/powershell.yml > /tmp/parseable-otlp-query.sql
|
|
41
|
+
sigma convert -t parseable -p parseable_sysmon -p parseable_ecs -O dataset=ecs-events examples/powershell.yml > /tmp/parseable-ecs-query.sql
|
|
42
|
+
test -s /tmp/parseable-query.sql
|
|
43
|
+
test -s /tmp/parseable-otlp-query.sql
|
|
44
|
+
test -s /tmp/parseable-ecs-query.sql
|
|
45
|
+
- name: Build distributions
|
|
46
|
+
if: matrix.python-version == '3.14'
|
|
47
|
+
run: python -m build
|
|
48
|
+
|
|
49
|
+
corpus-regression:
|
|
50
|
+
name: Sigma corpus regression
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
env:
|
|
53
|
+
SIGMA_CORPUS_COMMIT: 5c9b21756f4e3ba137c1773ac9ba5a8332188961
|
|
54
|
+
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@v4
|
|
57
|
+
- uses: actions/setup-python@v5
|
|
58
|
+
with:
|
|
59
|
+
python-version: "3.14"
|
|
60
|
+
cache: pip
|
|
61
|
+
cache-dependency-path: pyproject.toml
|
|
62
|
+
- name: Install backend
|
|
63
|
+
run: python -m pip install --upgrade pip && python -m pip install -e '.[test]'
|
|
64
|
+
- name: Fetch pinned Sigma corpus
|
|
65
|
+
run: |
|
|
66
|
+
git init "$RUNNER_TEMP/sigma-corpus"
|
|
67
|
+
git -C "$RUNNER_TEMP/sigma-corpus" remote add origin https://github.com/SigmaHQ/sigma.git
|
|
68
|
+
git -C "$RUNNER_TEMP/sigma-corpus" fetch --depth 1 origin "$SIGMA_CORPUS_COMMIT"
|
|
69
|
+
git -C "$RUNNER_TEMP/sigma-corpus" checkout --detach FETCH_HEAD
|
|
70
|
+
- name: Run compatibility regression gate
|
|
71
|
+
run: |
|
|
72
|
+
python scripts/corpus_sweep.py "$RUNNER_TEMP/sigma-corpus" \
|
|
73
|
+
--baseline reports/corpus-baseline.json \
|
|
74
|
+
--output-dir "$RUNNER_TEMP/corpus-report"
|
|
75
|
+
- name: Upload full corpus report
|
|
76
|
+
if: always()
|
|
77
|
+
uses: actions/upload-artifact@v4
|
|
78
|
+
with:
|
|
79
|
+
name: corpus-report
|
|
80
|
+
path: ${{ runner.temp }}/corpus-report/
|
|
81
|
+
if-no-files-found: error
|
|
82
|
+
|
|
83
|
+
publish:
|
|
84
|
+
name: Publish to PyPI
|
|
85
|
+
needs: [test, corpus-regression]
|
|
86
|
+
runs-on: ubuntu-latest
|
|
87
|
+
if: github.event_name == 'release'
|
|
88
|
+
|
|
89
|
+
steps:
|
|
90
|
+
- uses: actions/checkout@v4
|
|
91
|
+
- uses: actions/setup-python@v5
|
|
92
|
+
with:
|
|
93
|
+
python-version: "3.14"
|
|
94
|
+
- name: Install build tools
|
|
95
|
+
run: python -m pip install --upgrade pip build twine
|
|
96
|
+
- name: Verify release version
|
|
97
|
+
run: |
|
|
98
|
+
package_version="$(python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')"
|
|
99
|
+
test "v${package_version}" = "${GITHUB_REF_NAME}"
|
|
100
|
+
- name: Build distributions
|
|
101
|
+
run: python -m build
|
|
102
|
+
- name: Check distributions
|
|
103
|
+
run: twine check dist/*
|
|
104
|
+
- name: Publish to PyPI
|
|
105
|
+
env:
|
|
106
|
+
TWINE_USERNAME: __token__
|
|
107
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
108
|
+
run: twine upload dist/* --verbose
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
|
|
5
|
+
## 0.1.0 - 2026-09-08
|
|
6
|
+
|
|
7
|
+
Initial release.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Parseable SQL and predicate output formats.
|
|
12
|
+
- Sigma CLI and Python API integration through pySigma plugin discovery.
|
|
13
|
+
- Case-sensitive and case-insensitive string matching, wildcards, lists, comparisons,
|
|
14
|
+
regular expressions, null checks, existence checks, field references, and fieldless
|
|
15
|
+
keyword searches.
|
|
16
|
+
- IPv4 and IPv6 CIDR conversion using Parseable's `ip_in_cidr` SQL function. CIDR queries
|
|
17
|
+
require Parseable v3.2.1 or newer.
|
|
18
|
+
- Built-in processing pipelines for Parseable OTLP, flattened ECS, and native Sysmon schemas.
|
|
19
|
+
- Custom placeholder and field-mapping pipeline support.
|
|
20
|
+
- Unit and live Parseable integration tests.
|
|
21
|
+
- Pinned Sigma corpus compatibility regression checks in GitHub Actions.
|
|
22
|
+
|
|
23
|
+
### Known limitations
|
|
24
|
+
|
|
25
|
+
- Sigma correlation rules are not supported.
|
|
26
|
+
- Timestamp-part modifiers are not supported.
|
|
27
|
+
- Fieldless regular expressions are not supported.
|
|
28
|
+
- Deployment-specific Sigma placeholders require values supplied through a processing
|
|
29
|
+
pipeline.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Parseable pySigma contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: pysigma-backend-parseable
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: pySigma backend for Parseable SQL queries
|
|
5
|
+
Project-URL: Homepage, https://github.com/parseablehq/pySigma-backend-parseable
|
|
6
|
+
Project-URL: Issues, https://github.com/parseablehq/pySigma-backend-parseable/issues
|
|
7
|
+
Author: Parseable pySigma contributors
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: parseable,pysigma,security,sigma,sql
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Requires-Dist: pysigma<2,>=1.0.0
|
|
13
|
+
Provides-Extra: test
|
|
14
|
+
Requires-Dist: coverage[toml]>=7.8; extra == 'test'
|
|
15
|
+
Requires-Dist: pytest-cov>=6.1; extra == 'test'
|
|
16
|
+
Requires-Dist: pytest>=8.3; extra == 'test'
|
|
17
|
+
Requires-Dist: ruff>=0.12; extra == 'test'
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# pySigma backend for Parseable
|
|
21
|
+
|
|
22
|
+
Convert [Sigma](https://github.com/SigmaHQ/sigma) detection rules into SQL accepted by
|
|
23
|
+
[Parseable](https://github.com/parseablehq/parseable).
|
|
24
|
+
|
|
25
|
+
The backend generates SQL only. It does not create alerts, send queries, discover datasets,
|
|
26
|
+
or infer how fields are stored in your Parseable instance.
|
|
27
|
+
|
|
28
|
+
## Requirements
|
|
29
|
+
|
|
30
|
+
- Python 3.10 or newer
|
|
31
|
+
- pySigma 1.x
|
|
32
|
+
- Parseable v3.2.1 or newer when executing generated CIDR queries
|
|
33
|
+
- A Parseable dataset when executing the generated SQL
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
The package is not yet published. Install it from a checkout:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
python -m venv .venv
|
|
41
|
+
source .venv/bin/activate
|
|
42
|
+
python -m pip install -e .
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
For the `sigma` command-line interface:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
python -m pip install sigma-cli
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Confirm that the plugin is available:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
sigma list targets
|
|
55
|
+
sigma list pipelines parseable
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Quick start
|
|
59
|
+
|
|
60
|
+
Convert a rule into a complete query:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
sigma convert \
|
|
64
|
+
--target parseable \
|
|
65
|
+
--backend-option dataset=windows-events \
|
|
66
|
+
examples/powershell.yml
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Example output:
|
|
70
|
+
|
|
71
|
+
```sql
|
|
72
|
+
SELECT "Image", "CommandLine", "User"
|
|
73
|
+
FROM "windows-events"
|
|
74
|
+
WHERE LOWER("Image") LIKE '%\\powershell.exe' ESCAPE '\'
|
|
75
|
+
AND LOWER("CommandLine") LIKE '%-encodedcommand%' ESCAPE '\'
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The backend quotes dataset and column names, so dotted names such as `service.name` are
|
|
79
|
+
rendered as one SQL identifier: `"service.name"`.
|
|
80
|
+
|
|
81
|
+
### Python API
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from pathlib import Path
|
|
85
|
+
|
|
86
|
+
from sigma.backends.parseable import ParseableBackend
|
|
87
|
+
from sigma.collection import SigmaCollection
|
|
88
|
+
|
|
89
|
+
rules = SigmaCollection.from_yaml(Path("rule.yml").read_text())
|
|
90
|
+
backend = ParseableBackend(dataset="windows-events")
|
|
91
|
+
|
|
92
|
+
for query in backend.convert(rules):
|
|
93
|
+
print(query)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`convert()` returns a list because a Sigma document may contain multiple rules or
|
|
97
|
+
conditions.
|
|
98
|
+
|
|
99
|
+
## Output formats
|
|
100
|
+
|
|
101
|
+
The default format produces a complete query and requires a dataset:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
sigma convert -t parseable -O dataset=windows-events rule.yml
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```sql
|
|
108
|
+
SELECT * FROM "windows-events" WHERE "EventID" = 4625
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The `predicate` format produces only the condition for embedding in another query. It does
|
|
112
|
+
not require a dataset:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
sigma convert -t parseable -f predicate rule.yml
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```sql
|
|
119
|
+
"EventID" = 4625
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Backend options
|
|
123
|
+
|
|
124
|
+
| Option | Default | Description |
|
|
125
|
+
| ----------------------- | ----------------------------- | ------------------------------------------------------------ |
|
|
126
|
+
| `dataset` | none | Dataset in the `FROM` clause; required for default output |
|
|
127
|
+
| `limit` | none | Positive integer appended as `LIMIT` |
|
|
128
|
+
| `default_search_fields` | `body,message,event.original` | Comma-separated columns searched by fieldless Sigma keywords |
|
|
129
|
+
|
|
130
|
+
Example:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
sigma convert \
|
|
134
|
+
-t parseable \
|
|
135
|
+
-O dataset=application-logs \
|
|
136
|
+
-O limit=500 \
|
|
137
|
+
-O default_search_fields=body,message,log \
|
|
138
|
+
rule.yml
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Every configured search field must exist in the target dataset. DataFusion rejects a query
|
|
142
|
+
that references a missing column.
|
|
143
|
+
|
|
144
|
+
## Field mapping pipelines
|
|
145
|
+
|
|
146
|
+
Sigma rules use abstract field names. Parseable queries must use the exact columns created
|
|
147
|
+
at ingestion. Select the pipeline matching your stored event schema:
|
|
148
|
+
|
|
149
|
+
| Pipeline | Use when |
|
|
150
|
+
| ------------------ | --------------------------------------------------------------------- |
|
|
151
|
+
| `parseable_otlp` | OTLP log attributes are stored as literal semantic-convention columns |
|
|
152
|
+
| `parseable_ecs` | Nested ECS documents are flattened by Parseable using underscores |
|
|
153
|
+
| `parseable_sysmon` | Events use native Sysmon fields |
|
|
154
|
+
|
|
155
|
+
### OpenTelemetry
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
sigma convert \
|
|
159
|
+
-t parseable \
|
|
160
|
+
-p parseable_otlp \
|
|
161
|
+
-O dataset=otel-events \
|
|
162
|
+
rule.yml
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Representative mappings:
|
|
166
|
+
|
|
167
|
+
| Sigma | Parseable OTLP |
|
|
168
|
+
| ----------------- | ------------------------- |
|
|
169
|
+
| `Image` | `process.executable.path` |
|
|
170
|
+
| `CommandLine` | `process.command_line` |
|
|
171
|
+
| `ProcessId` | `process.pid` |
|
|
172
|
+
| `ParentProcessId` | `process.parent_pid` |
|
|
173
|
+
| `SourceIp` | `source.address` |
|
|
174
|
+
| `DestinationIp` | `destination.address` |
|
|
175
|
+
| `DestinationPort` | `destination.port` |
|
|
176
|
+
| `TargetFilename` | `file.path` |
|
|
177
|
+
| `QueryName` | `dns.question.name` |
|
|
178
|
+
| `Computer` | `host.name` |
|
|
179
|
+
|
|
180
|
+
Mappings are scoped by Sigma log source where field meaning changes. The pipeline does not
|
|
181
|
+
invent fields without a standard OpenTelemetry equivalent.
|
|
182
|
+
|
|
183
|
+
### ECS
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
sigma convert \
|
|
187
|
+
-t parseable \
|
|
188
|
+
-p parseable_ecs \
|
|
189
|
+
-O dataset=ecs-events \
|
|
190
|
+
rule.yml
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Nested ECS input such as `{"source":{"ip":"192.0.2.1"}}` becomes the Parseable column
|
|
194
|
+
`source_ip`.
|
|
195
|
+
|
|
196
|
+
| Sigma | Flattened ECS |
|
|
197
|
+
| ---------------- | --------------------------- |
|
|
198
|
+
| `EventID` | `event_code` |
|
|
199
|
+
| `Channel` | `winlog_channel` |
|
|
200
|
+
| `Image` | `process_executable` |
|
|
201
|
+
| `CommandLine` | `process_command_line` |
|
|
202
|
+
| `ParentImage` | `process_parent_executable` |
|
|
203
|
+
| `User` | `user_name` |
|
|
204
|
+
| `SourceIp` | `source_ip` |
|
|
205
|
+
| `DestinationIp` | `destination_ip` |
|
|
206
|
+
| `TargetFilename` | `file_path` |
|
|
207
|
+
| `QueryName` | `dns_question_name` |
|
|
208
|
+
|
|
209
|
+
Use a custom pipeline if your events contain literal dotted ECS keys or use different column
|
|
210
|
+
names.
|
|
211
|
+
|
|
212
|
+
### Sysmon
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
sigma convert \
|
|
216
|
+
-t parseable \
|
|
217
|
+
-p parseable_sysmon \
|
|
218
|
+
-O dataset=sysmon-events \
|
|
219
|
+
rule.yml
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
This pipeline retains native Sysmon fields and adds the appropriate `Channel` and `EventID`
|
|
223
|
+
conditions for generic Windows log sources. For Sysmon normalized to nested ECS before
|
|
224
|
+
ingestion, chain the pipelines:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
sigma convert \
|
|
228
|
+
-t parseable \
|
|
229
|
+
-p parseable_sysmon \
|
|
230
|
+
-p parseable_ecs \
|
|
231
|
+
-O dataset=ecs-sysmon-events \
|
|
232
|
+
rule.yml
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Custom schemas
|
|
236
|
+
|
|
237
|
+
Built-in pipelines cannot know organization-specific column names. Define a pySigma pipeline
|
|
238
|
+
for the schema actually present in your dataset:
|
|
239
|
+
|
|
240
|
+
```yaml
|
|
241
|
+
name: My Parseable field mapping
|
|
242
|
+
priority: 30
|
|
243
|
+
allowed_backends:
|
|
244
|
+
- parseable
|
|
245
|
+
transformations:
|
|
246
|
+
- id: organization_fields
|
|
247
|
+
type: field_name_mapping
|
|
248
|
+
mapping:
|
|
249
|
+
Image: exe_path
|
|
250
|
+
CommandLine: command
|
|
251
|
+
User: username
|
|
252
|
+
SourceIp: client_ip
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
sigma convert \
|
|
257
|
+
-t parseable \
|
|
258
|
+
-p company-parseable.yml \
|
|
259
|
+
-O dataset=company-events \
|
|
260
|
+
rule.yml
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Always compare generated columns with the Parseable dataset schema before deploying rules.
|
|
264
|
+
|
|
265
|
+
## Supported Sigma features
|
|
266
|
+
|
|
267
|
+
The backend supports:
|
|
268
|
+
|
|
269
|
+
- Case-insensitive Sigma string matching and the `cased` modifier
|
|
270
|
+
- `contains`, `startswith`, `endswith`, `exists`, `fieldref`, and comparison modifiers
|
|
271
|
+
- Sigma `*` and `?` wildcards
|
|
272
|
+
- String and numeric lists
|
|
273
|
+
- Regular expressions bound to a field
|
|
274
|
+
- Null checks and Boolean conditions
|
|
275
|
+
- Fieldless string and numeric keyword searches
|
|
276
|
+
- IPv4 and IPv6 CIDR expressions through Parseable's `ip_in_cidr` SQL function
|
|
277
|
+
|
|
278
|
+
Unsupported constructs fail explicitly with `SigmaFeatureNotSupportedByBackendError`:
|
|
279
|
+
|
|
280
|
+
- Sigma correlation rules
|
|
281
|
+
- Timestamp-part modifiers such as `minute` and `hour`
|
|
282
|
+
- Fieldless regular expressions
|
|
283
|
+
|
|
284
|
+
CIDR conversion requires a Parseable deployment that provides `ip_in_cidr(ip, cidr)`. The
|
|
285
|
+
function correctly parses IPv4 and IPv6 rather than approximating address ranges as text.
|
|
286
|
+
|
|
287
|
+
## Placeholders
|
|
288
|
+
|
|
289
|
+
Sigma placeholders such as `%Administrators%` are deployment-specific values. Resolve them
|
|
290
|
+
with a processing pipeline before conversion:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
sigma convert \
|
|
294
|
+
-t parseable \
|
|
295
|
+
-p examples/placeholder-pipeline.yml \
|
|
296
|
+
-O dataset=windows-events \
|
|
297
|
+
examples/placeholder-rule.yml
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Do not replace unknown placeholders with wildcards; that changes the detection's meaning.
|
|
301
|
+
|
|
302
|
+
## Development
|
|
303
|
+
|
|
304
|
+
Install development dependencies and run local checks:
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
python -m pip install -e '.[test]'
|
|
308
|
+
pytest tests -m 'not integration'
|
|
309
|
+
ruff check .
|
|
310
|
+
python -m build
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Live tests require `PARSEABLE_URL`, `PARSEABLE_INGESTION_URL`, and `PARSEABLE_API_KEY`.
|
|
314
|
+
They use fixture datasets and are intentionally excluded from the default test command:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
pytest tests/integration -m integration
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
The GitHub Actions corpus job checks conversion against a pinned Sigma corpus. Detailed
|
|
321
|
+
results and regression thresholds live in [`reports/`](reports/) rather than this README.
|
|
322
|
+
Successful conversion means valid SQL was generated; it does not prove that a deployment has
|
|
323
|
+
matching columns or representative data.
|
|
324
|
+
|
|
325
|
+
## License
|
|
326
|
+
|
|
327
|
+
MIT
|