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.
- prelude_cli_beta/cli.py +52 -0
- prelude_cli_beta/views/auth.py +56 -0
- prelude_cli_beta/views/build.py +488 -0
- prelude_cli_beta/views/configure.py +29 -0
- prelude_cli_beta/views/detect.py +438 -0
- prelude_cli_beta/views/generate.py +125 -0
- prelude_cli_beta/views/iam.py +368 -0
- prelude_cli_beta/views/jobs.py +50 -0
- prelude_cli_beta/views/partner.py +192 -0
- prelude_cli_beta/views/scm.py +744 -0
- prelude_cli_beta/views/shared.py +37 -0
- prelude_cli_beta-1407.dist-info/METADATA +38 -0
- prelude_cli_beta-1407.dist-info/RECORD +20 -0
- prelude_cli_beta-1407.dist-info/entry_points.txt +3 -0
- prelude_cli_beta-1407.dist-info/top_level.txt +1 -0
- prelude_cli_beta-1405.dist-info/METADATA +0 -46
- prelude_cli_beta-1405.dist-info/RECORD +0 -20
- prelude_cli_beta-1405.dist-info/top_level.txt +0 -1
- prelude_sdk_beta/controllers/build_controller.py +0 -309
- prelude_sdk_beta/controllers/detect_controller.py +0 -243
- prelude_sdk_beta/controllers/export_controller.py +0 -31
- prelude_sdk_beta/controllers/generate_controller.py +0 -40
- prelude_sdk_beta/controllers/http_controller.py +0 -63
- prelude_sdk_beta/controllers/iam_controller.py +0 -278
- prelude_sdk_beta/controllers/jobs_controller.py +0 -26
- prelude_sdk_beta/controllers/partner_controller.py +0 -166
- prelude_sdk_beta/controllers/probe_controller.py +0 -14
- prelude_sdk_beta/controllers/scm_controller.py +0 -424
- prelude_sdk_beta/models/account.py +0 -264
- prelude_sdk_beta/models/codes.py +0 -446
- {prelude_sdk_beta → prelude_cli_beta}/__init__.py +0 -0
- {prelude_sdk_beta/controllers → prelude_cli_beta/templates}/__init__.py +0 -0
- {prelude_sdk_beta/models → prelude_cli_beta/views}/__init__.py +0 -0
- {prelude_cli_beta-1405.dist-info → prelude_cli_beta-1407.dist-info}/WHEEL +0 -0
- {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()
|