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
@@ -1,243 +0,0 @@
1
- from prelude_sdk.controllers.http_controller import HttpController
2
- from prelude_sdk.models.account import verify_credentials
3
-
4
-
5
- class DetectController(HttpController):
6
-
7
- def __init__(self, account):
8
- super().__init__(account)
9
-
10
- def register_endpoint(self, host, serial_num, reg_string, tags=None):
11
- """Register (or re-register) an endpoint to your account"""
12
- body = dict(id=f"{host}:{serial_num}")
13
- if tags:
14
- body["tags"] = tags
15
- account, token = reg_string.split("/")
16
-
17
- res = self._session.post(
18
- f"{self.account.hq}/detect/endpoint",
19
- headers=dict(account=account, token=token, _product="py-sdk"),
20
- json=body,
21
- timeout=10,
22
- )
23
- return res.text
24
-
25
- @verify_credentials
26
- def update_endpoint(self, endpoint_id, tags=None):
27
- """Update an endpoint in your account"""
28
- body = dict()
29
- if tags is not None:
30
- body["tags"] = tags
31
-
32
- res = self.post(
33
- f"{self.account.hq}/detect/endpoint/{endpoint_id}",
34
- headers=self.account.headers,
35
- json=body,
36
- timeout=10,
37
- )
38
- return res.json()
39
-
40
- @verify_credentials
41
- def delete_endpoint(self, ident: str):
42
- """Delete an endpoint from your account"""
43
- params = dict(id=ident)
44
- res = self.delete(
45
- f"{self.account.hq}/detect/endpoint",
46
- headers=self.account.headers,
47
- json=params,
48
- timeout=10,
49
- )
50
- return res.json()
51
-
52
- @verify_credentials
53
- def list_endpoints(self, days: int = 90):
54
- """List all endpoints on your account"""
55
- params = dict(days=days)
56
- res = self.get(
57
- f"{self.account.hq}/detect/endpoint",
58
- headers=self.account.headers,
59
- params=params,
60
- timeout=10,
61
- )
62
- return res.json()
63
-
64
- @verify_credentials
65
- def describe_activity(self, filters: dict, view: str = "protected"):
66
- """Get report for an Account"""
67
- params = dict(view=view, **filters)
68
- res = self.get(
69
- f"{self.account.hq}/detect/activity",
70
- headers=self.account.headers,
71
- params=params,
72
- timeout=10,
73
- )
74
- return res.json()
75
-
76
- @verify_credentials
77
- def threat_hunt_activity(self, threat_hunt_id=None, test_id=None, threat_id=None):
78
- """Get threat hunt activity"""
79
- filters = dict(
80
- threat_hunt_id=threat_hunt_id, test_id=test_id, threat_id=threat_id
81
- )
82
- res = self.get(
83
- f"{self.account.hq}/detect/threat_hunt_activity",
84
- headers=self.account.headers,
85
- params=filters,
86
- timeout=10,
87
- )
88
- return res.json()
89
-
90
- @verify_credentials
91
- def list_tests(self, filters: dict = None):
92
- """List all tests available to an account"""
93
- res = self.get(
94
- f"{self.account.hq}/detect/tests",
95
- headers=self.account.headers,
96
- params=filters if filters else {},
97
- timeout=10,
98
- )
99
- return res.json()
100
-
101
- @verify_credentials
102
- def get_test(self, test_id):
103
- """Get properties of an existing test"""
104
- res = self.get(
105
- f"{self.account.hq}/detect/tests/{test_id}",
106
- headers=self.account.headers,
107
- timeout=10,
108
- )
109
- return res.json()
110
-
111
- @verify_credentials
112
- def list_techniques(self):
113
- """List techniques"""
114
- res = self.get(
115
- f"{self.account.hq}/detect/techniques",
116
- headers=self.account.headers,
117
- timeout=10,
118
- )
119
- return res.json()
120
-
121
- @verify_credentials
122
- def list_threats(self):
123
- """List threats"""
124
- res = self.get(
125
- f"{self.account.hq}/detect/threats",
126
- headers=self.account.headers,
127
- params={},
128
- timeout=10,
129
- )
130
- return res.json()
131
-
132
- @verify_credentials
133
- def get_threat(self, threat_id):
134
- """Get properties of an existing threat"""
135
- res = self.get(
136
- f"{self.account.hq}/detect/threats/{threat_id}",
137
- headers=self.account.headers,
138
- timeout=10,
139
- )
140
- return res.json()
141
-
142
- @verify_credentials
143
- def list_detections(self):
144
- """List detections"""
145
- res = self.get(
146
- f"{self.account.hq}/detect/detections",
147
- headers=self.account.headers,
148
- params={},
149
- timeout=10,
150
- )
151
- return res.json()
152
-
153
- @verify_credentials
154
- def get_detection(self, detection_id):
155
- """Get properties of an existing detection"""
156
- res = self.get(
157
- f"{self.account.hq}/detect/detections/{detection_id}",
158
- headers=self.account.headers,
159
- timeout=10,
160
- )
161
- return res.json()
162
-
163
- @verify_credentials
164
- def list_threat_hunts(self, filters: dict = None):
165
- """List threat hunts"""
166
- res = self.get(
167
- f"{self.account.hq}/detect/threat_hunts",
168
- headers=self.account.headers,
169
- params=filters if filters else {},
170
- timeout=10,
171
- )
172
- return res.json()
173
-
174
- @verify_credentials
175
- def get_threat_hunt(self, threat_hunt_id):
176
- """Get properties of an existing threat hunt"""
177
- res = self.get(
178
- f"{self.account.hq}/detect/threat_hunts/{threat_hunt_id}",
179
- headers=self.account.headers,
180
- timeout=10,
181
- )
182
- return res.json()
183
-
184
- @verify_credentials
185
- def do_threat_hunt(self, threat_hunt_id):
186
- """Run a threat hunt"""
187
- res = self.post(
188
- f"{self.account.hq}/detect/threat_hunts/{threat_hunt_id}",
189
- headers=self.account.headers,
190
- timeout=10,
191
- )
192
- return res.json()
193
-
194
- @verify_credentials
195
- def download(self, test_id, filename):
196
- """Clone a test file or attachment"""
197
- res = self.get(
198
- f"{self.account.hq}/detect/tests/{test_id}/{filename}",
199
- headers=self.account.headers,
200
- timeout=10,
201
- )
202
- return res.content
203
-
204
- @verify_credentials
205
- def schedule(self, items: list):
206
- """Schedule tests and threats so endpoints will start running them
207
-
208
- Example: items=[dict(run_code='DAILY', tags='grp-1,grp2', test_id='123-123-123'),
209
- dict(run_code='DAILY', tags='grp-1', threat_id='abc-def-ghi')]
210
- """
211
- res = self.post(
212
- url=f"{self.account.hq}/detect/queue",
213
- headers=self.account.headers,
214
- json=dict(items=items),
215
- timeout=10,
216
- )
217
- return res.json()
218
-
219
- @verify_credentials
220
- def unschedule(self, items: list):
221
- """Unschedule tests and threats so endpoints will stop running them
222
-
223
- Example: items=[dict(tags='grp-1,grp2', test_id='123-123-123'),
224
- dict(tags='grp-1', threat_id='abc-def-ghi')]
225
- """
226
- res = self.delete(
227
- f"{self.account.hq}/detect/queue",
228
- headers=self.account.headers,
229
- json=dict(items=items),
230
- timeout=10,
231
- )
232
- return res.json()
233
-
234
- @verify_credentials
235
- def accept_terms(self, name, version):
236
- """Accept terms and conditions"""
237
- res = self.post(
238
- f"{self.account.hq}/iam/terms",
239
- headers=self.account.headers,
240
- json=dict(name=name, version=version),
241
- timeout=10,
242
- )
243
- return res.json()
@@ -1,31 +0,0 @@
1
- from prelude_sdk.controllers.http_controller import HttpController
2
- from prelude_sdk.models.account import verify_credentials
3
- from prelude_sdk.models.codes import SCMCategory
4
-
5
-
6
- class ExportController(HttpController):
7
-
8
- def __init__(self, account):
9
- super().__init__(account)
10
-
11
- @verify_credentials
12
- def export_scm(
13
- self,
14
- export_type: SCMCategory,
15
- filter: str = None,
16
- orderby: str = None,
17
- top: int = None,
18
- ):
19
- """Download partner data as a CSV"""
20
- params = {
21
- "$filter": filter,
22
- "$orderby": orderby,
23
- "$top": top,
24
- }
25
- res = self.post(
26
- f"{self.account.hq}/export/scm/{export_type.name}",
27
- params=params,
28
- headers=self.account.headers,
29
- timeout=10,
30
- )
31
- return res.json()
@@ -1,40 +0,0 @@
1
- from prelude_sdk.controllers.http_controller import HttpController
2
- from prelude_sdk.models.account import verify_credentials
3
- from prelude_sdk.models.codes import Control
4
-
5
-
6
- class GenerateController(HttpController):
7
- def __init__(self, account):
8
- super().__init__(account)
9
-
10
- @verify_credentials
11
- def upload_threat_intel(self, file: str):
12
- with open(file, "rb") as f:
13
- body = f.read()
14
- res = self.post(
15
- f"{self.account.hq}/generate/threat-intel",
16
- data=body,
17
- headers=self.account.headers | {"Content-Type": "application/pdf"},
18
- timeout=30,
19
- )
20
- return res.json()
21
-
22
- @verify_credentials
23
- def get_threat_intel(self, job_id: str):
24
- res = self.get(
25
- f"{self.account.hq}/generate/threat-intel/{job_id}",
26
- headers=self.account.headers,
27
- timeout=10,
28
- )
29
- return res.json()
30
-
31
- @verify_credentials
32
- def generate_from_partner_advisory(self, partner: Control, advisory_id: str):
33
- params = dict(advisory_id=advisory_id)
34
- res = self.post(
35
- f"{self.account.hq}/generate/partner-advisories/{partner.name}",
36
- headers=self.account.headers,
37
- json=params,
38
- timeout=30,
39
- )
40
- return res.json()
@@ -1,63 +0,0 @@
1
- import os
2
- import requests
3
-
4
- from requests.adapters import HTTPAdapter, Retry
5
-
6
-
7
- PRELUDE_BACKOFF_FACTOR = int(os.getenv("PRELUDE_BACKOFF_FACTOR", 30))
8
- PRELUDE_BACKOFF_TOTAL = int(os.getenv("PRELUDE_BACKOFF_TOTAL", 0))
9
-
10
-
11
- class HttpController(object):
12
- def __init__(self, account):
13
- self._session = requests.Session()
14
- self.account = account
15
-
16
- retry = Retry(
17
- total=PRELUDE_BACKOFF_TOTAL,
18
- backoff_factor=PRELUDE_BACKOFF_FACTOR,
19
- status_forcelist=[429],
20
- )
21
-
22
- self._session.mount("http://", HTTPAdapter(max_retries=retry))
23
- self._session.mount("https://", HTTPAdapter(max_retries=retry))
24
-
25
- def get(self, url, retry=True, **kwargs):
26
- res = self._session.get(url, **kwargs)
27
- if res.status_code == 200:
28
- return res
29
- if res.status_code == 401 and retry and self.account.token_location:
30
- self.account.refresh_tokens()
31
- self.account.update_auth_header()
32
- return self.get(url, retry=False, **kwargs)
33
- raise Exception(res.text)
34
-
35
- def post(self, url, retry=True, **kwargs):
36
- res = self._session.post(url, **kwargs)
37
- if res.status_code == 200:
38
- return res
39
- if res.status_code == 401 and retry and self.account.token_location:
40
- self.account.refresh_tokens()
41
- self.account.update_auth_header()
42
- return self.post(url, retry=False, **kwargs)
43
- raise Exception(res.text)
44
-
45
- def delete(self, url, retry=True, **kwargs):
46
- res = self._session.delete(url, **kwargs)
47
- if res.status_code == 200:
48
- return res
49
- if res.status_code == 401 and retry and self.account.token_location:
50
- self.account.refresh_tokens()
51
- self.account.update_auth_header()
52
- return self.delete(url, retry=False, **kwargs)
53
- raise Exception(res.text)
54
-
55
- def put(self, url, retry=True, **kwargs):
56
- res = self._session.put(url, **kwargs)
57
- if res.status_code == 200:
58
- return res
59
- if res.status_code == 401 and retry and self.account.token_location:
60
- self.account.refresh_tokens()
61
- self.account.update_auth_header()
62
- return self.put(url, retry=False, **kwargs)
63
- raise Exception(res.text)
@@ -1,278 +0,0 @@
1
- from prelude_sdk.controllers.http_controller import HttpController
2
- from prelude_sdk.models.account import verify_credentials
3
- from prelude_sdk.models.codes import Mode, Permission
4
-
5
-
6
- class IAMAccountController(HttpController):
7
-
8
- def __init__(self, account):
9
- super().__init__(account)
10
-
11
- @verify_credentials
12
- def get_account(self):
13
- """Get account properties"""
14
- res = self.get(
15
- f"{self.account.hq}/iam/account", headers=self.account.headers, timeout=10
16
- )
17
- return res.json()
18
-
19
- @verify_credentials
20
- def purge_account(self):
21
- """Delete an account and all things in it"""
22
- res = self.delete(
23
- f"{self.account.hq}/iam/account", headers=self.account.headers, timeout=10
24
- )
25
- return res.json()
26
-
27
- @verify_credentials
28
- def update_account(self, mode: Mode = None, company: str = None, slug: str = None):
29
- """Update properties on an account"""
30
- body = dict()
31
- if mode is not None:
32
- body["mode"] = mode.name
33
- if company is not None:
34
- body["company"] = company
35
- if slug is not None:
36
- body["slug"] = slug
37
-
38
- res = self.put(
39
- f"{self.account.hq}/iam/account",
40
- headers=self.account.headers,
41
- json=body,
42
- timeout=10,
43
- )
44
- return res.json()
45
-
46
- @verify_credentials
47
- def attach_oidc(
48
- self,
49
- client_id: str,
50
- client_secret: str,
51
- issuer: str,
52
- oidc_url: str,
53
- ):
54
- """Attach OIDC to an account"""
55
- email_attr = "email"
56
- if issuer == "azure":
57
- email_attr = "upn"
58
- body = dict(
59
- client_id=client_id,
60
- client_secret=client_secret,
61
- email_attr=email_attr,
62
- issuer=issuer,
63
- oidc_url=oidc_url,
64
- )
65
-
66
- res = self.post(
67
- f"{self.account.hq}/iam/account/oidc",
68
- headers=self.account.headers,
69
- json=body,
70
- timeout=10,
71
- )
72
- return res.json()
73
-
74
- @verify_credentials
75
- def detach_oidc(self):
76
- """Detach OIDC to an account"""
77
- res = self.delete(
78
- f"{self.account.hq}/iam/account/oidc",
79
- headers=self.account.headers,
80
- timeout=10,
81
- )
82
- return res.json()
83
-
84
- @verify_credentials
85
- def invite_user(
86
- self,
87
- email: str,
88
- oidc: str | None,
89
- permission: Permission,
90
- name: str | None = None,
91
- ):
92
- """Invite a new user to the account"""
93
- body = dict(permission=permission.name, handle=email, oidc=oidc)
94
- if name:
95
- body["name"] = name
96
-
97
- res = self.post(
98
- url=f"{self.account.hq}/iam/account/user",
99
- json=body,
100
- headers=self.account.headers,
101
- timeout=10,
102
- )
103
- return res.json()
104
-
105
- @verify_credentials
106
- def create_service_user(self, name: str):
107
- """Create a service user"""
108
- body = dict(name=name)
109
-
110
- res = self.post(
111
- f"{self.account.hq}/iam/account/service_user",
112
- json=body,
113
- headers=self.account.headers,
114
- timeout=10,
115
- )
116
- return res.json()
117
-
118
- @verify_credentials
119
- def delete_service_user(self, handle: str):
120
- """Delete service user"""
121
- body = dict(handle=handle)
122
-
123
- res = self.delete(
124
- f"{self.account.hq}/iam/account/service_user",
125
- json=body,
126
- headers=self.account.headers,
127
- timeout=10,
128
- )
129
- return res.json()
130
-
131
- @verify_credentials
132
- def update_account_user(
133
- self,
134
- email: str,
135
- oidc: str | None,
136
- permission: Permission = None,
137
- ):
138
- """Update properties on an account user"""
139
- body = dict(handle=email, oidc=oidc)
140
- if permission is not None:
141
- body["permission"] = permission.name
142
-
143
- res = self.put(
144
- f"{self.account.hq}/iam/account/user",
145
- json=body,
146
- headers=self.account.headers,
147
- timeout=10,
148
- )
149
- return res.json()
150
-
151
- @verify_credentials
152
- def remove_user(self, email: str, oidc: str | None):
153
- """Remove user from the account"""
154
- params = dict(handle=email, oidc=oidc)
155
-
156
- res = self.delete(
157
- f"{self.account.hq}/iam/account/user",
158
- params=params,
159
- headers=self.account.headers,
160
- timeout=10,
161
- )
162
- return res.json()
163
-
164
- @verify_credentials
165
- def audit_logs(self, days: int = 7, limit: int = 1000):
166
- """Get audit logs from the last X days"""
167
- params = dict(days=days, limit=limit)
168
- res = self.get(
169
- f"{self.account.hq}/iam/audit",
170
- headers=self.account.headers,
171
- params=params,
172
- timeout=30,
173
- )
174
- return res.json()
175
-
176
-
177
- def sign_up(self, company, email, name):
178
- """(NOT AVAIABLE IN PRODUCTION) Create a new user and account"""
179
- body = dict(company=company, email=email, name=name)
180
-
181
- res = self._session.post(
182
- f"{self.account.hq}/iam/new_user_and_account",
183
- headers=self.account.headers,
184
- json=body,
185
- timeout=20,
186
- )
187
- data = res.json()
188
- if self.account.profile:
189
- self.account.keychain.configure_keychain(
190
- account=data["account_id"],
191
- handle=data["user_id"],
192
- hq=self.account.hq,
193
- profile=self.account.profile,
194
- )
195
- return data
196
-
197
-
198
- class IAMUserController(HttpController):
199
-
200
- def __init__(self, account):
201
- super().__init__(account)
202
-
203
- @verify_credentials
204
- def list_accounts(self):
205
- """List all accounts for your user"""
206
- res = self.get(
207
- f"{self.account.hq}/iam/user/account",
208
- headers=self.account.headers,
209
- timeout=10,
210
- )
211
- return res.json()
212
-
213
- @verify_credentials
214
- def purge_user(self):
215
- """Delete your user"""
216
- res = self.delete(
217
- f"{self.account.hq}/iam/user", headers=self.account.headers, timeout=10
218
- )
219
- return res.json()
220
-
221
- @verify_credentials
222
- def update_user(
223
- self,
224
- name: str = None,
225
- ):
226
- """Update properties on a user"""
227
- body = dict()
228
- if name is not None:
229
- body["name"] = name
230
-
231
- res = self.put(
232
- f"{self.account.hq}/iam/user",
233
- json=body,
234
- headers=self.account.headers,
235
- timeout=10,
236
- )
237
- return res.json()
238
-
239
- def forgot_password(self):
240
- """Send a forgot password email"""
241
- body = dict(handle=self.account.handle)
242
-
243
- res = self.post(
244
- f"{self.account.hq}/iam/user/forgot_password",
245
- json=body,
246
- headers=self.account.headers,
247
- timeout=10,
248
- )
249
- return res.json()
250
-
251
- def confirm_forgot_password(self, confirmation_code: str, new_password: str):
252
- """Change a password using confirmation code"""
253
- body = dict(
254
- handle=self.account.handle,
255
- confirmation_code=confirmation_code,
256
- password=new_password,
257
- )
258
-
259
- res = self.post(
260
- f"{self.account.hq}/iam/user/forgot_password",
261
- json=body,
262
- headers=self.account.headers,
263
- timeout=10,
264
- )
265
- return res.json()
266
-
267
- @verify_credentials
268
- def change_password(self, current_password: str, new_password: str):
269
- """Change your password"""
270
- body = dict(current_password=current_password, new_password=new_password)
271
-
272
- res = self.post(
273
- f"{self.account.hq}/iam/user/change_password",
274
- json=body,
275
- headers=self.account.headers,
276
- timeout=10,
277
- )
278
- return res.json()
@@ -1,26 +0,0 @@
1
- from prelude_sdk.controllers.http_controller import HttpController
2
- from prelude_sdk.models.account import verify_credentials
3
-
4
-
5
- class JobsController(HttpController):
6
-
7
- def __init__(self, account):
8
- super().__init__(account)
9
-
10
- @verify_credentials
11
- def job_statuses(self):
12
- """Get job statuses"""
13
- res = self.get(
14
- f"{self.account.hq}/jobs/statuses", headers=self.account.headers, timeout=30
15
- )
16
- return res.json()
17
-
18
- @verify_credentials
19
- def job_status(self, job_id: str):
20
- """Get job status given job ID"""
21
- res = self.get(
22
- f"{self.account.hq}/jobs/statuses/{job_id}",
23
- headers=self.account.headers,
24
- timeout=30,
25
- )
26
- return res.json()