prelude-cli-beta 1405__py3-none-any.whl → 1406__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 +47 -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 +471 -0
  11. prelude_cli_beta/views/shared.py +37 -0
  12. prelude_cli_beta-1406.dist-info/METADATA +38 -0
  13. prelude_cli_beta-1406.dist-info/RECORD +20 -0
  14. prelude_cli_beta-1406.dist-info/entry_points.txt +3 -0
  15. prelude_cli_beta-1406.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-1406.dist-info}/WHEEL +0 -0
  35. {prelude_cli_beta-1405.dist-info → prelude_cli_beta-1406.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,471 @@
1
+ import click
2
+ import requests
3
+ from time import sleep
4
+
5
+ from prelude_cli_beta.views.shared import Spinner, pretty_print
6
+ from prelude_sdk_beta.controllers.export_controller import ExportController
7
+ from prelude_sdk_beta.controllers.jobs_controller import JobsController
8
+ from prelude_sdk_beta.controllers.scm_controller import ScmController
9
+ from prelude_sdk_beta.models.codes import (
10
+ Control,
11
+ ControlCategory,
12
+ PartnerEvents,
13
+ RunCode,
14
+ SCMCategory,
15
+ )
16
+
17
+
18
+ @click.group()
19
+ @click.pass_context
20
+ def scm(ctx):
21
+ """SCM system commands"""
22
+ ctx.obj = ScmController(account=ctx.obj)
23
+
24
+
25
+ @scm.command("endpoints")
26
+ @click.option(
27
+ "--limit", default=100, help="maximum number of results to return", type=int
28
+ )
29
+ @click.option("--odata_filter", help="OData filter string", default=None)
30
+ @click.option("--odata_orderby", help="OData orderby string", default=None)
31
+ @click.pass_obj
32
+ @pretty_print
33
+ def endpoints(controller, limit, odata_filter, odata_orderby):
34
+ """List endpoints with SCM data"""
35
+ with Spinner(description="Fetching endpoints from partner"):
36
+ return controller.endpoints(
37
+ filter=odata_filter, orderby=odata_orderby, top=limit
38
+ )
39
+
40
+
41
+ @scm.command("inboxes")
42
+ @click.option(
43
+ "--limit", default=100, help="maximum number of results to return", type=int
44
+ )
45
+ @click.option("--odata_filter", help="OData filter string", default=None)
46
+ @click.option("--odata_orderby", help="OData orderby string", default=None)
47
+ @click.pass_obj
48
+ @pretty_print
49
+ def endpoints(controller, limit, odata_filter, odata_orderby):
50
+ """List inboxes with SCM data"""
51
+ with Spinner(description="Fetching inboxes from partner"):
52
+ return controller.inboxes(filter=odata_filter, orderby=odata_orderby, top=limit)
53
+
54
+
55
+ @scm.command("users")
56
+ @click.option(
57
+ "--limit", default=100, help="maximum number of results to return", type=int
58
+ )
59
+ @click.option("--odata_filter", help="OData filter string", default=None)
60
+ @click.option("--odata_orderby", help="OData orderby string", default=None)
61
+ @click.pass_obj
62
+ @pretty_print
63
+ def endpoints(controller, limit, odata_filter, odata_orderby):
64
+ """List users with SCM data"""
65
+ with Spinner(description="Fetching users from partner"):
66
+ return controller.users(filter=odata_filter, orderby=odata_orderby, top=limit)
67
+
68
+
69
+ @scm.command("technique-summary")
70
+ @click.option(
71
+ "-q",
72
+ "--techniques",
73
+ help="comma-separated list of techniques to filter by",
74
+ type=str,
75
+ required=True,
76
+ )
77
+ @click.pass_obj
78
+ @pretty_print
79
+ def technique_summary(controller, techniques):
80
+ """Get policy summary per technique"""
81
+ with Spinner(description="Getting policy summary by technique"):
82
+ return controller.technique_summary(techniques=techniques)
83
+
84
+
85
+ @scm.command("evaluation-summary")
86
+ @click.option(
87
+ "--endpoint_odata_filter", help="OData filter string for endpoints", default=None
88
+ )
89
+ @click.option(
90
+ "--inbox_odata_filter", help="OData filter string for inboxes", default=None
91
+ )
92
+ @click.option("--user_odata_filter", help="OData filter string for users", default=None)
93
+ @click.option(
94
+ "-q",
95
+ "--techniques",
96
+ help="comma-separated list of techniques to filter by",
97
+ type=str,
98
+ default=None,
99
+ )
100
+ @click.pass_obj
101
+ @pretty_print
102
+ def evaluation_summary(
103
+ controller, endpoint_odata_filter, inbox_odata_filter, user_odata_filter, techniques
104
+ ):
105
+ """Get policy evaluation summary for all partners"""
106
+ with Spinner(description="Getting policy evaluation summary"):
107
+ return controller.evaluation_summary(
108
+ endpoint_filter=endpoint_odata_filter,
109
+ inbox_filter=inbox_odata_filter,
110
+ user_filter=user_odata_filter,
111
+ techniques=techniques,
112
+ )
113
+
114
+
115
+ @scm.command("evaluation")
116
+ @click.argument(
117
+ "partner",
118
+ type=click.Choice(
119
+ [c.name for c in Control if c != Control.INVALID], case_sensitive=False
120
+ ),
121
+ )
122
+ @click.option("--instance_id", required=True, help="instance ID of the partner")
123
+ @click.option("--odata_filter", help="OData filter string", default=None)
124
+ @click.option(
125
+ "-q",
126
+ "--techniques",
127
+ help="comma-separated list of techniques to filter by",
128
+ type=str,
129
+ default=None,
130
+ )
131
+ @click.pass_obj
132
+ @pretty_print
133
+ def evaluation(controller, partner, instance_id, odata_filter, techniques):
134
+ """Get policy evaluation for given partner"""
135
+ with Spinner(description="Getting policy evaluation"):
136
+ return controller.evaluation(
137
+ partner=Control[partner],
138
+ instance_id=instance_id,
139
+ filter=odata_filter,
140
+ techniques=techniques,
141
+ )
142
+
143
+
144
+ @scm.command("sync")
145
+ @click.argument(
146
+ "partner",
147
+ type=click.Choice(
148
+ [c.name for c in Control if c != Control.INVALID], case_sensitive=False
149
+ ),
150
+ required=True,
151
+ )
152
+ @click.option("--instance_id", required=True, help="instance ID of the partner")
153
+ @click.pass_obj
154
+ @pretty_print
155
+ def sync(controller, partner, instance_id):
156
+ """Update policy evaluation for given partner"""
157
+ with Spinner(description="Updating policy evaluation"):
158
+ job_id = controller.update_evaluation(
159
+ partner=Control[partner], instance_id=instance_id
160
+ )["job_id"]
161
+ jobs = JobsController(account=controller.account)
162
+ while (result := jobs.job_status(job_id))["end_time"] is None:
163
+ sleep(3)
164
+ return result
165
+
166
+
167
+ @scm.command("export")
168
+ @click.argument(
169
+ "type",
170
+ type=click.Choice(
171
+ [c.name for c in SCMCategory if c.value > 0], case_sensitive=False
172
+ ),
173
+ )
174
+ @click.option(
175
+ "-o",
176
+ "--output_file",
177
+ help="csv filename to export to",
178
+ type=click.Path(writable=True),
179
+ required=True,
180
+ )
181
+ @click.option(
182
+ "--limit", default=None, help="maximum number of results to return", type=int
183
+ )
184
+ @click.option("--odata_filter", help="OData filter string", default=None)
185
+ @click.option("--odata_orderby", help="OData orderby string", default=None)
186
+ @click.pass_obj
187
+ @pretty_print
188
+ def export(controller, type, output_file, limit, odata_filter, odata_orderby):
189
+ """Export SCM data"""
190
+ with Spinner(description="Exporting SCM data"):
191
+ export = ExportController(account=controller.account)
192
+ jobs = JobsController(account=controller.account)
193
+ job_id = export.export_scm(
194
+ export_type=SCMCategory[type],
195
+ filter=odata_filter,
196
+ orderby=odata_orderby,
197
+ top=limit,
198
+ )["job_id"]
199
+ while (result := jobs.job_status(job_id))["end_time"] is None:
200
+ sleep(3)
201
+ if result["successful"]:
202
+ data = requests.get(result["results"]["url"], timeout=10).content
203
+ with open(output_file, "wb") as f:
204
+ f.write(data)
205
+ return result, f"Exported data to {output_file}"
206
+
207
+
208
+ @scm.command("groups")
209
+ @click.option("--odata_filter", help="OData filter string", default=None)
210
+ @click.option("--odata_orderby", help="OData orderby string", default=None)
211
+ @click.pass_obj
212
+ @pretty_print
213
+ def list_partner_groups(controller, odata_filter, odata_orderby):
214
+ """List all partner groups"""
215
+ with Spinner(description="Fetching partner groups"):
216
+ return controller.list_partner_groups(filter=odata_filter, orderby=odata_orderby)
217
+
218
+
219
+ @scm.command("sync-groups")
220
+ @click.argument(
221
+ "partner",
222
+ type=click.Choice(
223
+ [c.name for c in Control if c != Control.INVALID], case_sensitive=False
224
+ ),
225
+ required=True,
226
+ )
227
+ @click.option("--instance_id", required=True, help="instance ID of the partner")
228
+ @click.option("--group_ids", required=True, help="comma-separated list of group IDs")
229
+ @click.pass_obj
230
+ @pretty_print
231
+ def sync_groups(controller, partner, instance_id, group_ids):
232
+ """Update groups for a partner"""
233
+ with Spinner(description="Updating groups"):
234
+ job_id = controller.update_partner_groups(
235
+ partner=Control[partner],
236
+ instance_id=instance_id,
237
+ group_ids=group_ids.split(","),
238
+ )["job_id"]
239
+ jobs = JobsController(account=controller.account)
240
+ while (result := jobs.job_status(job_id))["end_time"] is None:
241
+ sleep(3)
242
+ return result
243
+
244
+
245
+ @scm.command("create-threat")
246
+ @click.argument("name")
247
+ @click.option(
248
+ "-d", "--description", help="description of the threat", default=None, type=str
249
+ )
250
+ @click.option("--id", help="uuid for threat", default=None, type=str)
251
+ @click.option(
252
+ "-g", "--generated", help="was the threat AI generated", default=False, type=bool
253
+ )
254
+ @click.option(
255
+ "-p", "--published", help="date the threat was published", default=None, type=str
256
+ )
257
+ @click.option(
258
+ "-s", "--source", help="source of threat (ex. www.cisa.gov)", default=None, type=str
259
+ )
260
+ @click.option(
261
+ "-i",
262
+ "--source_id",
263
+ help="ID of the threat, per the source (ex. aa23-075a)",
264
+ default=None,
265
+ type=str,
266
+ )
267
+ @click.option(
268
+ "-q",
269
+ "--techniques",
270
+ help="comma-separated list of techniques (MITRE ATT&CK IDs)",
271
+ default=None,
272
+ type=str,
273
+ )
274
+ @click.pass_obj
275
+ @pretty_print
276
+ def create_threat(
277
+ controller,
278
+ name,
279
+ description,
280
+ id,
281
+ generated,
282
+ published,
283
+ source,
284
+ source_id,
285
+ techniques,
286
+ ):
287
+ """Create an scm threat"""
288
+ with Spinner(description="Creating scm threat"):
289
+ return controller.create_threat(
290
+ name=name,
291
+ description=description,
292
+ id=id,
293
+ generated=generated,
294
+ published=published,
295
+ source=source,
296
+ source_id=source_id,
297
+ techniques=techniques,
298
+ )
299
+
300
+
301
+ @scm.command("delete-threat")
302
+ @click.argument("threat_id")
303
+ @click.confirmation_option(prompt="Are you sure?")
304
+ @click.pass_obj
305
+ @pretty_print
306
+ def delete_threat(controller, threat_id):
307
+ """Delete an scm threat"""
308
+ with Spinner(description="Removing scm threat"):
309
+ return controller.delete_threat(id=threat_id)
310
+
311
+
312
+ @scm.command("threats")
313
+ @click.pass_obj
314
+ @pretty_print
315
+ def list_threats(controller):
316
+ """List all scm threats"""
317
+ with Spinner(description="Fetching scm threats"):
318
+ return controller.list_threats()
319
+
320
+
321
+ @scm.command("threat")
322
+ @click.argument("threat_id")
323
+ @click.pass_obj
324
+ @pretty_print
325
+ def get_threat(controller, threat_id):
326
+ """Get specific scm threat"""
327
+ with Spinner(description="Fetching scm threat"):
328
+ return controller.get_threat(id=threat_id)
329
+
330
+
331
+ @scm.command("threat-intel")
332
+ @click.argument(
333
+ "threat_pdf",
334
+ type=click.Path(exists=True, file_okay=True, dir_okay=False, readable=True),
335
+ )
336
+ @click.pass_obj
337
+ @pretty_print
338
+ def parse_threat_intel(controller, threat_pdf):
339
+ with Spinner("Parsing PDF"):
340
+ return controller.parse_threat_intel(threat_pdf)
341
+
342
+
343
+ @scm.command("from-advisory")
344
+ @click.argument(
345
+ "partner", type=click.Choice([Control.CROWDSTRIKE.name], case_sensitive=False)
346
+ )
347
+ @click.option(
348
+ "-a", "--advisory_id", required=True, type=str, help="Partner advisory ID"
349
+ )
350
+ @click.pass_obj
351
+ @pretty_print
352
+ def parse_from_partner_advisory(controller, partner, advisory_id):
353
+ with Spinner("Uploading"):
354
+ return controller.parse_from_partner_advisory(
355
+ partner=Control[partner], advisory_id=advisory_id
356
+ )
357
+
358
+
359
+ @scm.command("list-notifications")
360
+ @click.pass_obj
361
+ @pretty_print
362
+ def list_notifications(controller):
363
+ with Spinner("Fetching notifications"):
364
+ return controller.list_notifications()
365
+
366
+
367
+ @scm.command("delete-notification")
368
+ @click.argument("notification_id", type=str)
369
+ @click.confirmation_option(prompt="Are you sure?")
370
+ @click.pass_obj
371
+ @pretty_print
372
+ def delete_notification(controller, notification_id):
373
+ with Spinner("Deleting notification"):
374
+ return controller.delete_notification(notification_id)
375
+
376
+
377
+ @scm.command("upsert-notification")
378
+ @click.argument(
379
+ "control_category",
380
+ type=click.Choice([c.name for c in ControlCategory], case_sensitive=False),
381
+ )
382
+ @click.option(
383
+ "-e",
384
+ "--emails",
385
+ help="comma-separated list of emails to notify",
386
+ default=None,
387
+ type=str,
388
+ )
389
+ @click.option(
390
+ "-v",
391
+ "--event",
392
+ help="event to trigger notification for",
393
+ type=click.Choice([e.name for e in PartnerEvents], case_sensitive=False),
394
+ required=True,
395
+ )
396
+ @click.option("-f", "--filter", help="OData filter string", default=None, type=str)
397
+ @click.option(
398
+ "-i", "--id", help="ID of the notification to update", default=None, type=str
399
+ )
400
+ @click.option("-m", "--message", help="notification message", default="", type=str)
401
+ @click.option(
402
+ "-r",
403
+ "--run_code",
404
+ help="notification frequency",
405
+ type=click.Choice([r.name for r in RunCode], case_sensitive=False),
406
+ required=True,
407
+ )
408
+ @click.option(
409
+ "-s",
410
+ "--scheduled_hour",
411
+ help="scheduled UTC hour to receive notifications",
412
+ type=int,
413
+ required=True,
414
+ )
415
+ @click.option(
416
+ "-u",
417
+ "--slack_urls",
418
+ help="comma-separated list of Slack Webhook URLs to notify",
419
+ default=None,
420
+ type=str,
421
+ )
422
+ @click.option(
423
+ "-p",
424
+ "--suppress_empty",
425
+ help="suppress notifications with no results",
426
+ default=True,
427
+ type=bool,
428
+ )
429
+ @click.option(
430
+ "-u",
431
+ "--teams_urls",
432
+ help="comma-separated list of Teams Webhook URLs to notify",
433
+ default=None,
434
+ type=str,
435
+ )
436
+ @click.option(
437
+ "-t", "--title", help="notification title", default="SCM Notification", type=str
438
+ )
439
+ @click.pass_obj
440
+ @pretty_print
441
+ def upsert_notification(
442
+ controller,
443
+ control_category,
444
+ emails,
445
+ event,
446
+ filter,
447
+ id,
448
+ message,
449
+ run_code,
450
+ scheduled_hour,
451
+ slack_urls,
452
+ suppress_empty,
453
+ teams_urls,
454
+ title,
455
+ ):
456
+ """Upsert an SCM notification"""
457
+ with Spinner("Upserting notification"):
458
+ return controller.upsert_notification(
459
+ control_category=ControlCategory[control_category],
460
+ emails=emails.split(",") if emails else None,
461
+ event=PartnerEvents[event],
462
+ filter=filter,
463
+ id=id,
464
+ message=message,
465
+ run_code=RunCode[run_code],
466
+ scheduled_hour=scheduled_hour,
467
+ slack_urls=slack_urls.split(",") if slack_urls else None,
468
+ suppress_empty=suppress_empty,
469
+ teams_urls=teams_urls.split(",") if teams_urls else None,
470
+ title=title,
471
+ )
@@ -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: 1406
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==1406
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=FiBYXVT0_Ft6sTAlB00tMfGsRdSHhnNnm0dHWZ06VMU,1289
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=_SkwYXIR-fSIBnXZfID0aHkH-quK6ePdhkxx18wczl0,14025
14
+ prelude_cli_beta/views/shared.py,sha256=ZKvY8N1Vi6RtEbJli5PDzJ9R6L_bX2F27n1tm6Knvgs,1101
15
+ prelude_cli_beta-1406.dist-info/licenses/LICENSE,sha256=ttdT5omfN6LNmtQoIjUhkkFhz6i44SDMRNwKrbfyTf8,1069
16
+ prelude_cli_beta-1406.dist-info/METADATA,sha256=TDssBOmg9KcpnuYki6XYu_-tlsMMGHO3TPTkW5vzZy8,993
17
+ prelude_cli_beta-1406.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
+ prelude_cli_beta-1406.dist-info/entry_points.txt,sha256=WowrC6fz2D6S8S-5OY0g-bxUGGSZZ_Z6KzSXXd34pC4,88
19
+ prelude_cli_beta-1406.dist-info/top_level.txt,sha256=j50aCGsQamLMiQh9PcolDBCAeUJzi9y08e0i9Gqshkk,17
20
+ prelude_cli_beta-1406.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