pangea-sdk 3.7.0__py3-none-any.whl → 3.8.0__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.
- pangea/__init__.py +1 -1
- pangea/asyncio/request.py +123 -32
- pangea/asyncio/services/__init__.py +1 -0
- pangea/asyncio/services/audit.py +236 -21
- pangea/asyncio/services/authn.py +79 -50
- pangea/asyncio/services/authz.py +259 -0
- pangea/asyncio/services/base.py +9 -6
- pangea/asyncio/services/file_scan.py +3 -4
- pangea/asyncio/services/intel.py +5 -6
- pangea/asyncio/services/redact.py +21 -3
- pangea/asyncio/services/vault.py +28 -12
- pangea/config.py +10 -18
- pangea/dump_audit.py +1 -0
- pangea/exceptions.py +8 -0
- pangea/request.py +164 -74
- pangea/response.py +63 -17
- pangea/services/__init__.py +1 -0
- pangea/services/audit/audit.py +241 -55
- pangea/services/audit/exceptions.py +1 -2
- pangea/services/audit/models.py +83 -21
- pangea/services/audit/signing.py +1 -0
- pangea/services/audit/util.py +1 -0
- pangea/services/authn/authn.py +38 -4
- pangea/services/authn/models.py +9 -9
- pangea/services/authz.py +377 -0
- pangea/services/base.py +34 -14
- pangea/services/embargo.py +1 -2
- pangea/services/file_scan.py +3 -4
- pangea/services/intel.py +3 -4
- pangea/services/redact.py +21 -3
- pangea/services/vault/vault.py +29 -12
- pangea/utils.py +2 -3
- {pangea_sdk-3.7.0.dist-info → pangea_sdk-3.8.0.dist-info}/METADATA +33 -6
- pangea_sdk-3.8.0.dist-info/RECORD +46 -0
- pangea_sdk-3.7.0.dist-info/RECORD +0 -44
- {pangea_sdk-3.7.0.dist-info → pangea_sdk-3.8.0.dist-info}/WHEEL +0 -0
pangea/services/authz.py
ADDED
@@ -0,0 +1,377 @@
|
|
1
|
+
# Copyright 2022 Pangea Cyber Corporation
|
2
|
+
# Author: Pangea Cyber Corporation
|
3
|
+
|
4
|
+
import enum
|
5
|
+
from typing import Any, Dict, List, Optional, Union
|
6
|
+
|
7
|
+
from pangea.response import APIRequestModel, APIResponseModel, PangeaResponse, PangeaResponseResult
|
8
|
+
from pangea.services.base import ServiceBase
|
9
|
+
|
10
|
+
|
11
|
+
class ItemOrder(str, enum.Enum):
|
12
|
+
ASC = "asc"
|
13
|
+
DESC = "desc"
|
14
|
+
|
15
|
+
def __str__(self):
|
16
|
+
return str(self.value)
|
17
|
+
|
18
|
+
def __repr__(self):
|
19
|
+
return str(self.value)
|
20
|
+
|
21
|
+
|
22
|
+
class TupleOrderBy(str, enum.Enum):
|
23
|
+
RESOURCE_TYPE = "resource_type"
|
24
|
+
RESOURCE_ID = "resource_id"
|
25
|
+
RELATION = "relation"
|
26
|
+
SUBJECT_TYPE = "subject_type"
|
27
|
+
SUBJECT_ID = "subject_id"
|
28
|
+
SUBJECT_ACTION = "subject_action"
|
29
|
+
|
30
|
+
def __str__(self):
|
31
|
+
return str(self.value)
|
32
|
+
|
33
|
+
def __repr__(self):
|
34
|
+
return str(self.value)
|
35
|
+
|
36
|
+
|
37
|
+
class Resource(PangeaResponseResult):
|
38
|
+
type: str
|
39
|
+
id: Optional[str] = None
|
40
|
+
|
41
|
+
|
42
|
+
class Subject(PangeaResponseResult):
|
43
|
+
type: str
|
44
|
+
id: Optional[str] = None
|
45
|
+
action: Optional[str] = None
|
46
|
+
|
47
|
+
|
48
|
+
class Tuple(PangeaResponseResult):
|
49
|
+
resource: Resource
|
50
|
+
relation: str
|
51
|
+
subject: Subject
|
52
|
+
|
53
|
+
|
54
|
+
class TupleCreateRequest(APIRequestModel):
|
55
|
+
tuples: List[Tuple]
|
56
|
+
|
57
|
+
|
58
|
+
class TupleCreateResult(PangeaResponseResult):
|
59
|
+
pass
|
60
|
+
|
61
|
+
|
62
|
+
class TupleListFilter(APIRequestModel):
|
63
|
+
resource_type: Optional[str] = None
|
64
|
+
resource_type__contains: Optional[List[str]] = None
|
65
|
+
resource_type__in: Optional[List[str]] = None
|
66
|
+
resource_id: Optional[str] = None
|
67
|
+
resource_id__contains: Optional[List[str]] = None
|
68
|
+
resource_id__in: Optional[List[str]] = None
|
69
|
+
relation: Optional[str] = None
|
70
|
+
relation__contains: Optional[List[str]] = None
|
71
|
+
relation__in: Optional[List[str]] = None
|
72
|
+
subject_type: Optional[str] = None
|
73
|
+
subject_type__contains: Optional[List[str]] = None
|
74
|
+
subject_type__in: Optional[List[str]] = None
|
75
|
+
subject_id: Optional[str] = None
|
76
|
+
subject_id__contains: Optional[List[str]] = None
|
77
|
+
subject_id__in: Optional[List[str]] = None
|
78
|
+
subject_action: Optional[str] = None
|
79
|
+
subject_action__contains: Optional[List[str]] = None
|
80
|
+
subject_action__in: Optional[List[str]] = None
|
81
|
+
|
82
|
+
|
83
|
+
class TupleListRequest(APIRequestModel):
|
84
|
+
filter: Optional[Union[Dict, TupleListFilter]] = None
|
85
|
+
size: Optional[int] = None
|
86
|
+
last: Optional[str] = None
|
87
|
+
order: Optional[ItemOrder] = None
|
88
|
+
order_by: Optional[TupleOrderBy] = None
|
89
|
+
|
90
|
+
|
91
|
+
class TupleListResult(PangeaResponseResult):
|
92
|
+
tuples: List[Tuple]
|
93
|
+
last: str
|
94
|
+
count: int
|
95
|
+
|
96
|
+
|
97
|
+
class TupleDeleteRequest(APIRequestModel):
|
98
|
+
tuples: List[Tuple]
|
99
|
+
|
100
|
+
|
101
|
+
class TupleDeleteResult(PangeaResponseResult):
|
102
|
+
pass
|
103
|
+
|
104
|
+
|
105
|
+
class CheckRequest(APIRequestModel):
|
106
|
+
resource: Resource
|
107
|
+
action: str
|
108
|
+
subject: Subject
|
109
|
+
debug: Optional[bool] = None
|
110
|
+
attributes: Optional[Dict[str, Any]] = None
|
111
|
+
|
112
|
+
|
113
|
+
class DebugPath(APIResponseModel):
|
114
|
+
type: str
|
115
|
+
id: str
|
116
|
+
action: Optional[str]
|
117
|
+
|
118
|
+
|
119
|
+
class Debug(APIResponseModel):
|
120
|
+
path: List[DebugPath]
|
121
|
+
|
122
|
+
|
123
|
+
class CheckResult(PangeaResponseResult):
|
124
|
+
schema_id: str
|
125
|
+
schema_version: int
|
126
|
+
depth: int
|
127
|
+
allowed: bool
|
128
|
+
debug: Optional[Debug] = None
|
129
|
+
|
130
|
+
|
131
|
+
class ListResourcesRequest(APIRequestModel):
|
132
|
+
type: str
|
133
|
+
action: str
|
134
|
+
subject: Subject
|
135
|
+
|
136
|
+
|
137
|
+
class ListResourcesResult(PangeaResponseResult):
|
138
|
+
ids: List[str]
|
139
|
+
|
140
|
+
|
141
|
+
class ListSubjectsRequest(APIRequestModel):
|
142
|
+
resource: Resource
|
143
|
+
action: str
|
144
|
+
|
145
|
+
|
146
|
+
class ListSubjectsResult(PangeaResponseResult):
|
147
|
+
subjects: List[Subject]
|
148
|
+
|
149
|
+
|
150
|
+
class AuthZ(ServiceBase):
|
151
|
+
"""AuthZ service client. (Beta)
|
152
|
+
|
153
|
+
Provides methods to interact with the Pangea AuthZ Service.
|
154
|
+
Documentation for the AuthZ Service API can be found at
|
155
|
+
<https://pangea.cloud/docs/api/authz>. Note that this service is in Beta and
|
156
|
+
is subject to change.
|
157
|
+
|
158
|
+
Examples:
|
159
|
+
import os
|
160
|
+
from pangea.config import PangeaConfig
|
161
|
+
from pangea.services import AuthZ
|
162
|
+
|
163
|
+
PANGEA_TOKEN = os.getenv("PANGEA_AUTHZ_TOKEN")
|
164
|
+
|
165
|
+
authz_config = PangeaConfig(domain="aws.us.pangea.cloud")
|
166
|
+
|
167
|
+
# Setup Pangea AuthZ service client
|
168
|
+
authz = AuthZ(token=PANGEA_TOKEN, config=authz_config)
|
169
|
+
"""
|
170
|
+
|
171
|
+
service_name = "authz"
|
172
|
+
|
173
|
+
def __init__(self, token: str, config=None, logger_name="pangea", config_id: Optional[str] = None):
|
174
|
+
super().__init__(token, config, logger_name, config_id=config_id)
|
175
|
+
|
176
|
+
def tuple_create(self, tuples: List[Tuple]) -> PangeaResponse[TupleCreateResult]:
|
177
|
+
"""Create tuples. (Beta)
|
178
|
+
|
179
|
+
Create tuples in the AuthZ Service. The request will fail if there is no schema
|
180
|
+
or the tuples do not validate against the schema.
|
181
|
+
How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
|
182
|
+
|
183
|
+
Args:
|
184
|
+
tuples (List[Tuple]): List of tuples to be created.
|
185
|
+
|
186
|
+
Raises:
|
187
|
+
PangeaAPIException: If an API Error happens.
|
188
|
+
|
189
|
+
Returns:
|
190
|
+
Pangea Response with empty result.
|
191
|
+
Available response fields can be found in our
|
192
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/create).
|
193
|
+
|
194
|
+
Examples:
|
195
|
+
response = authz.tuple_create(
|
196
|
+
tuples=[
|
197
|
+
Tuple(
|
198
|
+
resource=Resource(type="file", id="file_1"),
|
199
|
+
relation="owner",
|
200
|
+
subject=Subject(type="user", id="user_1"),
|
201
|
+
)
|
202
|
+
]
|
203
|
+
)
|
204
|
+
"""
|
205
|
+
|
206
|
+
input_data = TupleCreateRequest(tuples=tuples)
|
207
|
+
return self.request.post("v1/tuple/create", TupleCreateResult, data=input_data.dict(exclude_none=True))
|
208
|
+
|
209
|
+
def tuple_list(
|
210
|
+
self,
|
211
|
+
filter: TupleListFilter,
|
212
|
+
size: Optional[int] = None,
|
213
|
+
last: Optional[str] = None,
|
214
|
+
order: Optional[ItemOrder] = None,
|
215
|
+
order_by: Optional[TupleOrderBy] = None,
|
216
|
+
) -> PangeaResponse[TupleListResult]:
|
217
|
+
"""List tuples. (Beta)
|
218
|
+
|
219
|
+
Return a paginated list of filtered tuples. The filter is given in terms
|
220
|
+
of a tuple. Fill out the fields that you want to filter. If the filter
|
221
|
+
is empty it will return all the tuples.
|
222
|
+
How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
|
223
|
+
|
224
|
+
Args:
|
225
|
+
filter (TupleListFilter): The filter for listing tuples.
|
226
|
+
size (Optional[int]): The size of the result set. Default is None.
|
227
|
+
last (Optional[str]): The last token from a previous response. Default is None.
|
228
|
+
order (Optional[ItemOrder]): Order results asc(ending) or desc(ending).
|
229
|
+
order_by (Optional[TupleOrderBy]): Which field to order results by.
|
230
|
+
|
231
|
+
Raises:
|
232
|
+
PangeaAPIException: If an API Error happens.
|
233
|
+
|
234
|
+
Returns:
|
235
|
+
Pangea Response with a list of tuples and the last token.
|
236
|
+
Available response fields can be found in our
|
237
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/list).
|
238
|
+
|
239
|
+
Examples:
|
240
|
+
authz.tuple_list(TupleListFilter(subject_type="user", subject_id="user_1"))
|
241
|
+
"""
|
242
|
+
input_data = TupleListRequest(
|
243
|
+
filter=filter.dict(exclude_none=True), size=size, last=last, order=order, order_by=order_by
|
244
|
+
)
|
245
|
+
return self.request.post("v1/tuple/list", TupleListResult, data=input_data.dict(exclude_none=True))
|
246
|
+
|
247
|
+
def tuple_delete(self, tuples: List[Tuple]) -> PangeaResponse[TupleDeleteResult]:
|
248
|
+
"""Delete tuples. (Beta)
|
249
|
+
|
250
|
+
Delete tuples in the AuthZ Service.
|
251
|
+
How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
|
252
|
+
|
253
|
+
Args:
|
254
|
+
tuples (List[Tuple]): List of tuples to be deleted.
|
255
|
+
|
256
|
+
Raises:
|
257
|
+
PangeaAPIException: If an API Error happens.
|
258
|
+
|
259
|
+
Returns:
|
260
|
+
Pangea Response with empty result.
|
261
|
+
Available response fields can be found in our
|
262
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/delete).
|
263
|
+
|
264
|
+
Examples:
|
265
|
+
response = authz.tuple_delete(
|
266
|
+
tuples=[
|
267
|
+
Tuple(
|
268
|
+
resource=Resource(type="file", id="file_1"),
|
269
|
+
relation="owner",
|
270
|
+
subject=Subject(type="user", id="user_1"),
|
271
|
+
)
|
272
|
+
]
|
273
|
+
)
|
274
|
+
"""
|
275
|
+
|
276
|
+
input_data = TupleDeleteRequest(tuples=tuples)
|
277
|
+
return self.request.post("v1/tuple/delete", TupleDeleteResult, data=input_data.dict(exclude_none=True))
|
278
|
+
|
279
|
+
def check(
|
280
|
+
self,
|
281
|
+
resource: Resource,
|
282
|
+
action: str,
|
283
|
+
subject: Subject,
|
284
|
+
debug: Optional[bool] = None,
|
285
|
+
attributes: Optional[Dict[str, Union[int, str]]] = None,
|
286
|
+
) -> PangeaResponse[CheckResult]:
|
287
|
+
"""Perform a check request. (Beta)
|
288
|
+
|
289
|
+
Check if a subject has permission to perform an action on the resource.
|
290
|
+
How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
|
291
|
+
|
292
|
+
Args:
|
293
|
+
resource (Resource): The resource to check.
|
294
|
+
action (str): The action to check.
|
295
|
+
subject (Subject): The subject to check.
|
296
|
+
debug (Optional[bool]): Setting this value to True will provide a detailed analysis of the check.
|
297
|
+
attributes (Optional[Dict[str, Union[int, str]]]): Additional attributes for the check.
|
298
|
+
|
299
|
+
Raises:
|
300
|
+
PangeaAPIException: If an API Error happens.
|
301
|
+
|
302
|
+
Returns:
|
303
|
+
Pangea Response with the result of the check.
|
304
|
+
Available response fields can be found in our
|
305
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/check).
|
306
|
+
|
307
|
+
Examples:
|
308
|
+
response = authz.check(
|
309
|
+
resource=Resource(type="file", id="file_1"),
|
310
|
+
action="update",
|
311
|
+
subject=Subject(type="user", id="user_1"),
|
312
|
+
debug=True,
|
313
|
+
)
|
314
|
+
"""
|
315
|
+
|
316
|
+
input_data = CheckRequest(resource=resource, action=action, subject=subject, debug=debug, attributes=attributes)
|
317
|
+
return self.request.post("v1/check", CheckResult, data=input_data.dict(exclude_none=True))
|
318
|
+
|
319
|
+
def list_resources(self, type: str, action: str, subject: Subject) -> PangeaResponse[ListResourcesResult]:
|
320
|
+
"""List resources. (Beta)
|
321
|
+
|
322
|
+
Given a type, action, and subject, list all the resources in the
|
323
|
+
type that the subject has access to the action with.
|
324
|
+
How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
|
325
|
+
|
326
|
+
Args:
|
327
|
+
type (str): The type to filter resources.
|
328
|
+
action (str): The action to filter resources.
|
329
|
+
subject (Subject): The subject to filter resources.
|
330
|
+
|
331
|
+
Raises:
|
332
|
+
PangeaAPIException: If an API Error happens.
|
333
|
+
|
334
|
+
Returns:
|
335
|
+
Pangea Response with a list of resource IDs.
|
336
|
+
Available response fields can be found in our
|
337
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-resources).
|
338
|
+
|
339
|
+
Examples:
|
340
|
+
authz.list_resources(
|
341
|
+
type="file",
|
342
|
+
action="update",
|
343
|
+
subject=Subject(type="user", id="user_1"),
|
344
|
+
)
|
345
|
+
"""
|
346
|
+
|
347
|
+
input_data = ListResourcesRequest(type=type, action=action, subject=subject)
|
348
|
+
return self.request.post("v1/list-resources", ListResourcesResult, data=input_data.dict(exclude_none=True))
|
349
|
+
|
350
|
+
def list_subjects(self, resource: Resource, action: str) -> PangeaResponse[ListSubjectsResult]:
|
351
|
+
"""List subjects. (Beta)
|
352
|
+
|
353
|
+
Given a resource and an action, return the list of subjects who have
|
354
|
+
access to the action for the given resource.
|
355
|
+
How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
|
356
|
+
|
357
|
+
Args:
|
358
|
+
resource (Resource): The resource to filter subjects.
|
359
|
+
action (str): The action to filter subjects.
|
360
|
+
|
361
|
+
Raises:
|
362
|
+
PangeaAPIException: If an API Error happens.
|
363
|
+
|
364
|
+
Returns:
|
365
|
+
Pangea Response with a list of subjects.
|
366
|
+
Available response fields can be found in our
|
367
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-subjects).
|
368
|
+
|
369
|
+
Examples:
|
370
|
+
response = authz.list_subjects(
|
371
|
+
resource=Resource(type="file", id="file_1"),
|
372
|
+
action="update",
|
373
|
+
)
|
374
|
+
"""
|
375
|
+
|
376
|
+
input_data = ListSubjectsRequest(resource=resource, action=action)
|
377
|
+
return self.request.post("v1/list-subjects", ListSubjectsResult, data=input_data.dict(exclude_none=True))
|
pangea/services/base.py
CHANGED
@@ -1,45 +1,62 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
from __future__ import annotations
|
3
4
|
|
4
5
|
import copy
|
5
6
|
import logging
|
6
|
-
from typing import Optional, Type, Union
|
7
|
+
from typing import Dict, Optional, Type, Union
|
8
|
+
|
9
|
+
from typing_extensions import TypeVar
|
7
10
|
|
8
11
|
from pangea.asyncio.request import PangeaRequestAsync
|
9
12
|
from pangea.config import PangeaConfig
|
10
13
|
from pangea.exceptions import AcceptedRequestException
|
11
14
|
from pangea.request import PangeaRequest
|
12
|
-
from pangea.response import PangeaResponse, PangeaResponseResult
|
15
|
+
from pangea.response import AttachedFile, PangeaResponse, PangeaResponseResult
|
16
|
+
|
17
|
+
TResult = TypeVar("TResult", bound=PangeaResponseResult, default=PangeaResponseResult)
|
13
18
|
|
14
19
|
|
15
20
|
class ServiceBase(object):
|
16
21
|
service_name: str = "base"
|
17
22
|
|
18
23
|
def __init__(
|
19
|
-
self,
|
20
|
-
|
24
|
+
self,
|
25
|
+
token: str,
|
26
|
+
config: PangeaConfig | None = None,
|
27
|
+
logger_name: str = "pangea",
|
28
|
+
config_id: str | None = None,
|
29
|
+
) -> None:
|
30
|
+
"""
|
31
|
+
Initializes a new Pangea service client.
|
32
|
+
|
33
|
+
Args:
|
34
|
+
token: Pangea API token.
|
35
|
+
config: Configuration.
|
36
|
+
logger_name: Logger name.
|
37
|
+
"""
|
21
38
|
if not token:
|
22
39
|
raise Exception("No token provided")
|
23
40
|
|
24
|
-
self.config =
|
41
|
+
self.config = copy.deepcopy(config) if config is not None else PangeaConfig()
|
25
42
|
self.logger = logging.getLogger(logger_name)
|
26
43
|
self._token = token
|
27
|
-
self.config_id: Optional[
|
28
|
-
self._request: Union[PangeaRequest, PangeaRequestAsync] = None
|
29
|
-
extra_headers = {}
|
44
|
+
self.config_id: Optional[str] = config_id
|
45
|
+
self._request: Optional[Union[PangeaRequest, PangeaRequestAsync]] = None
|
46
|
+
extra_headers: Dict = {}
|
30
47
|
self.request.set_extra_headers(extra_headers)
|
31
48
|
|
32
49
|
@property
|
33
|
-
def token(self):
|
50
|
+
def token(self) -> str:
|
34
51
|
return self._token
|
35
52
|
|
36
53
|
@token.setter
|
37
|
-
def token(self, value):
|
54
|
+
def token(self, value: str) -> None:
|
38
55
|
self._token = value
|
39
56
|
|
40
57
|
@property
|
41
|
-
def request(self):
|
42
|
-
if
|
58
|
+
def request(self) -> PangeaRequest:
|
59
|
+
if self._request is None or isinstance(self._request, PangeaRequestAsync):
|
43
60
|
self._request = PangeaRequest(
|
44
61
|
config=self.config,
|
45
62
|
token=self.token,
|
@@ -55,8 +72,8 @@ class ServiceBase(object):
|
|
55
72
|
exception: Optional[AcceptedRequestException] = None,
|
56
73
|
response: Optional[PangeaResponse] = None,
|
57
74
|
request_id: Optional[str] = None,
|
58
|
-
result_class:
|
59
|
-
) -> PangeaResponse:
|
75
|
+
result_class: Type[TResult] = PangeaResponseResult, # type: ignore[assignment]
|
76
|
+
) -> PangeaResponse[TResult]:
|
60
77
|
"""
|
61
78
|
Poll result
|
62
79
|
|
@@ -82,3 +99,6 @@ class ServiceBase(object):
|
|
82
99
|
return self.request.poll_result_by_id(request_id=request_id, result_class=result_class, check_response=True)
|
83
100
|
else:
|
84
101
|
raise AttributeError("Need to set exception, response or request_id")
|
102
|
+
|
103
|
+
def download_file(self, url: str, filename: Optional[str] = None) -> AttachedFile:
|
104
|
+
return self.request.download_file(url=url, filename=filename)
|
pangea/services/embargo.py
CHANGED
@@ -3,8 +3,7 @@
|
|
3
3
|
from typing import Any, Dict, List
|
4
4
|
|
5
5
|
from pangea.response import APIRequestModel, APIResponseModel, PangeaResponse, PangeaResponseResult
|
6
|
-
|
7
|
-
from .base import ServiceBase
|
6
|
+
from pangea.services.base import ServiceBase
|
8
7
|
|
9
8
|
|
10
9
|
class IPCheckRequest(APIRequestModel):
|
pangea/services/file_scan.py
CHANGED
@@ -2,14 +2,13 @@
|
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
3
|
import io
|
4
4
|
import logging
|
5
|
-
from typing import Dict, List, Optional
|
5
|
+
from typing import Dict, List, Optional, Tuple
|
6
6
|
|
7
7
|
from pangea.request import PangeaConfig, PangeaRequest
|
8
8
|
from pangea.response import APIRequestModel, PangeaResponse, PangeaResponseResult, TransferMethod
|
9
|
+
from pangea.services.base import ServiceBase
|
9
10
|
from pangea.utils import FileUploadParams, get_file_upload_params
|
10
11
|
|
11
|
-
from .base import ServiceBase
|
12
|
-
|
13
12
|
|
14
13
|
class FileScanRequest(APIRequestModel):
|
15
14
|
"""
|
@@ -129,7 +128,7 @@ class FileScan(ServiceBase):
|
|
129
128
|
size = params.size
|
130
129
|
else:
|
131
130
|
crc, sha, size = None, None, None
|
132
|
-
files = [("upload", ("filename", file, "application/octet-stream"))]
|
131
|
+
files: List[Tuple] = [("upload", ("filename", file, "application/octet-stream"))]
|
133
132
|
else:
|
134
133
|
raise ValueError("Need to set file_path or file arguments")
|
135
134
|
|
pangea/services/intel.py
CHANGED
@@ -6,10 +6,9 @@ from typing import Dict, List, Optional
|
|
6
6
|
|
7
7
|
from pangea.exceptions import PangeaException
|
8
8
|
from pangea.response import APIRequestModel, PangeaResponse, PangeaResponseResult
|
9
|
+
from pangea.services.base import ServiceBase
|
9
10
|
from pangea.utils import hash_256_filepath
|
10
11
|
|
11
|
-
from .base import ServiceBase
|
12
|
-
|
13
12
|
|
14
13
|
class IntelCommonRequest(APIRequestModel):
|
15
14
|
"""
|
@@ -840,7 +839,7 @@ class IpIntel(ServiceBase):
|
|
840
839
|
|
841
840
|
def reputation_bulk(
|
842
841
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
843
|
-
) -> PangeaResponse[
|
842
|
+
) -> PangeaResponse[IPReputationBulkResult]:
|
844
843
|
"""
|
845
844
|
Reputation V2
|
846
845
|
|
@@ -1196,7 +1195,7 @@ class UrlIntel(ServiceBase):
|
|
1196
1195
|
verbose: Optional[bool] = None,
|
1197
1196
|
raw: Optional[bool] = None,
|
1198
1197
|
provider: Optional[str] = None,
|
1199
|
-
) -> PangeaResponse[
|
1198
|
+
) -> PangeaResponse[URLReputationBulkResult]:
|
1200
1199
|
"""
|
1201
1200
|
Reputation V2
|
1202
1201
|
|
pangea/services/redact.py
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
from __future__ import annotations
|
3
4
|
|
4
5
|
import enum
|
5
6
|
from typing import Dict, List, Optional, Union
|
6
7
|
|
8
|
+
from pangea.config import PangeaConfig
|
7
9
|
from pangea.response import APIRequestModel, APIResponseModel, PangeaResponse, PangeaResponseResult
|
8
|
-
|
9
|
-
from .base import ServiceBase
|
10
|
+
from pangea.services.base import ServiceBase
|
10
11
|
|
11
12
|
|
12
13
|
class RedactFormat(str, enum.Enum):
|
@@ -133,7 +134,24 @@ class Redact(ServiceBase):
|
|
133
134
|
|
134
135
|
service_name = "redact"
|
135
136
|
|
136
|
-
def __init__(
|
137
|
+
def __init__(
|
138
|
+
self, token: str, config: PangeaConfig | None = None, logger_name: str = "pangea", config_id: str | None = None
|
139
|
+
) -> None:
|
140
|
+
"""
|
141
|
+
Redact client
|
142
|
+
|
143
|
+
Initializes a new Redact client.
|
144
|
+
|
145
|
+
Args:
|
146
|
+
token: Pangea API token.
|
147
|
+
config: Configuration.
|
148
|
+
logger_name: Logger name.
|
149
|
+
config_id: Configuration ID.
|
150
|
+
|
151
|
+
Examples:
|
152
|
+
config = PangeaConfig(domain="pangea_domain")
|
153
|
+
redact = Redact(token="pangea_token", config=config)
|
154
|
+
"""
|
137
155
|
super().__init__(token, config, logger_name, config_id=config_id)
|
138
156
|
|
139
157
|
def redact(
|
pangea/services/vault/vault.py
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
from __future__ import annotations
|
4
|
+
|
3
5
|
import datetime
|
4
6
|
from typing import Dict, Optional, Union
|
5
7
|
|
8
|
+
from pangea.config import PangeaConfig
|
6
9
|
from pangea.response import PangeaResponse
|
7
10
|
from pangea.services.base import ServiceBase
|
8
11
|
from pangea.services.vault.models.asymmetric import (
|
@@ -48,8 +51,8 @@ from pangea.services.vault.models.common import (
|
|
48
51
|
StateChangeRequest,
|
49
52
|
StateChangeResult,
|
50
53
|
SymmetricAlgorithm,
|
51
|
-
TDict,
|
52
54
|
Tags,
|
55
|
+
TDict,
|
53
56
|
UpdateRequest,
|
54
57
|
UpdateResult,
|
55
58
|
)
|
@@ -91,17 +94,31 @@ class Vault(ServiceBase):
|
|
91
94
|
vault_config = PangeaConfig(domain="pangea.cloud")
|
92
95
|
|
93
96
|
# Setup Pangea Vault service
|
94
|
-
vault = Vault(token=PANGEA_VAULT_TOKEN, config=
|
97
|
+
vault = Vault(token=PANGEA_VAULT_TOKEN, config=vault_config)
|
95
98
|
"""
|
96
99
|
|
97
100
|
service_name = "vault"
|
98
101
|
|
99
102
|
def __init__(
|
100
103
|
self,
|
101
|
-
token,
|
102
|
-
config=None,
|
103
|
-
logger_name="pangea",
|
104
|
-
):
|
104
|
+
token: str,
|
105
|
+
config: PangeaConfig | None = None,
|
106
|
+
logger_name: str = "pangea",
|
107
|
+
) -> None:
|
108
|
+
"""
|
109
|
+
Vault client
|
110
|
+
|
111
|
+
Initializes a new Vault client.
|
112
|
+
|
113
|
+
Args:
|
114
|
+
token: Pangea API token.
|
115
|
+
config: Configuration.
|
116
|
+
logger_name: Logger name.
|
117
|
+
|
118
|
+
Examples:
|
119
|
+
config = PangeaConfig(domain="pangea_domain")
|
120
|
+
vault = Vault(token="pangea_token", config=config)
|
121
|
+
"""
|
105
122
|
super().__init__(token, config, logger_name)
|
106
123
|
|
107
124
|
# Delete endpoint
|
@@ -866,8 +883,8 @@ class Vault(ServiceBase):
|
|
866
883
|
|
867
884
|
Default is `deactivated`.
|
868
885
|
public_key (EncodedPublicKey, optional): The public key (in PEM format)
|
869
|
-
private_key
|
870
|
-
key
|
886
|
+
private_key (EncodedPrivateKey, optional): The private key (in PEM format)
|
887
|
+
key (EncodedSymmetricKey, optional): The key material (in base64)
|
871
888
|
|
872
889
|
Raises:
|
873
890
|
PangeaAPIException: If an API Error happens
|
@@ -1216,7 +1233,7 @@ class Vault(ServiceBase):
|
|
1216
1233
|
Args:
|
1217
1234
|
id (str): The item ID.
|
1218
1235
|
structured_data (dict): Structured data for applying bulk operations.
|
1219
|
-
filter (str
|
1236
|
+
filter (str): A filter expression for applying bulk operations to the data field.
|
1220
1237
|
version (int, optional): The item version. Defaults to the current version.
|
1221
1238
|
additional_data (str, optional): User provided authentication data.
|
1222
1239
|
|
@@ -1237,7 +1254,7 @@ class Vault(ServiceBase):
|
|
1237
1254
|
)
|
1238
1255
|
"""
|
1239
1256
|
|
1240
|
-
input = EncryptStructuredRequest(
|
1257
|
+
input: EncryptStructuredRequest[TDict] = EncryptStructuredRequest(
|
1241
1258
|
id=id, structured_data=structured_data, filter=filter, version=version, additional_data=additional_data
|
1242
1259
|
)
|
1243
1260
|
return self.request.post(
|
@@ -1265,7 +1282,7 @@ class Vault(ServiceBase):
|
|
1265
1282
|
Args:
|
1266
1283
|
id (str): The item ID.
|
1267
1284
|
structured_data (dict): Structured data to decrypt.
|
1268
|
-
filter (str
|
1285
|
+
filter (str): A filter expression for applying bulk operations to the data field.
|
1269
1286
|
version (int, optional): The item version. Defaults to the current version.
|
1270
1287
|
additional_data (str, optional): User provided authentication data.
|
1271
1288
|
|
@@ -1286,7 +1303,7 @@ class Vault(ServiceBase):
|
|
1286
1303
|
)
|
1287
1304
|
"""
|
1288
1305
|
|
1289
|
-
input = EncryptStructuredRequest(
|
1306
|
+
input: EncryptStructuredRequest[TDict] = EncryptStructuredRequest(
|
1290
1307
|
id=id, structured_data=structured_data, filter=filter, version=version, additional_data=additional_data
|
1291
1308
|
)
|
1292
1309
|
return self.request.post(
|