prelude-cli-beta 1402__py3-none-any.whl → 1404__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.
- prelude_cli_beta-1404.dist-info/METADATA +46 -0
- prelude_cli_beta-1404.dist-info/RECORD +20 -0
- prelude_cli_beta-1404.dist-info/top_level.txt +1 -0
- prelude_sdk_beta/controllers/build_controller.py +309 -0
- prelude_sdk_beta/controllers/detect_controller.py +243 -0
- prelude_sdk_beta/controllers/export_controller.py +31 -0
- prelude_sdk_beta/controllers/generate_controller.py +40 -0
- prelude_sdk_beta/controllers/http_controller.py +63 -0
- prelude_sdk_beta/controllers/iam_controller.py +278 -0
- prelude_sdk_beta/controllers/jobs_controller.py +26 -0
- prelude_sdk_beta/controllers/partner_controller.py +166 -0
- prelude_sdk_beta/controllers/probe_controller.py +14 -0
- prelude_sdk_beta/controllers/scm_controller.py +424 -0
- prelude_sdk_beta/models/account.py +264 -0
- prelude_sdk_beta/models/codes.py +446 -0
- prelude_cli_beta/cli.py +0 -47
- prelude_cli_beta/views/auth.py +0 -56
- prelude_cli_beta/views/build.py +0 -488
- prelude_cli_beta/views/configure.py +0 -29
- prelude_cli_beta/views/detect.py +0 -438
- prelude_cli_beta/views/generate.py +0 -125
- prelude_cli_beta/views/iam.py +0 -368
- prelude_cli_beta/views/jobs.py +0 -50
- prelude_cli_beta/views/partner.py +0 -192
- prelude_cli_beta/views/scm.py +0 -471
- prelude_cli_beta/views/shared.py +0 -37
- prelude_cli_beta-1402.dist-info/METADATA +0 -38
- prelude_cli_beta-1402.dist-info/RECORD +0 -20
- prelude_cli_beta-1402.dist-info/entry_points.txt +0 -3
- prelude_cli_beta-1402.dist-info/top_level.txt +0 -1
- {prelude_cli_beta-1402.dist-info → prelude_cli_beta-1404.dist-info}/WHEEL +0 -0
- {prelude_cli_beta-1402.dist-info → prelude_cli_beta-1404.dist-info}/licenses/LICENSE +0 -0
- {prelude_cli_beta → prelude_sdk_beta}/__init__.py +0 -0
- {prelude_cli_beta/templates → prelude_sdk_beta/controllers}/__init__.py +0 -0
- {prelude_cli_beta/views → prelude_sdk_beta/models}/__init__.py +0 -0
prelude_cli_beta/views/scm.py
DELETED
|
@@ -1,471 +0,0 @@
|
|
|
1
|
-
import click
|
|
2
|
-
import requests
|
|
3
|
-
from time import sleep
|
|
4
|
-
|
|
5
|
-
from prelude_cli.views.shared import Spinner, pretty_print
|
|
6
|
-
from prelude_sdk.controllers.export_controller import ExportController
|
|
7
|
-
from prelude_sdk.controllers.jobs_controller import JobsController
|
|
8
|
-
from prelude_sdk.controllers.scm_controller import ScmController
|
|
9
|
-
from prelude_sdk.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
|
-
)
|
prelude_cli_beta/views/shared.py
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
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)
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: prelude-cli-beta
|
|
3
|
-
Version: 1402
|
|
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==2.6.13a1402
|
|
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
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
prelude_cli_beta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
prelude_cli_beta/cli.py,sha256=uxX3WkgjEu7gSSFVtcPA-sCPoaS-2L81OfKveM3ia2I,1239
|
|
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=frbmcuQhVFRLibQBJEDppiRPdDBjGHCycUEaqIIkIhE,1859
|
|
6
|
-
prelude_cli_beta/views/build.py,sha256=casUGNyvBvE8uM9Cw1PjGQUFqLb1Rg29d_ZbZOPmmhw,16488
|
|
7
|
-
prelude_cli_beta/views/configure.py,sha256=saj0kR9mQqBp7cCmq-yfEr3UwZCZIV1vL8WDQLDAO7o,991
|
|
8
|
-
prelude_cli_beta/views/detect.py,sha256=sHc2P4kqZwrnlfxCP6JI1PjWQ3Hzky4xeNWFlZDZNWs,12992
|
|
9
|
-
prelude_cli_beta/views/generate.py,sha256=xSy0TN6wtUV5_rDolPdPPI0dp5wZC9nxhmLG0YVLc70,4664
|
|
10
|
-
prelude_cli_beta/views/iam.py,sha256=Q8Q4vWxpTRWtbXBUMeIDWT69UklihrFdtVpHaJTwGPU,9998
|
|
11
|
-
prelude_cli_beta/views/jobs.py,sha256=8F6BiPoYj3LADHa8gpbbrd2eVLetsI1g-N98i8AyPq8,1440
|
|
12
|
-
prelude_cli_beta/views/partner.py,sha256=MlcqOVDANtwBHUqGD-nROEGmptb6741HPUcFU6RF_as,6364
|
|
13
|
-
prelude_cli_beta/views/scm.py,sha256=4x5EwP0HyuiOe_Lops8qCTX52pj1y7mTGbc11FbWZHM,14000
|
|
14
|
-
prelude_cli_beta/views/shared.py,sha256=ZKvY8N1Vi6RtEbJli5PDzJ9R6L_bX2F27n1tm6Knvgs,1101
|
|
15
|
-
prelude_cli_beta-1402.dist-info/licenses/LICENSE,sha256=ttdT5omfN6LNmtQoIjUhkkFhz6i44SDMRNwKrbfyTf8,1069
|
|
16
|
-
prelude_cli_beta-1402.dist-info/METADATA,sha256=fwQdkYxkZYwz5RJwphsZAxQPzW63BCEVifkJkrRBwC8,995
|
|
17
|
-
prelude_cli_beta-1402.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
18
|
-
prelude_cli_beta-1402.dist-info/entry_points.txt,sha256=WowrC6fz2D6S8S-5OY0g-bxUGGSZZ_Z6KzSXXd34pC4,88
|
|
19
|
-
prelude_cli_beta-1402.dist-info/top_level.txt,sha256=j50aCGsQamLMiQh9PcolDBCAeUJzi9y08e0i9Gqshkk,17
|
|
20
|
-
prelude_cli_beta-1402.dist-info/RECORD,,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
prelude_cli_beta
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|