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.
- prelude_sdk_beta/__init__.py +0 -0
- prelude_sdk_beta/controllers/__init__.py +0 -0
- prelude_sdk_beta/controllers/build_controller.py +315 -0
- prelude_sdk_beta/controllers/detect_controller.py +256 -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 +83 -0
- prelude_sdk_beta/controllers/iam_controller.py +285 -0
- prelude_sdk_beta/controllers/jobs_controller.py +37 -0
- prelude_sdk_beta/controllers/partner_controller.py +154 -0
- prelude_sdk_beta/controllers/probe_controller.py +14 -0
- prelude_sdk_beta/controllers/scm_controller.py +664 -0
- prelude_sdk_beta/models/__init__.py +0 -0
- prelude_sdk_beta/models/account.py +269 -0
- prelude_sdk_beta/models/codes.py +654 -0
- prelude_sdk_beta-1447.dist-info/METADATA +46 -0
- prelude_sdk_beta-1447.dist-info/RECORD +20 -0
- prelude_sdk_beta-1447.dist-info/WHEEL +5 -0
- prelude_sdk_beta-1447.dist-info/licenses/LICENSE +9 -0
- prelude_sdk_beta-1447.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,83 @@
|
|
|
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 resolve_enums(self, data, enum_params: list[tuple]):
|
|
26
|
+
for [enum_class, key] in enum_params:
|
|
27
|
+
self._resolve_enum(data, enum_class, key)
|
|
28
|
+
|
|
29
|
+
def _resolve_enum(self, data, enum_class, key):
|
|
30
|
+
if isinstance(data, list):
|
|
31
|
+
for item in data:
|
|
32
|
+
if isinstance(item, dict):
|
|
33
|
+
self._resolve_enum(item, enum_class, key)
|
|
34
|
+
elif isinstance(data, dict):
|
|
35
|
+
for k, v in data.items():
|
|
36
|
+
if k == key:
|
|
37
|
+
if isinstance(v, list):
|
|
38
|
+
for i, item in enumerate(v):
|
|
39
|
+
v[i] = enum_class[item].name
|
|
40
|
+
elif v is not None:
|
|
41
|
+
data[k] = enum_class[v].name
|
|
42
|
+
elif isinstance(v, dict) or isinstance(v, list):
|
|
43
|
+
self._resolve_enum(v, enum_class, key)
|
|
44
|
+
|
|
45
|
+
def get(self, url, retry=True, **kwargs):
|
|
46
|
+
res = self._session.get(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.get(url, retry=False, **kwargs)
|
|
53
|
+
raise Exception(res.text)
|
|
54
|
+
|
|
55
|
+
def post(self, url, retry=True, **kwargs):
|
|
56
|
+
res = self._session.post(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.post(url, retry=False, **kwargs)
|
|
63
|
+
raise Exception(res.text)
|
|
64
|
+
|
|
65
|
+
def delete(self, url, retry=True, **kwargs):
|
|
66
|
+
res = self._session.delete(url, **kwargs)
|
|
67
|
+
if res.status_code == 200:
|
|
68
|
+
return res
|
|
69
|
+
if res.status_code == 401 and retry and self.account.token_location:
|
|
70
|
+
self.account.refresh_tokens()
|
|
71
|
+
self.account.update_auth_header()
|
|
72
|
+
return self.delete(url, retry=False, **kwargs)
|
|
73
|
+
raise Exception(res.text)
|
|
74
|
+
|
|
75
|
+
def put(self, url, retry=True, **kwargs):
|
|
76
|
+
res = self._session.put(url, **kwargs)
|
|
77
|
+
if res.status_code == 200:
|
|
78
|
+
return res
|
|
79
|
+
if res.status_code == 401 and retry and self.account.token_location:
|
|
80
|
+
self.account.refresh_tokens()
|
|
81
|
+
self.account.update_auth_header()
|
|
82
|
+
return self.put(url, retry=False, **kwargs)
|
|
83
|
+
raise Exception(res.text)
|
|
@@ -0,0 +1,285 @@
|
|
|
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 Control, 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
|
+
account = res.json()
|
|
18
|
+
if self.account.resolve_enums:
|
|
19
|
+
self.resolve_enums(
|
|
20
|
+
account, [(Mode, "mode"), (Permission, "permission"), (Control, "id")]
|
|
21
|
+
)
|
|
22
|
+
return account
|
|
23
|
+
|
|
24
|
+
@verify_credentials
|
|
25
|
+
def purge_account(self):
|
|
26
|
+
"""Delete an account and all things in it"""
|
|
27
|
+
res = self.delete(
|
|
28
|
+
f"{self.account.hq}/iam/account", headers=self.account.headers, timeout=10
|
|
29
|
+
)
|
|
30
|
+
return res.json()
|
|
31
|
+
|
|
32
|
+
@verify_credentials
|
|
33
|
+
def update_account(self, mode: Mode = None, company: str = None, slug: str = None):
|
|
34
|
+
"""Update properties on an account"""
|
|
35
|
+
body = dict()
|
|
36
|
+
if mode is not None:
|
|
37
|
+
body["mode"] = mode.name
|
|
38
|
+
if company is not None:
|
|
39
|
+
body["company"] = company
|
|
40
|
+
if slug is not None:
|
|
41
|
+
body["slug"] = slug
|
|
42
|
+
|
|
43
|
+
res = self.put(
|
|
44
|
+
f"{self.account.hq}/iam/account",
|
|
45
|
+
headers=self.account.headers,
|
|
46
|
+
json=body,
|
|
47
|
+
timeout=10,
|
|
48
|
+
)
|
|
49
|
+
return res.json()
|
|
50
|
+
|
|
51
|
+
@verify_credentials
|
|
52
|
+
def attach_oidc(
|
|
53
|
+
self,
|
|
54
|
+
client_id: str,
|
|
55
|
+
client_secret: str,
|
|
56
|
+
issuer: str,
|
|
57
|
+
oidc_url: str,
|
|
58
|
+
):
|
|
59
|
+
"""Attach OIDC to an account"""
|
|
60
|
+
email_attr = "email"
|
|
61
|
+
if issuer == "azure":
|
|
62
|
+
email_attr = "upn"
|
|
63
|
+
body = dict(
|
|
64
|
+
client_id=client_id,
|
|
65
|
+
client_secret=client_secret,
|
|
66
|
+
email_attr=email_attr,
|
|
67
|
+
issuer=issuer,
|
|
68
|
+
oidc_url=oidc_url,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
res = self.post(
|
|
72
|
+
f"{self.account.hq}/iam/account/oidc",
|
|
73
|
+
headers=self.account.headers,
|
|
74
|
+
json=body,
|
|
75
|
+
timeout=10,
|
|
76
|
+
)
|
|
77
|
+
return res.json()
|
|
78
|
+
|
|
79
|
+
@verify_credentials
|
|
80
|
+
def detach_oidc(self):
|
|
81
|
+
"""Detach OIDC to an account"""
|
|
82
|
+
res = self.delete(
|
|
83
|
+
f"{self.account.hq}/iam/account/oidc",
|
|
84
|
+
headers=self.account.headers,
|
|
85
|
+
timeout=10,
|
|
86
|
+
)
|
|
87
|
+
return res.json()
|
|
88
|
+
|
|
89
|
+
@verify_credentials
|
|
90
|
+
def invite_user(
|
|
91
|
+
self,
|
|
92
|
+
email: str,
|
|
93
|
+
oidc: str | None,
|
|
94
|
+
permission: Permission,
|
|
95
|
+
name: str | None = None,
|
|
96
|
+
):
|
|
97
|
+
"""Invite a new user to the account"""
|
|
98
|
+
body = dict(permission=permission.name, handle=email, oidc=oidc)
|
|
99
|
+
if name:
|
|
100
|
+
body["name"] = name
|
|
101
|
+
|
|
102
|
+
res = self.post(
|
|
103
|
+
url=f"{self.account.hq}/iam/account/user",
|
|
104
|
+
json=body,
|
|
105
|
+
headers=self.account.headers,
|
|
106
|
+
timeout=10,
|
|
107
|
+
)
|
|
108
|
+
user = res.json()
|
|
109
|
+
if self.account.resolve_enums:
|
|
110
|
+
self.resolve_enums(user, [(Permission, "permission")])
|
|
111
|
+
return user
|
|
112
|
+
|
|
113
|
+
@verify_credentials
|
|
114
|
+
def create_service_user(self, name: str):
|
|
115
|
+
"""Create a service user"""
|
|
116
|
+
body = dict(name=name)
|
|
117
|
+
|
|
118
|
+
res = self.post(
|
|
119
|
+
f"{self.account.hq}/iam/account/service_user",
|
|
120
|
+
json=body,
|
|
121
|
+
headers=self.account.headers,
|
|
122
|
+
timeout=10,
|
|
123
|
+
)
|
|
124
|
+
return res.json()
|
|
125
|
+
|
|
126
|
+
@verify_credentials
|
|
127
|
+
def delete_service_user(self, handle: str):
|
|
128
|
+
"""Delete service user"""
|
|
129
|
+
body = dict(handle=handle)
|
|
130
|
+
|
|
131
|
+
res = self.delete(
|
|
132
|
+
f"{self.account.hq}/iam/account/service_user",
|
|
133
|
+
json=body,
|
|
134
|
+
headers=self.account.headers,
|
|
135
|
+
timeout=10,
|
|
136
|
+
)
|
|
137
|
+
return res.json()
|
|
138
|
+
|
|
139
|
+
@verify_credentials
|
|
140
|
+
def update_account_user(
|
|
141
|
+
self,
|
|
142
|
+
email: str,
|
|
143
|
+
oidc: str | None,
|
|
144
|
+
permission: Permission = None,
|
|
145
|
+
):
|
|
146
|
+
"""Update properties on an account user"""
|
|
147
|
+
body = dict(handle=email, oidc=oidc)
|
|
148
|
+
if permission is not None:
|
|
149
|
+
body["permission"] = permission.name
|
|
150
|
+
|
|
151
|
+
res = self.put(
|
|
152
|
+
f"{self.account.hq}/iam/account/user",
|
|
153
|
+
json=body,
|
|
154
|
+
headers=self.account.headers,
|
|
155
|
+
timeout=10,
|
|
156
|
+
)
|
|
157
|
+
return res.json()
|
|
158
|
+
|
|
159
|
+
@verify_credentials
|
|
160
|
+
def remove_user(self, email: str, oidc: str | None):
|
|
161
|
+
"""Remove user from the account"""
|
|
162
|
+
params = dict(handle=email, oidc=oidc)
|
|
163
|
+
|
|
164
|
+
res = self.delete(
|
|
165
|
+
f"{self.account.hq}/iam/account/user",
|
|
166
|
+
params=params,
|
|
167
|
+
headers=self.account.headers,
|
|
168
|
+
timeout=10,
|
|
169
|
+
)
|
|
170
|
+
return res.json()
|
|
171
|
+
|
|
172
|
+
@verify_credentials
|
|
173
|
+
def audit_logs(self, days: int = 7, limit: int = 1000):
|
|
174
|
+
"""Get audit logs from the last X days"""
|
|
175
|
+
params = dict(days=days, limit=limit)
|
|
176
|
+
res = self.get(
|
|
177
|
+
f"{self.account.hq}/iam/audit",
|
|
178
|
+
headers=self.account.headers,
|
|
179
|
+
params=params,
|
|
180
|
+
timeout=30,
|
|
181
|
+
)
|
|
182
|
+
return res.json()
|
|
183
|
+
|
|
184
|
+
def sign_up(self, company, email, name):
|
|
185
|
+
"""(NOT AVAIABLE IN PRODUCTION) Create a new user and account"""
|
|
186
|
+
body = dict(company=company, email=email, name=name)
|
|
187
|
+
|
|
188
|
+
res = self._session.post(
|
|
189
|
+
f"{self.account.hq}/iam/new_user_and_account",
|
|
190
|
+
headers=self.account.headers,
|
|
191
|
+
json=body,
|
|
192
|
+
timeout=20,
|
|
193
|
+
)
|
|
194
|
+
data = res.json()
|
|
195
|
+
if self.account.profile:
|
|
196
|
+
self.account.keychain.configure_keychain(
|
|
197
|
+
account=data["account_id"],
|
|
198
|
+
handle=data["user_id"],
|
|
199
|
+
hq=self.account.hq,
|
|
200
|
+
profile=self.account.profile,
|
|
201
|
+
)
|
|
202
|
+
return data
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class IAMUserController(HttpController):
|
|
206
|
+
|
|
207
|
+
def __init__(self, account):
|
|
208
|
+
super().__init__(account)
|
|
209
|
+
|
|
210
|
+
@verify_credentials
|
|
211
|
+
def list_accounts(self):
|
|
212
|
+
"""List all accounts for your user"""
|
|
213
|
+
res = self.get(
|
|
214
|
+
f"{self.account.hq}/iam/user/account",
|
|
215
|
+
headers=self.account.headers,
|
|
216
|
+
timeout=10,
|
|
217
|
+
)
|
|
218
|
+
return res.json()
|
|
219
|
+
|
|
220
|
+
@verify_credentials
|
|
221
|
+
def purge_user(self):
|
|
222
|
+
"""Delete your user"""
|
|
223
|
+
res = self.delete(
|
|
224
|
+
f"{self.account.hq}/iam/user", headers=self.account.headers, timeout=10
|
|
225
|
+
)
|
|
226
|
+
return res.json()
|
|
227
|
+
|
|
228
|
+
@verify_credentials
|
|
229
|
+
def update_user(
|
|
230
|
+
self,
|
|
231
|
+
name: str = None,
|
|
232
|
+
):
|
|
233
|
+
"""Update properties on a user"""
|
|
234
|
+
body = dict()
|
|
235
|
+
if name is not None:
|
|
236
|
+
body["name"] = name
|
|
237
|
+
|
|
238
|
+
res = self.put(
|
|
239
|
+
f"{self.account.hq}/iam/user",
|
|
240
|
+
json=body,
|
|
241
|
+
headers=self.account.headers,
|
|
242
|
+
timeout=10,
|
|
243
|
+
)
|
|
244
|
+
return res.json()
|
|
245
|
+
|
|
246
|
+
def forgot_password(self):
|
|
247
|
+
"""Send a forgot password email"""
|
|
248
|
+
body = dict(handle=self.account.handle)
|
|
249
|
+
|
|
250
|
+
res = self.post(
|
|
251
|
+
f"{self.account.hq}/iam/user/forgot_password",
|
|
252
|
+
json=body,
|
|
253
|
+
headers=self.account.headers,
|
|
254
|
+
timeout=10,
|
|
255
|
+
)
|
|
256
|
+
return res.json()
|
|
257
|
+
|
|
258
|
+
def confirm_forgot_password(self, confirmation_code: str, new_password: str):
|
|
259
|
+
"""Change a password using confirmation code"""
|
|
260
|
+
body = dict(
|
|
261
|
+
handle=self.account.handle,
|
|
262
|
+
confirmation_code=confirmation_code,
|
|
263
|
+
password=new_password,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
res = self.post(
|
|
267
|
+
f"{self.account.hq}/iam/user/forgot_password",
|
|
268
|
+
json=body,
|
|
269
|
+
headers=self.account.headers,
|
|
270
|
+
timeout=10,
|
|
271
|
+
)
|
|
272
|
+
return res.json()
|
|
273
|
+
|
|
274
|
+
@verify_credentials
|
|
275
|
+
def change_password(self, current_password: str, new_password: str):
|
|
276
|
+
"""Change your password"""
|
|
277
|
+
body = dict(current_password=current_password, new_password=new_password)
|
|
278
|
+
|
|
279
|
+
res = self.post(
|
|
280
|
+
f"{self.account.hq}/iam/user/change_password",
|
|
281
|
+
json=body,
|
|
282
|
+
headers=self.account.headers,
|
|
283
|
+
timeout=10,
|
|
284
|
+
)
|
|
285
|
+
return res.json()
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from itertools import chain
|
|
2
|
+
|
|
3
|
+
from prelude_sdk_beta.controllers.http_controller import HttpController
|
|
4
|
+
from prelude_sdk_beta.models.account import verify_credentials
|
|
5
|
+
from prelude_sdk_beta.models.codes import BackgroundJobTypes, Control
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class JobsController(HttpController):
|
|
9
|
+
|
|
10
|
+
def __init__(self, account):
|
|
11
|
+
super().__init__(account)
|
|
12
|
+
|
|
13
|
+
@verify_credentials
|
|
14
|
+
def job_statuses(self):
|
|
15
|
+
"""Get job statuses"""
|
|
16
|
+
res = self.get(
|
|
17
|
+
f"{self.account.hq}/jobs/statuses", headers=self.account.headers, timeout=30
|
|
18
|
+
)
|
|
19
|
+
jobs = res.json()
|
|
20
|
+
if self.account.resolve_enums:
|
|
21
|
+
self.resolve_enums(jobs, [(Control, "control")])
|
|
22
|
+
return jobs
|
|
23
|
+
|
|
24
|
+
@verify_credentials
|
|
25
|
+
def job_status(self, job_id: str):
|
|
26
|
+
"""Get job status given job ID"""
|
|
27
|
+
res = self.get(
|
|
28
|
+
f"{self.account.hq}/jobs/statuses/{job_id}",
|
|
29
|
+
headers=self.account.headers,
|
|
30
|
+
timeout=30,
|
|
31
|
+
)
|
|
32
|
+
job = res.json()
|
|
33
|
+
if self.account.resolve_enums:
|
|
34
|
+
self.resolve_enums(
|
|
35
|
+
job, [(Control, "control"), (BackgroundJobTypes, "job_type")]
|
|
36
|
+
)
|
|
37
|
+
return job
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
|
+
|
|
3
|
+
from prelude_sdk_beta.controllers.http_controller import HttpController
|
|
4
|
+
from prelude_sdk_beta.models.account import verify_credentials
|
|
5
|
+
from prelude_sdk_beta.models.codes import Control
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PartnerController(HttpController):
|
|
9
|
+
|
|
10
|
+
def __init__(self, account):
|
|
11
|
+
super().__init__(account)
|
|
12
|
+
|
|
13
|
+
@verify_credentials
|
|
14
|
+
def attach(
|
|
15
|
+
self,
|
|
16
|
+
partner: Control,
|
|
17
|
+
api: str,
|
|
18
|
+
user: str,
|
|
19
|
+
secret: str,
|
|
20
|
+
name: str | None = None,
|
|
21
|
+
instance_id: str | None = None,
|
|
22
|
+
):
|
|
23
|
+
"""Attach a partner to your account"""
|
|
24
|
+
params = dict()
|
|
25
|
+
if name:
|
|
26
|
+
params["name"] = name
|
|
27
|
+
if api:
|
|
28
|
+
params["api"] = api
|
|
29
|
+
if user:
|
|
30
|
+
params["user"] = user
|
|
31
|
+
if secret:
|
|
32
|
+
params["secret"] = secret
|
|
33
|
+
extra = f"/{instance_id}" if instance_id else ""
|
|
34
|
+
res = self.post(
|
|
35
|
+
f"{self.account.hq}/partner/{partner.name}{extra}",
|
|
36
|
+
headers=self.account.headers,
|
|
37
|
+
json=params,
|
|
38
|
+
timeout=10,
|
|
39
|
+
)
|
|
40
|
+
return res.json()
|
|
41
|
+
|
|
42
|
+
@verify_credentials
|
|
43
|
+
def detach(self, partner: Control, instance_id: str):
|
|
44
|
+
"""Detach a partner from your Detect account"""
|
|
45
|
+
res = self.delete(
|
|
46
|
+
f"{self.account.hq}/partner/{partner.name}/{instance_id}",
|
|
47
|
+
headers=self.account.headers,
|
|
48
|
+
timeout=30,
|
|
49
|
+
)
|
|
50
|
+
return res.json()
|
|
51
|
+
|
|
52
|
+
@verify_credentials
|
|
53
|
+
def block(self, partner: Control, test_id: str):
|
|
54
|
+
"""Report to a partner to block a test"""
|
|
55
|
+
params = dict(test_id=test_id)
|
|
56
|
+
res = self.post(
|
|
57
|
+
f"{self.account.hq}/partner/block/{partner.name}",
|
|
58
|
+
headers=self.account.headers,
|
|
59
|
+
json=params,
|
|
60
|
+
timeout=30,
|
|
61
|
+
)
|
|
62
|
+
return res.json()
|
|
63
|
+
|
|
64
|
+
@verify_credentials
|
|
65
|
+
def endpoints(
|
|
66
|
+
self,
|
|
67
|
+
partner: Control,
|
|
68
|
+
platform: str,
|
|
69
|
+
hostname: str = "",
|
|
70
|
+
offset: int = 0,
|
|
71
|
+
count: int = 100,
|
|
72
|
+
):
|
|
73
|
+
"""Get a list of endpoints from a partner"""
|
|
74
|
+
params = dict(platform=platform, hostname=hostname, offset=offset, count=count)
|
|
75
|
+
res = self.get(
|
|
76
|
+
f"{self.account.hq}/partner/endpoints/{partner.name}",
|
|
77
|
+
headers=self.account.headers,
|
|
78
|
+
params=params,
|
|
79
|
+
timeout=30,
|
|
80
|
+
)
|
|
81
|
+
return res.json()
|
|
82
|
+
|
|
83
|
+
@verify_credentials
|
|
84
|
+
def deploy(self, partner: Control, host_ids: list):
|
|
85
|
+
"""Deploy probes on all specified partner endpoints"""
|
|
86
|
+
params = dict(host_ids=host_ids)
|
|
87
|
+
res = self.post(
|
|
88
|
+
f"{self.account.hq}/partner/deploy/{partner.name}",
|
|
89
|
+
headers=self.account.headers,
|
|
90
|
+
json=params,
|
|
91
|
+
timeout=30,
|
|
92
|
+
)
|
|
93
|
+
return res.json()
|
|
94
|
+
|
|
95
|
+
@verify_credentials
|
|
96
|
+
def list_reports(self, partner: Control, test_id: str | None):
|
|
97
|
+
"""Get reports to a partner for a test"""
|
|
98
|
+
params = dict(test_id=test_id) if test_id else dict()
|
|
99
|
+
res = self.get(
|
|
100
|
+
f"{self.account.hq}/partner/reports/{partner.name}",
|
|
101
|
+
headers=self.account.headers,
|
|
102
|
+
json=params,
|
|
103
|
+
timeout=30,
|
|
104
|
+
)
|
|
105
|
+
return res.json()
|
|
106
|
+
|
|
107
|
+
@verify_credentials
|
|
108
|
+
def observed_detected(self, test_id: str | None = None, hours: int | None = None):
|
|
109
|
+
"""Get observed_detected stats"""
|
|
110
|
+
params = dict()
|
|
111
|
+
if test_id:
|
|
112
|
+
params["test_id"] = test_id
|
|
113
|
+
if hours:
|
|
114
|
+
params["start_epoch_ms"] = (
|
|
115
|
+
datetime.now(timezone.utc).timestamp() - hours * 60 * 60
|
|
116
|
+
) * 1000
|
|
117
|
+
|
|
118
|
+
res = self.get(
|
|
119
|
+
f"{self.account.hq}/partner/observed_detected",
|
|
120
|
+
headers=self.account.headers,
|
|
121
|
+
json=params,
|
|
122
|
+
timeout=30,
|
|
123
|
+
)
|
|
124
|
+
return res.json()
|
|
125
|
+
|
|
126
|
+
@verify_credentials
|
|
127
|
+
def list_advisories(
|
|
128
|
+
self, partner: Control, start: str = None, limit: int = None, offset: int = None
|
|
129
|
+
):
|
|
130
|
+
"""Get advisory reports provided by a partner"""
|
|
131
|
+
params = dict()
|
|
132
|
+
if start:
|
|
133
|
+
params["start"] = start
|
|
134
|
+
if limit:
|
|
135
|
+
params["limit"] = limit
|
|
136
|
+
if offset:
|
|
137
|
+
params["offset"] = offset
|
|
138
|
+
res = self.get(
|
|
139
|
+
f"{self.account.hq}/partner/advisories/{partner.name}",
|
|
140
|
+
headers=self.account.headers,
|
|
141
|
+
params=params,
|
|
142
|
+
timeout=30,
|
|
143
|
+
)
|
|
144
|
+
return res.json()
|
|
145
|
+
|
|
146
|
+
@verify_credentials
|
|
147
|
+
def partner_groups(self, partner: Control, instance_id: str):
|
|
148
|
+
"""Get a list of partner groups"""
|
|
149
|
+
res = self.get(
|
|
150
|
+
f"{self.account.hq}/partner/groups/{partner.name}/{instance_id}",
|
|
151
|
+
headers=self.account.headers,
|
|
152
|
+
timeout=30,
|
|
153
|
+
)
|
|
154
|
+
return res.json()
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from prelude_sdk_beta.controllers.http_controller import HttpController
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ProbeController(HttpController):
|
|
5
|
+
|
|
6
|
+
def __init__(self, account):
|
|
7
|
+
super().__init__(account)
|
|
8
|
+
|
|
9
|
+
def download(self, name: str, dos: str):
|
|
10
|
+
"""Download a probe executable"""
|
|
11
|
+
res = self.get(
|
|
12
|
+
f"{self.account.hq}/download/{name}", headers=dict(dos=dos), timeout=10
|
|
13
|
+
)
|
|
14
|
+
return res.text
|