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,264 +0,0 @@
|
|
|
1
|
-
import configparser
|
|
2
|
-
import json
|
|
3
|
-
import os
|
|
4
|
-
from functools import wraps
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
|
|
7
|
-
import requests
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Keychain:
|
|
11
|
-
|
|
12
|
-
def __init__(
|
|
13
|
-
self,
|
|
14
|
-
keychain_location: str | None = os.path.join(
|
|
15
|
-
Path.home(), ".prelude", "keychain.ini"
|
|
16
|
-
),
|
|
17
|
-
):
|
|
18
|
-
self.keychain_location = keychain_location
|
|
19
|
-
if self.keychain_location and not os.path.exists(self.keychain_location):
|
|
20
|
-
head, _ = os.path.split(Path(self.keychain_location))
|
|
21
|
-
Path(head).mkdir(parents=True, exist_ok=True)
|
|
22
|
-
open(self.keychain_location, "x").close()
|
|
23
|
-
self.configure_keychain("", "")
|
|
24
|
-
|
|
25
|
-
def read_keychain(self):
|
|
26
|
-
cfg = configparser.ConfigParser()
|
|
27
|
-
cfg.read(self.keychain_location)
|
|
28
|
-
return cfg
|
|
29
|
-
|
|
30
|
-
def configure_keychain(
|
|
31
|
-
self,
|
|
32
|
-
account,
|
|
33
|
-
handle,
|
|
34
|
-
hq="https://api.us1.preludesecurity.com",
|
|
35
|
-
oidc=None,
|
|
36
|
-
profile="default",
|
|
37
|
-
slug=None,
|
|
38
|
-
):
|
|
39
|
-
cfg = self.read_keychain()
|
|
40
|
-
cfg[profile] = {"account": account, "handle": handle, "hq": hq}
|
|
41
|
-
if oidc:
|
|
42
|
-
cfg[profile]["oidc"] = oidc
|
|
43
|
-
if slug:
|
|
44
|
-
cfg[profile]["slug"] = slug
|
|
45
|
-
with open(self.keychain_location, "w") as f:
|
|
46
|
-
cfg.write(f)
|
|
47
|
-
|
|
48
|
-
def get_profile(self, profile="default") -> dict:
|
|
49
|
-
try:
|
|
50
|
-
cfg = self.read_keychain()
|
|
51
|
-
profile = next(s for s in cfg.sections() if s == profile)
|
|
52
|
-
return dict(cfg[profile].items())
|
|
53
|
-
except StopIteration:
|
|
54
|
-
raise Exception(
|
|
55
|
-
"Could not find profile %s for account in %s"
|
|
56
|
-
% (profile, self.keychain_location)
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def exchange_token(
|
|
61
|
-
account: str, handle: str, hq: str, auth_flow: str, auth_params: dict
|
|
62
|
-
):
|
|
63
|
-
"""
|
|
64
|
-
Two token exchange auth flows:
|
|
65
|
-
1) Password auth: auth_flow = "password", auth_params = {"password": "your_password"}
|
|
66
|
-
2) Refresh token auth: auth_flow = "refresh", auth_params = {"refresh_token": "your_refresh_token"}
|
|
67
|
-
3) Exchange an OIDC authorization code for tokens:
|
|
68
|
-
auth_flow = "oauth_code", auth_params = {"code": "your_authorization_code", "verifier": "your_verifier", "source": "cli"}
|
|
69
|
-
"""
|
|
70
|
-
res = requests.post(
|
|
71
|
-
f"{hq}/iam/token",
|
|
72
|
-
headers=dict(account=account, _product="py-sdk"),
|
|
73
|
-
json=dict(auth_flow=auth_flow, handle=handle, **auth_params),
|
|
74
|
-
timeout=10,
|
|
75
|
-
)
|
|
76
|
-
if res.status_code == 401:
|
|
77
|
-
raise Exception("Error logging in: Unauthorized")
|
|
78
|
-
if not res.ok:
|
|
79
|
-
raise Exception("Error logging in: %s" % res.text)
|
|
80
|
-
return res.json()
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
class Account:
|
|
84
|
-
|
|
85
|
-
@staticmethod
|
|
86
|
-
def from_keychain(profile: str = "default"):
|
|
87
|
-
"""
|
|
88
|
-
Create an account object from a pre-configured profile in your keychain file
|
|
89
|
-
"""
|
|
90
|
-
keychain = Keychain()
|
|
91
|
-
profile_items = keychain.get_profile(profile)
|
|
92
|
-
if any([item not in profile_items for item in ["account", "handle", "hq"]]):
|
|
93
|
-
raise ValueError(
|
|
94
|
-
"Please make sure you are using an up-to-date profile with the following fields: account, handle, hq"
|
|
95
|
-
)
|
|
96
|
-
return _Account(
|
|
97
|
-
account=profile_items["account"],
|
|
98
|
-
handle=profile_items["handle"],
|
|
99
|
-
hq=profile_items["hq"],
|
|
100
|
-
oidc=profile_items.get("oidc"),
|
|
101
|
-
profile=profile,
|
|
102
|
-
slug=profile_items.get("slug"),
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
@staticmethod
|
|
106
|
-
def from_token(
|
|
107
|
-
account: str,
|
|
108
|
-
handle: str,
|
|
109
|
-
token: str | None = None,
|
|
110
|
-
refresh_token: str | None = None,
|
|
111
|
-
hq: str = "https://api.us1.preludesecurity.com",
|
|
112
|
-
oidc: str | None = None,
|
|
113
|
-
slug: str | None = None,
|
|
114
|
-
):
|
|
115
|
-
"""
|
|
116
|
-
Create an account object from an access token or a refresh token
|
|
117
|
-
"""
|
|
118
|
-
if not any([token, refresh_token]):
|
|
119
|
-
raise ValueError("Please provide either an access token or a refresh token")
|
|
120
|
-
if refresh_token:
|
|
121
|
-
res = exchange_token(
|
|
122
|
-
account, handle, hq, "refresh", dict(refresh_token=refresh_token)
|
|
123
|
-
)
|
|
124
|
-
token = res["token"]
|
|
125
|
-
return _Account(
|
|
126
|
-
account,
|
|
127
|
-
handle,
|
|
128
|
-
hq,
|
|
129
|
-
keychain_location=None,
|
|
130
|
-
oidc=oidc,
|
|
131
|
-
slug=slug,
|
|
132
|
-
token=token,
|
|
133
|
-
token_location=None,
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
class _Account:
|
|
138
|
-
|
|
139
|
-
def __init__(
|
|
140
|
-
self,
|
|
141
|
-
account: str,
|
|
142
|
-
handle: str,
|
|
143
|
-
hq: str,
|
|
144
|
-
oidc: str | None = None,
|
|
145
|
-
profile: str | None = None,
|
|
146
|
-
slug: str | None = None,
|
|
147
|
-
token: str | None = None,
|
|
148
|
-
keychain_location: str | None = os.path.join(
|
|
149
|
-
Path.home(), ".prelude", "keychain.ini"
|
|
150
|
-
),
|
|
151
|
-
token_location: str | None = os.path.join(
|
|
152
|
-
Path.home(), ".prelude", "tokens.json"
|
|
153
|
-
),
|
|
154
|
-
):
|
|
155
|
-
if token is None and token_location is None:
|
|
156
|
-
raise ValueError(
|
|
157
|
-
"Please provide either an access token or a token location"
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
super().__init__()
|
|
161
|
-
self.account = account
|
|
162
|
-
self.handle = handle
|
|
163
|
-
self.headers = dict(account=account, _product="py-sdk")
|
|
164
|
-
self.hq = hq
|
|
165
|
-
self.keychain = Keychain(keychain_location)
|
|
166
|
-
self.oidc = oidc
|
|
167
|
-
self.profile = profile
|
|
168
|
-
self.slug = slug
|
|
169
|
-
self.token = token
|
|
170
|
-
self.token_location = token_location
|
|
171
|
-
if self.token_location and not os.path.exists(self.token_location):
|
|
172
|
-
head, _ = os.path.split(Path(self.token_location))
|
|
173
|
-
Path(head).mkdir(parents=True, exist_ok=True)
|
|
174
|
-
with open(self.token_location, "x") as f:
|
|
175
|
-
json.dump({}, f)
|
|
176
|
-
self.source = "cli" if self.oidc else "main"
|
|
177
|
-
|
|
178
|
-
@property
|
|
179
|
-
def token_key(self):
|
|
180
|
-
return f"{self.handle}/{self.oidc}" if self.oidc else self.handle
|
|
181
|
-
|
|
182
|
-
def _read_tokens(self):
|
|
183
|
-
with open(self.token_location, "r") as f:
|
|
184
|
-
return json.load(f)
|
|
185
|
-
|
|
186
|
-
def save_new_token(self, new_tokens):
|
|
187
|
-
existing_tokens = self._read_tokens()
|
|
188
|
-
if self.token_key not in existing_tokens:
|
|
189
|
-
existing_tokens[self.token_key] = dict()
|
|
190
|
-
existing_tokens[self.token_key][self.hq] = new_tokens
|
|
191
|
-
with open(self.token_location, "w") as f:
|
|
192
|
-
json.dump(existing_tokens, f)
|
|
193
|
-
|
|
194
|
-
def _verify(self):
|
|
195
|
-
if not self.token_location:
|
|
196
|
-
raise ValueError("Please provide a token location to continue")
|
|
197
|
-
if self.profile and not any([self.handle, self.account]):
|
|
198
|
-
raise ValueError(
|
|
199
|
-
"Please configure your %s profile to continue" % self.profile
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
def password_login(self, password, new_password=None):
|
|
203
|
-
self._verify()
|
|
204
|
-
tokens = exchange_token(
|
|
205
|
-
self.account,
|
|
206
|
-
self.handle,
|
|
207
|
-
self.hq,
|
|
208
|
-
"password_change" if new_password else "password",
|
|
209
|
-
dict(password=password, new_password=new_password),
|
|
210
|
-
)
|
|
211
|
-
self.save_new_token(tokens)
|
|
212
|
-
return tokens
|
|
213
|
-
|
|
214
|
-
def refresh_tokens(self):
|
|
215
|
-
self._verify()
|
|
216
|
-
existing_tokens = self._read_tokens().get(self.token_key, {}).get(self.hq, {})
|
|
217
|
-
if not (refresh_token := existing_tokens.get("refresh_token")):
|
|
218
|
-
raise Exception("No refresh token found, please login first to continue")
|
|
219
|
-
tokens = exchange_token(
|
|
220
|
-
self.account,
|
|
221
|
-
self.handle,
|
|
222
|
-
self.hq,
|
|
223
|
-
"refresh",
|
|
224
|
-
dict(refresh_token=refresh_token, source=self.source),
|
|
225
|
-
)
|
|
226
|
-
tokens = existing_tokens | tokens
|
|
227
|
-
self.save_new_token(tokens)
|
|
228
|
-
return tokens
|
|
229
|
-
|
|
230
|
-
def exchange_authorization_code(self, authorization_code: str, verifier: str):
|
|
231
|
-
self._verify()
|
|
232
|
-
tokens = exchange_token(
|
|
233
|
-
self.account,
|
|
234
|
-
self.handle,
|
|
235
|
-
self.hq,
|
|
236
|
-
"oauth_code",
|
|
237
|
-
dict(code=authorization_code, verifier=verifier, source=self.source),
|
|
238
|
-
)
|
|
239
|
-
existing_tokens = self._read_tokens().get(self.token_key, {}).get(self.hq, {})
|
|
240
|
-
tokens = existing_tokens | tokens
|
|
241
|
-
self.save_new_token(tokens)
|
|
242
|
-
return tokens
|
|
243
|
-
|
|
244
|
-
def get_token(self):
|
|
245
|
-
if self.token:
|
|
246
|
-
return self.token
|
|
247
|
-
|
|
248
|
-
tokens = self._read_tokens().get(self.token_key, {}).get(self.hq, {})
|
|
249
|
-
if "token" not in tokens:
|
|
250
|
-
raise Exception("Please login to continue")
|
|
251
|
-
return tokens["token"]
|
|
252
|
-
|
|
253
|
-
def update_auth_header(self):
|
|
254
|
-
self.headers |= dict(authorization=f"Bearer {self.get_token()}")
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
def verify_credentials(func):
|
|
258
|
-
@wraps(verify_credentials)
|
|
259
|
-
def handler(*args, **kwargs):
|
|
260
|
-
args[0].account.update_auth_header()
|
|
261
|
-
return func(*args, **kwargs)
|
|
262
|
-
|
|
263
|
-
handler.__wrapped__ = func
|
|
264
|
-
return handler
|
prelude_sdk_beta/models/codes.py
DELETED
|
@@ -1,446 +0,0 @@
|
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|