prelude-sdk-beta 1447__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.
@@ -0,0 +1,664 @@
1
+ from prelude_sdk_beta.controllers.http_controller import HttpController
2
+ from prelude_sdk_beta.models.account import verify_credentials
3
+ from prelude_sdk_beta.models.codes import (
4
+ Control,
5
+ ControlCategory,
6
+ PartnerEvents,
7
+ PolicyType,
8
+ NotationType,
9
+ RunCode,
10
+ SCMCategory,
11
+ )
12
+
13
+
14
+ class ScmController(HttpController):
15
+ default = "-1"
16
+
17
+ def __init__(self, account):
18
+ super().__init__(account)
19
+
20
+ @verify_credentials
21
+ def endpoints(self, filter: str = None, orderby: str = None, top: int = None):
22
+ """List endpoints with SCM analysis"""
23
+ params = {"$filter": filter, "$orderby": orderby, "$top": top}
24
+ res = self.get(
25
+ f"{self.account.hq}/scm/endpoints",
26
+ headers=self.account.headers,
27
+ params=params,
28
+ timeout=30,
29
+ )
30
+ data = res.json()
31
+ if self.account.resolve_enums:
32
+ self.resolve_enums(
33
+ data,
34
+ [
35
+ (Control, "controls"),
36
+ (Control, "control"),
37
+ (ControlCategory, "category"),
38
+ (PartnerEvents, "event"),
39
+ ],
40
+ )
41
+ return data
42
+
43
+ @verify_credentials
44
+ def inboxes(self, filter: str = None, orderby: str = None, top: int = None):
45
+ """List inboxes with SCM analysis"""
46
+ params = {"$filter": filter, "$orderby": orderby, "$top": top}
47
+ res = self.get(
48
+ f"{self.account.hq}/scm/inboxes",
49
+ headers=self.account.headers,
50
+ params=params,
51
+ timeout=30,
52
+ )
53
+ data = res.json()
54
+ if self.account.resolve_enums:
55
+ self.resolve_enums(
56
+ data,
57
+ [
58
+ (Control, "controls"),
59
+ (Control, "control"),
60
+ (ControlCategory, "category"),
61
+ (PartnerEvents, "event"),
62
+ ],
63
+ )
64
+ return data
65
+
66
+ @verify_credentials
67
+ def network_devices(self, filter: str = None, orderby: str = None, top: int = None):
68
+ """List network_devices with SCM analysis"""
69
+ params = {"$filter": filter, "$orderby": orderby, "$top": top}
70
+ res = self.get(
71
+ f"{self.account.hq}/scm/network_devices",
72
+ headers=self.account.headers,
73
+ params=params,
74
+ timeout=30,
75
+ )
76
+ data = res.json()
77
+ if self.account.resolve_enums:
78
+ self.resolve_enums(
79
+ data,
80
+ [
81
+ (Control, "controls"),
82
+ (Control, "control"),
83
+ (ControlCategory, "category"),
84
+ (PartnerEvents, "event"),
85
+ ],
86
+ )
87
+ return data
88
+
89
+ @verify_credentials
90
+ def users(self, filter: str = None, orderby: str = None, top: int = None):
91
+ """List users with SCM analysis"""
92
+ params = {"$filter": filter, "$orderby": orderby, "$top": top}
93
+ res = self.get(
94
+ f"{self.account.hq}/scm/users",
95
+ headers=self.account.headers,
96
+ params=params,
97
+ timeout=30,
98
+ )
99
+ data = res.json()
100
+ if self.account.resolve_enums:
101
+ self.resolve_enums(
102
+ data,
103
+ [
104
+ (Control, "controls"),
105
+ (Control, "control"),
106
+ (ControlCategory, "category"),
107
+ (PartnerEvents, "event"),
108
+ ],
109
+ )
110
+ return data
111
+
112
+ @verify_credentials
113
+ def technique_summary(self, techniques: str):
114
+ """Get policy evaluation summary by technique"""
115
+ res = self.get(
116
+ f"{self.account.hq}/scm/technique_summary",
117
+ params=dict(techniques=techniques),
118
+ headers=self.account.headers,
119
+ timeout=30,
120
+ )
121
+ return res.json()
122
+
123
+ @verify_credentials
124
+ def evaluation_summary(
125
+ self,
126
+ endpoint_filter: str = None,
127
+ inbox_filter: str = None,
128
+ user_filter: str = None,
129
+ techniques: str = None,
130
+ ):
131
+ """Get policy evaluation summary"""
132
+ params = dict(
133
+ endpoints_filter=endpoint_filter,
134
+ inboxes_filter=inbox_filter,
135
+ users_filter=user_filter,
136
+ )
137
+ if techniques:
138
+ params["techniques"] = techniques
139
+ res = self.get(
140
+ f"{self.account.hq}/scm/evaluation_summary",
141
+ params=params,
142
+ headers=self.account.headers,
143
+ timeout=30,
144
+ )
145
+ data = res.json()
146
+ if self.account.resolve_enums:
147
+ self.resolve_enums(
148
+ data, [(Control, "control"), (ControlCategory, "category")]
149
+ )
150
+ return data
151
+
152
+ @verify_credentials
153
+ def evaluation(
154
+ self,
155
+ partner: Control,
156
+ instance_id: str,
157
+ filter: str = None,
158
+ policy_types: str = None,
159
+ techniques: str = None,
160
+ ):
161
+ """Get policy evaluations for given partner"""
162
+ params = {"$filter": filter}
163
+ if policy_types:
164
+ params["policy_types"] = policy_types
165
+ if techniques:
166
+ params["techniques"] = techniques
167
+ res = self.get(
168
+ f"{self.account.hq}/scm/evaluations/{partner.name}/{instance_id}",
169
+ params=params,
170
+ headers=self.account.headers,
171
+ timeout=30,
172
+ )
173
+ data = res.json()
174
+ if self.account.resolve_enums:
175
+ self.resolve_enums(data, [(PolicyType, "policy_type")])
176
+ return data
177
+
178
+ @verify_credentials
179
+ def update_evaluation(self, partner: Control, instance_id: str):
180
+ """Update policy evaluations for given partner"""
181
+ res = self.post(
182
+ f"{self.account.hq}/scm/evaluations/{partner.name}/{instance_id}",
183
+ headers=self.account.headers,
184
+ timeout=60,
185
+ )
186
+ return res.json()
187
+
188
+ @verify_credentials
189
+ def list_partner_groups(self, filter: str = None, orderby: str = None):
190
+ """List groups"""
191
+ params = {"$filter": filter, "$orderby": orderby}
192
+ res = self.get(
193
+ f"{self.account.hq}/scm/groups",
194
+ headers=self.account.headers,
195
+ params=params,
196
+ timeout=10,
197
+ )
198
+ groups = res.json()
199
+ if self.account.resolve_enums:
200
+ self.resolve_enums(groups, [(Control, "control")])
201
+ return groups
202
+
203
+ @verify_credentials
204
+ def update_partner_groups(
205
+ self, partner: Control, instance_id: str, group_ids: list[str]
206
+ ):
207
+ """Update groups"""
208
+ body = dict(group_ids=group_ids)
209
+ res = self.post(
210
+ f"{self.account.hq}/scm/groups/{partner.name}/{instance_id}",
211
+ headers=self.account.headers,
212
+ json=body,
213
+ timeout=10,
214
+ )
215
+ return res.json()
216
+
217
+ @verify_credentials
218
+ def list_object_exceptions(self):
219
+ """List object exceptions"""
220
+ res = self.get(
221
+ f"{self.account.hq}/scm/exceptions/objects",
222
+ headers=self.account.headers,
223
+ timeout=10,
224
+ )
225
+ exceptions = res.json()
226
+ if self.account.resolve_enums:
227
+ self.resolve_enums(exceptions, [(ControlCategory, "category")])
228
+ return exceptions
229
+
230
+ @verify_credentials
231
+ def create_object_exception(
232
+ self, category: ControlCategory, filter, name=None, expires: str = None
233
+ ):
234
+ """Create an object exception"""
235
+ body = dict(category=category.name, filter=filter)
236
+ if name:
237
+ body["name"] = name
238
+ if expires:
239
+ body["expires"] = expires
240
+ res = self.post(
241
+ f"{self.account.hq}/scm/exceptions/objects",
242
+ json=body,
243
+ headers=self.account.headers,
244
+ timeout=10,
245
+ )
246
+ return res.json()
247
+
248
+ @verify_credentials
249
+ def update_object_exception(
250
+ self, exception_id, expires=default, filter=None, name=None
251
+ ):
252
+ """Update an object exception"""
253
+ body = dict()
254
+ if expires != self.default:
255
+ body["expires"] = expires
256
+ if filter:
257
+ body["filter"] = filter
258
+ if name:
259
+ body["name"] = name
260
+ res = self.post(
261
+ f"{self.account.hq}/scm/exceptions/objects/{exception_id}",
262
+ json=body,
263
+ headers=self.account.headers,
264
+ timeout=10,
265
+ )
266
+ return res.json()
267
+
268
+ @verify_credentials
269
+ def delete_object_exception(self, exception_id):
270
+ """Delete an object exception"""
271
+ res = self.delete(
272
+ f"{self.account.hq}/scm/exceptions/objects/{exception_id}",
273
+ headers=self.account.headers,
274
+ timeout=10,
275
+ )
276
+ return res.json()
277
+
278
+ @verify_credentials
279
+ def list_policy_exceptions(self):
280
+ """List policy exceptions"""
281
+ res = self.get(
282
+ f"{self.account.hq}/scm/exceptions/policies",
283
+ headers=self.account.headers,
284
+ timeout=10,
285
+ )
286
+ exceptions = res.json()
287
+ if self.account.resolve_enums:
288
+ self.resolve_enums(
289
+ exceptions, [(Control, "control"), (ControlCategory, "category")]
290
+ )
291
+ return exceptions
292
+
293
+ @verify_credentials
294
+ def create_policy_exception(
295
+ self, partner: Control, instance_id: str, policy_id, setting_names, expires=None
296
+ ):
297
+ """Create policy exceptions"""
298
+ body = dict(
299
+ control=partner.name,
300
+ expires=expires,
301
+ instance_id=instance_id,
302
+ policy_id=policy_id,
303
+ setting_names=setting_names,
304
+ )
305
+ res = self.post(
306
+ f"{self.account.hq}/scm/exceptions/policies",
307
+ json=body,
308
+ headers=self.account.headers,
309
+ timeout=10,
310
+ )
311
+ return res.json()
312
+
313
+ @verify_credentials
314
+ def update_policy_exception(
315
+ self,
316
+ partner: Control,
317
+ instance_id: str,
318
+ policy_id,
319
+ expires=default,
320
+ setting_names=None,
321
+ ):
322
+ """Update policy exceptions"""
323
+ body = dict(control=partner.name, instance_id=instance_id, policy_id=policy_id)
324
+ if expires != self.default:
325
+ body["expires"] = expires
326
+ if setting_names:
327
+ body["setting_names"] = setting_names
328
+ res = self.put(
329
+ f"{self.account.hq}/scm/exceptions/policies",
330
+ json=body,
331
+ headers=self.account.headers,
332
+ timeout=10,
333
+ )
334
+ return res.json()
335
+
336
+ @verify_credentials
337
+ def delete_policy_exception(self, instance_id: str, policy_id: str):
338
+ """Delete policy exceptions"""
339
+ body = dict(instance_id=instance_id, policy_id=policy_id)
340
+ res = self.delete(
341
+ f"{self.account.hq}/scm/exceptions/policies",
342
+ json=body,
343
+ headers=self.account.headers,
344
+ timeout=10,
345
+ )
346
+ return res.json()
347
+
348
+ @verify_credentials
349
+ def list_views(self):
350
+ """List views"""
351
+ res = self.get(
352
+ f"{self.account.hq}/scm/views",
353
+ headers=self.account.headers,
354
+ timeout=10,
355
+ )
356
+ views = res.json()
357
+ if self.account.resolve_enums:
358
+ self.resolve_enums(views, [(ControlCategory, "category")])
359
+ return views
360
+
361
+ @verify_credentials
362
+ def create_view(self, category: ControlCategory, filter: str, name: str):
363
+ """Create a view"""
364
+ body = dict(category=category.name, filter=filter, name=name)
365
+ res = self.post(
366
+ f"{self.account.hq}/scm/views",
367
+ json=body,
368
+ headers=self.account.headers,
369
+ timeout=10,
370
+ )
371
+ return res.json()
372
+
373
+ @verify_credentials
374
+ def update_view(
375
+ self, view_id, category: ControlCategory = None, filter=None, name=None
376
+ ):
377
+ """Update a view"""
378
+ body = dict()
379
+ if category:
380
+ body["category"] = category.name
381
+ if filter:
382
+ body["filter"] = filter
383
+ if name:
384
+ body["name"] = name
385
+ res = self.post(
386
+ f"{self.account.hq}/scm/views/{view_id}",
387
+ json=body,
388
+ headers=self.account.headers,
389
+ timeout=10,
390
+ )
391
+ return res.json()
392
+
393
+ @verify_credentials
394
+ def delete_view(self, view_id):
395
+ """Delete a view"""
396
+ res = self.delete(
397
+ f"{self.account.hq}/scm/views/{view_id}",
398
+ headers=self.account.headers,
399
+ timeout=10,
400
+ )
401
+ return res.json()
402
+
403
+ @verify_credentials
404
+ def create_threat(
405
+ self,
406
+ name,
407
+ description=None,
408
+ id=None,
409
+ generated=None,
410
+ published=None,
411
+ source=None,
412
+ source_id=None,
413
+ techniques=None,
414
+ ):
415
+ """Create an scm threat"""
416
+ body = dict(name=name)
417
+ if description:
418
+ body["description"] = description
419
+ if id:
420
+ body["id"] = id
421
+ if generated:
422
+ body["generated"] = generated
423
+ if published:
424
+ body["published"] = published
425
+ if source:
426
+ body["source"] = source
427
+ if source_id:
428
+ body["source_id"] = source_id
429
+ if techniques:
430
+ body["techniques"] = techniques
431
+
432
+ res = self.post(
433
+ f"{self.account.hq}/scm/threats",
434
+ json=body,
435
+ headers=self.account.headers,
436
+ timeout=10,
437
+ )
438
+ return res.json()
439
+
440
+ @verify_credentials
441
+ def delete_threat(self, id):
442
+ """Delete an existing scm threat"""
443
+ res = self.delete(
444
+ f"{self.account.hq}/scm/threats/{id}",
445
+ headers=self.account.headers,
446
+ timeout=10,
447
+ )
448
+ return res.json()
449
+
450
+ @verify_credentials
451
+ def get_threat(self, id):
452
+ """Get specific scm threat"""
453
+ res = self.get(
454
+ f"{self.account.hq}/scm/threats/{id}",
455
+ headers=self.account.headers,
456
+ timeout=10,
457
+ )
458
+ return res.json()
459
+
460
+ @verify_credentials
461
+ def list_threats(self):
462
+ """List all scm threats"""
463
+ res = self.get(
464
+ f"{self.account.hq}/scm/threats", headers=self.account.headers, timeout=10
465
+ )
466
+ return res.json()
467
+
468
+ @verify_credentials
469
+ def parse_threat_intel(self, file: str):
470
+ with open(file, "rb") as f:
471
+ body = f.read()
472
+ res = self.post(
473
+ f"{self.account.hq}/scm/threat-intel",
474
+ data=body,
475
+ headers=self.account.headers | {"Content-Type": "application/pdf"},
476
+ timeout=30,
477
+ )
478
+ return res.json()
479
+
480
+ @verify_credentials
481
+ def parse_from_partner_advisory(self, partner: Control, advisory_id: str):
482
+ params = dict(advisory_id=advisory_id)
483
+ res = self.post(
484
+ f"{self.account.hq}/scm/partner-advisories/{partner.name}",
485
+ headers=self.account.headers,
486
+ json=params,
487
+ timeout=30,
488
+ )
489
+ return res.json()
490
+
491
+ @verify_credentials
492
+ def list_notifications(self):
493
+ res = self.get(
494
+ f"{self.account.hq}/scm/notifications",
495
+ headers=self.account.headers,
496
+ timeout=10,
497
+ )
498
+ notifications = res.json()
499
+ if self.account.resolve_enums:
500
+ self.resolve_enums(
501
+ notifications,
502
+ [
503
+ (ControlCategory, "control_category"),
504
+ (PartnerEvents, "event"),
505
+ (RunCode, "run_code"),
506
+ ],
507
+ )
508
+ return notifications
509
+
510
+ @verify_credentials
511
+ def delete_notification(self, notification_id: str):
512
+ res = self.delete(
513
+ f"{self.account.hq}/scm/notifications/{notification_id}",
514
+ headers=self.account.headers,
515
+ timeout=10,
516
+ )
517
+ return res.json()
518
+
519
+ @verify_credentials
520
+ def upsert_notification(
521
+ self,
522
+ control_category: ControlCategory,
523
+ event: PartnerEvents,
524
+ run_code: RunCode,
525
+ scheduled_hour: int,
526
+ emails: list[str] = None,
527
+ filter: str = None,
528
+ id: str = None,
529
+ message: str = "",
530
+ slack_urls: list[str] = None,
531
+ suppress_empty: bool = True,
532
+ teams_urls: list[str] = None,
533
+ title: str = "SCM Notification",
534
+ ):
535
+ body = dict(
536
+ control_category=control_category.name,
537
+ event=event.name,
538
+ run_code=run_code.name,
539
+ scheduled_hour=scheduled_hour,
540
+ suppress_empty=suppress_empty,
541
+ )
542
+ if id:
543
+ body["id"] = id
544
+ if filter:
545
+ body["filter"] = filter
546
+ if emails:
547
+ body["email"] = dict(emails=emails, message=message, subject=title)
548
+ if slack_urls:
549
+ body["slack"] = dict(hook_urls=slack_urls, message=message)
550
+ if teams_urls:
551
+ body["teams"] = dict(hook_urls=teams_urls, message=message)
552
+ res = self.put(
553
+ f"{self.account.hq}/scm/notifications",
554
+ json=body,
555
+ headers=self.account.headers,
556
+ timeout=10,
557
+ )
558
+ return res.json()
559
+
560
+ @verify_credentials
561
+ def list_notations(self):
562
+ """List notations"""
563
+ res = self.get(
564
+ f"{self.account.hq}/scm/notations",
565
+ headers=self.account.headers,
566
+ timeout=10,
567
+ )
568
+ notations = res.json()
569
+ if self.account.resolve_enums:
570
+ self.resolve_enums(notations, [(NotationType, "event")])
571
+ return notations
572
+
573
+ @verify_credentials
574
+ def list_history(
575
+ self, start_date: str = None, end_date: str = None, filter: str = None
576
+ ):
577
+ """List history"""
578
+ params = {"start_date": start_date, "end_date": end_date, "$filter": filter}
579
+ res = self.get(
580
+ f"{self.account.hq}/scm/history",
581
+ headers=self.account.headers,
582
+ params=params,
583
+ timeout=10,
584
+ )
585
+ history = res.json()
586
+ if self.account.resolve_enums:
587
+ self.resolve_enums(
588
+ history,
589
+ [
590
+ (Control, "control"),
591
+ (PartnerEvents, "event"),
592
+ (SCMCategory, "category"),
593
+ ],
594
+ )
595
+ return history
596
+
597
+ @verify_credentials
598
+ def get_report(self, report_id: str):
599
+ """Get SCM report by ID"""
600
+ res = self.get(
601
+ f"{self.account.hq}/scm/reports/{report_id}",
602
+ headers=self.account.headers,
603
+ timeout=10,
604
+ )
605
+ return res.json()
606
+
607
+ @verify_credentials
608
+ def list_reports(self):
609
+ """List SCM reports"""
610
+ res = self.get(
611
+ f"{self.account.hq}/scm/reports",
612
+ headers=self.account.headers,
613
+ timeout=10,
614
+ )
615
+ return res.json()
616
+
617
+ @verify_credentials
618
+ def delete_report(self, report_id: str):
619
+ """Delete SCM report by ID"""
620
+ res = self.delete(
621
+ f"{self.account.hq}/scm/reports/{report_id}",
622
+ headers=self.account.headers,
623
+ timeout=10,
624
+ )
625
+ return res.json()
626
+
627
+ @verify_credentials
628
+ def put_report(self, report_data: dict, report_id: str = None):
629
+ """Put SCM report by ID"""
630
+ res = self.put(
631
+ f"{self.account.hq}/scm/reports",
632
+ headers=self.account.headers,
633
+ json=dict(report=report_data, id=report_id),
634
+ timeout=10,
635
+ )
636
+ return res.json()
637
+
638
+ @verify_credentials
639
+ def get_chart_data(
640
+ self,
641
+ scm_category: SCMCategory,
642
+ sort_by: str,
643
+ group_by: str,
644
+ group_limit: int,
645
+ scopes: str = None,
646
+ filter: str = None,
647
+ ):
648
+ """Get SCM chart data"""
649
+ params = {
650
+ "scm_category": scm_category.name,
651
+ "sort_by": sort_by,
652
+ "group_by": group_by,
653
+ "group_limit": group_limit,
654
+ "scopes": scopes,
655
+ }
656
+ if filter:
657
+ params["$filter"] = filter
658
+ res = self.get(
659
+ f"{self.account.hq}/scm/chart_data",
660
+ headers=self.account.headers,
661
+ params=params,
662
+ timeout=30,
663
+ )
664
+ return res.json()
File without changes