prelude-cli-beta 1402__py3-none-any.whl → 1405__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-1405.dist-info/METADATA +46 -0
  2. prelude_cli_beta-1405.dist-info/RECORD +20 -0
  3. prelude_cli_beta-1405.dist-info/top_level.txt +1 -0
  4. prelude_sdk_beta/controllers/build_controller.py +309 -0
  5. prelude_sdk_beta/controllers/detect_controller.py +243 -0
  6. prelude_sdk_beta/controllers/export_controller.py +31 -0
  7. prelude_sdk_beta/controllers/generate_controller.py +40 -0
  8. prelude_sdk_beta/controllers/http_controller.py +63 -0
  9. prelude_sdk_beta/controllers/iam_controller.py +278 -0
  10. prelude_sdk_beta/controllers/jobs_controller.py +26 -0
  11. prelude_sdk_beta/controllers/partner_controller.py +166 -0
  12. prelude_sdk_beta/controllers/probe_controller.py +14 -0
  13. prelude_sdk_beta/controllers/scm_controller.py +424 -0
  14. prelude_sdk_beta/models/account.py +264 -0
  15. prelude_sdk_beta/models/codes.py +446 -0
  16. prelude_cli_beta/cli.py +0 -47
  17. prelude_cli_beta/views/auth.py +0 -56
  18. prelude_cli_beta/views/build.py +0 -488
  19. prelude_cli_beta/views/configure.py +0 -29
  20. prelude_cli_beta/views/detect.py +0 -438
  21. prelude_cli_beta/views/generate.py +0 -125
  22. prelude_cli_beta/views/iam.py +0 -368
  23. prelude_cli_beta/views/jobs.py +0 -50
  24. prelude_cli_beta/views/partner.py +0 -192
  25. prelude_cli_beta/views/scm.py +0 -471
  26. prelude_cli_beta/views/shared.py +0 -37
  27. prelude_cli_beta-1402.dist-info/METADATA +0 -38
  28. prelude_cli_beta-1402.dist-info/RECORD +0 -20
  29. prelude_cli_beta-1402.dist-info/entry_points.txt +0 -3
  30. prelude_cli_beta-1402.dist-info/top_level.txt +0 -1
  31. {prelude_cli_beta-1402.dist-info → prelude_cli_beta-1405.dist-info}/WHEEL +0 -0
  32. {prelude_cli_beta-1402.dist-info → prelude_cli_beta-1405.dist-info}/licenses/LICENSE +0 -0
  33. {prelude_cli_beta → prelude_sdk_beta}/__init__.py +0 -0
  34. {prelude_cli_beta/templates → prelude_sdk_beta/controllers}/__init__.py +0 -0
  35. {prelude_cli_beta/views → prelude_sdk_beta/models}/__init__.py +0 -0
@@ -0,0 +1,446 @@
1
+ import logging
2
+
3
+ from enum import Enum, EnumMeta
4
+
5
+
6
+ class MissingItem(EnumMeta):
7
+ def __getitem__(cls, name):
8
+ try:
9
+ return super().__getitem__(name.upper())
10
+ except (AttributeError, KeyError):
11
+ try:
12
+ return cls(int(name))
13
+ except ValueError:
14
+ return cls(name)
15
+
16
+
17
+ class RunCode(Enum, metaclass=MissingItem):
18
+ INVALID = -1
19
+ DAILY = 1
20
+ WEEKLY = 2
21
+ MONTHLY = 3
22
+ SMART = 4
23
+ DEBUG = 5
24
+ RUN_ONCE = 6
25
+ MONDAY = 10
26
+ TUESDAY = 11
27
+ WEDNESDAY = 12
28
+ THURSDAY = 13
29
+ FRIDAY = 14
30
+ SATURDAY = 15
31
+ SUNDAY = 16
32
+ MONTH_1 = 20
33
+
34
+ @classmethod
35
+ def _missing_(cls, value):
36
+ return RunCode.DAILY
37
+
38
+
39
+ class Mode(Enum, metaclass=MissingItem):
40
+ MANUAL = 0
41
+ FROZEN = 1
42
+ AUTOPILOT = 2
43
+
44
+ @classmethod
45
+ def _missing_(cls, value):
46
+ return Mode.MANUAL
47
+
48
+
49
+ class Permission(Enum, metaclass=MissingItem):
50
+ INVALID = -1
51
+ ADMIN = 0
52
+ EXECUTIVE = 1
53
+ BUILD = 2
54
+ SERVICE = 3
55
+ SUPPORT = 5
56
+
57
+ @classmethod
58
+ def _missing_(cls, value):
59
+ return Permission.INVALID
60
+
61
+
62
+ class ExitCode(Enum):
63
+ MISSING = -1
64
+ UNKNOWN_ERROR = 1
65
+ MALFORMED_TEST = 2
66
+ UNREPORTED = 3
67
+ PROCESS_BLOCKED = 9
68
+ PROCESS_BLOCKED_GRACEFULLY = 15
69
+ PROTECTED = 100
70
+ UNPROTECTED = 101
71
+ TIMED_OUT = 102
72
+ FAILED_CLEANUP = 103
73
+ TEST_NOT_RELEVANT = 104
74
+ DYNAMIC_QUARANTINE = 105
75
+ BLOCKED_AT_PERIMETER = 106
76
+ EXPLOIT_PREVENTED = 107
77
+ ENDPOINT_NOT_RELEVANT = 108
78
+ INSUFFICIENT_PRIVILEGES = 109
79
+ INCORRECTLY_BLOCKED = 110
80
+ PREVENTED_EXECUTION = 126
81
+ STATIC_QUARANTINE = 127
82
+ BLOCKED = 137
83
+ UNEXPECTED_ERROR = 256
84
+
85
+ @classmethod
86
+ def _missing_(cls, value):
87
+ if value and not isinstance(value, int):
88
+ return cls(int(value))
89
+ logging.warning("Unknown ExitCode: %s", str(value))
90
+ return ExitCode.MISSING
91
+
92
+ @property
93
+ def state(self):
94
+ for k, v in State.mapping().items():
95
+ if self in v:
96
+ return k
97
+ return State.NONE
98
+
99
+
100
+ class State(Enum):
101
+ NONE = 0
102
+ PROTECTED = 1
103
+ UNPROTECTED = 2
104
+ ERROR = 3
105
+ NOT_RELEVANT = 4
106
+
107
+ @classmethod
108
+ def mapping(cls):
109
+ return {
110
+ State.ERROR: [
111
+ ExitCode.FAILED_CLEANUP,
112
+ ExitCode.INCORRECTLY_BLOCKED,
113
+ ExitCode.MALFORMED_TEST,
114
+ ExitCode.TIMED_OUT,
115
+ ExitCode.UNEXPECTED_ERROR,
116
+ ExitCode.UNKNOWN_ERROR,
117
+ ExitCode.UNREPORTED,
118
+ ],
119
+ State.NONE: [ExitCode.MISSING],
120
+ State.NOT_RELEVANT: [
121
+ ExitCode.ENDPOINT_NOT_RELEVANT,
122
+ ExitCode.INSUFFICIENT_PRIVILEGES,
123
+ ExitCode.TEST_NOT_RELEVANT,
124
+ ],
125
+ State.PROTECTED: [
126
+ ExitCode.BLOCKED,
127
+ ExitCode.BLOCKED_AT_PERIMETER,
128
+ ExitCode.DYNAMIC_QUARANTINE,
129
+ ExitCode.EXPLOIT_PREVENTED,
130
+ ExitCode.PREVENTED_EXECUTION,
131
+ ExitCode.PROCESS_BLOCKED,
132
+ ExitCode.PROCESS_BLOCKED_GRACEFULLY,
133
+ ExitCode.PROTECTED,
134
+ ExitCode.STATIC_QUARANTINE,
135
+ ],
136
+ State.UNPROTECTED: [
137
+ ExitCode.UNPROTECTED,
138
+ ],
139
+ }
140
+
141
+
142
+ class DOS(Enum):
143
+ none = "none"
144
+ arm64 = "arm64"
145
+ x86_64 = "x86_64"
146
+ aarch64 = "arm64"
147
+ amd64 = "x86_64"
148
+ x86 = "x86_64"
149
+
150
+ @classmethod
151
+ def normalize(cls, dos: str):
152
+ try:
153
+ arch = dos.split("-", 1)[-1]
154
+ return dos[: -len(arch)].lower() + cls[arch.lower()].value
155
+ except (KeyError, IndexError, AttributeError):
156
+ return cls.none.value
157
+
158
+
159
+ class Control(Enum, metaclass=MissingItem):
160
+ INVALID = -1
161
+ NONE = 0
162
+ CROWDSTRIKE = 1
163
+ DEFENDER = 2
164
+ SPLUNK = 3
165
+ SENTINELONE = 4
166
+ VECTR = 5
167
+ S3 = 6
168
+ INTUNE = 7
169
+ SERVICENOW = 8
170
+ OKTA = 9
171
+ M365 = 10
172
+ ENTRA = 11
173
+ JAMF = 12
174
+ CROWDSTRIKE_IDENTITY = 13
175
+ GMAIL = 14
176
+ GOOGLE_IDENTITY = 15
177
+ DEFENDER_DISCOVERY = 16
178
+ TENABLE = 17
179
+ EC2 = 18
180
+ AWS_SSM = 19
181
+ AZURE_VM = 20
182
+ GITHUB = 21
183
+ TENABLE_DISCOVERY = 22
184
+ QUALYS = 23
185
+ QUALYS_DISCOVERY = 24
186
+
187
+ @classmethod
188
+ def _missing_(cls, value):
189
+ return Control.INVALID
190
+
191
+ @property
192
+ def control_category(self):
193
+ for k, v in ControlCategory.mapping().items():
194
+ if self in v:
195
+ return k
196
+ return ControlCategory.NONE
197
+
198
+ @property
199
+ def scm_category(self):
200
+ for k, v in SCMCategory.control_mapping().items():
201
+ if self in v:
202
+ return k
203
+ return SCMCategory.NONE
204
+
205
+
206
+ class ControlCategory(Enum, metaclass=MissingItem):
207
+ INVALID = -1
208
+ NONE = 0
209
+ CLOUD = 1
210
+ EMAIL = 2
211
+ IDENTITY = 3
212
+ NETWORK = 4
213
+ XDR = 5
214
+ ASSET_MANAGER = 6
215
+ DISCOVERED_DEVICES = 7
216
+ VULN_MANAGER = 8
217
+ SIEM = 9
218
+ PRIVATE_REPO = 10
219
+
220
+ @classmethod
221
+ def _missing_(cls, value):
222
+ return ControlCategory.INVALID
223
+
224
+ @classmethod
225
+ def mapping(cls):
226
+ return {
227
+ ControlCategory.ASSET_MANAGER: [
228
+ Control.AWS_SSM,
229
+ Control.INTUNE,
230
+ Control.JAMF,
231
+ ],
232
+ ControlCategory.CLOUD: [],
233
+ ControlCategory.DISCOVERED_DEVICES: [
234
+ Control.AZURE_VM,
235
+ Control.DEFENDER_DISCOVERY,
236
+ Control.EC2,
237
+ Control.QUALYS_DISCOVERY,
238
+ Control.SERVICENOW,
239
+ Control.TENABLE_DISCOVERY,
240
+ ],
241
+ ControlCategory.EMAIL: [
242
+ Control.GMAIL,
243
+ Control.M365,
244
+ ],
245
+ ControlCategory.IDENTITY: [
246
+ Control.CROWDSTRIKE_IDENTITY,
247
+ Control.ENTRA,
248
+ Control.GOOGLE_IDENTITY,
249
+ Control.OKTA,
250
+ ],
251
+ ControlCategory.NETWORK: [],
252
+ ControlCategory.PRIVATE_REPO: [
253
+ Control.GITHUB,
254
+ ],
255
+ ControlCategory.SIEM: [
256
+ Control.S3,
257
+ Control.SPLUNK,
258
+ Control.VECTR,
259
+ ],
260
+ ControlCategory.VULN_MANAGER: [Control.QUALYS, Control.TENABLE],
261
+ ControlCategory.XDR: [
262
+ Control.CROWDSTRIKE,
263
+ Control.DEFENDER,
264
+ Control.SENTINELONE,
265
+ ],
266
+ }
267
+
268
+
269
+ class SCMCategory(Enum, metaclass=MissingItem):
270
+ INVALID = -1
271
+ NONE = 0
272
+ ENDPOINT = 1
273
+ INBOX = 2
274
+ USER = 3
275
+
276
+ @classmethod
277
+ def _missing_(cls, value):
278
+ return SCMCategory.INVALID
279
+
280
+ @classmethod
281
+ def control_mapping(cls):
282
+ return {
283
+ SCMCategory.ENDPOINT: [
284
+ Control.AWS_SSM,
285
+ Control.AZURE_VM,
286
+ Control.CROWDSTRIKE,
287
+ Control.DEFENDER,
288
+ Control.DEFENDER_DISCOVERY,
289
+ Control.EC2,
290
+ Control.INTUNE,
291
+ Control.JAMF,
292
+ Control.QUALYS,
293
+ Control.QUALYS_DISCOVERY,
294
+ Control.SENTINELONE,
295
+ Control.SERVICENOW,
296
+ Control.TENABLE,
297
+ Control.TENABLE_DISCOVERY,
298
+ ],
299
+ SCMCategory.USER: [
300
+ Control.CROWDSTRIKE_IDENTITY,
301
+ Control.ENTRA,
302
+ Control.GOOGLE_IDENTITY,
303
+ Control.OKTA,
304
+ ],
305
+ SCMCategory.INBOX: [
306
+ Control.GMAIL,
307
+ Control.M365,
308
+ ],
309
+ }
310
+
311
+ @classmethod
312
+ def category_mapping(cls):
313
+ return {
314
+ SCMCategory.ENDPOINT: [
315
+ ControlCategory.ASSET_MANAGER,
316
+ ControlCategory.DISCOVERED_DEVICES,
317
+ ControlCategory.VULN_MANAGER,
318
+ ControlCategory.XDR,
319
+ ],
320
+ SCMCategory.USER: [ControlCategory.IDENTITY],
321
+ SCMCategory.INBOX: [ControlCategory.EMAIL],
322
+ }
323
+
324
+
325
+ class BackgroundJobTypes(Enum, metaclass=MissingItem):
326
+ INVALID = -1
327
+ UPDATE_SCM = 1
328
+ DEPLOY_PROBE = 2
329
+ OBSERVED_DETECTED = 3
330
+ PRELUDE_ENDPOINT_SYNC = 4
331
+ EXPORT_SCM = 5
332
+ PARTNER_GROUPS = 6
333
+
334
+ @classmethod
335
+ def _missing_(cls, value):
336
+ return BackgroundJobTypes.INVALID
337
+
338
+
339
+ class EDRResponse(Enum, metaclass=MissingItem):
340
+ INVALID = -1
341
+ OBSERVE = 1
342
+ DETECT = 2
343
+ PREVENT = 3
344
+
345
+ @classmethod
346
+ def _missing_(cls, value):
347
+ return EDRResponse.INVALID
348
+
349
+
350
+ class PartnerEvents(Enum, metaclass=MissingItem):
351
+ INVALID = -1
352
+ REDUCED_FUNCTIONALITY_MODE = 1
353
+ NO_EDR = 2
354
+ MISSING_EDR_POLICY = 3
355
+ MISSING_AV_POLICY = 4
356
+ MISSING_MFA = 5
357
+ NO_ASSET_MANAGER = 6
358
+ MISCONFIGURED_POLICY_SETTING = 7
359
+ MISSING_SCAN = 8
360
+ OUT_OF_DATE_SCAN = 9
361
+ NO_VULN_MANAGER = 10
362
+ USER_MISSING_ASSET_MANAGER = 11
363
+ USER_MISSING_EDR = 12
364
+ USER_MISSING_VULN_MANAGER = 13
365
+
366
+ @classmethod
367
+ def _missing_(cls, value):
368
+ return PartnerEvents.INVALID
369
+
370
+ @classmethod
371
+ def control_category_mapping(cls):
372
+ return {
373
+ PartnerEvents.REDUCED_FUNCTIONALITY_MODE: [ControlCategory.XDR],
374
+ PartnerEvents.NO_EDR: [
375
+ ControlCategory.XDR,
376
+ ],
377
+ PartnerEvents.MISSING_EDR_POLICY: [ControlCategory.XDR],
378
+ PartnerEvents.MISSING_AV_POLICY: [ControlCategory.XDR],
379
+ PartnerEvents.MISSING_MFA: [ControlCategory.IDENTITY],
380
+ PartnerEvents.NO_ASSET_MANAGER: [ControlCategory.ASSET_MANAGER],
381
+ PartnerEvents.MISCONFIGURED_POLICY_SETTING: [
382
+ ControlCategory.XDR,
383
+ ControlCategory.EMAIL,
384
+ ControlCategory.IDENTITY,
385
+ ],
386
+ PartnerEvents.MISSING_SCAN: [ControlCategory.VULN_MANAGER],
387
+ PartnerEvents.OUT_OF_DATE_SCAN: [ControlCategory.VULN_MANAGER],
388
+ PartnerEvents.NO_VULN_MANAGER: [ControlCategory.VULN_MANAGER],
389
+ PartnerEvents.USER_MISSING_ASSET_MANAGER: [ControlCategory.IDENTITY],
390
+ PartnerEvents.USER_MISSING_EDR: [ControlCategory.IDENTITY],
391
+ PartnerEvents.USER_MISSING_VULN_MANAGER: [ControlCategory.IDENTITY],
392
+ }
393
+
394
+
395
+ class AlertTypes(Enum, metaclass=MissingItem):
396
+ INVALID = -1
397
+ NEW_REDUCED_FUNCTIONALITY_MODE_ENDPOINTS = 1
398
+ NEW_NO_EDR_ENDPOINTS = 2
399
+ NEW_MISSING_EDR_POLICY_ENDPOINTS = 3
400
+ NEW_MISSING_AV_POLICY_ENDPOINTS = 4
401
+ NEW_MISSING_MFA_USERS = 5
402
+ NEW_NO_ASSET_MANAGER_ENDPOINTS = 6
403
+ NEW_POLICY_SETTING_FAILURE = 7
404
+ NEW_POLICY_SETTING_PASS = 8
405
+ NEW_MISSING_SCAN_ENDPOINTS = 9
406
+ NEW_NO_VULN_MANAGER_ENDPOINTS = 10
407
+ NEW_OUT_OF_DATE_SCAN_ENDPOINTS = 11
408
+ NEW_USER_MISSING_ASSET_MANAGER = 12
409
+ NEW_USER_MISSING_EDR = 13
410
+ NEW_USER_MISSING_VULN_MANAGER = 14
411
+
412
+ @classmethod
413
+ def _missing_(cls, value):
414
+ return AlertTypes.INVALID
415
+
416
+
417
+ class PolicyType(Enum, metaclass=MissingItem):
418
+ INVALID = 0
419
+ EDR = 1
420
+ AV = 2
421
+ IDENTITY_PASSWORD = 3
422
+ EMAIL_ANTIPHISH = 4
423
+ EMAIL_OUTBOUND = 5
424
+ EMAIL_CONTENT = 6
425
+ EMAIL_MALWARE = 7
426
+ EMAIL_ATTACHMENT = 8
427
+ EMAIL_LINKS = 9
428
+ EMAIL_DKIM = 10
429
+ DEVICE_COMPLIANCE = 11
430
+ IDENTITY_MFA = 12
431
+
432
+ @classmethod
433
+ def _missing_(cls, value):
434
+ return PolicyType.INVALID
435
+
436
+
437
+ class Platform(Enum, metaclass=MissingItem):
438
+ INVALID = 0
439
+ WINDOWS = 1
440
+ DARWIN = 2
441
+ LINUX = 3
442
+ ALL = 4
443
+
444
+ @classmethod
445
+ def _missing_(cls, value):
446
+ return Platform.INVALID
prelude_cli_beta/cli.py DELETED
@@ -1,47 +0,0 @@
1
- import click
2
-
3
- from prelude_cli.views.auth import auth
4
- from prelude_cli.views.build import build
5
- from prelude_cli.views.configure import configure
6
- from prelude_cli.views.detect import detect
7
- from prelude_cli.views.generate import generate
8
- from prelude_cli.views.iam import iam
9
- from prelude_cli.views.jobs import jobs
10
- from prelude_cli.views.partner import partner
11
- from prelude_cli.views.scm import scm
12
- from prelude_sdk.models.account import Account, Keychain
13
-
14
-
15
- def complete_profile(ctx, param, incomplete):
16
- return [x for x in Keychain().read_keychain() if x.startswith(incomplete)]
17
-
18
-
19
- @click.group(invoke_without_command=True)
20
- @click.version_option()
21
- @click.pass_context
22
- @click.option(
23
- "--profile",
24
- default="default",
25
- help="The prelude keychain profile to use",
26
- show_default=True,
27
- shell_complete=complete_profile,
28
- )
29
- def cli(ctx, profile):
30
- ctx.obj = Account.from_keychain(profile=profile)
31
- if ctx.invoked_subcommand is None:
32
- click.echo(ctx.get_help())
33
-
34
-
35
- cli.add_command(auth)
36
- cli.add_command(build)
37
- cli.add_command(configure)
38
- cli.add_command(detect)
39
- cli.add_command(generate)
40
- cli.add_command(iam)
41
- cli.add_command(jobs)
42
- cli.add_command(partner)
43
- cli.add_command(scm)
44
-
45
-
46
- if __name__ == "__main__":
47
- cli()
@@ -1,56 +0,0 @@
1
- import click
2
- import webbrowser
3
-
4
- from prelude_cli.views.shared import Spinner, pretty_print
5
-
6
-
7
- @click.group()
8
- @click.pass_context
9
- def auth(ctx):
10
- """Authentication"""
11
- pass
12
-
13
-
14
- @auth.command("login")
15
- @click.option("-p", "--password", type=str, help="password for login")
16
- @click.option(
17
- "-t",
18
- "--temp_password",
19
- type=str,
20
- help="temporary password for login (if set, `password` will become your new password)",
21
- )
22
- @click.pass_obj
23
- @pretty_print
24
- def login(account, password, temp_password):
25
- """Login using password or SSO"""
26
- if not account.oidc:
27
- password = password or click.prompt("Password", type=str, hide_input=True)
28
- with Spinner(description="Logging in and saving tokens"):
29
- new_password = password if temp_password else None
30
- password = temp_password or password
31
- return (
32
- account.password_login(password, new_password),
33
- "Login with password successful",
34
- )
35
-
36
- url = f"{account.hq.replace('api', 'platform')}/cli-auth?handle={account.handle}&provider={account.oidc}"
37
- if account.oidc == "custom":
38
- slug = account.slug or click.prompt("Please enter your account slug")
39
- url += f"&slug={slug}"
40
- webbrowser.open(url)
41
- code = click.prompt(
42
- f"Launching browser for authentication:\n\n{url}\n\nPlease enter your authorization code here"
43
- )
44
- verifier, authorization_code = code.split("/")
45
- with Spinner(description="Logging in and saving tokens"):
46
- tokens = account.exchange_authorization_code(authorization_code, verifier)
47
- return tokens, "Login with SSO successful"
48
-
49
-
50
- @auth.command("refresh")
51
- @click.pass_obj
52
- @pretty_print
53
- def refresh(account):
54
- """Refresh your tokens"""
55
- with Spinner(description="Refreshing tokens"):
56
- return account.refresh_tokens(), "New access tokens saved"