scanner-cli 0.1.0rc7__py3-none-any.whl → 0.1.0rc9__py3-none-any.whl
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.
- {scanner_cli-0.1.0rc7.dist-info → scanner_cli-0.1.0rc9.dist-info}/METADATA +3 -3
- scanner_cli-0.1.0rc9.dist-info/RECORD +9 -0
- {scanner_cli-0.1.0rc7.dist-info → scanner_cli-0.1.0rc9.dist-info}/WHEEL +1 -1
- src/cli.py +45 -22
- scanner_cli-0.1.0rc7.dist-info/RECORD +0 -9
- {scanner_cli-0.1.0rc7.dist-info → scanner_cli-0.1.0rc9.dist-info}/entry_points.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: scanner-cli
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.0rc9
|
4
4
|
Summary: Python command-line interface for Scanner API
|
5
5
|
Author: Scanner, Inc.
|
6
6
|
Author-email: support@scanner.dev
|
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.13
|
13
13
|
Requires-Dist: PyYAML (>=6.0.2,<7.0.0)
|
14
14
|
Requires-Dist: click (>=8.1.7,<9.0.0)
|
15
|
-
Requires-Dist: scanner-client (>=0.1.
|
15
|
+
Requires-Dist: scanner-client (>=0.1.0rc10,<0.2.0)
|
16
16
|
Description-Content-Type: text/markdown
|
17
17
|
|
18
18
|
# scanner-cli
|
@@ -0,0 +1,9 @@
|
|
1
|
+
src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
src/cli.py,sha256=wk7Dmm0yyBZ7U8nLJSKui4EyGHYg-L53VyLA2Q4bLfs,9421
|
3
|
+
src/migrate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
+
src/migrate/elastic.py,sha256=y_cn_3Y_t8NHwYcpAQQLfnCkEBSULoU_vxxGwk47QAc,8681
|
5
|
+
src/sync.py,sha256=WABCtvI6fpwXNJKo9lzafw3HkGYljpGjre5ywKnO0yA,7738
|
6
|
+
scanner_cli-0.1.0rc9.dist-info/METADATA,sha256=wuTJITM3W5MKe4u9y7HSX6sCwYeekMbXaXJ41gBvWik,5942
|
7
|
+
scanner_cli-0.1.0rc9.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
8
|
+
scanner_cli-0.1.0rc9.dist-info/entry_points.txt,sha256=vqXMrIG6N6pY66bNf0y-gbUxbU8v5dXvuL3mV832Fh8,43
|
9
|
+
scanner_cli-0.1.0rc9.dist-info/RECORD,,
|
src/cli.py
CHANGED
@@ -114,7 +114,7 @@ def cli():
|
|
114
114
|
@cli.command()
|
115
115
|
@_default_click_options
|
116
116
|
def validate(api_url: str, api_key: str, file_paths: str, directories: str, recursive: bool):
|
117
|
-
""" Validate detection
|
117
|
+
""" Validate detection rule files """
|
118
118
|
_validate_default_options(api_url, api_key, file_paths, directories)
|
119
119
|
|
120
120
|
scanner_client = Scanner(api_url, api_key)
|
@@ -129,19 +129,25 @@ def validate(api_url: str, api_key: str, file_paths: str, directories: str, recu
|
|
129
129
|
result = scanner_client.detection_rule_yaml.validate(file)
|
130
130
|
|
131
131
|
if result.is_valid:
|
132
|
-
|
132
|
+
if result.warning:
|
133
|
+
click.echo(f"{file}: " + click.style("OK. ", fg="green") + click.style(f"Warning: {result.warning}", fg="yellow"))
|
134
|
+
else:
|
135
|
+
click.echo(f"{file}: " + click.style("OK", fg="green"))
|
133
136
|
else:
|
134
137
|
any_failures = True
|
135
138
|
click.echo(f"{file}: " + click.style(f"{result.error}", fg="red"))
|
136
139
|
except Exception as e:
|
137
140
|
any_failures = True
|
138
|
-
|
141
|
+
response = e.args[0]
|
142
|
+
click.echo(f"{file}: " + click.style(f"An exception occurred when attempting to validate file: {response.content}", fg="red"))
|
139
143
|
|
140
144
|
if any_failures:
|
141
145
|
# To make it so the CLI exits with a non-zero exit code
|
142
146
|
raise click.ClickException(
|
143
|
-
"validate failed for one or more files"
|
147
|
+
"`validate` failed for one or more files. See https://docs.scanner.dev/scanner/using-scanner/beta-features/detection-rules-as-code/writing-detection-rules for requirements."
|
144
148
|
)
|
149
|
+
else:
|
150
|
+
click.secho("All specified detection rule files are valid. Use `run-tests` to run the detection rule tests.", bold=True)
|
145
151
|
|
146
152
|
|
147
153
|
@cli.command()
|
@@ -155,36 +161,53 @@ def run_tests(api_url: str, api_key: str, file_paths: str, directories: str, rec
|
|
155
161
|
files = _get_valid_files(file_paths, directories, recursive)
|
156
162
|
click.echo(f'Running tests on {len(files)} {"file" if len(files) == 1 else "files"}')
|
157
163
|
|
158
|
-
|
164
|
+
any_validation_errors: bool = False
|
165
|
+
any_test_failures: bool = False
|
159
166
|
|
160
167
|
for file in files:
|
168
|
+
click.secho(f"{file}", bold=True)
|
161
169
|
try:
|
162
|
-
|
163
|
-
|
170
|
+
# Check for validation errors
|
171
|
+
validation_result = scanner_client.detection_rule_yaml.validate(file)
|
172
|
+
if not validation_result.is_valid:
|
173
|
+
any_validation_errors = True
|
174
|
+
click.secho(f"Validation error: {validation_result.error}", fg="red")
|
175
|
+
click.echo("")
|
176
|
+
continue
|
177
|
+
|
178
|
+
if validation_result.warning:
|
179
|
+
click.secho(f"Warning: {validation_result.warning}", fg="yellow")
|
180
|
+
|
181
|
+
# Run detection rule tests
|
182
|
+
run_tests_response = scanner_client.detection_rule_yaml.run_tests(file)
|
183
|
+
results = run_tests_response.results.to_dict()
|
164
184
|
|
165
|
-
click.secho(f"{file}", bold=True)
|
166
185
|
if len(results) == 0:
|
167
186
|
click.secho("No tests found", fg="yellow")
|
168
187
|
else:
|
169
|
-
for name, status in
|
188
|
+
for name, status in results.items():
|
170
189
|
if status == "Passed":
|
171
|
-
click.echo(f"{name}: " + click.style("
|
190
|
+
click.echo(f"{name}: " + click.style("OK", fg="green"))
|
172
191
|
else:
|
173
|
-
|
174
|
-
click.echo(f"{name}: " + click.style("
|
175
|
-
|
176
|
-
click.echo("")
|
192
|
+
any_test_failures = True
|
193
|
+
click.echo(f"{name}: " + click.style("Test failed", fg="red"))
|
177
194
|
except Exception as e:
|
178
|
-
|
179
|
-
|
180
|
-
click.secho(
|
181
|
-
click.echo("")
|
195
|
+
any_test_failures = True
|
196
|
+
response = e.args[0]
|
197
|
+
click.secho(f"An exception occurred when attempting to run tests: {response.content}", fg="red")
|
182
198
|
|
183
|
-
|
199
|
+
click.echo("")
|
200
|
+
|
201
|
+
error_messages = []
|
202
|
+
if any_validation_errors:
|
203
|
+
error_messages.append("Validation failed for one or more files. See https://docs.scanner.dev/scanner/using-scanner/beta-features/detection-rules-as-code/writing-detection-rules for requirements.")
|
204
|
+
|
205
|
+
if any_test_failures:
|
206
|
+
error_messages.append("`run-tests` failed for one or more files. See https://docs.scanner.dev/scanner/using-scanner/beta-features/detection-rules-as-code/cli#failing-tests for more information.")
|
207
|
+
|
208
|
+
if error_messages:
|
184
209
|
# To make it so the CLI exits with a non-zero exit code
|
185
|
-
raise click.ClickException(
|
186
|
-
"run-tests failed for one or more files"
|
187
|
-
)
|
210
|
+
raise click.ClickException("\n".join(error_messages))
|
188
211
|
|
189
212
|
|
190
213
|
@cli.command()
|
@@ -1,9 +0,0 @@
|
|
1
|
-
src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
src/cli.py,sha256=z0MT8XdVjccgfYLhbkl2S4mjMiIqfG-LZzwnfVgJctM,7781
|
3
|
-
src/migrate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
-
src/migrate/elastic.py,sha256=y_cn_3Y_t8NHwYcpAQQLfnCkEBSULoU_vxxGwk47QAc,8681
|
5
|
-
src/sync.py,sha256=WABCtvI6fpwXNJKo9lzafw3HkGYljpGjre5ywKnO0yA,7738
|
6
|
-
scanner_cli-0.1.0rc7.dist-info/METADATA,sha256=bIzAcU3Dg2bt75c77WpdL6c1Y2CB7CgMvAUg7FNSLhY,5941
|
7
|
-
scanner_cli-0.1.0rc7.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
8
|
-
scanner_cli-0.1.0rc7.dist-info/entry_points.txt,sha256=vqXMrIG6N6pY66bNf0y-gbUxbU8v5dXvuL3mV832Fh8,43
|
9
|
-
scanner_cli-0.1.0rc7.dist-info/RECORD,,
|
File without changes
|