pySigma-backend-sqlite 2.1.0__tar.gz → 2.1.1__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_sqlite-2.1.0 → pysigma_backend_sqlite-2.1.1}/PKG-INFO +27 -34
- {pysigma_backend_sqlite-2.1.0 → pysigma_backend_sqlite-2.1.1}/README.md +25 -32
- {pysigma_backend_sqlite-2.1.0 → pysigma_backend_sqlite-2.1.1}/pyproject.toml +10 -8
- {pysigma_backend_sqlite-2.1.0 → pysigma_backend_sqlite-2.1.1}/sigma/backends/sqlite/correlation.py +93 -72
- {pysigma_backend_sqlite-2.1.0 → pysigma_backend_sqlite-2.1.1}/sigma/backends/sqlite/runtime.py +35 -39
- {pysigma_backend_sqlite-2.1.0 → pysigma_backend_sqlite-2.1.1}/sigma/backends/sqlite/sqlite.py +232 -462
- {pysigma_backend_sqlite-2.1.0 → pysigma_backend_sqlite-2.1.1}/LICENSE +0 -0
- {pysigma_backend_sqlite-2.1.0 → pysigma_backend_sqlite-2.1.1}/sigma/backends/sqlite/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pySigma-backend-sqlite
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.1
|
|
4
4
|
Summary: pySigma sqlite backend
|
|
5
5
|
License-Expression: LGPL-3.0-only
|
|
6
6
|
License-File: LICENSE
|
|
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.13
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.14
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.15
|
|
15
|
-
Requires-Dist: pysigma (>=2.0.
|
|
15
|
+
Requires-Dist: pysigma (>=2.0.1,<3.0)
|
|
16
16
|
Project-URL: Repository, https://github.com/SigmaHQ/pySigma-backend-sqlite
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
|
|
@@ -35,9 +35,9 @@ Maintained by [wagga](https://github.com/wagga40/).
|
|
|
35
35
|
pip install pysigma-backend-sqlite
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
Requires Python 3.11+ and [pySigma](https://github.com/SigmaHQ/pySigma) 2.
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
Requires Python 3.11+ and [pySigma](https://github.com/SigmaHQ/pySigma) 2.0.1 or
|
|
39
|
+
newer. Correlation output needs SQLite 3.38 or newer. sigma-cli 3.1 still requires
|
|
40
|
+
pySigma 1.x, so alongside it pip installs backend 2.0.0, which has no keyword search.
|
|
41
41
|
|
|
42
42
|
## Quick start
|
|
43
43
|
|
|
@@ -68,35 +68,31 @@ Processing pipelines map a logsource to concrete fields. With
|
|
|
68
68
|
SELECT * FROM logs WHERE Channel='Microsoft-Windows-Sysmon/Operational' AND (EventID=1 AND Image LIKE '%\\whoami.exe' ESCAPE '\')
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
With sigma-cli:
|
|
71
|
+
The sysmon and windows pipelines still declare `pysigma<2`; install them with
|
|
72
|
+
`pip install --no-deps pysigma-pipeline-sysmon pysigma-pipeline-windows`. With sigma-cli:
|
|
74
73
|
|
|
75
74
|
```shell
|
|
76
75
|
sigma convert -t sqlite -f zircolite -p sysmon -p windows-logsources rules/
|
|
77
76
|
```
|
|
78
77
|
|
|
79
|
-
sigma-cli 3.1 still requires pySigma 1.x, so it installs backend 2.0.0.
|
|
80
|
-
|
|
81
78
|
## Output formats
|
|
82
79
|
|
|
83
80
|
| Format | Output |
|
|
84
81
|
|---|---|
|
|
85
82
|
| `default` | One `SELECT * FROM logs WHERE ...` statement per rule |
|
|
86
|
-
| `zircolite` | A JSON list with one entry per rule: Sigma metadata, the SQL, and what a consumer needs to run it. See [output format](https://github.com/
|
|
83
|
+
| `zircolite` | A JSON list with one entry per rule: Sigma metadata, the SQL, and what a consumer needs to run it. See [output format](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/output-format.md) |
|
|
87
84
|
|
|
88
85
|
## Options
|
|
89
86
|
|
|
90
|
-
Pass options as constructor keywords, or from sigma-cli with `-O name=value`.
|
|
91
|
-
|
|
92
|
-
and does not change the timestamp expression.
|
|
87
|
+
Pass options as constructor keywords, or from sigma-cli with `-O name=value`. Set
|
|
88
|
+
them at construction; changing attributes afterwards is unsupported.
|
|
93
89
|
|
|
94
90
|
| Option | Default | Purpose |
|
|
95
91
|
|---|---|---|
|
|
96
92
|
| `table` | `logs` | Table to query. A pipeline `setState` on `table` takes precedence |
|
|
97
93
|
| `collate_nocase` | `false` | Emit `field='value' COLLATE NOCASE` for tables without `NOCASE` columns |
|
|
98
94
|
| `max_flat_operands` | `100` | Longer AND/OR chains are nested to stay under SQLite's expression depth limit |
|
|
99
|
-
| `fulltext_field` | none | Column of searchable event text; enables [keyword search](https://github.com/
|
|
95
|
+
| `fulltext_field` | none | Column of searchable event text; enables [keyword search](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/keyword-search.md) |
|
|
100
96
|
| `timestamp_field` | `timestamp` | Event time column used by correlations |
|
|
101
97
|
| `timestamp_format` | `iso` | `iso`, `unix`, `unix_ms` or `unix_us` |
|
|
102
98
|
| `timestamp_seconds_expression` | ISO parser | SQL turning `{field}` into Unix seconds; overrides `timestamp_format` |
|
|
@@ -123,35 +119,32 @@ The SQL keeps Sigma's meaning without help from the caller:
|
|
|
123
119
|
- **Negation.** Sigma reads a condition on a missing field as false; SQLite reads
|
|
124
120
|
it as `NULL`, and `NOT NULL` drops the row. Every `NOT` therefore wraps its
|
|
125
121
|
operand: `EventID=1 AND (NOT COALESCE((CommandLine LIKE '%foo%' ESCAPE '\'), 0))`.
|
|
126
|
-
- **Case.** `LIKE` ignores case
|
|
127
|
-
|
|
122
|
+
- **Case.** `LIKE` ignores case; `=` does only on `NOCASE` columns (Zircolite's
|
|
123
|
+
layout), otherwise set `collate_nocase`.
|
|
128
124
|
- **Booleans.** `Flag: true` matches text or integer storage: `(Flag='true' OR Flag=1)`.
|
|
129
|
-
- **Long lists.** Chains above `max_flat_operands` are regrouped, so rules with
|
|
130
|
-
thousands of values don't fail with "Expression tree is too large".
|
|
131
125
|
- **Field names.** SQLite keywords and names with characters other than letters,
|
|
132
126
|
digits and `_` are quoted with backticks. `field: null` becomes `field IS NULL`.
|
|
133
127
|
|
|
134
128
|
## Correlations
|
|
135
129
|
|
|
136
|
-
All Sigma correlation types run in SQLite
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
event IDs. Semantics are described in [correlations](https://github.com/wagga40/pySigma-backend-sqlite/blob/main/docs/correlations.md);
|
|
141
|
-
upgrading from backend 1.x is covered in the [migration guide](https://github.com/wagga40/pySigma-backend-sqlite/blob/main/docs/migration-v2.md).
|
|
130
|
+
All Sigma correlation types run in SQLite, including chains, aliases and extended
|
|
131
|
+
temporal conditions. See [correlations](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/correlations.md)
|
|
132
|
+
for their semantics and the [migration guide](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/migration-v2.md)
|
|
133
|
+
for upgrading from backend 1.x.
|
|
142
134
|
|
|
143
135
|
## Keyword search
|
|
144
136
|
|
|
145
|
-
Keyword (fieldless)
|
|
146
|
-
|
|
147
|
-
an error rather than guess. See [keyword search](https://github.com/wagga40/pySigma-backend-sqlite/blob/main/docs/keyword-search.md).
|
|
137
|
+
Keyword (fieldless) rules need `fulltext_field`, a column holding each event's
|
|
138
|
+
searchable text. See [keyword search](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/keyword-search.md).
|
|
148
139
|
|
|
149
140
|
## Limitations
|
|
150
141
|
|
|
151
142
|
- **REGEXP.** SQLite has no built-in `REGEXP`. Register one that is false for `NULL`:
|
|
152
143
|
`connection.create_function("regexp", 2, lambda p, v: v is not None and re.search(p, str(v)) is not None)`.
|
|
153
|
-
pySigma
|
|
154
|
-
backreferences
|
|
144
|
+
pySigma validates `|re` with RE2 by default, rejecting lookarounds and
|
|
145
|
+
backreferences. For trusted rules, pass `policy=TrustedPolicy` (from
|
|
146
|
+
`sigma.policy.profiles`) to `SigmaCollection.from_yaml()`; the patterns must then
|
|
147
|
+
suit Python's `re`.
|
|
155
148
|
- **CIDR.** SQLite has no network type. Prefix patterns match IPv6 addresses only
|
|
156
149
|
in the spellings pySigma expands to.
|
|
157
150
|
- **Case folding** (`NOCASE`, `LIKE`) is ASCII only.
|
|
@@ -160,7 +153,7 @@ an error rather than guess. See [keyword search](https://github.com/wagga40/pySi
|
|
|
160
153
|
- **Field existence.** SQL `NULL` cannot tell a missing field from an explicit null.
|
|
161
154
|
- **Multi-field `value_count`** (a list in `condition.field`) is rejected.
|
|
162
155
|
- **Unknown columns.** A query naming a column the table lacks fails to prepare.
|
|
163
|
-
Add missing columns as `NULL` first; see [output format](https://github.com/
|
|
156
|
+
Add missing columns as `NULL` first; see [output format](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/output-format.md).
|
|
164
157
|
|
|
165
158
|
## Development
|
|
166
159
|
|
|
@@ -170,7 +163,7 @@ poetry run pytest
|
|
|
170
163
|
SQLITE_MIN_BINARY=/path/to/sqlite-3.38 poetry run pytest tests/test_sqlite_minimum.py
|
|
171
164
|
```
|
|
172
165
|
|
|
173
|
-
`tools/audit_corpus.py` converts and prepares a SigmaHQ checkout per profile
|
|
174
|
-
(coverage
|
|
175
|
-
sparse and dense correlation windows.
|
|
166
|
+
`tools/audit_corpus.py` converts and prepares a SigmaHQ checkout per profile (see
|
|
167
|
+
[coverage](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/keyword-search.md#coverage)).
|
|
168
|
+
`tools/benchmark_correlations.py` times sparse and dense correlation windows.
|
|
176
169
|
|
|
@@ -17,9 +17,9 @@ Maintained by [wagga](https://github.com/wagga40/).
|
|
|
17
17
|
pip install pysigma-backend-sqlite
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Requires Python 3.11+ and [pySigma](https://github.com/SigmaHQ/pySigma) 2.
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
Requires Python 3.11+ and [pySigma](https://github.com/SigmaHQ/pySigma) 2.0.1 or
|
|
21
|
+
newer. Correlation output needs SQLite 3.38 or newer. sigma-cli 3.1 still requires
|
|
22
|
+
pySigma 1.x, so alongside it pip installs backend 2.0.0, which has no keyword search.
|
|
23
23
|
|
|
24
24
|
## Quick start
|
|
25
25
|
|
|
@@ -50,35 +50,31 @@ Processing pipelines map a logsource to concrete fields. With
|
|
|
50
50
|
SELECT * FROM logs WHERE Channel='Microsoft-Windows-Sysmon/Operational' AND (EventID=1 AND Image LIKE '%\\whoami.exe' ESCAPE '\')
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
With sigma-cli:
|
|
53
|
+
The sysmon and windows pipelines still declare `pysigma<2`; install them with
|
|
54
|
+
`pip install --no-deps pysigma-pipeline-sysmon pysigma-pipeline-windows`. With sigma-cli:
|
|
56
55
|
|
|
57
56
|
```shell
|
|
58
57
|
sigma convert -t sqlite -f zircolite -p sysmon -p windows-logsources rules/
|
|
59
58
|
```
|
|
60
59
|
|
|
61
|
-
sigma-cli 3.1 still requires pySigma 1.x, so it installs backend 2.0.0.
|
|
62
|
-
|
|
63
60
|
## Output formats
|
|
64
61
|
|
|
65
62
|
| Format | Output |
|
|
66
63
|
|---|---|
|
|
67
64
|
| `default` | One `SELECT * FROM logs WHERE ...` statement per rule |
|
|
68
|
-
| `zircolite` | A JSON list with one entry per rule: Sigma metadata, the SQL, and what a consumer needs to run it. See [output format](https://github.com/
|
|
65
|
+
| `zircolite` | A JSON list with one entry per rule: Sigma metadata, the SQL, and what a consumer needs to run it. See [output format](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/output-format.md) |
|
|
69
66
|
|
|
70
67
|
## Options
|
|
71
68
|
|
|
72
|
-
Pass options as constructor keywords, or from sigma-cli with `-O name=value`.
|
|
73
|
-
|
|
74
|
-
and does not change the timestamp expression.
|
|
69
|
+
Pass options as constructor keywords, or from sigma-cli with `-O name=value`. Set
|
|
70
|
+
them at construction; changing attributes afterwards is unsupported.
|
|
75
71
|
|
|
76
72
|
| Option | Default | Purpose |
|
|
77
73
|
|---|---|---|
|
|
78
74
|
| `table` | `logs` | Table to query. A pipeline `setState` on `table` takes precedence |
|
|
79
75
|
| `collate_nocase` | `false` | Emit `field='value' COLLATE NOCASE` for tables without `NOCASE` columns |
|
|
80
76
|
| `max_flat_operands` | `100` | Longer AND/OR chains are nested to stay under SQLite's expression depth limit |
|
|
81
|
-
| `fulltext_field` | none | Column of searchable event text; enables [keyword search](https://github.com/
|
|
77
|
+
| `fulltext_field` | none | Column of searchable event text; enables [keyword search](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/keyword-search.md) |
|
|
82
78
|
| `timestamp_field` | `timestamp` | Event time column used by correlations |
|
|
83
79
|
| `timestamp_format` | `iso` | `iso`, `unix`, `unix_ms` or `unix_us` |
|
|
84
80
|
| `timestamp_seconds_expression` | ISO parser | SQL turning `{field}` into Unix seconds; overrides `timestamp_format` |
|
|
@@ -105,35 +101,32 @@ The SQL keeps Sigma's meaning without help from the caller:
|
|
|
105
101
|
- **Negation.** Sigma reads a condition on a missing field as false; SQLite reads
|
|
106
102
|
it as `NULL`, and `NOT NULL` drops the row. Every `NOT` therefore wraps its
|
|
107
103
|
operand: `EventID=1 AND (NOT COALESCE((CommandLine LIKE '%foo%' ESCAPE '\'), 0))`.
|
|
108
|
-
- **Case.** `LIKE` ignores case
|
|
109
|
-
|
|
104
|
+
- **Case.** `LIKE` ignores case; `=` does only on `NOCASE` columns (Zircolite's
|
|
105
|
+
layout), otherwise set `collate_nocase`.
|
|
110
106
|
- **Booleans.** `Flag: true` matches text or integer storage: `(Flag='true' OR Flag=1)`.
|
|
111
|
-
- **Long lists.** Chains above `max_flat_operands` are regrouped, so rules with
|
|
112
|
-
thousands of values don't fail with "Expression tree is too large".
|
|
113
107
|
- **Field names.** SQLite keywords and names with characters other than letters,
|
|
114
108
|
digits and `_` are quoted with backticks. `field: null` becomes `field IS NULL`.
|
|
115
109
|
|
|
116
110
|
## Correlations
|
|
117
111
|
|
|
118
|
-
All Sigma correlation types run in SQLite
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
event IDs. Semantics are described in [correlations](https://github.com/wagga40/pySigma-backend-sqlite/blob/main/docs/correlations.md);
|
|
123
|
-
upgrading from backend 1.x is covered in the [migration guide](https://github.com/wagga40/pySigma-backend-sqlite/blob/main/docs/migration-v2.md).
|
|
112
|
+
All Sigma correlation types run in SQLite, including chains, aliases and extended
|
|
113
|
+
temporal conditions. See [correlations](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/correlations.md)
|
|
114
|
+
for their semantics and the [migration guide](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/migration-v2.md)
|
|
115
|
+
for upgrading from backend 1.x.
|
|
124
116
|
|
|
125
117
|
## Keyword search
|
|
126
118
|
|
|
127
|
-
Keyword (fieldless)
|
|
128
|
-
|
|
129
|
-
an error rather than guess. See [keyword search](https://github.com/wagga40/pySigma-backend-sqlite/blob/main/docs/keyword-search.md).
|
|
119
|
+
Keyword (fieldless) rules need `fulltext_field`, a column holding each event's
|
|
120
|
+
searchable text. See [keyword search](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/keyword-search.md).
|
|
130
121
|
|
|
131
122
|
## Limitations
|
|
132
123
|
|
|
133
124
|
- **REGEXP.** SQLite has no built-in `REGEXP`. Register one that is false for `NULL`:
|
|
134
125
|
`connection.create_function("regexp", 2, lambda p, v: v is not None and re.search(p, str(v)) is not None)`.
|
|
135
|
-
pySigma
|
|
136
|
-
backreferences
|
|
126
|
+
pySigma validates `|re` with RE2 by default, rejecting lookarounds and
|
|
127
|
+
backreferences. For trusted rules, pass `policy=TrustedPolicy` (from
|
|
128
|
+
`sigma.policy.profiles`) to `SigmaCollection.from_yaml()`; the patterns must then
|
|
129
|
+
suit Python's `re`.
|
|
137
130
|
- **CIDR.** SQLite has no network type. Prefix patterns match IPv6 addresses only
|
|
138
131
|
in the spellings pySigma expands to.
|
|
139
132
|
- **Case folding** (`NOCASE`, `LIKE`) is ASCII only.
|
|
@@ -142,7 +135,7 @@ an error rather than guess. See [keyword search](https://github.com/wagga40/pySi
|
|
|
142
135
|
- **Field existence.** SQL `NULL` cannot tell a missing field from an explicit null.
|
|
143
136
|
- **Multi-field `value_count`** (a list in `condition.field`) is rejected.
|
|
144
137
|
- **Unknown columns.** A query naming a column the table lacks fails to prepare.
|
|
145
|
-
Add missing columns as `NULL` first; see [output format](https://github.com/
|
|
138
|
+
Add missing columns as `NULL` first; see [output format](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/output-format.md).
|
|
146
139
|
|
|
147
140
|
## Development
|
|
148
141
|
|
|
@@ -152,6 +145,6 @@ poetry run pytest
|
|
|
152
145
|
SQLITE_MIN_BINARY=/path/to/sqlite-3.38 poetry run pytest tests/test_sqlite_minimum.py
|
|
153
146
|
```
|
|
154
147
|
|
|
155
|
-
`tools/audit_corpus.py` converts and prepares a SigmaHQ checkout per profile
|
|
156
|
-
(coverage
|
|
157
|
-
sparse and dense correlation windows.
|
|
148
|
+
`tools/audit_corpus.py` converts and prepares a SigmaHQ checkout per profile (see
|
|
149
|
+
[coverage](https://github.com/SigmaHQ/pySigma-backend-sqlite/blob/main/docs/keyword-search.md#coverage)).
|
|
150
|
+
`tools/benchmark_correlations.py` times sparse and dense correlation windows.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pySigma-backend-sqlite"
|
|
3
|
-
version = "2.1.
|
|
3
|
+
version = "2.1.1"
|
|
4
4
|
requires-python = ">=3.11,<4.0"
|
|
5
|
-
dependencies = ["pysigma>=2.0.
|
|
5
|
+
dependencies = ["pysigma>=2.0.1,<3.0"]
|
|
6
6
|
description = "pySigma sqlite backend"
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
authors = [
|
|
@@ -16,18 +16,20 @@ packages = [
|
|
|
16
16
|
]
|
|
17
17
|
|
|
18
18
|
[tool.poetry.group.dev.dependencies]
|
|
19
|
-
black = "^24.1"
|
|
20
19
|
pytest = "^8.0"
|
|
21
|
-
pytest-cov = "^
|
|
20
|
+
pytest-cov = "^7.1"
|
|
22
21
|
coverage = "^7.4"
|
|
22
|
+
ruff = "^0.16.10"
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
[tool.pytest.ini_options]
|
|
26
26
|
testpaths = ["tests"]
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
|
|
28
|
+
[tool.ruff]
|
|
29
|
+
target-version = "py311"
|
|
30
|
+
|
|
31
|
+
[tool.ruff.lint]
|
|
32
|
+
select = ["E4", "E7", "E9", "F", "I", "UP"]
|
|
31
33
|
|
|
32
34
|
[build-system]
|
|
33
35
|
requires = ["poetry-core>=2.0.0"]
|