prelude-cli-beta 1405__py3-none-any.whl → 1407__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.

Potentially problematic release.


This version of prelude-cli-beta might be problematic. Click here for more details.

Files changed (35) hide show
  1. prelude_cli_beta/cli.py +52 -0
  2. prelude_cli_beta/views/auth.py +56 -0
  3. prelude_cli_beta/views/build.py +488 -0
  4. prelude_cli_beta/views/configure.py +29 -0
  5. prelude_cli_beta/views/detect.py +438 -0
  6. prelude_cli_beta/views/generate.py +125 -0
  7. prelude_cli_beta/views/iam.py +368 -0
  8. prelude_cli_beta/views/jobs.py +50 -0
  9. prelude_cli_beta/views/partner.py +192 -0
  10. prelude_cli_beta/views/scm.py +744 -0
  11. prelude_cli_beta/views/shared.py +37 -0
  12. prelude_cli_beta-1407.dist-info/METADATA +38 -0
  13. prelude_cli_beta-1407.dist-info/RECORD +20 -0
  14. prelude_cli_beta-1407.dist-info/entry_points.txt +3 -0
  15. prelude_cli_beta-1407.dist-info/top_level.txt +1 -0
  16. prelude_cli_beta-1405.dist-info/METADATA +0 -46
  17. prelude_cli_beta-1405.dist-info/RECORD +0 -20
  18. prelude_cli_beta-1405.dist-info/top_level.txt +0 -1
  19. prelude_sdk_beta/controllers/build_controller.py +0 -309
  20. prelude_sdk_beta/controllers/detect_controller.py +0 -243
  21. prelude_sdk_beta/controllers/export_controller.py +0 -31
  22. prelude_sdk_beta/controllers/generate_controller.py +0 -40
  23. prelude_sdk_beta/controllers/http_controller.py +0 -63
  24. prelude_sdk_beta/controllers/iam_controller.py +0 -278
  25. prelude_sdk_beta/controllers/jobs_controller.py +0 -26
  26. prelude_sdk_beta/controllers/partner_controller.py +0 -166
  27. prelude_sdk_beta/controllers/probe_controller.py +0 -14
  28. prelude_sdk_beta/controllers/scm_controller.py +0 -424
  29. prelude_sdk_beta/models/account.py +0 -264
  30. prelude_sdk_beta/models/codes.py +0 -446
  31. {prelude_sdk_beta → prelude_cli_beta}/__init__.py +0 -0
  32. {prelude_sdk_beta/controllers → prelude_cli_beta/templates}/__init__.py +0 -0
  33. {prelude_sdk_beta/models → prelude_cli_beta/views}/__init__.py +0 -0
  34. {prelude_cli_beta-1405.dist-info → prelude_cli_beta-1407.dist-info}/WHEEL +0 -0
  35. {prelude_cli_beta-1405.dist-info → prelude_cli_beta-1407.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,37 @@
1
+ from functools import wraps
2
+ from rich import print_json
3
+ from rich.progress import Progress, TextColumn, SpinnerColumn
4
+
5
+
6
+ def pretty_print(func):
7
+ @wraps(func)
8
+ def handler(*args, **kwargs):
9
+ try:
10
+ res = func(*args, **kwargs)
11
+ msg = None
12
+ if isinstance(res, tuple):
13
+ res, msg = res
14
+ if not isinstance(res, list):
15
+ res = [res]
16
+ return print_json(data=dict(status="complete", results=res, message=msg))
17
+ except Exception as e:
18
+ return print_json(
19
+ data=dict(
20
+ status="error",
21
+ results=None,
22
+ message=" ".join(str(arg) for arg in e.args),
23
+ )
24
+ )
25
+
26
+ return handler
27
+
28
+
29
+ class Spinner(Progress):
30
+ def __init__(self, description="Loading"):
31
+ super().__init__(
32
+ SpinnerColumn(style="green", spinner_name="line"),
33
+ TextColumn("[green]{task.description}..."),
34
+ transient=True,
35
+ refresh_per_second=10,
36
+ )
37
+ self.add_task(description)
@@ -0,0 +1,38 @@
1
+ Metadata-Version: 2.4
2
+ Name: prelude-cli-beta
3
+ Version: 1407
4
+ Summary: For interacting with the Prelude SDK
5
+ Home-page: https://github.com/preludeorg
6
+ Author: Prelude Research
7
+ Author-email: support@preludesecurity.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: prelude-sdk-beta==1407
15
+ Requires-Dist: click>8
16
+ Requires-Dist: rich
17
+ Requires-Dist: python-dateutil
18
+ Requires-Dist: pyyaml
19
+ Dynamic: license-file
20
+
21
+ # Prelude CLI
22
+
23
+ Interact with the full range of features in Prelude Detect, organized by:
24
+
25
+ - IAM: manage your account
26
+ - Build: write and maintain your collection of security tests
27
+ - Detect: schedule security tests for your endpoints
28
+
29
+ ## Quick start
30
+ ```bash
31
+ pip install prelude-cli
32
+ prelude --help
33
+ prelude --interactive
34
+ ```
35
+
36
+ ## Documentation
37
+
38
+ https://docs.preludesecurity.com/docs/prelude-cli
@@ -0,0 +1,20 @@
1
+ prelude_cli_beta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ prelude_cli_beta/cli.py,sha256=H3JbHuFxb46JbhsLZpH2I_5Vt9airCxUVGhqBAW6lIM,1454
3
+ prelude_cli_beta/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ prelude_cli_beta/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ prelude_cli_beta/views/auth.py,sha256=W-Bc6p3CXpHiQXJCQ4FoB3SdB9xIoeJlV4WMUezSBZ4,1864
6
+ prelude_cli_beta/views/build.py,sha256=olBRS2zjqxkvXKFmWLbqjKbbP_MDkwyjeAimHGRyfvw,16508
7
+ prelude_cli_beta/views/configure.py,sha256=saj0kR9mQqBp7cCmq-yfEr3UwZCZIV1vL8WDQLDAO7o,991
8
+ prelude_cli_beta/views/detect.py,sha256=jhx38nTRjZwxPAN4QbjyMkmk1mZDqZGh4uKPyG_FZ1s,13012
9
+ prelude_cli_beta/views/generate.py,sha256=hfrlmRkb6aSo4LPaPVLhTRUFm8cxZwDqTEjLEPMlBMU,4679
10
+ prelude_cli_beta/views/iam.py,sha256=J8y6kJGbQkEexcia69q6vLJ3aEhLyUFteCylTptBHBQ,10013
11
+ prelude_cli_beta/views/jobs.py,sha256=2FeiJxHrw4zfgtUJq_bEoG84i_9TqZ5w6CulA80WoNA,1455
12
+ prelude_cli_beta/views/partner.py,sha256=16zXcX5ZhiNZqKSXG9ePPGB9K3A-OgrVIdJGDJhB6f0,6379
13
+ prelude_cli_beta/views/scm.py,sha256=DKIl9DjVNmShphD5LDHRBP_BLZAbm8CBuU8PI3gUxjY,21617
14
+ prelude_cli_beta/views/shared.py,sha256=ZKvY8N1Vi6RtEbJli5PDzJ9R6L_bX2F27n1tm6Knvgs,1101
15
+ prelude_cli_beta-1407.dist-info/licenses/LICENSE,sha256=ttdT5omfN6LNmtQoIjUhkkFhz6i44SDMRNwKrbfyTf8,1069
16
+ prelude_cli_beta-1407.dist-info/METADATA,sha256=Q_5LBqVGpbz0pFHtUghXGxq9B5GKHeVSbZ7QdKLGjT4,993
17
+ prelude_cli_beta-1407.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
+ prelude_cli_beta-1407.dist-info/entry_points.txt,sha256=WowrC6fz2D6S8S-5OY0g-bxUGGSZZ_Z6KzSXXd34pC4,88
19
+ prelude_cli_beta-1407.dist-info/top_level.txt,sha256=j50aCGsQamLMiQh9PcolDBCAeUJzi9y08e0i9Gqshkk,17
20
+ prelude_cli_beta-1407.dist-info/RECORD,,
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ prelude = prelude_cli.cli:cli
3
+ prelude-beta = prelude_cli_beta.cli:cli
@@ -0,0 +1 @@
1
+ prelude_cli_beta
@@ -1,46 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: prelude-cli-beta
3
- Version: 1405
4
- Summary: For interacting with the Prelude API
5
- Home-page: https://github.com/preludeorg
6
- Author: Prelude Research
7
- Author-email: support@preludesecurity.com
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.10
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: requests
15
- Dynamic: license-file
16
-
17
- # Prelude SDK
18
-
19
- Interact with the Prelude Service API via Python.
20
-
21
- > The prelude-cli utility wraps around this SDK to provide a rich command line experience.
22
-
23
- Install this package to write your own tooling that works with Build or Detect functionality.
24
-
25
- - IAM: manage your account
26
- - Build: write and maintain your collection of security tests
27
- - Detect: schedule security tests for your endpoints
28
-
29
- ## Quick start
30
-
31
- ```bash
32
- pip install prelude-sdk
33
- ```
34
-
35
- ## Documentation
36
-
37
- TBD
38
-
39
- ## Testing
40
-
41
- To test the Python SDK and Probes, run the following commands from the python/sdk/ directory:
42
-
43
- ```bash
44
- pip install -r tests/requirements.txt
45
- pytest tests --api https://api.preludesecurity.com --email <EMAIL>
46
- ```
@@ -1,20 +0,0 @@
1
- prelude_cli_beta-1405.dist-info/licenses/LICENSE,sha256=ttdT5omfN6LNmtQoIjUhkkFhz6i44SDMRNwKrbfyTf8,1069
2
- prelude_sdk_beta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- prelude_sdk_beta/controllers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- prelude_sdk_beta/controllers/build_controller.py,sha256=tMWMMp7SttZl9rnja_mMkkRRApLOSAjBBZKFrsXPR7c,8802
5
- prelude_sdk_beta/controllers/detect_controller.py,sha256=zB30PESzSqds8bNG2FKxM9miwO0PponTk9XWfZ4WvPA,7499
6
- prelude_sdk_beta/controllers/export_controller.py,sha256=lIRmO7b2sMLyA8WAsGFqtXuCp79r25zgopJGM5KnxvA,847
7
- prelude_sdk_beta/controllers/generate_controller.py,sha256=JUYlBdMh8alSMvin32qb3hB1JNGbT-BarEgxhMhg9PI,1304
8
- prelude_sdk_beta/controllers/http_controller.py,sha256=cj1SxmAX049ioAhTOQR4atuM82nJgd11S60-ISCg738,2300
9
- prelude_sdk_beta/controllers/iam_controller.py,sha256=eDT0kw1IfA_enQF_1kC_vSWS7-LFL9PO24EoxxM8Ax4,7856
10
- prelude_sdk_beta/controllers/jobs_controller.py,sha256=Ekf41oD72gBJeEfSfGYUfxpsQI-SUqY8EdtBmzqEIM0,755
11
- prelude_sdk_beta/controllers/partner_controller.py,sha256=T4D3Nl1SF6OLIiGPR81cPGAxUd4GSnKZ9Jl-rbAHZFE,5113
12
- prelude_sdk_beta/controllers/probe_controller.py,sha256=rwBnqkFJa1KuVwZMluM-pfo8bhQFB6JKSRSeK7s-kew,406
13
- prelude_sdk_beta/controllers/scm_controller.py,sha256=l30RZa4X19nBm6E411kAT36LM1CDl15Bd0yC3_jUb80,12778
14
- prelude_sdk_beta/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- prelude_sdk_beta/models/account.py,sha256=ksyTZDOZpbT8XDu-Ygs_51ZG25oBd8qiwjO6-L6HH9Y,8734
16
- prelude_sdk_beta/models/codes.py,sha256=-gxBflkV-RdE3LwGSDDSO48eK-J8skZ5CivMD2MYc5w,11425
17
- prelude_cli_beta-1405.dist-info/METADATA,sha256=fBpqVU1UPe3eZAb9WL7FPXfB8A4FA4f2iQZZ2pNblwo,1190
18
- prelude_cli_beta-1405.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
- prelude_cli_beta-1405.dist-info/top_level.txt,sha256=pqXTtEd5ElvJKoO6HAz232H9FW5j6X7gW4kEEakfSFM,17
20
- prelude_cli_beta-1405.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- prelude_sdk_beta
@@ -1,309 +0,0 @@
1
- import urllib
2
-
3
- from prelude_sdk.controllers.http_controller import HttpController
4
- from prelude_sdk.models.account import verify_credentials
5
- from prelude_sdk.models.codes import Control, EDRResponse
6
-
7
-
8
- class BuildController(HttpController):
9
-
10
- def __init__(self, account):
11
- super().__init__(account)
12
-
13
- @verify_credentials
14
- def clone_test(self, source_test_id):
15
- """Clone a test"""
16
- res = self.post(
17
- f"{self.account.hq}/build/tests",
18
- json=dict(source_test_id=source_test_id),
19
- headers=self.account.headers,
20
- timeout=10,
21
- )
22
- return res.json()
23
-
24
- @verify_credentials
25
- def create_test(self, name, unit, technique=None, test_id=None):
26
- """Create or update a test"""
27
- body = dict(name=name, unit=unit)
28
- if technique:
29
- body["technique"] = technique
30
- if test_id:
31
- body["id"] = test_id
32
-
33
- res = self.post(
34
- f"{self.account.hq}/build/tests",
35
- json=body,
36
- headers=self.account.headers,
37
- timeout=10,
38
- )
39
- return res.json()
40
-
41
- @verify_credentials
42
- def update_test(
43
- self,
44
- test_id,
45
- name=None,
46
- unit=None,
47
- technique=None,
48
- crowdstrike_expected_outcome: EDRResponse = None,
49
- ):
50
- """Update a test"""
51
- body = dict()
52
- if crowdstrike_expected_outcome:
53
- body["expected"] = dict(crowdstrike=crowdstrike_expected_outcome.value)
54
- if name:
55
- body["name"] = name
56
- if unit:
57
- body["unit"] = unit
58
- if technique is not None:
59
- body["technique"] = technique
60
-
61
- res = self.post(
62
- f"{self.account.hq}/build/tests/{test_id}",
63
- json=body,
64
- headers=self.account.headers,
65
- timeout=10,
66
- )
67
- return res.json()
68
-
69
- @verify_credentials
70
- def delete_test(self, test_id, purge):
71
- """Delete an existing test"""
72
- res = self.delete(
73
- f"{self.account.hq}/build/tests/{test_id}",
74
- json=dict(purge=purge),
75
- headers=self.account.headers,
76
- timeout=10,
77
- )
78
- return res.json()
79
-
80
- @verify_credentials
81
- def undelete_test(self, test_id):
82
- """Undelete a tombstoned test"""
83
- res = self.post(
84
- f"{self.account.hq}/build/tests/{test_id}/undelete",
85
- headers=self.account.headers,
86
- timeout=10,
87
- )
88
- return res.json()
89
-
90
- @verify_credentials
91
- def upload(self, test_id, filename, data, skip_compile=False):
92
- """Upload a test or attachment"""
93
- if len(data) > 1000000:
94
- raise ValueError(f"File size must be under 1MB ({filename})")
95
-
96
- h = self.account.headers | {"Content-Type": "application/octet-stream"}
97
- query_params = ""
98
- if skip_compile:
99
- query_params = "?" + urllib.parse.urlencode(dict(skip_compile=True))
100
- res = self.post(
101
- f"{self.account.hq}/build/tests/{test_id}/{filename}{query_params}",
102
- data=data,
103
- headers=h,
104
- timeout=10,
105
- )
106
- return res.json()
107
-
108
- @verify_credentials
109
- def compile_code_string(self, code: str, source_test_id: str = None):
110
- """Compile a code string"""
111
- res = self.post(
112
- f"{self.account.hq}/build/compile",
113
- json=dict(code=code, source_test_id=source_test_id),
114
- headers=self.account.headers,
115
- timeout=10,
116
- )
117
- return res.json()
118
-
119
- @verify_credentials
120
- def get_compile_status(self, job_id):
121
- res = self.get(
122
- f"{self.account.hq}/build/compile/{job_id}",
123
- headers=self.account.headers,
124
- timeout=10,
125
- )
126
- return res.json()
127
-
128
- @verify_credentials
129
- def create_threat(
130
- self, name, published, threat_id=None, source_id=None, source=None, tests=None
131
- ):
132
- """Create a threat"""
133
- body = dict(name=name, published=published)
134
- if threat_id:
135
- body["id"] = threat_id
136
- if source_id:
137
- body["source_id"] = source_id
138
- if source:
139
- body["source"] = source
140
- if tests:
141
- body["tests"] = tests
142
-
143
- res = self.post(
144
- f"{self.account.hq}/build/threats",
145
- json=body,
146
- headers=self.account.headers,
147
- timeout=10,
148
- )
149
- return res.json()
150
-
151
- @verify_credentials
152
- def update_threat(
153
- self,
154
- threat_id,
155
- name=None,
156
- source_id=None,
157
- source=None,
158
- published=None,
159
- tests=None,
160
- ):
161
- """Update a threat"""
162
- body = dict()
163
- if name:
164
- body["name"] = name
165
- if source_id is not None:
166
- body["source_id"] = source_id
167
- if source is not None:
168
- body["source"] = source
169
- if published is not None:
170
- body["published"] = published
171
- if tests is not None:
172
- body["tests"] = tests
173
-
174
- res = self.post(
175
- f"{self.account.hq}/build/threats/{threat_id}",
176
- json=body,
177
- headers=self.account.headers,
178
- timeout=10,
179
- )
180
- return res.json()
181
-
182
- @verify_credentials
183
- def delete_threat(self, threat_id, purge):
184
- """Delete an existing threat"""
185
- res = self.delete(
186
- f"{self.account.hq}/build/threats/{threat_id}",
187
- json=dict(purge=purge),
188
- headers=self.account.headers,
189
- timeout=10,
190
- )
191
- return res.json()
192
-
193
- @verify_credentials
194
- def undelete_threat(self, threat_id):
195
- """Undelete a tombstoned threat"""
196
- res = self.post(
197
- f"{self.account.hq}/build/threats/{threat_id}/undelete",
198
- headers=self.account.headers,
199
- timeout=10,
200
- )
201
- return res.json()
202
-
203
- @verify_credentials
204
- def create_detection(
205
- self, rule: str, test_id: str, detection_id=None, rule_id=None
206
- ):
207
- """Create a detection"""
208
- body = dict(rule=rule, test_id=test_id)
209
- if detection_id:
210
- body["detection_id"] = detection_id
211
- if rule_id:
212
- body["rule_id"] = rule_id
213
-
214
- res = self.post(
215
- f"{self.account.hq}/build/detections",
216
- json=body,
217
- headers=self.account.headers,
218
- timeout=10,
219
- )
220
- return res.json()
221
-
222
- @verify_credentials
223
- def update_detection(self, detection_id: str, rule=None, test_id=None):
224
- """Update a detection"""
225
- body = dict()
226
- if rule:
227
- body["rule"] = rule
228
- if test_id:
229
- body["test_id"] = test_id
230
-
231
- res = self.post(
232
- f"{self.account.hq}/build/detections/{detection_id}",
233
- json=body,
234
- headers=self.account.headers,
235
- timeout=10,
236
- )
237
- return res.json()
238
-
239
- @verify_credentials
240
- def delete_detection(self, detection_id: str):
241
- """Delete an existing detection"""
242
- res = self.delete(
243
- f"{self.account.hq}/build/detections/{detection_id}",
244
- headers=self.account.headers,
245
- timeout=10,
246
- )
247
- return res.json()
248
-
249
- @verify_credentials
250
- def create_threat_hunt(
251
- self,
252
- control: Control,
253
- test_id: str,
254
- name: str,
255
- query: str,
256
- threat_hunt_id: str = None,
257
- ):
258
- """Create a threat hunt"""
259
- body = dict(
260
- control=control.name,
261
- name=name,
262
- query=query,
263
- test_id=test_id,
264
- )
265
- if threat_hunt_id:
266
- body["id"] = threat_hunt_id
267
-
268
- res = self.post(
269
- f"{self.account.hq}/build/threat_hunts",
270
- json=body,
271
- headers=self.account.headers,
272
- timeout=10,
273
- )
274
- return res.json()
275
-
276
- @verify_credentials
277
- def update_threat_hunt(
278
- self,
279
- threat_hunt_id: str,
280
- name: str = None,
281
- query: str = None,
282
- test_id: str = None,
283
- ):
284
- """Update a threat hunt"""
285
- body = dict()
286
- if name:
287
- body["name"] = name
288
- if query:
289
- body["query"] = query
290
- if test_id:
291
- body["test_id"] = test_id
292
-
293
- res = self.post(
294
- f"{self.account.hq}/build/threat_hunts/{threat_hunt_id}",
295
- json=body,
296
- headers=self.account.headers,
297
- timeout=10,
298
- )
299
- return res.json()
300
-
301
- @verify_credentials
302
- def delete_threat_hunt(self, threat_hunt_id: str):
303
- """Delete an existing threat hunt"""
304
- res = self.delete(
305
- f"{self.account.hq}/build/threat_hunts/{threat_hunt_id}",
306
- headers=self.account.headers,
307
- timeout=10,
308
- )
309
- return res.json()