pangea-sdk 3.8.0b4__py3-none-any.whl → 4.0.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 -2
- pangea/asyncio/request.py +17 -22
- pangea/asyncio/services/__init__.py +0 -2
- pangea/asyncio/services/audit.py +188 -23
- pangea/asyncio/services/authn.py +167 -108
- pangea/asyncio/services/authz.py +36 -45
- pangea/asyncio/services/embargo.py +2 -2
- pangea/asyncio/services/file_scan.py +3 -3
- pangea/asyncio/services/intel.py +44 -26
- pangea/asyncio/services/redact.py +60 -4
- pangea/asyncio/services/vault.py +145 -30
- pangea/dump_audit.py +1 -1
- pangea/request.py +30 -24
- pangea/response.py +34 -42
- pangea/services/__init__.py +0 -2
- pangea/services/audit/audit.py +202 -34
- pangea/services/audit/models.py +56 -8
- pangea/services/audit/util.py +3 -3
- pangea/services/authn/authn.py +116 -65
- pangea/services/authn/models.py +88 -4
- pangea/services/authz.py +51 -56
- pangea/services/base.py +23 -6
- pangea/services/embargo.py +2 -2
- pangea/services/file_scan.py +3 -2
- pangea/services/intel.py +25 -23
- pangea/services/redact.py +124 -4
- pangea/services/vault/models/common.py +121 -6
- pangea/services/vault/models/symmetric.py +2 -2
- pangea/services/vault/vault.py +143 -32
- pangea/utils.py +20 -109
- pangea/verify_audit.py +267 -83
- {pangea_sdk-3.8.0b4.dist-info → pangea_sdk-4.0.0.dist-info}/METADATA +12 -20
- pangea_sdk-4.0.0.dist-info/RECORD +46 -0
- {pangea_sdk-3.8.0b4.dist-info → pangea_sdk-4.0.0.dist-info}/WHEEL +1 -1
- pangea/asyncio/__init__.py +0 -1
- pangea/asyncio/file_uploader.py +0 -39
- pangea/asyncio/services/sanitize.py +0 -185
- pangea/asyncio/services/share.py +0 -573
- pangea/file_uploader.py +0 -35
- pangea/services/sanitize.py +0 -275
- pangea/services/share/file_format.py +0 -170
- pangea/services/share/share.py +0 -877
- pangea_sdk-3.8.0b4.dist-info/RECORD +0 -54
pangea/asyncio/services/authz.py
CHANGED
@@ -28,12 +28,11 @@ from pangea.services.authz import (
|
|
28
28
|
|
29
29
|
|
30
30
|
class AuthZAsync(ServiceBaseAsync):
|
31
|
-
"""AuthZ service client.
|
31
|
+
"""AuthZ service client.
|
32
32
|
|
33
33
|
Provides methods to interact with the Pangea AuthZ Service.
|
34
34
|
Documentation for the AuthZ Service API can be found at
|
35
|
-
<https://pangea.cloud/docs/api/authz>.
|
36
|
-
is subject to change.
|
35
|
+
<https://pangea.cloud/docs/api/authz>.
|
37
36
|
|
38
37
|
Examples:
|
39
38
|
import os
|
@@ -54,11 +53,10 @@ class AuthZAsync(ServiceBaseAsync):
|
|
54
53
|
super().__init__(token, config, logger_name, config_id=config_id)
|
55
54
|
|
56
55
|
async def tuple_create(self, tuples: List[Tuple]) -> PangeaResponse[TupleCreateResult]:
|
57
|
-
"""Create tuples.
|
56
|
+
"""Create tuples.
|
58
57
|
|
59
58
|
Create tuples in the AuthZ Service. The request will fail if there is no schema
|
60
59
|
or the tuples do not validate against the schema.
|
61
|
-
How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
|
62
60
|
|
63
61
|
Args:
|
64
62
|
tuples (List[Tuple]): List of tuples to be created.
|
@@ -69,15 +67,15 @@ class AuthZAsync(ServiceBaseAsync):
|
|
69
67
|
Returns:
|
70
68
|
Pangea Response with empty result.
|
71
69
|
Available response fields can be found in our
|
72
|
-
[API Documentation](https://pangea.cloud/docs/api/authz#/
|
70
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/create).
|
73
71
|
|
74
72
|
Examples:
|
75
73
|
await authz.tuple_create(
|
76
74
|
tuples=[
|
77
75
|
Tuple(
|
78
|
-
resource=Resource(
|
76
|
+
resource=Resource(type="file", id="file_1"),
|
79
77
|
relation="owner",
|
80
|
-
subject=Subject(
|
78
|
+
subject=Subject(type="user", id="user_1"),
|
81
79
|
)
|
82
80
|
]
|
83
81
|
)
|
@@ -85,7 +83,7 @@ class AuthZAsync(ServiceBaseAsync):
|
|
85
83
|
|
86
84
|
input_data = TupleCreateRequest(tuples=tuples)
|
87
85
|
return await self.request.post(
|
88
|
-
"
|
86
|
+
"v1/tuple/create", TupleCreateResult, data=input_data.model_dump(exclude_none=True)
|
89
87
|
)
|
90
88
|
|
91
89
|
async def tuple_list(
|
@@ -96,12 +94,11 @@ class AuthZAsync(ServiceBaseAsync):
|
|
96
94
|
order: Optional[ItemOrder] = None,
|
97
95
|
order_by: Optional[TupleOrderBy] = None,
|
98
96
|
) -> PangeaResponse[TupleListResult]:
|
99
|
-
"""List tuples.
|
97
|
+
"""List tuples.
|
100
98
|
|
101
99
|
Return a paginated list of filtered tuples. The filter is given in terms
|
102
100
|
of a tuple. Fill out the fields that you want to filter. If the filter
|
103
101
|
is empty it will return all the tuples.
|
104
|
-
How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
|
105
102
|
|
106
103
|
Args:
|
107
104
|
filter (TupleListFilter): The filter for listing tuples.
|
@@ -116,21 +113,20 @@ class AuthZAsync(ServiceBaseAsync):
|
|
116
113
|
Returns:
|
117
114
|
Pangea Response with a list of tuples and the last token.
|
118
115
|
Available response fields can be found in our
|
119
|
-
[API Documentation](https://pangea.cloud/docs/api/authz#/
|
116
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/list).
|
120
117
|
|
121
118
|
Examples:
|
122
|
-
await authz.tuple_list(TupleListFilter(
|
119
|
+
await authz.tuple_list(TupleListFilter(subject_type="user", subject_id="user_1"))
|
123
120
|
"""
|
124
121
|
input_data = TupleListRequest(
|
125
|
-
filter=filter.
|
122
|
+
filter=filter.model_dump(exclude_none=True), size=size, last=last, order=order, order_by=order_by
|
126
123
|
)
|
127
|
-
return await self.request.post("
|
124
|
+
return await self.request.post("v1/tuple/list", TupleListResult, data=input_data.model_dump(exclude_none=True))
|
128
125
|
|
129
126
|
async def tuple_delete(self, tuples: List[Tuple]) -> PangeaResponse[TupleDeleteResult]:
|
130
|
-
"""Delete tuples.
|
127
|
+
"""Delete tuples.
|
131
128
|
|
132
129
|
Delete tuples in the AuthZ Service.
|
133
|
-
How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
|
134
130
|
|
135
131
|
Args:
|
136
132
|
tuples (List[Tuple]): List of tuples to be deleted.
|
@@ -141,15 +137,15 @@ class AuthZAsync(ServiceBaseAsync):
|
|
141
137
|
Returns:
|
142
138
|
Pangea Response with empty result.
|
143
139
|
Available response fields can be found in our
|
144
|
-
[API Documentation](https://pangea.cloud/docs/api/authz#/
|
140
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/delete).
|
145
141
|
|
146
142
|
Examples:
|
147
143
|
await authz.tuple_delete(
|
148
144
|
tuples=[
|
149
145
|
Tuple(
|
150
|
-
resource=Resource(
|
146
|
+
resource=Resource(type="file", id="file_1"),
|
151
147
|
relation="owner",
|
152
|
-
subject=Subject(
|
148
|
+
subject=Subject(type="user", id="user_1"),
|
153
149
|
)
|
154
150
|
]
|
155
151
|
)
|
@@ -157,7 +153,7 @@ class AuthZAsync(ServiceBaseAsync):
|
|
157
153
|
|
158
154
|
input_data = TupleDeleteRequest(tuples=tuples)
|
159
155
|
return await self.request.post(
|
160
|
-
"
|
156
|
+
"v1/tuple/delete", TupleDeleteResult, data=input_data.model_dump(exclude_none=True)
|
161
157
|
)
|
162
158
|
|
163
159
|
async def check(
|
@@ -168,10 +164,9 @@ class AuthZAsync(ServiceBaseAsync):
|
|
168
164
|
debug: Optional[bool] = None,
|
169
165
|
attributes: Optional[Dict[str, Union[int, str]]] = None,
|
170
166
|
) -> PangeaResponse[CheckResult]:
|
171
|
-
"""Perform a check request.
|
167
|
+
"""Perform a check request.
|
172
168
|
|
173
169
|
Check if a subject has permission to perform an action on the resource.
|
174
|
-
How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
|
175
170
|
|
176
171
|
Args:
|
177
172
|
resource (Resource): The resource to check.
|
@@ -186,31 +181,28 @@ class AuthZAsync(ServiceBaseAsync):
|
|
186
181
|
Returns:
|
187
182
|
Pangea Response with the result of the check.
|
188
183
|
Available response fields can be found in our
|
189
|
-
[API Documentation](https://pangea.cloud/docs/api/authz#/
|
184
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/check).
|
190
185
|
|
191
186
|
Examples:
|
192
187
|
await authz.check(
|
193
|
-
resource=Resource(
|
188
|
+
resource=Resource(type="file", id="file_1"),
|
194
189
|
action="update",
|
195
|
-
subject=Subject(
|
190
|
+
subject=Subject(type="user", id="user_1"),
|
196
191
|
debug=True,
|
197
192
|
)
|
198
193
|
"""
|
199
194
|
|
200
195
|
input_data = CheckRequest(resource=resource, action=action, subject=subject, debug=debug, attributes=attributes)
|
201
|
-
return await self.request.post("
|
196
|
+
return await self.request.post("v1/check", CheckResult, data=input_data.model_dump(exclude_none=True))
|
202
197
|
|
203
|
-
async def list_resources(
|
204
|
-
|
205
|
-
) -> PangeaResponse[ListResourcesResult]:
|
206
|
-
"""List resources. (Beta)
|
198
|
+
async def list_resources(self, type: str, action: str, subject: Subject) -> PangeaResponse[ListResourcesResult]:
|
199
|
+
"""List resources.
|
207
200
|
|
208
|
-
Given a
|
209
|
-
|
210
|
-
How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
|
201
|
+
Given a type, action, and subject, list all the resources in the
|
202
|
+
type that the subject has access to the action with.
|
211
203
|
|
212
204
|
Args:
|
213
|
-
|
205
|
+
type (str): The type to filter resources.
|
214
206
|
action (str): The action to filter resources.
|
215
207
|
subject (Subject): The subject to filter resources.
|
216
208
|
|
@@ -220,27 +212,26 @@ class AuthZAsync(ServiceBaseAsync):
|
|
220
212
|
Returns:
|
221
213
|
Pangea Response with a list of resource IDs.
|
222
214
|
Available response fields can be found in our
|
223
|
-
[API Documentation](https://pangea.cloud/docs/api/authz#/
|
215
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-resources).
|
224
216
|
|
225
217
|
Examples:
|
226
218
|
await authz.list_resources(
|
227
|
-
|
219
|
+
type="file",
|
228
220
|
action="update",
|
229
|
-
subject=Subject(
|
221
|
+
subject=Subject(type="user", id="user_1"),
|
230
222
|
)
|
231
223
|
"""
|
232
224
|
|
233
|
-
input_data = ListResourcesRequest(
|
225
|
+
input_data = ListResourcesRequest(type=type, action=action, subject=subject)
|
234
226
|
return await self.request.post(
|
235
|
-
"
|
227
|
+
"v1/list-resources", ListResourcesResult, data=input_data.model_dump(exclude_none=True)
|
236
228
|
)
|
237
229
|
|
238
230
|
async def list_subjects(self, resource: Resource, action: str) -> PangeaResponse[ListSubjectsResult]:
|
239
|
-
"""List subjects.
|
231
|
+
"""List subjects.
|
240
232
|
|
241
233
|
Given a resource and an action, return the list of subjects who have
|
242
234
|
access to the action for the given resource.
|
243
|
-
How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
|
244
235
|
|
245
236
|
Args:
|
246
237
|
resource (Resource): The resource to filter subjects.
|
@@ -252,16 +243,16 @@ class AuthZAsync(ServiceBaseAsync):
|
|
252
243
|
Returns:
|
253
244
|
Pangea Response with a list of subjects.
|
254
245
|
Available response fields can be found in our
|
255
|
-
[API Documentation](https://pangea.cloud/docs/api/authz#/
|
246
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-subjects).
|
256
247
|
|
257
248
|
Examples:
|
258
249
|
await authz.list_subjects(
|
259
|
-
resource=Resource(
|
250
|
+
resource=Resource(type="file", id="file_1"),
|
260
251
|
action="update",
|
261
252
|
)
|
262
253
|
"""
|
263
254
|
|
264
255
|
input_data = ListSubjectsRequest(resource=resource, action=action)
|
265
256
|
return await self.request.post(
|
266
|
-
"
|
257
|
+
"v1/list-subjects", ListSubjectsResult, data=input_data.model_dump(exclude_none=True)
|
267
258
|
)
|
@@ -57,7 +57,7 @@ class EmbargoAsync(ServiceBaseAsync):
|
|
57
57
|
response = embargo.ip_check("190.6.64.94")
|
58
58
|
"""
|
59
59
|
input = e.IPCheckRequest(ip=ip)
|
60
|
-
return await self.request.post("v1/ip/check", e.EmbargoResult, data=input.
|
60
|
+
return await self.request.post("v1/ip/check", e.EmbargoResult, data=input.model_dump())
|
61
61
|
|
62
62
|
async def iso_check(self, iso_code: str) -> PangeaResponse[e.EmbargoResult]:
|
63
63
|
"""
|
@@ -84,4 +84,4 @@ class EmbargoAsync(ServiceBaseAsync):
|
|
84
84
|
response = embargo.iso_check("CU")
|
85
85
|
"""
|
86
86
|
input = e.ISOCheckRequest(iso_code=iso_code)
|
87
|
-
return await self.request.post("v1/iso/check", result_class=e.EmbargoResult, data=input.
|
87
|
+
return await self.request.post("v1/iso/check", result_class=e.EmbargoResult, data=input.model_dump())
|
@@ -109,7 +109,7 @@ class FileScanAsync(ServiceBaseAsync):
|
|
109
109
|
transfer_method=transfer_method,
|
110
110
|
source_url=source_url,
|
111
111
|
)
|
112
|
-
data = input.
|
112
|
+
data = input.model_dump(exclude_none=True)
|
113
113
|
return await self.request.post("v1/scan", m.FileScanResult, data=data, files=files, poll_result=sync_call)
|
114
114
|
|
115
115
|
async def request_upload_url(
|
@@ -131,7 +131,7 @@ class FileScanAsync(ServiceBaseAsync):
|
|
131
131
|
input.sha256 = params.sha256_hex
|
132
132
|
input.size = params.size
|
133
133
|
|
134
|
-
data = input.
|
134
|
+
data = input.model_dump(exclude_none=True)
|
135
135
|
return await self.request.request_presigned_url("v1/scan", m.FileScanResult, data=data)
|
136
136
|
|
137
137
|
|
@@ -154,7 +154,7 @@ class FileUploaderAsync:
|
|
154
154
|
) -> None:
|
155
155
|
if transfer_method == TransferMethod.PUT_URL:
|
156
156
|
files = [("file", ("filename", file, "application/octet-stream"))]
|
157
|
-
await self._request.put_presigned_url(url=url, files=files)
|
157
|
+
await self._request.put_presigned_url(url=url, files=files)
|
158
158
|
elif transfer_method == TransferMethod.POST_URL:
|
159
159
|
files = [("file", ("filename", file, "application/octet-stream"))]
|
160
160
|
await self._request.post_presigned_url(url=url, data=file_details, files=files) # type: ignore[arg-type]
|
pangea/asyncio/services/intel.py
CHANGED
@@ -67,7 +67,9 @@ class FileIntelAsync(ServiceBaseAsync):
|
|
67
67
|
|
68
68
|
"""
|
69
69
|
input = m.FileReputationRequest(hash=hash, hash_type=hash_type, verbose=verbose, raw=raw, provider=provider)
|
70
|
-
return await self.request.post(
|
70
|
+
return await self.request.post(
|
71
|
+
"v1/reputation", m.FileReputationResult, data=input.model_dump(exclude_none=True)
|
72
|
+
)
|
71
73
|
|
72
74
|
async def hash_reputation_bulk(
|
73
75
|
self,
|
@@ -76,7 +78,7 @@ class FileIntelAsync(ServiceBaseAsync):
|
|
76
78
|
provider: Optional[str] = None,
|
77
79
|
verbose: Optional[bool] = None,
|
78
80
|
raw: Optional[bool] = None,
|
79
|
-
) -> PangeaResponse[m.
|
81
|
+
) -> PangeaResponse[m.FileReputationBulkResult]:
|
80
82
|
"""
|
81
83
|
Reputation check
|
82
84
|
|
@@ -103,7 +105,9 @@ class FileIntelAsync(ServiceBaseAsync):
|
|
103
105
|
input = m.FileReputationBulkRequest( # type: ignore[call-arg]
|
104
106
|
hashes=hashes, hash_type=hash_type, verbose=verbose, raw=raw, provider=provider
|
105
107
|
)
|
106
|
-
return await self.request.post(
|
108
|
+
return await self.request.post(
|
109
|
+
"v2/reputation", m.FileReputationBulkResult, data=input.model_dump(exclude_none=True)
|
110
|
+
)
|
107
111
|
|
108
112
|
async def filepath_reputation(
|
109
113
|
self,
|
@@ -144,7 +148,9 @@ class FileIntelAsync(ServiceBaseAsync):
|
|
144
148
|
hash = hashlib.sha256(data.read()).hexdigest()
|
145
149
|
|
146
150
|
input = m.FileReputationRequest(hash=hash, hash_type="sha256", verbose=verbose, raw=raw, provider=provider)
|
147
|
-
return await self.request.post(
|
151
|
+
return await self.request.post(
|
152
|
+
"v1/reputation", m.FileReputationResult, data=input.model_dump(exclude_none=True)
|
153
|
+
)
|
148
154
|
|
149
155
|
async def filepath_reputation_bulk(
|
150
156
|
self,
|
@@ -182,7 +188,7 @@ class FileIntelAsync(ServiceBaseAsync):
|
|
182
188
|
hash = hash_256_filepath(filepath)
|
183
189
|
hashes.append(hash)
|
184
190
|
|
185
|
-
return await self.hash_reputation_bulk(
|
191
|
+
return await self.hash_reputation_bulk(
|
186
192
|
hashes=hashes, hash_type="sha256", verbose=verbose, raw=raw, provider=provider
|
187
193
|
)
|
188
194
|
|
@@ -243,7 +249,9 @@ class DomainIntelAsync(ServiceBaseAsync):
|
|
243
249
|
)
|
244
250
|
"""
|
245
251
|
input = m.DomainReputationRequest(domain=domain, verbose=verbose, provider=provider, raw=raw)
|
246
|
-
return await self.request.post(
|
252
|
+
return await self.request.post(
|
253
|
+
"v1/reputation", m.DomainReputationResult, data=input.model_dump(exclude_none=True)
|
254
|
+
)
|
247
255
|
|
248
256
|
async def reputation_bulk(
|
249
257
|
self,
|
@@ -251,7 +259,7 @@ class DomainIntelAsync(ServiceBaseAsync):
|
|
251
259
|
verbose: Optional[bool] = None,
|
252
260
|
raw: Optional[bool] = None,
|
253
261
|
provider: Optional[str] = None,
|
254
|
-
) -> PangeaResponse[m.
|
262
|
+
) -> PangeaResponse[m.DomainReputationBulkResult]:
|
255
263
|
"""
|
256
264
|
Reputation
|
257
265
|
|
@@ -277,7 +285,7 @@ class DomainIntelAsync(ServiceBaseAsync):
|
|
277
285
|
"""
|
278
286
|
input = m.DomainReputationBulkRequest(domains=domains, verbose=verbose, provider=provider, raw=raw)
|
279
287
|
return await self.request.post(
|
280
|
-
"v2/reputation", m.DomainReputationBulkResult, data=input.
|
288
|
+
"v2/reputation", m.DomainReputationBulkResult, data=input.model_dump(exclude_none=True)
|
281
289
|
)
|
282
290
|
|
283
291
|
async def who_is(
|
@@ -310,7 +318,7 @@ class DomainIntelAsync(ServiceBaseAsync):
|
|
310
318
|
)
|
311
319
|
"""
|
312
320
|
input = m.DomainWhoIsRequest(domain=domain, verbose=verbose, provider=provider, raw=raw) # type: ignore[call-arg]
|
313
|
-
return await self.request.post("v1/whois", m.DomainWhoIsResult, data=input.
|
321
|
+
return await self.request.post("v1/whois", m.DomainWhoIsResult, data=input.model_dump(exclude_none=True))
|
314
322
|
|
315
323
|
|
316
324
|
class IpIntelAsync(ServiceBaseAsync):
|
@@ -369,11 +377,11 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
369
377
|
)
|
370
378
|
"""
|
371
379
|
input = m.IPReputationRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
372
|
-
return await self.request.post("v1/reputation", m.IPReputationResult, data=input.
|
380
|
+
return await self.request.post("v1/reputation", m.IPReputationResult, data=input.model_dump(exclude_none=True))
|
373
381
|
|
374
382
|
async def reputation_bulk(
|
375
383
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
376
|
-
) -> PangeaResponse[m.
|
384
|
+
) -> PangeaResponse[m.IPReputationBulkResult]:
|
377
385
|
"""
|
378
386
|
Reputation
|
379
387
|
|
@@ -398,7 +406,9 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
398
406
|
FIXME:
|
399
407
|
"""
|
400
408
|
input = m.IPReputationBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
401
|
-
return await self.request.post(
|
409
|
+
return await self.request.post(
|
410
|
+
"v2/reputation", m.IPReputationBulkResult, data=input.model_dump(exclude_none=True)
|
411
|
+
)
|
402
412
|
|
403
413
|
async def geolocate(
|
404
414
|
self, ip: str, verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -430,7 +440,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
430
440
|
)
|
431
441
|
"""
|
432
442
|
input = m.IPGeolocateRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
433
|
-
return await self.request.post("v1/geolocate", m.IPGeolocateResult, data=input.
|
443
|
+
return await self.request.post("v1/geolocate", m.IPGeolocateResult, data=input.model_dump(exclude_none=True))
|
434
444
|
|
435
445
|
async def geolocate_bulk(
|
436
446
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -459,7 +469,9 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
459
469
|
FIXME:
|
460
470
|
"""
|
461
471
|
input = m.IPGeolocateBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
462
|
-
return await self.request.post(
|
472
|
+
return await self.request.post(
|
473
|
+
"v2/geolocate", m.IPGeolocateBulkResult, data=input.model_dump(exclude_none=True)
|
474
|
+
)
|
463
475
|
|
464
476
|
async def get_domain(
|
465
477
|
self, ip: str, verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -491,7 +503,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
491
503
|
)
|
492
504
|
"""
|
493
505
|
input = m.IPDomainRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
494
|
-
return await self.request.post("v1/domain", m.IPDomainResult, data=input.
|
506
|
+
return await self.request.post("v1/domain", m.IPDomainResult, data=input.model_dump(exclude_none=True))
|
495
507
|
|
496
508
|
async def get_domain_bulk(
|
497
509
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -520,7 +532,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
520
532
|
FIXME:
|
521
533
|
"""
|
522
534
|
input = m.IPDomainBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
523
|
-
return await self.request.post("v2/domain", m.IPDomainBulkResult, data=input.
|
535
|
+
return await self.request.post("v2/domain", m.IPDomainBulkResult, data=input.model_dump(exclude_none=True))
|
524
536
|
|
525
537
|
async def is_vpn(
|
526
538
|
self, ip: str, verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -552,7 +564,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
552
564
|
)
|
553
565
|
"""
|
554
566
|
input = m.IPVPNRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
555
|
-
return await self.request.post("v1/vpn", m.IPVPNResult, data=input.
|
567
|
+
return await self.request.post("v1/vpn", m.IPVPNResult, data=input.model_dump(exclude_none=True))
|
556
568
|
|
557
569
|
async def is_vpn_bulk(
|
558
570
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -581,7 +593,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
581
593
|
FIXME:
|
582
594
|
"""
|
583
595
|
input = m.IPVPNBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
584
|
-
return await self.request.post("v2/vpn", m.IPVPNBulkResult, data=input.
|
596
|
+
return await self.request.post("v2/vpn", m.IPVPNBulkResult, data=input.model_dump(exclude_none=True))
|
585
597
|
|
586
598
|
async def is_proxy(
|
587
599
|
self, ip: str, verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -613,7 +625,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
613
625
|
)
|
614
626
|
"""
|
615
627
|
input = m.IPProxyRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
616
|
-
return await self.request.post("v1/proxy", m.IPProxyResult, data=input.
|
628
|
+
return await self.request.post("v1/proxy", m.IPProxyResult, data=input.model_dump(exclude_none=True))
|
617
629
|
|
618
630
|
async def is_proxy_bulk(
|
619
631
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -642,7 +654,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
642
654
|
FIXME:
|
643
655
|
"""
|
644
656
|
input = m.IPProxyBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
645
|
-
return await self.request.post("v2/proxy", m.IPProxyBulkResult, data=input.
|
657
|
+
return await self.request.post("v2/proxy", m.IPProxyBulkResult, data=input.model_dump(exclude_none=True))
|
646
658
|
|
647
659
|
|
648
660
|
class UrlIntelAsync(ServiceBaseAsync):
|
@@ -702,7 +714,7 @@ class UrlIntelAsync(ServiceBaseAsync):
|
|
702
714
|
"""
|
703
715
|
|
704
716
|
input = m.URLReputationRequest(url=url, provider=provider, verbose=verbose, raw=raw)
|
705
|
-
return await self.request.post("v1/reputation", m.URLReputationResult, data=input.
|
717
|
+
return await self.request.post("v1/reputation", m.URLReputationResult, data=input.model_dump(exclude_none=True))
|
706
718
|
|
707
719
|
async def reputation_bulk(
|
708
720
|
self,
|
@@ -736,7 +748,9 @@ class UrlIntelAsync(ServiceBaseAsync):
|
|
736
748
|
"""
|
737
749
|
|
738
750
|
input = m.URLReputationBulkRequest(urls=urls, provider=provider, verbose=verbose, raw=raw)
|
739
|
-
return await self.request.post(
|
751
|
+
return await self.request.post(
|
752
|
+
"v2/reputation", m.URLReputationBulkResult, data=input.model_dump(exclude_none=True)
|
753
|
+
)
|
740
754
|
|
741
755
|
|
742
756
|
class UserIntelAsync(ServiceBaseAsync):
|
@@ -822,7 +836,9 @@ class UserIntelAsync(ServiceBaseAsync):
|
|
822
836
|
verbose=verbose,
|
823
837
|
raw=raw,
|
824
838
|
)
|
825
|
-
return await self.request.post(
|
839
|
+
return await self.request.post(
|
840
|
+
"v1/user/breached", m.UserBreachedResult, data=input.model_dump(exclude_none=True)
|
841
|
+
)
|
826
842
|
|
827
843
|
async def user_breached_bulk(
|
828
844
|
self,
|
@@ -876,7 +892,9 @@ class UserIntelAsync(ServiceBaseAsync):
|
|
876
892
|
verbose=verbose,
|
877
893
|
raw=raw,
|
878
894
|
)
|
879
|
-
return await self.request.post(
|
895
|
+
return await self.request.post(
|
896
|
+
"v2/user/breached", m.UserBreachedBulkResult, data=input.model_dump(exclude_none=True)
|
897
|
+
)
|
880
898
|
|
881
899
|
async def password_breached(
|
882
900
|
self,
|
@@ -919,7 +937,7 @@ class UserIntelAsync(ServiceBaseAsync):
|
|
919
937
|
hash_type=hash_type, hash_prefix=hash_prefix, provider=provider, verbose=verbose, raw=raw
|
920
938
|
)
|
921
939
|
return await self.request.post(
|
922
|
-
"v1/password/breached", m.UserPasswordBreachedResult, data=input.
|
940
|
+
"v1/password/breached", m.UserPasswordBreachedResult, data=input.model_dump(exclude_none=True)
|
923
941
|
)
|
924
942
|
|
925
943
|
async def password_breached_bulk(
|
@@ -959,5 +977,5 @@ class UserIntelAsync(ServiceBaseAsync):
|
|
959
977
|
hash_type=hash_type, hash_prefixes=hash_prefixes, provider=provider, verbose=verbose, raw=raw
|
960
978
|
)
|
961
979
|
return await self.request.post(
|
962
|
-
"v2/password/breached", m.UserPasswordBreachedBulkResult, data=input.
|
980
|
+
"v2/password/breached", m.UserPasswordBreachedBulkResult, data=input.model_dump(exclude_none=True)
|
963
981
|
)
|
@@ -1,10 +1,12 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
from __future__ import annotations
|
3
4
|
|
4
5
|
from typing import Dict, List, Optional, Union
|
5
6
|
|
6
7
|
import pangea.services.redact as m
|
7
8
|
from pangea.asyncio.services.base import ServiceBaseAsync
|
9
|
+
from pangea.config import PangeaConfig
|
8
10
|
from pangea.response import PangeaResponse
|
9
11
|
|
10
12
|
|
@@ -35,7 +37,24 @@ class RedactAsync(ServiceBaseAsync):
|
|
35
37
|
|
36
38
|
service_name = "redact"
|
37
39
|
|
38
|
-
def __init__(
|
40
|
+
def __init__(
|
41
|
+
self, token: str, config: PangeaConfig | None = None, logger_name: str = "pangea", config_id: str | None = None
|
42
|
+
) -> None:
|
43
|
+
"""
|
44
|
+
Redact client
|
45
|
+
|
46
|
+
Initializes a new Redact client.
|
47
|
+
|
48
|
+
Args:
|
49
|
+
token: Pangea API token.
|
50
|
+
config: Configuration.
|
51
|
+
logger_name: Logger name.
|
52
|
+
|
53
|
+
Examples:
|
54
|
+
config = PangeaConfig(domain="pangea_domain")
|
55
|
+
redact = RedactAsync(token="pangea_token", config=config)
|
56
|
+
"""
|
57
|
+
|
39
58
|
super().__init__(token, config, logger_name, config_id=config_id)
|
40
59
|
|
41
60
|
async def redact(
|
@@ -45,6 +64,7 @@ class RedactAsync(ServiceBaseAsync):
|
|
45
64
|
rules: Optional[List[str]] = None,
|
46
65
|
rulesets: Optional[List[str]] = None,
|
47
66
|
return_result: Optional[bool] = None,
|
67
|
+
redaction_method_overrides: Optional[m.RedactionMethodOverrides] = None,
|
48
68
|
) -> PangeaResponse[m.RedactResult]:
|
49
69
|
"""
|
50
70
|
Redact
|
@@ -60,6 +80,7 @@ class RedactAsync(ServiceBaseAsync):
|
|
60
80
|
rules (list[str], optional): An array of redact rule short names
|
61
81
|
rulesets (list[str], optional): An array of redact rulesets short names
|
62
82
|
return_result(bool, optional): Setting this value to false will omit the redacted result only returning count
|
83
|
+
redaction_method_overrides: A set of redaction method overrides for any enabled rule. These methods override the config declared methods
|
63
84
|
|
64
85
|
Raises:
|
65
86
|
PangeaAPIException: If an API Error happens
|
@@ -73,8 +94,15 @@ class RedactAsync(ServiceBaseAsync):
|
|
73
94
|
response = redact.redact(text="Jenny Jenny... 555-867-5309")
|
74
95
|
"""
|
75
96
|
|
76
|
-
input = m.RedactRequest(
|
77
|
-
|
97
|
+
input = m.RedactRequest(
|
98
|
+
text=text,
|
99
|
+
debug=debug,
|
100
|
+
rules=rules,
|
101
|
+
rulesets=rulesets,
|
102
|
+
return_result=return_result,
|
103
|
+
redaction_method_overrides=redaction_method_overrides,
|
104
|
+
)
|
105
|
+
return await self.request.post("v1/redact", m.RedactResult, data=input.model_dump(exclude_none=True))
|
78
106
|
|
79
107
|
async def redact_structured(
|
80
108
|
self,
|
@@ -85,6 +113,7 @@ class RedactAsync(ServiceBaseAsync):
|
|
85
113
|
rules: Optional[List[str]] = None,
|
86
114
|
rulesets: Optional[List[str]] = None,
|
87
115
|
return_result: Optional[bool] = None,
|
116
|
+
redaction_method_overrides: Optional[m.RedactionMethodOverrides] = None,
|
88
117
|
) -> PangeaResponse[m.StructuredResult]:
|
89
118
|
"""
|
90
119
|
Redact structured
|
@@ -104,6 +133,7 @@ class RedactAsync(ServiceBaseAsync):
|
|
104
133
|
rules (list[str], optional): An array of redact rule short names
|
105
134
|
rulesets (list[str], optional): An array of redact rulesets short names
|
106
135
|
return_result(bool, optional): Setting this value to false will omit the redacted result only returning count
|
136
|
+
redaction_method_overrides: A set of redaction method overrides for any enabled rule. These methods override the config declared methods
|
107
137
|
|
108
138
|
Raises:
|
109
139
|
PangeaAPIException: If an API Error happens
|
@@ -130,5 +160,31 @@ class RedactAsync(ServiceBaseAsync):
|
|
130
160
|
rules=rules,
|
131
161
|
rulesets=rulesets,
|
132
162
|
return_result=return_result,
|
163
|
+
redaction_method_overrides=redaction_method_overrides,
|
164
|
+
)
|
165
|
+
return await self.request.post(
|
166
|
+
"v1/redact_structured", m.StructuredResult, data=input.model_dump(exclude_none=True)
|
133
167
|
)
|
134
|
-
|
168
|
+
|
169
|
+
async def unredact(self, redacted_data: m.RedactedData, fpe_context: str) -> PangeaResponse[m.UnredactResult]:
|
170
|
+
"""
|
171
|
+
Unredact
|
172
|
+
|
173
|
+
Decrypt or unredact fpe redactions
|
174
|
+
|
175
|
+
OperationId: redact_post_v1_unredact
|
176
|
+
|
177
|
+
Args:
|
178
|
+
redacted_data: Data to unredact
|
179
|
+
fpe_context (base64): FPE context used to decrypt and unredact data
|
180
|
+
|
181
|
+
Raises:
|
182
|
+
PangeaAPIException: If an API Error happens
|
183
|
+
|
184
|
+
Returns:
|
185
|
+
Pangea Response with redacted data in the response.result field,
|
186
|
+
available response fields can be found in our
|
187
|
+
[API Documentation](https://pangea.cloud/docs/api/redact#unredact)
|
188
|
+
"""
|
189
|
+
input = m.UnredactRequest(redacted_data=redacted_data, fpe_context=fpe_context)
|
190
|
+
return await self.request.post("v1/unredact", m.UnredactResult, data=input.model_dump(exclude_none=True))
|