scanner-cli 0.1.0rc4__py3-none-any.whl → 0.1.0rc5__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.0rc4.dist-info → scanner_cli-0.1.0rc5.dist-info}/METADATA +11 -11
- scanner_cli-0.1.0rc5.dist-info/RECORD +6 -0
- src/cli.py +45 -27
- scanner_cli-0.1.0rc4.dist-info/RECORD +0 -6
- {scanner_cli-0.1.0rc4.dist-info → scanner_cli-0.1.0rc5.dist-info}/WHEEL +0 -0
- {scanner_cli-0.1.0rc4.dist-info → scanner_cli-0.1.0rc5.dist-info}/entry_points.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: scanner-cli
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.0rc5
|
4
4
|
Summary: Python command-line interface for Scanner API
|
5
5
|
Author: Scanner, Inc.
|
6
6
|
Author-email: support@scanner.dev
|
@@ -26,40 +26,40 @@ pip install scanner-cli
|
|
26
26
|
```
|
27
27
|
|
28
28
|
You will need to provide the API URL of your Scanner instance and an API key. Go
|
29
|
-
to
|
29
|
+
to **Settings > API Keys** to find your API URL and API key.
|
30
30
|
|
31
31
|
You can either set these values as environment variables:
|
32
32
|
|
33
33
|
```
|
34
|
-
export SCANNER_API_URL=<
|
35
|
-
export SCANNER_API_KEY=<
|
34
|
+
export SCANNER_API_URL=<Scanner API URL>
|
35
|
+
export SCANNER_API_KEY=<Scanner API key>
|
36
36
|
```
|
37
37
|
|
38
38
|
or provide them as arguments to the CLI:
|
39
39
|
|
40
40
|
```
|
41
|
-
scanner-cli <command> --api-url=<
|
41
|
+
scanner-cli <command> --api-url=<Scanner API URL> --api-key=<Scanner API key>
|
42
42
|
```
|
43
43
|
|
44
|
-
|
44
|
+
## Commands
|
45
45
|
|
46
46
|
Available commands are
|
47
47
|
- `run-tests` - run tests on detection rules as code
|
48
48
|
- `validate` - validate detection rules as code
|
49
49
|
|
50
|
-
To validate or run tests on files
|
50
|
+
To validate or run tests on files:
|
51
51
|
|
52
52
|
```
|
53
|
-
scanner-cli <command> -f detections/
|
53
|
+
scanner-cli <command> -f detections/errors.yaml -f detections/unauthorized_logins.yaml
|
54
54
|
```
|
55
55
|
|
56
|
-
To validate or run tests on directories
|
56
|
+
To validate or run tests on directories:
|
57
57
|
|
58
58
|
```
|
59
|
-
scanner-cli <command> -d detections
|
59
|
+
scanner-cli <command> -d detections
|
60
60
|
```
|
61
61
|
|
62
|
-
This will validate or run tests on
|
62
|
+
This will only validate or run tests on YAML files with the correct schema header.
|
63
63
|
|
64
64
|
A file or directory must be provided. Multiple files and/or directories can be provided.
|
65
65
|
|
@@ -0,0 +1,6 @@
|
|
1
|
+
src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
src/cli.py,sha256=EPfmwoCBiSUKGBReXF5PENDFTWKb-eIAWZkiSNwmogY,5035
|
3
|
+
scanner_cli-0.1.0rc5.dist-info/METADATA,sha256=Lng5KIO2L5pH2I6giDr_3qTlMfUAXdFPm2NY4Iew7vs,1600
|
4
|
+
scanner_cli-0.1.0rc5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
5
|
+
scanner_cli-0.1.0rc5.dist-info/entry_points.txt,sha256=vqXMrIG6N6pY66bNf0y-gbUxbU8v5dXvuL3mV832Fh8,43
|
6
|
+
scanner_cli-0.1.0rc5.dist-info/RECORD,,
|
src/cli.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
""" Contains code for Python CLI """
|
2
2
|
|
3
|
+
import glob
|
3
4
|
import os
|
4
5
|
from typing import Any, Callable
|
5
6
|
|
@@ -33,6 +34,14 @@ _CLICK_OPTIONS = [
|
|
33
34
|
help="Directory to validate. Only .yml or .yaml files with the correct schema header will be validated.",
|
34
35
|
multiple=True,
|
35
36
|
),
|
37
|
+
click.option(
|
38
|
+
"-r",
|
39
|
+
"recursive",
|
40
|
+
is_flag=True,
|
41
|
+
show_default=True,
|
42
|
+
default=False,
|
43
|
+
help="Recursively search directory for valid YAML files.",
|
44
|
+
),
|
36
45
|
]
|
37
46
|
|
38
47
|
|
@@ -51,7 +60,7 @@ def _is_valid_file(file_path: str) -> bool:
|
|
51
60
|
return False
|
52
61
|
|
53
62
|
|
54
|
-
def _get_valid_files_in_directory(directory: str) -> list[str]:
|
63
|
+
def _get_valid_files_in_directory(directory: str, recursive: bool) -> list[str]:
|
55
64
|
if not os.path.exists(directory):
|
56
65
|
raise click.exceptions.ClickException(
|
57
66
|
message=(
|
@@ -59,14 +68,14 @@ def _get_valid_files_in_directory(directory: str) -> list[str]:
|
|
59
68
|
)
|
60
69
|
)
|
61
70
|
|
62
|
-
return [f
|
71
|
+
return [f for f in glob.iglob(f"{directory}/**", recursive=recursive) if _is_valid_file(f)]
|
63
72
|
|
64
73
|
|
65
|
-
def _get_valid_files(file_paths: str, directories: str) -> list[str]:
|
74
|
+
def _get_valid_files(file_paths: str, directories: str, recursive: bool) -> list[str]:
|
66
75
|
files = [f for f in file_paths if _is_valid_file(f)]
|
67
76
|
|
68
77
|
for d in directories:
|
69
|
-
files.extend(_get_valid_files_in_directory(d))
|
78
|
+
files.extend(_get_valid_files_in_directory(d, recursive))
|
70
79
|
|
71
80
|
return files
|
72
81
|
|
@@ -101,50 +110,59 @@ def cli():
|
|
101
110
|
|
102
111
|
@cli.command()
|
103
112
|
@_click_options
|
104
|
-
def validate(api_url: str, api_key: str, file_paths: str, directories: str):
|
113
|
+
def validate(api_url: str, api_key: str, file_paths: str, directories: str, recursive: bool):
|
105
114
|
""" Validate detection rules """
|
106
115
|
_validate_shared_options(api_url, api_key, file_paths, directories)
|
107
116
|
|
108
117
|
scanner_client = Scanner(api_url, api_key)
|
109
118
|
|
110
|
-
files = _get_valid_files(file_paths, directories)
|
119
|
+
files = _get_valid_files(file_paths, directories, recursive)
|
111
120
|
click.echo(f'Validating {len(files)} {"file" if len(files) == 1 else "files"}')
|
112
121
|
|
113
122
|
for file in files:
|
114
|
-
|
123
|
+
try:
|
124
|
+
result = scanner_client.detection_rule_yaml.validate(file)
|
125
|
+
|
126
|
+
if result.is_valid:
|
127
|
+
click.echo(f"{file}: " + click.style("Valid", fg="green"))
|
128
|
+
else:
|
129
|
+
click.echo(f"{file}: " + click.style(f"{result.error}", fg="red"))
|
130
|
+
except Exception as e:
|
131
|
+
click.echo(f"{file}: " + click.style(e, fg="red"))
|
115
132
|
|
116
|
-
if result.is_valid:
|
117
|
-
click.echo(f"{file}: " + click.style("Valid", fg="green"))
|
118
|
-
else:
|
119
|
-
click.echo(f"{file}: " + click.style(f"{result.error}", fg="red"))
|
120
133
|
|
121
134
|
|
122
135
|
@cli.command()
|
123
136
|
@_click_options
|
124
|
-
def run_tests(api_url: str, api_key: str, file_paths: str, directories: str):
|
137
|
+
def run_tests(api_url: str, api_key: str, file_paths: str, directories: str, recursive: bool):
|
125
138
|
""" Run detection rule tests """
|
126
139
|
_validate_shared_options(api_url, api_key, file_paths, directories)
|
127
140
|
|
128
141
|
scanner_client = Scanner(api_url, api_key)
|
129
142
|
|
130
|
-
files = _get_valid_files(file_paths, directories)
|
143
|
+
files = _get_valid_files(file_paths, directories, recursive)
|
131
144
|
click.echo(f'Running tests on {len(files)} {"file" if len(files) == 1 else "files"}')
|
132
145
|
|
133
146
|
for file in files:
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
147
|
+
try:
|
148
|
+
response = scanner_client.detection_rule_yaml.run_tests(file)
|
149
|
+
results = response.results.to_dict()
|
150
|
+
|
151
|
+
click.secho(f"{file}", bold=True)
|
152
|
+
if len(results) == 0:
|
153
|
+
click.secho("No tests found", fg="yellow")
|
154
|
+
else:
|
155
|
+
for name, status in response.results.to_dict().items():
|
156
|
+
if status == "Passed":
|
157
|
+
click.echo(f"{name}: " + click.style("Passed", fg="green"))
|
158
|
+
else:
|
159
|
+
click.echo(f"{name}: " + click.style("Failed", fg="red"))
|
160
|
+
|
161
|
+
click.echo("")
|
162
|
+
except Exception as e:
|
163
|
+
click.secho(f"{file}", bold=True)
|
164
|
+
click.secho(e, fg="red")
|
165
|
+
click.echo("")
|
148
166
|
|
149
167
|
|
150
168
|
if __name__ == "__main__":
|
@@ -1,6 +0,0 @@
|
|
1
|
-
src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
src/cli.py,sha256=Hv5WA0LfmqgkT-9BRqcyUz2h8uTPEeeLkiPl3iy7saw,4398
|
3
|
-
scanner_cli-0.1.0rc4.dist-info/METADATA,sha256=ScPgaZo7ZYQV5Mecdf-eHthhbRtwHyGKJU9Gwk3-WYY,1618
|
4
|
-
scanner_cli-0.1.0rc4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
5
|
-
scanner_cli-0.1.0rc4.dist-info/entry_points.txt,sha256=vqXMrIG6N6pY66bNf0y-gbUxbU8v5dXvuL3mV832Fh8,43
|
6
|
-
scanner_cli-0.1.0rc4.dist-info/RECORD,,
|
File without changes
|
File without changes
|