pangea-sdk 3.8.0__py3-none-any.whl → 5.3.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- pangea/__init__.py +2 -1
- pangea/asyncio/__init__.py +1 -0
- pangea/asyncio/file_uploader.py +39 -0
- pangea/asyncio/request.py +46 -23
- pangea/asyncio/services/__init__.py +2 -0
- pangea/asyncio/services/audit.py +46 -20
- pangea/asyncio/services/authn.py +123 -61
- pangea/asyncio/services/authz.py +57 -31
- pangea/asyncio/services/base.py +21 -2
- pangea/asyncio/services/embargo.py +2 -2
- pangea/asyncio/services/file_scan.py +24 -9
- pangea/asyncio/services/intel.py +104 -30
- pangea/asyncio/services/redact.py +52 -3
- pangea/asyncio/services/sanitize.py +217 -0
- pangea/asyncio/services/share.py +733 -0
- pangea/asyncio/services/vault.py +1709 -766
- pangea/crypto/rsa.py +135 -0
- pangea/deep_verify.py +7 -1
- pangea/dump_audit.py +9 -8
- pangea/file_uploader.py +35 -0
- pangea/request.py +70 -49
- pangea/response.py +36 -17
- pangea/services/__init__.py +2 -0
- pangea/services/audit/audit.py +57 -29
- pangea/services/audit/models.py +12 -3
- pangea/services/audit/signing.py +6 -5
- pangea/services/audit/util.py +3 -3
- pangea/services/authn/authn.py +120 -66
- pangea/services/authn/models.py +167 -11
- pangea/services/authz.py +53 -30
- pangea/services/base.py +16 -2
- pangea/services/embargo.py +2 -2
- pangea/services/file_scan.py +32 -15
- pangea/services/intel.py +155 -30
- pangea/services/redact.py +132 -3
- pangea/services/sanitize.py +388 -0
- pangea/services/share/file_format.py +170 -0
- pangea/services/share/share.py +1440 -0
- pangea/services/vault/models/asymmetric.py +120 -18
- pangea/services/vault/models/common.py +439 -141
- pangea/services/vault/models/keys.py +94 -0
- pangea/services/vault/models/secret.py +27 -3
- pangea/services/vault/models/symmetric.py +68 -22
- pangea/services/vault/vault.py +1690 -766
- pangea/tools.py +6 -7
- pangea/utils.py +94 -33
- pangea/verify_audit.py +270 -83
- {pangea_sdk-3.8.0.dist-info → pangea_sdk-5.3.0.dist-info}/METADATA +21 -29
- pangea_sdk-5.3.0.dist-info/RECORD +56 -0
- {pangea_sdk-3.8.0.dist-info → pangea_sdk-5.3.0.dist-info}/WHEEL +1 -1
- pangea_sdk-3.8.0.dist-info/RECORD +0 -46
pangea/services/intel.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
from __future__ import annotations
|
4
|
+
|
3
5
|
import enum
|
4
6
|
import hashlib
|
5
7
|
from typing import Dict, List, Optional
|
@@ -524,7 +526,7 @@ class FileIntel(ServiceBase):
|
|
524
526
|
)
|
525
527
|
"""
|
526
528
|
input = FileReputationRequest(hash=hash, hash_type=hash_type, verbose=verbose, raw=raw, provider=provider)
|
527
|
-
return self.request.post("v1/reputation", FileReputationResult, data=input.
|
529
|
+
return self.request.post("v1/reputation", FileReputationResult, data=input.model_dump(exclude_none=True))
|
528
530
|
|
529
531
|
def hash_reputation_bulk(
|
530
532
|
self,
|
@@ -563,7 +565,7 @@ class FileIntel(ServiceBase):
|
|
563
565
|
input = FileReputationBulkRequest( # type: ignore[call-arg]
|
564
566
|
hashes=hashes, hash_type=hash_type, verbose=verbose, raw=raw, provider=provider
|
565
567
|
)
|
566
|
-
return self.request.post("v2/reputation", FileReputationBulkResult, data=input.
|
568
|
+
return self.request.post("v2/reputation", FileReputationBulkResult, data=input.model_dump(exclude_none=True))
|
567
569
|
|
568
570
|
def filepath_reputation(
|
569
571
|
self,
|
@@ -708,7 +710,7 @@ class DomainIntel(ServiceBase):
|
|
708
710
|
)
|
709
711
|
"""
|
710
712
|
input = DomainReputationRequest(domain=domain, verbose=verbose, provider=provider, raw=raw)
|
711
|
-
return self.request.post("v1/reputation", DomainReputationResult, data=input.
|
713
|
+
return self.request.post("v1/reputation", DomainReputationResult, data=input.model_dump(exclude_none=True))
|
712
714
|
|
713
715
|
def reputation_bulk(
|
714
716
|
self,
|
@@ -744,7 +746,7 @@ class DomainIntel(ServiceBase):
|
|
744
746
|
)
|
745
747
|
"""
|
746
748
|
input = DomainReputationBulkRequest(domains=domains, verbose=verbose, provider=provider, raw=raw)
|
747
|
-
return self.request.post("v2/reputation", DomainReputationBulkResult, data=input.
|
749
|
+
return self.request.post("v2/reputation", DomainReputationBulkResult, data=input.model_dump(exclude_none=True))
|
748
750
|
|
749
751
|
def who_is(
|
750
752
|
self, domain: str, verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -776,7 +778,7 @@ class DomainIntel(ServiceBase):
|
|
776
778
|
)
|
777
779
|
"""
|
778
780
|
input = DomainWhoIsRequest(domain=domain, verbose=verbose, provider=provider, raw=raw) # type: ignore[call-arg]
|
779
|
-
return self.request.post("v1/whois", DomainWhoIsResult, data=input.
|
781
|
+
return self.request.post("v1/whois", DomainWhoIsResult, data=input.model_dump(exclude_none=True))
|
780
782
|
|
781
783
|
|
782
784
|
class IpIntel(ServiceBase):
|
@@ -819,7 +821,7 @@ class IpIntel(ServiceBase):
|
|
819
821
|
ip (str): The IP to be looked up
|
820
822
|
verbose (bool, optional): Echo the API parameters in the response
|
821
823
|
raw (bool, optional): Include raw data from this provider
|
822
|
-
provider (str, optional): Use reputation data from this provider
|
824
|
+
provider (str, optional): Use reputation data from this provider
|
823
825
|
|
824
826
|
Raises:
|
825
827
|
PangeaAPIException: If an API Error happens
|
@@ -835,7 +837,7 @@ class IpIntel(ServiceBase):
|
|
835
837
|
)
|
836
838
|
"""
|
837
839
|
input = IPReputationRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
838
|
-
return self.request.post("v1/reputation", IPReputationResult, data=input.
|
840
|
+
return self.request.post("v1/reputation", IPReputationResult, data=input.model_dump(exclude_none=True))
|
839
841
|
|
840
842
|
def reputation_bulk(
|
841
843
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -851,7 +853,7 @@ class IpIntel(ServiceBase):
|
|
851
853
|
ips (List[str]): The IP list to be looked up
|
852
854
|
verbose (bool, optional): Echo the API parameters in the response
|
853
855
|
raw (bool, optional): Include raw data from this provider
|
854
|
-
provider (str, optional): Use reputation data from this provider
|
856
|
+
provider (str, optional): Use reputation data from this provider
|
855
857
|
|
856
858
|
Raises:
|
857
859
|
PangeaAPIException: If an API Error happens
|
@@ -867,7 +869,7 @@ class IpIntel(ServiceBase):
|
|
867
869
|
)
|
868
870
|
"""
|
869
871
|
input = IPReputationBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
870
|
-
return self.request.post("v2/reputation", IPReputationBulkResult, data=input.
|
872
|
+
return self.request.post("v2/reputation", IPReputationBulkResult, data=input.model_dump(exclude_none=True))
|
871
873
|
|
872
874
|
def geolocate(
|
873
875
|
self, ip: str, verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -899,7 +901,7 @@ class IpIntel(ServiceBase):
|
|
899
901
|
)
|
900
902
|
"""
|
901
903
|
input = IPGeolocateRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
902
|
-
return self.request.post("v1/geolocate", IPGeolocateResult, data=input.
|
904
|
+
return self.request.post("v1/geolocate", IPGeolocateResult, data=input.model_dump(exclude_none=True))
|
903
905
|
|
904
906
|
def geolocate_bulk(
|
905
907
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -931,7 +933,7 @@ class IpIntel(ServiceBase):
|
|
931
933
|
)
|
932
934
|
"""
|
933
935
|
input = IPGeolocateBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
934
|
-
return self.request.post("v2/geolocate", IPGeolocateBulkResult, data=input.
|
936
|
+
return self.request.post("v2/geolocate", IPGeolocateBulkResult, data=input.model_dump(exclude_none=True))
|
935
937
|
|
936
938
|
def get_domain(
|
937
939
|
self, ip: str, verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -963,7 +965,7 @@ class IpIntel(ServiceBase):
|
|
963
965
|
)
|
964
966
|
"""
|
965
967
|
input = IPDomainRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
966
|
-
return self.request.post("v1/domain", IPDomainResult, data=input.
|
968
|
+
return self.request.post("v1/domain", IPDomainResult, data=input.model_dump(exclude_none=True))
|
967
969
|
|
968
970
|
def get_domain_bulk(
|
969
971
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -995,7 +997,7 @@ class IpIntel(ServiceBase):
|
|
995
997
|
)
|
996
998
|
"""
|
997
999
|
input = IPDomainBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
998
|
-
return self.request.post("v2/domain", IPDomainBulkResult, data=input.
|
1000
|
+
return self.request.post("v2/domain", IPDomainBulkResult, data=input.model_dump(exclude_none=True))
|
999
1001
|
|
1000
1002
|
def is_vpn(
|
1001
1003
|
self, ip: str, verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -1027,7 +1029,7 @@ class IpIntel(ServiceBase):
|
|
1027
1029
|
)
|
1028
1030
|
"""
|
1029
1031
|
input = IPVPNRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
1030
|
-
return self.request.post("v1/vpn", IPVPNResult, data=input.
|
1032
|
+
return self.request.post("v1/vpn", IPVPNResult, data=input.model_dump(exclude_none=True))
|
1031
1033
|
|
1032
1034
|
def is_vpn_bulk(
|
1033
1035
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -1059,7 +1061,7 @@ class IpIntel(ServiceBase):
|
|
1059
1061
|
)
|
1060
1062
|
"""
|
1061
1063
|
input = IPVPNBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
1062
|
-
return self.request.post("v2/vpn", IPVPNBulkResult, data=input.
|
1064
|
+
return self.request.post("v2/vpn", IPVPNBulkResult, data=input.model_dump(exclude_none=True))
|
1063
1065
|
|
1064
1066
|
def is_proxy(
|
1065
1067
|
self, ip: str, verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -1091,7 +1093,7 @@ class IpIntel(ServiceBase):
|
|
1091
1093
|
)
|
1092
1094
|
"""
|
1093
1095
|
input = IPProxyRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
1094
|
-
return self.request.post("v1/proxy", IPProxyResult, data=input.
|
1096
|
+
return self.request.post("v1/proxy", IPProxyResult, data=input.model_dump(exclude_none=True))
|
1095
1097
|
|
1096
1098
|
def is_proxy_bulk(
|
1097
1099
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -1123,7 +1125,7 @@ class IpIntel(ServiceBase):
|
|
1123
1125
|
)
|
1124
1126
|
"""
|
1125
1127
|
input = IPProxyBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
1126
|
-
return self.request.post("v2/proxy", IPProxyBulkResult, data=input.
|
1128
|
+
return self.request.post("v2/proxy", IPProxyBulkResult, data=input.model_dump(exclude_none=True))
|
1127
1129
|
|
1128
1130
|
|
1129
1131
|
class UrlIntel(ServiceBase):
|
@@ -1170,7 +1172,7 @@ class UrlIntel(ServiceBase):
|
|
1170
1172
|
url (str): The URL to be looked up
|
1171
1173
|
verbose (bool, optional): Echo the API parameters in the response
|
1172
1174
|
raw (bool, optional): Include raw data from this provider
|
1173
|
-
provider (str, optional): Use reputation data from this provider
|
1175
|
+
provider (str, optional): Use reputation data from this provider
|
1174
1176
|
|
1175
1177
|
Raises:
|
1176
1178
|
PangeaAPIException: If an API Error happens
|
@@ -1187,7 +1189,7 @@ class UrlIntel(ServiceBase):
|
|
1187
1189
|
"""
|
1188
1190
|
|
1189
1191
|
input = URLReputationRequest(url=url, provider=provider, verbose=verbose, raw=raw)
|
1190
|
-
return self.request.post("v1/reputation", URLReputationResult, data=input.
|
1192
|
+
return self.request.post("v1/reputation", URLReputationResult, data=input.model_dump(exclude_none=True))
|
1191
1193
|
|
1192
1194
|
def reputation_bulk(
|
1193
1195
|
self,
|
@@ -1207,7 +1209,7 @@ class UrlIntel(ServiceBase):
|
|
1207
1209
|
urls (List[str]): The URL list to be looked up
|
1208
1210
|
verbose (bool, optional): Echo the API parameters in the response
|
1209
1211
|
raw (bool, optional): Include raw data from this provider
|
1210
|
-
provider (str, optional): Use reputation data from this provider
|
1212
|
+
provider (str, optional): Use reputation data from this provider
|
1211
1213
|
|
1212
1214
|
Raises:
|
1213
1215
|
PangeaAPIException: If an API Error happens
|
@@ -1224,7 +1226,7 @@ class UrlIntel(ServiceBase):
|
|
1224
1226
|
"""
|
1225
1227
|
|
1226
1228
|
input = URLReputationBulkRequest(urls=urls, provider=provider, verbose=verbose, raw=raw)
|
1227
|
-
return self.request.post("v2/reputation", URLReputationBulkResult, data=input.
|
1229
|
+
return self.request.post("v2/reputation", URLReputationBulkResult, data=input.model_dump(exclude_none=True))
|
1228
1230
|
|
1229
1231
|
|
1230
1232
|
class UserBreachedRequest(IntelCommonRequest):
|
@@ -1237,6 +1239,7 @@ class UserBreachedRequest(IntelCommonRequest):
|
|
1237
1239
|
phone_number (str): A phone number to search for. minLength: 7, maxLength: 15.
|
1238
1240
|
start (str): Earliest date for search
|
1239
1241
|
end (str): Latest date for search
|
1242
|
+
cursor (str, optional): A token given in the raw response from SpyCloud. Post this back to paginate results
|
1240
1243
|
"""
|
1241
1244
|
|
1242
1245
|
email: Optional[str] = None
|
@@ -1245,6 +1248,10 @@ class UserBreachedRequest(IntelCommonRequest):
|
|
1245
1248
|
phone_number: Optional[str] = None
|
1246
1249
|
start: Optional[str] = None
|
1247
1250
|
end: Optional[str] = None
|
1251
|
+
cursor: Optional[str] = None
|
1252
|
+
|
1253
|
+
severity: Optional[List[int]] = None
|
1254
|
+
"""Filter for records that match one of the given severities"""
|
1248
1255
|
|
1249
1256
|
|
1250
1257
|
class UserBreachedBulkRequest(IntelCommonRequest):
|
@@ -1255,6 +1262,7 @@ class UserBreachedBulkRequest(IntelCommonRequest):
|
|
1255
1262
|
usernames (List[str]): An username' list to search for
|
1256
1263
|
ips (List[str]): An ip's list to search for
|
1257
1264
|
phone_numbers (List[str]): A phone number's list to search for. minLength: 7, maxLength: 15.
|
1265
|
+
domains (List[str]): Search for user under these domains.
|
1258
1266
|
start (str): Earliest date for search
|
1259
1267
|
end (str): Latest date for search
|
1260
1268
|
"""
|
@@ -1263,9 +1271,13 @@ class UserBreachedBulkRequest(IntelCommonRequest):
|
|
1263
1271
|
usernames: Optional[List[str]] = None
|
1264
1272
|
ips: Optional[List[str]] = None
|
1265
1273
|
phone_numbers: Optional[List[str]] = None
|
1274
|
+
domains: Optional[List[str]] = None
|
1266
1275
|
start: Optional[str] = None
|
1267
1276
|
end: Optional[str] = None
|
1268
1277
|
|
1278
|
+
severity: Optional[List[int]] = None
|
1279
|
+
"""Filter for records that match one of the given severities"""
|
1280
|
+
|
1269
1281
|
|
1270
1282
|
class UserBreachedCommonData(PangeaResponseResult):
|
1271
1283
|
"""
|
@@ -1314,7 +1326,7 @@ class UserPasswordBreachedRequest(IntelCommonRequest):
|
|
1314
1326
|
|
1315
1327
|
class UserPasswordBreachedBulkRequest(IntelCommonRequest):
|
1316
1328
|
"""
|
1317
|
-
User password breached
|
1329
|
+
User password breached bulk request data
|
1318
1330
|
|
1319
1331
|
hash_type (str): Hash type to be looked up
|
1320
1332
|
hash_prefixes (List[str]): The list of prefixes of the hashes to be looked up.
|
@@ -1348,6 +1360,44 @@ class UserPasswordBreachedBulkResult(IntelCommonResult):
|
|
1348
1360
|
data: Dict[str, UserPasswordBreachedData]
|
1349
1361
|
|
1350
1362
|
|
1363
|
+
class BreachRequest(APIRequestModel):
|
1364
|
+
"""Breach request data"""
|
1365
|
+
|
1366
|
+
breach_id: Optional[str] = None
|
1367
|
+
"""The ID of a breach returned by a provider."""
|
1368
|
+
|
1369
|
+
verbose: Optional[bool] = None
|
1370
|
+
"""Echo back the parameters of the API in the response."""
|
1371
|
+
|
1372
|
+
provider: Optional[str] = None
|
1373
|
+
"""Provider of the information. Default provider defined by the configuration."""
|
1374
|
+
|
1375
|
+
severity: Optional[List[int]] = None
|
1376
|
+
"""Filter for records that match one of the given severities"""
|
1377
|
+
|
1378
|
+
start: Optional[str] = None
|
1379
|
+
"""This parameter allows you to define the starting point for a date range query on the spycloud_publish_date field."""
|
1380
|
+
|
1381
|
+
end: Optional[str] = None
|
1382
|
+
"""This parameter allows you to define the ending point for a date range query on the spycloud_publish_date field."""
|
1383
|
+
|
1384
|
+
cursor: Optional[str] = None
|
1385
|
+
"""A token given in the raw response from SpyCloud. Post this back to paginate results"""
|
1386
|
+
|
1387
|
+
|
1388
|
+
class BreachResult(PangeaResponseResult):
|
1389
|
+
"""Breach result"""
|
1390
|
+
|
1391
|
+
found: bool
|
1392
|
+
"""A flag indicating if the lookup was successful."""
|
1393
|
+
|
1394
|
+
data: Optional[Dict] = None
|
1395
|
+
"""Breach details given by the provider."""
|
1396
|
+
|
1397
|
+
parameters: Optional[Dict] = None
|
1398
|
+
"""The parameters, which were passed in the request, echoed back."""
|
1399
|
+
|
1400
|
+
|
1351
1401
|
class UserIntel(ServiceBase):
|
1352
1402
|
"""User Intel service client.
|
1353
1403
|
|
@@ -1385,6 +1435,8 @@ class UserIntel(ServiceBase):
|
|
1385
1435
|
verbose: Optional[bool] = None,
|
1386
1436
|
raw: Optional[bool] = None,
|
1387
1437
|
provider: Optional[str] = None,
|
1438
|
+
cursor: Optional[str] = None,
|
1439
|
+
severity: Optional[List[int]] = None,
|
1388
1440
|
) -> PangeaResponse[UserBreachedResult]:
|
1389
1441
|
"""
|
1390
1442
|
Look up breached users
|
@@ -1402,7 +1454,9 @@ class UserIntel(ServiceBase):
|
|
1402
1454
|
end (str): Latest date for search
|
1403
1455
|
verbose (bool, optional): Echo the API parameters in the response
|
1404
1456
|
raw (bool, optional): Include raw data from this provider
|
1405
|
-
provider (str, optional): Use reputation data from this provider
|
1457
|
+
provider (str, optional): Use reputation data from this provider
|
1458
|
+
cursor (str, optional): A token given in the raw response from SpyCloud. Post this back to paginate results
|
1459
|
+
severity (List[int], optional): Filter for records that match one of the given severities
|
1406
1460
|
|
1407
1461
|
Raises:
|
1408
1462
|
PangeaAPIException: If an API Error happens
|
@@ -1430,8 +1484,10 @@ class UserIntel(ServiceBase):
|
|
1430
1484
|
end=end,
|
1431
1485
|
verbose=verbose,
|
1432
1486
|
raw=raw,
|
1487
|
+
cursor=cursor,
|
1488
|
+
severity=severity,
|
1433
1489
|
)
|
1434
|
-
return self.request.post("v1/user/breached", UserBreachedResult, data=input.
|
1490
|
+
return self.request.post("v1/user/breached", UserBreachedResult, data=input.model_dump(exclude_none=True))
|
1435
1491
|
|
1436
1492
|
def user_breached_bulk(
|
1437
1493
|
self,
|
@@ -1439,11 +1495,13 @@ class UserIntel(ServiceBase):
|
|
1439
1495
|
usernames: Optional[List[str]] = None,
|
1440
1496
|
ips: Optional[List[str]] = None,
|
1441
1497
|
phone_numbers: Optional[List[str]] = None,
|
1498
|
+
domains: Optional[List[str]] = None,
|
1442
1499
|
start: Optional[str] = None,
|
1443
1500
|
end: Optional[str] = None,
|
1444
1501
|
verbose: Optional[bool] = None,
|
1445
1502
|
raw: Optional[bool] = None,
|
1446
1503
|
provider: Optional[str] = None,
|
1504
|
+
severity: Optional[List[int]] = None,
|
1447
1505
|
) -> PangeaResponse[UserBreachedBulkResult]:
|
1448
1506
|
"""
|
1449
1507
|
Look up breached users V2
|
@@ -1457,11 +1515,13 @@ class UserIntel(ServiceBase):
|
|
1457
1515
|
usernames (List[str]): A list of usernames to search for
|
1458
1516
|
ips (List[str]): A list of ips to search for
|
1459
1517
|
phone_numbers (List[str]): A list of phone numbers to search for. minLength: 7, maxLength: 15.
|
1518
|
+
domains (List[str]): Search for user under these domains.
|
1460
1519
|
start (str): Earliest date for search
|
1461
1520
|
end (str): Latest date for search
|
1462
1521
|
verbose (bool, optional): Echo the API parameters in the response
|
1463
1522
|
raw (bool, optional): Include raw data from this provider
|
1464
|
-
provider (str, optional): Use reputation data from this provider
|
1523
|
+
provider (str, optional): Use reputation data from this provider
|
1524
|
+
severity (List[int], optional): Filter for records that match one of the given severities
|
1465
1525
|
|
1466
1526
|
Raises:
|
1467
1527
|
PangeaAPIException: If an API Error happens
|
@@ -1484,13 +1544,15 @@ class UserIntel(ServiceBase):
|
|
1484
1544
|
phone_numbers=phone_numbers,
|
1485
1545
|
usernames=usernames,
|
1486
1546
|
ips=ips,
|
1547
|
+
domains=domains,
|
1487
1548
|
provider=provider,
|
1488
1549
|
start=start,
|
1489
1550
|
end=end,
|
1490
1551
|
verbose=verbose,
|
1491
1552
|
raw=raw,
|
1553
|
+
severity=severity,
|
1492
1554
|
)
|
1493
|
-
return self.request.post("v2/user/breached", UserBreachedBulkResult, data=input.
|
1555
|
+
return self.request.post("v2/user/breached", UserBreachedBulkResult, data=input.model_dump(exclude_none=True))
|
1494
1556
|
|
1495
1557
|
def password_breached(
|
1496
1558
|
self,
|
@@ -1512,7 +1574,7 @@ class UserIntel(ServiceBase):
|
|
1512
1574
|
hash_prefix (str): The prefix of the hash to be looked up.
|
1513
1575
|
verbose (bool, optional): Echo the API parameters in the response
|
1514
1576
|
raw (bool, optional): Include raw data from this provider
|
1515
|
-
provider (str, optional): Use reputation data from this provider
|
1577
|
+
provider (str, optional): Use reputation data from this provider
|
1516
1578
|
|
1517
1579
|
Raises:
|
1518
1580
|
PangeaAPIException: If an API Error happens
|
@@ -1532,7 +1594,9 @@ class UserIntel(ServiceBase):
|
|
1532
1594
|
input = UserPasswordBreachedRequest(
|
1533
1595
|
hash_type=hash_type, hash_prefix=hash_prefix, provider=provider, verbose=verbose, raw=raw
|
1534
1596
|
)
|
1535
|
-
return self.request.post(
|
1597
|
+
return self.request.post(
|
1598
|
+
"v1/password/breached", UserPasswordBreachedResult, data=input.model_dump(exclude_none=True)
|
1599
|
+
)
|
1536
1600
|
|
1537
1601
|
def password_breached_bulk(
|
1538
1602
|
self,
|
@@ -1554,7 +1618,7 @@ class UserIntel(ServiceBase):
|
|
1554
1618
|
hash_prefixes (List[str]): The list of prefixes of the hashes to be looked up.
|
1555
1619
|
verbose (bool, optional): Echo the API parameters in the response
|
1556
1620
|
raw (bool, optional): Include raw data from this provider
|
1557
|
-
provider (str, optional): Use reputation data from this provider
|
1621
|
+
provider (str, optional): Use reputation data from this provider
|
1558
1622
|
|
1559
1623
|
Raises:
|
1560
1624
|
PangeaAPIException: If an API Error happens
|
@@ -1575,9 +1639,59 @@ class UserIntel(ServiceBase):
|
|
1575
1639
|
hash_type=hash_type, hash_prefixes=hash_prefixes, provider=provider, verbose=verbose, raw=raw
|
1576
1640
|
)
|
1577
1641
|
return self.request.post(
|
1578
|
-
"v2/password/breached", UserPasswordBreachedBulkResult, data=input.
|
1642
|
+
"v2/password/breached", UserPasswordBreachedBulkResult, data=input.model_dump(exclude_none=True)
|
1579
1643
|
)
|
1580
1644
|
|
1645
|
+
def breach(
|
1646
|
+
self,
|
1647
|
+
breach_id: Optional[str] = None,
|
1648
|
+
verbose: Optional[bool] = None,
|
1649
|
+
provider: Optional[str] = None,
|
1650
|
+
cursor: Optional[str] = None,
|
1651
|
+
start: Optional[str] = None,
|
1652
|
+
end: Optional[str] = None,
|
1653
|
+
severity: Optional[List[int]] = None,
|
1654
|
+
) -> PangeaResponse[BreachResult]:
|
1655
|
+
"""
|
1656
|
+
Look up information about a specific breach
|
1657
|
+
|
1658
|
+
Given a provider specific breach ID, find details about the breach.
|
1659
|
+
|
1660
|
+
OperationId: user_intel_post_v1_breach
|
1661
|
+
|
1662
|
+
Args:
|
1663
|
+
breach_id (str, optional): The ID of a breach returned by a provider
|
1664
|
+
verbose (bool, optional): Echo the API parameters in the response
|
1665
|
+
provider (str, optional): Use reputation data from this provider
|
1666
|
+
cursor (str, optional): A token given in the raw response from SpyCloud. Post this back to paginate results
|
1667
|
+
start (str, optional): This parameter allows you to define the starting point for a date range query on the spycloud_publish_date field
|
1668
|
+
end (str, optional): This parameter allows you to define the ending point for a date range query on the spycloud_publish_date field
|
1669
|
+
severity (List[int], optional): Filter for records that match one of the given severities
|
1670
|
+
|
1671
|
+
Raises:
|
1672
|
+
PangeaAPIException: If an API Error happens
|
1673
|
+
|
1674
|
+
Returns:
|
1675
|
+
A PangeaResponse where the breach details are in the
|
1676
|
+
response.result field. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/user-intel)
|
1677
|
+
|
1678
|
+
Examples:
|
1679
|
+
response = user_intel.breach(
|
1680
|
+
breach_id="66111",
|
1681
|
+
)
|
1682
|
+
"""
|
1683
|
+
|
1684
|
+
input = BreachRequest(
|
1685
|
+
breach_id=breach_id,
|
1686
|
+
provider=provider,
|
1687
|
+
verbose=verbose,
|
1688
|
+
cursor=cursor,
|
1689
|
+
start=start,
|
1690
|
+
end=end,
|
1691
|
+
severity=severity,
|
1692
|
+
)
|
1693
|
+
return self.request.post("v1/breach", BreachResult, data=input.model_dump(exclude_none=True))
|
1694
|
+
|
1581
1695
|
class PasswordStatus(enum.Enum):
|
1582
1696
|
BREACHED = 0
|
1583
1697
|
UNBREACHED = 1
|
@@ -1585,6 +1699,17 @@ class UserIntel(ServiceBase):
|
|
1585
1699
|
|
1586
1700
|
@staticmethod
|
1587
1701
|
def is_password_breached(response: PangeaResponse[UserBreachedResult], hash: str) -> PasswordStatus:
|
1702
|
+
"""
|
1703
|
+
Check if a password was breached
|
1704
|
+
|
1705
|
+
Helper function that simplifies searching the response's raw data for
|
1706
|
+
the full hash.
|
1707
|
+
|
1708
|
+
Args:
|
1709
|
+
response: API response from an earlier request
|
1710
|
+
hash: Password hash
|
1711
|
+
"""
|
1712
|
+
|
1588
1713
|
if response.result.raw_data is None: # type: ignore[union-attr]
|
1589
1714
|
raise PangeaException("Need raw data to check if hash is breached. Send request with raw=true")
|
1590
1715
|
|
pangea/services/redact.py
CHANGED
@@ -17,6 +17,44 @@ class RedactFormat(str, enum.Enum):
|
|
17
17
|
"""JSON format."""
|
18
18
|
|
19
19
|
|
20
|
+
class RedactType(str, enum.Enum):
|
21
|
+
MASK = "mask"
|
22
|
+
PARTIAL_MASKING = "partial_masking"
|
23
|
+
REPLACEMENT = "replacement"
|
24
|
+
DETECT_ONLY = "detect_only"
|
25
|
+
HASH = "hash"
|
26
|
+
FPE = "fpe"
|
27
|
+
|
28
|
+
|
29
|
+
class FPEAlphabet(str, enum.Enum):
|
30
|
+
NUMERIC = "numeric"
|
31
|
+
ALPHANUMERICLOWER = "alphanumericlower"
|
32
|
+
ALPHANUMERIC = "alphanumeric"
|
33
|
+
|
34
|
+
|
35
|
+
class MaskingType(str, enum.Enum):
|
36
|
+
MASK = "mask"
|
37
|
+
UNMASK = "unmask"
|
38
|
+
|
39
|
+
|
40
|
+
class PartialMasking(APIRequestModel):
|
41
|
+
masking_type: Optional[MaskingType] = None
|
42
|
+
unmasked_from_left: Optional[int] = None
|
43
|
+
unmasked_from_right: Optional[int] = None
|
44
|
+
masked_from_left: Optional[int] = None
|
45
|
+
masked_from_right: Optional[int] = None
|
46
|
+
chars_to_ignore: Optional[List[str]] = None
|
47
|
+
masking_char: Optional[List[str]] = None
|
48
|
+
|
49
|
+
|
50
|
+
class RedactionMethodOverrides(APIRequestModel):
|
51
|
+
redaction_type: RedactType
|
52
|
+
hash: Optional[Dict] = None
|
53
|
+
fpe_alphabet: Optional[FPEAlphabet] = None
|
54
|
+
partial_masking: Optional[PartialMasking] = None
|
55
|
+
redaction_value: Optional[str] = None
|
56
|
+
|
57
|
+
|
20
58
|
class RedactRequest(APIRequestModel):
|
21
59
|
"""
|
22
60
|
Input class to make a redact request
|
@@ -27,6 +65,18 @@ class RedactRequest(APIRequestModel):
|
|
27
65
|
rules: Optional[List[str]] = None
|
28
66
|
rulesets: Optional[List[str]] = None
|
29
67
|
return_result: Optional[bool] = None
|
68
|
+
redaction_method_overrides: Optional[RedactionMethodOverrides] = None
|
69
|
+
vault_parameters: Optional[VaultParameters] = None
|
70
|
+
llm_request: Optional[bool] = None
|
71
|
+
"""Is this redact call going to be used in an LLM request?"""
|
72
|
+
|
73
|
+
|
74
|
+
class VaultParameters(APIRequestModel):
|
75
|
+
fpe_key_id: Optional[str] = None
|
76
|
+
"""A vault key ID of an exportable key used to redact with FPE instead of using the service config default."""
|
77
|
+
|
78
|
+
salt_secret_id: Optional[str] = None
|
79
|
+
"""A vault secret ID of a secret used to salt a hash instead of using the service config default."""
|
30
80
|
|
31
81
|
|
32
82
|
class RecognizerResult(APIResponseModel):
|
@@ -69,11 +119,13 @@ class RedactResult(PangeaResponseResult):
|
|
69
119
|
redact_text: Redacted text result
|
70
120
|
count: Number of redactions present in the text
|
71
121
|
report: Describes the decision process for redactions
|
122
|
+
fpe_context: FPE context used to encrypt and redact data
|
72
123
|
"""
|
73
124
|
|
74
125
|
redacted_text: Optional[str] = None
|
75
126
|
count: int
|
76
127
|
report: Optional[DebugReport] = None
|
128
|
+
fpe_context: Optional[str] = None
|
77
129
|
|
78
130
|
|
79
131
|
class StructuredRequest(APIRequestModel):
|
@@ -94,6 +146,10 @@ class StructuredRequest(APIRequestModel):
|
|
94
146
|
rules: Optional[List[str]] = None
|
95
147
|
rulesets: Optional[List[str]] = None
|
96
148
|
return_result: Optional[bool] = None
|
149
|
+
redaction_method_overrides: Optional[RedactionMethodOverrides] = None
|
150
|
+
vault_parameters: Optional[VaultParameters] = None
|
151
|
+
llm_request: Optional[bool] = None
|
152
|
+
"""Is this redact call going to be used in an LLM request?"""
|
97
153
|
|
98
154
|
|
99
155
|
class StructuredResult(PangeaResponseResult):
|
@@ -107,6 +163,32 @@ class StructuredResult(PangeaResponseResult):
|
|
107
163
|
report: Optional[DebugReport] = None
|
108
164
|
|
109
165
|
|
166
|
+
class UnredactRequest(APIRequestModel):
|
167
|
+
"""
|
168
|
+
Class input to unredact data request
|
169
|
+
|
170
|
+
Arguments:
|
171
|
+
redacted_data: Data to unredact
|
172
|
+
fpe_context (base64): FPE context used to decrypt and unredact data
|
173
|
+
|
174
|
+
"""
|
175
|
+
|
176
|
+
redacted_data: RedactedData
|
177
|
+
fpe_context: str
|
178
|
+
|
179
|
+
|
180
|
+
RedactedData = Union[str, Dict]
|
181
|
+
|
182
|
+
|
183
|
+
class UnredactResult(PangeaResponseResult):
|
184
|
+
"""
|
185
|
+
Result class after an unredact request
|
186
|
+
|
187
|
+
"""
|
188
|
+
|
189
|
+
data: RedactedData
|
190
|
+
|
191
|
+
|
110
192
|
class Redact(ServiceBase):
|
111
193
|
"""Redact service client.
|
112
194
|
|
@@ -161,6 +243,9 @@ class Redact(ServiceBase):
|
|
161
243
|
rules: Optional[List[str]] = None,
|
162
244
|
rulesets: Optional[List[str]] = None,
|
163
245
|
return_result: Optional[bool] = None,
|
246
|
+
redaction_method_overrides: Optional[RedactionMethodOverrides] = None,
|
247
|
+
llm_request: Optional[bool] = None,
|
248
|
+
vault_parameters: Optional[VaultParameters] = None,
|
164
249
|
) -> PangeaResponse[RedactResult]:
|
165
250
|
"""
|
166
251
|
Redact
|
@@ -176,6 +261,9 @@ class Redact(ServiceBase):
|
|
176
261
|
rules (list[str], optional): An array of redact rule short names
|
177
262
|
rulesets (list[str], optional): An array of redact rulesets short names
|
178
263
|
return_result(bool, optional): Setting this value to false will omit the redacted result only returning count
|
264
|
+
redaction_method_overrides: A set of redaction method overrides for any enabled rule. These methods override the config declared methods
|
265
|
+
llm_request: Boolean flag to enable FPE redaction for LLM requests
|
266
|
+
vault_parameters: A set of vault parameters to use for redaction
|
179
267
|
|
180
268
|
Raises:
|
181
269
|
PangeaAPIException: If an API Error happens
|
@@ -189,8 +277,17 @@ class Redact(ServiceBase):
|
|
189
277
|
response = redact.redact(text="Jenny Jenny... 555-867-5309")
|
190
278
|
"""
|
191
279
|
|
192
|
-
input = RedactRequest(
|
193
|
-
|
280
|
+
input = RedactRequest(
|
281
|
+
text=text,
|
282
|
+
debug=debug,
|
283
|
+
rules=rules,
|
284
|
+
rulesets=rulesets,
|
285
|
+
return_result=return_result,
|
286
|
+
redaction_method_overrides=redaction_method_overrides,
|
287
|
+
llm_request=llm_request,
|
288
|
+
vault_parameters=vault_parameters,
|
289
|
+
)
|
290
|
+
return self.request.post("v1/redact", RedactResult, data=input.model_dump(exclude_none=True))
|
194
291
|
|
195
292
|
def redact_structured(
|
196
293
|
self,
|
@@ -201,6 +298,9 @@ class Redact(ServiceBase):
|
|
201
298
|
rules: Optional[List[str]] = None,
|
202
299
|
rulesets: Optional[List[str]] = None,
|
203
300
|
return_result: Optional[bool] = None,
|
301
|
+
redaction_method_overrides: Optional[RedactionMethodOverrides] = None,
|
302
|
+
llm_request: Optional[bool] = None,
|
303
|
+
vault_parameters: Optional[VaultParameters] = None,
|
204
304
|
) -> PangeaResponse[StructuredResult]:
|
205
305
|
"""
|
206
306
|
Redact structured
|
@@ -220,6 +320,9 @@ class Redact(ServiceBase):
|
|
220
320
|
rules (list[str], optional): An array of redact rule short names
|
221
321
|
rulesets (list[str], optional): An array of redact rulesets short names
|
222
322
|
return_result(bool, optional): Setting this value to false will omit the redacted result only returning count
|
323
|
+
redaction_method_overrides: A set of redaction method overrides for any enabled rule. These methods override the config declared methods
|
324
|
+
llm_request: Boolean flag to enable FPE redaction for LLM requests
|
325
|
+
vault_parameters: A set of vault parameters to use for redaction
|
223
326
|
|
224
327
|
Raises:
|
225
328
|
PangeaAPIException: If an API Error happens
|
@@ -246,5 +349,31 @@ class Redact(ServiceBase):
|
|
246
349
|
rules=rules,
|
247
350
|
rulesets=rulesets,
|
248
351
|
return_result=return_result,
|
352
|
+
redaction_method_overrides=redaction_method_overrides,
|
353
|
+
llm_request=llm_request,
|
354
|
+
vault_parameters=vault_parameters,
|
249
355
|
)
|
250
|
-
return self.request.post("v1/redact_structured", StructuredResult, data=input.
|
356
|
+
return self.request.post("v1/redact_structured", StructuredResult, data=input.model_dump(exclude_none=True))
|
357
|
+
|
358
|
+
def unredact(self, redacted_data: RedactedData, fpe_context: str) -> PangeaResponse[UnredactResult]:
|
359
|
+
"""
|
360
|
+
Unredact
|
361
|
+
|
362
|
+
Decrypt or unredact fpe redactions
|
363
|
+
|
364
|
+
OperationId: redact_post_v1_unredact
|
365
|
+
|
366
|
+
Args:
|
367
|
+
redacted_data: Data to unredact
|
368
|
+
fpe_context (base64): FPE context used to decrypt and unredact data
|
369
|
+
|
370
|
+
Raises:
|
371
|
+
PangeaAPIException: If an API Error happens
|
372
|
+
|
373
|
+
Returns:
|
374
|
+
Pangea Response with redacted data in the response.result field,
|
375
|
+
available response fields can be found in our
|
376
|
+
[API Documentation](https://pangea.cloud/docs/api/redact#unredact)
|
377
|
+
"""
|
378
|
+
input = UnredactRequest(redacted_data=redacted_data, fpe_context=fpe_context)
|
379
|
+
return self.request.post("v1/unredact", UnredactResult, data=input.model_dump(exclude_none=True))
|