Skip to content

Commit

Permalink
[FR] Bundle KQL & Kibana libs into base dependencies (#3662)
Browse files Browse the repository at this point in the history
(cherry picked from commit 7883754)
  • Loading branch information
Mikaayenson authored and github-actions[bot] committed May 13, 2024
1 parent eb3bcdd commit 7790d43
Show file tree
Hide file tree
Showing 12 changed files with 21 additions and 29 deletions.
1 change: 0 additions & 1 deletion .github/workflows/backport.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install .[dev]
pip install lib/kql lib/kibana
- name: Prune non-${{matrix.target_branch}} rules
env:
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/get-target-branches.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ jobs:
python -m pip install --upgrade pip
pip cache purge
pip install .[dev]
pip install lib/kql lib/kibana
- id: get-branch-list
run: |
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/lock-versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ jobs:
python -m pip install --upgrade pip
pip cache purge
pip install .[dev]
pip install lib/kql lib/kibana
- name: Build release package
run: |
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/manual-backport.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ jobs:
python -m pip install --upgrade pip
pip cache purge
pip install .[dev]
pip install lib/kql lib/kibana
- name: Prune non-"${{github.event.inputs.target_branch}}" rules
env:
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ jobs:
python -m pip install --upgrade pip
pip cache purge
pip install .[dev]
pip install lib/kql lib/kibana
- name: Python Lint
run: |
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/release-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ jobs:
python -m pip install --upgrade pip
pip cache purge
pip install .[dev]
pip install lib/kql lib/kibana
- name: Build Integration Docs
env:
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/release-fleet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ jobs:
python -m pip install --upgrade pip
pip cache purge
pip install .[dev]
pip install lib/kql lib/kibana
- name: Bump prebuilt rules package version
env:
Expand Down
23 changes: 12 additions & 11 deletions CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Using the environment variable `DR_BYPASS_TAGS_VALIDATION` will bypass the Detec

## Importing rules into the repo

You can import rules into the repo using the `create-rule` or `import-rules` commands. Both of these commands will
You can import rules into the repo using the `create-rule` or `import-rules-to-repo` commands. Both of these commands will
require that the rules are schema-compliant and able to pass full validation. The biggest benefit to using these
commands is that they will strip[*](#note) additional fields[**](#note-2) and prompt for missing required
fields.
Expand Down Expand Up @@ -76,10 +76,10 @@ and will accept any valid rule in the following formats:
* yaml (yup)
* ndjson (as long as it contains only a single rule and has the extension `.ndjson` or `.jsonl`)

#### `import-rules`
#### `import-rules-to-repo`

```console
Usage: detection_rules import-rules [OPTIONS] [INPUT_FILE]...
Usage: detection_rules import-rules-to-repo [OPTIONS] [INPUT_FILE]...

Import rules from json, toml, yaml, or Kibana exported rule file(s).

Expand Down Expand Up @@ -269,22 +269,23 @@ Alternatively, rules can be exported into a consolidated ndjson file which can b
directly.

```console
Usage: detection_rules export-rules [OPTIONS]
Usage: detection_rules export-rules-from-repo [OPTIONS]

Export rule(s) into an importable ndjson file.

Options:
-f, --rule-file FILE
-d, --directory DIRECTORY Recursively export rules from a directory
-d, --directory DIRECTORY Recursively load rules from a directory
-id, --rule-id TEXT
-o, --outfile FILE Name of file for exported rules
-o, --outfile PATH Name of file for exported rules
-r, --replace-id Replace rule IDs with new IDs before export
--stack-version [7.8|7.9|7.10|7.11|7.12]
--stack-version [7.10|7.11|7.12|7.13|7.14|7.15|7.16|7.8|7.9|8.0|8.1|8.10|8.11|8.12|8.13|8.2|8.3|8.4|8.5|8.6|8.7|8.8|8.9]
Downgrade a rule version to be compatible
with older instances of Kibana
-s, --skip-unsupported If `--stack-version` is passed, skip rule
types which are unsupported (an error will
be raised otherwise)
--include-metadata Add metadata to the exported rules
-h, --help Show this message and exit.
```

Expand Down Expand Up @@ -336,7 +337,7 @@ Options:
Example usage of a successful upload:

```
python -m detection_rules kibana import-rules -f test-export-rules/credential_access_NEW_RULE.toml
python -m detection_rules kibana import-rules -f test-export-rules/credential_access_NEW_RULE.toml
█▀▀▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄ ▄ █▀▀▄ ▄ ▄ ▄ ▄▄▄ ▄▄▄
█ █ █▄▄ █ █▄▄ █ █ █ █ █ █▀▄ █ █▄▄▀ █ █ █ █▄▄ █▄▄
Expand Down Expand Up @@ -375,7 +376,7 @@ python -m detection_rules kibana import-rules -f test-export-rules/credential_ac

The rule loader detects a collision in name and fails as intended:
```
python -m detection_rules kibana import-rules -d test-export-rules
python -m detection_rules kibana import-rules -d test-export-rules
█▀▀▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄ ▄ █▀▀▄ ▄ ▄ ▄ ▄▄▄ ▄▄▄
█ █ █▄▄ █ █▄▄ █ █ █ █ █ █▀▄ █ █▄▄▀ █ █ █ █▄▄ █▄▄
Expand Down Expand Up @@ -533,7 +534,7 @@ web_application_suspicious_activity_unauthorized_method.toml.toml
Output of the `_errors.txt` file:

```
cat test-export-rules/_errors.txt
cat test-export-rules/_errors.txt
- Stolen Credentials Used to Login to Okta Account After MFA Reset - {'_schema': ['Setup header found in both note and setup fields.']}
- First Occurrence of Okta User Session Started via Proxy - {'rule': [ValidationError({'type': ['Must be equal to eql.'], 'language': ['Must be equal to eql.']}), ValidationError({'type': ['Must be equal to esql.'], 'language': ['Must be equal to esql.']}), ValidationError({'type': ['Must be equal to threshold.'], 'threshold': ['Missing data for required field.']}), ValidationError({'type': ['Must be equal to threat_match.'], 'threat_mapping': ['Missing data for required field.'], 'threat_index': ['Missing data for required field.']}), ValidationError({'type': ['Must be equal to machine_learning.'], 'anomaly_threshold': ['Missing data for required field.'], 'machine_learning_job_id': ['Missing data for required field.']}), ValidationError({'type': ['Must be equal to query.']}), ValidationError({'new_terms': ['Missing data for required field.']})]}
- ESQL test: cmd child of Explorer - {'rule': [ValidationError({'type': ['Must be equal to eql.'], 'threat': {0: {'tactic': {'reference': ['String does not match expected pattern.']}, 'technique': {0: {'reference': ['String does not match expected pattern.']}}}}, 'language': ['Must be equal to eql.']}), ValidationError({'threat': {0: {'tactic': {'reference': ['String does not match expected pattern.']}, 'technique': {0: {'reference': ['String does not match expected pattern.']}}}}}), ValidationError({'type': ['Must be equal to threshold.'], 'threat': {0: {'tactic': {'reference': ['String does not match expected pattern.']}, 'technique': {0: {'reference': ['String does not match expected pattern.']}}}}, 'threshold': ['Missing data for required field.']}), ValidationError({'type': ['Must be equal to threat_match.'], 'threat': {0: {'tactic': {'reference': ['String does not match expected pattern.']}, 'technique': {0: {'reference': ['String does not match expected pattern.']}}}}, 'threat_mapping': ['Missing data for required field.'], 'threat_index': ['Missing data for required field.']}), ValidationError({'type': ['Must be equal to machine_learning.'], 'threat': {0: {'tactic': {'reference': ['String does not match expected pattern.']}, 'technique': {0: {'reference': ['String does not match expected pattern.']}}}}, 'anomaly_threshold': ['Missing data for required field.'], 'machine_learning_job_id': ['Missing data for required field.']}), ValidationError({'type': ['Must be equal to query.'], 'threat': {0: {'tactic': {'reference': ['String does not match expected pattern.']}, 'technique': {0: {'reference': ['String does not match expected pattern.']}}}}}), ValidationError({'type': ['Must be equal to new_terms.'], 'threat': {0: {'tactic': {'reference': ['String does not match expected pattern.']}, 'technique': {0: {'reference': ['String does not match expected pattern.']}}}}, 'new_terms': ['Missing data for required field.']})]}
Expand All @@ -552,7 +553,7 @@ Unknown field
data_stream.dataset:osquery_manager.result and osquery_meta.counter>0 and osquery_meta.type:diff and osquery.last_run_code:0 and osquery_meta.action:removed
^^^^^^^^^^^^^^^^^
stack: 8.9.0, beats: 8.9.0, ecs: 8.9.0
- name - {'rule': [ValidationError({'type': ['Must be equal to eql.'], 'language': ['Must be equal to eql.']}), ValidationError({'type': ['Must be equal to esql.'], 'language': ['Must be equal to esql.']}), ValidationError({'type': ['Must be equal to threshold.'], 'threshold': ['Missing data for required field.']}), ValidationError({'type': ['Must be equal to threat_match.'], 'threat_mapping': ['Missing data for required field.'], 'threat_index': ['Missing data for required field.']}), ValidationError({'type': ['Must be equal to machine_learning.'], 'anomaly_threshold': ['Missing data for required field.'], 'machine_learning_job_id': ['Missing data for required field.']}), ValidationError({'type': ['Must be equal to query.']}), ValidationError({'new_terms': ['Missing data for required field.']})]}(venv312) ➜ detection-rules-fork git:(refresh-kibana-module-with-new-APIs) ✗
- name - {'rule': [ValidationError({'type': ['Must be equal to eql.'], 'language': ['Must be equal to eql.']}), ValidationError({'type': ['Must be equal to esql.'], 'language': ['Must be equal to esql.']}), ValidationError({'type': ['Must be equal to threshold.'], 'threshold': ['Missing data for required field.']}), ValidationError({'type': ['Must be equal to threat_match.'], 'threat_mapping': ['Missing data for required field.'], 'threat_index': ['Missing data for required field.']}), ValidationError({'type': ['Must be equal to machine_learning.'], 'anomaly_threshold': ['Missing data for required field.'], 'machine_learning_job_id': ['Missing data for required field.']}), ValidationError({'type': ['Must be equal to query.']}), ValidationError({'new_terms': ['Missing data for required field.']})]}(venv312) ➜ detection-rules-fork git:(refresh-kibana-module-with-new-APIs) ✗
```


Expand Down
7 changes: 1 addition & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,10 @@ clean:
rm -rf $(VENV) *.egg-info .eggs .egg htmlcov build dist packages .build .tmp .tox __pycache__ lib/kql/build lib/kibana/build lib/kql/*.egg-info lib/kibana/*.egg-info

.PHONY: deps
deps: $(VENV) install-packages
deps: $(VENV)
@echo "Installing all dependencies..."
$(PIP) install .[dev]

.PHONY: install-packages
install-packages:
@echo "Installing kql and kibana packages..."
$(PIP) install lib/kql lib/kibana

.PHONY: pytest
pytest: $(VENV) deps
$(PYTHON) -m detection_rules test
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,17 @@ Collecting Click==7.0
Downloading Click-7.0-py2.py3-none-any.whl (81 kB)
|████████████████████████████████| 81 kB 2.6 MB/s
...
pip3 install packages/kibana packages/kql
```

Note: The `kibana` and `kql` packages are not available on PyPI and must be installed from the `packages` directory or `git`.
Note: The `kibana` and `kql` packages are not available on PyPI and must be installed from the `lib` directory.

```console

# Install from the repository
pip3 install git+https://github.com/elastic/detection-rules.git#subdirectory=kibana
pip3 install git+https://github.com/elastic/detection-rules.git#subdirectory=kql

# or locally
# Or locally for development
pip3 install lib/kibana lib/kql
```

Expand Down
2 changes: 1 addition & 1 deletion detection_rules/etc/test_cli.bash
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ echo "Viewing rule: threat_intel_indicator_match_address.toml"
python -m detection_rules view-rule rules/cross-platform/threat_intel_indicator_match_address.toml

echo "Exporting rule by ID: 0a97b20f-4144-49ea-be32-b540ecc445de"
python -m detection_rules export-rules --rule-id 0a97b20f-4144-49ea-be32-b540ecc445de
python -m detection_rules export-rules-from-repo --rule-id 0a97b20f-4144-49ea-be32-b540ecc445de

echo "Updating rule data schemas"
python -m detection_rules dev schemas update-rule-data
Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ dependencies = [
"typing-inspect==0.9.0",
"typing-extensions==4.10.0",
"XlsxWriter~=3.2.0",
"semver==3.0.2"
"semver==3.0.2",
"detection-rules-kql @ git+https://github.com/elastic/detection-rules.git#subdirectory=lib/kql",
"detection-rules-kibana @ git+https://github.com/elastic/detection-rules.git#subdirectory=lib/kibana"
]
[project.optional-dependencies]
dev = ["pep8-naming==0.13.0", "PyGithub==2.2.0", "flake8==7.0.0", "pyflakes==3.2.0", "pytest>=8.1.1", "pre-commit==3.6.2"]
Expand Down

0 comments on commit 7790d43

Please sign in to comment.