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.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: scanner-cli
3
- Version: 0.1.0rc7
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.0rc8,<0.2.0)
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,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.1
2
+ Generator: poetry-core 2.1.2
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
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 rules """
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
- click.echo(f"{file}: " + click.style("Valid", fg="green"))
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
- click.echo(f"{file}: " + click.style(e, fg="red"))
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
- any_failures: bool = False
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
- response = scanner_client.detection_rule_yaml.run_tests(file)
163
- results = response.results.to_dict()
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 response.results.to_dict().items():
188
+ for name, status in results.items():
170
189
  if status == "Passed":
171
- click.echo(f"{name}: " + click.style("Passed", fg="green"))
190
+ click.echo(f"{name}: " + click.style("OK", fg="green"))
172
191
  else:
173
- any_failures = True
174
- click.echo(f"{name}: " + click.style("Failed", fg="red"))
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
- any_failures = True
179
- click.secho(f"{file}", bold=True)
180
- click.secho(e, fg="red")
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
- if any_failures:
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,,