pangea-sdk 3.8.0b1__py3-none-any.whl → 5.3.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/file_uploader.py +1 -1
- pangea/asyncio/request.py +49 -31
- pangea/asyncio/services/__init__.py +2 -0
- pangea/asyncio/services/audit.py +192 -31
- pangea/asyncio/services/authn.py +187 -109
- pangea/asyncio/services/authz.py +285 -0
- 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 +108 -34
- pangea/asyncio/services/redact.py +72 -4
- pangea/asyncio/services/sanitize.py +217 -0
- pangea/asyncio/services/share.py +246 -73
- pangea/asyncio/services/vault.py +1710 -750
- pangea/crypto/rsa.py +135 -0
- pangea/deep_verify.py +7 -1
- pangea/dump_audit.py +9 -8
- pangea/request.py +83 -59
- pangea/response.py +49 -31
- pangea/services/__init__.py +2 -0
- pangea/services/audit/audit.py +205 -42
- pangea/services/audit/models.py +56 -8
- pangea/services/audit/signing.py +6 -5
- pangea/services/audit/util.py +3 -3
- pangea/services/authn/authn.py +140 -70
- pangea/services/authn/models.py +167 -11
- pangea/services/authz.py +400 -0
- pangea/services/base.py +39 -8
- pangea/services/embargo.py +2 -2
- pangea/services/file_scan.py +32 -15
- pangea/services/intel.py +157 -32
- pangea/services/redact.py +152 -4
- pangea/services/sanitize.py +388 -0
- pangea/services/share/share.py +683 -107
- 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 -749
- pangea/tools.py +6 -7
- pangea/utils.py +16 -27
- pangea/verify_audit.py +270 -83
- {pangea_sdk-3.8.0b1.dist-info → pangea_sdk-5.3.0.dist-info}/METADATA +43 -35
- pangea_sdk-5.3.0.dist-info/RECORD +56 -0
- {pangea_sdk-3.8.0b1.dist-info → pangea_sdk-5.3.0.dist-info}/WHEEL +1 -1
- pangea_sdk-3.8.0b1.dist-info/RECORD +0 -50
    
        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,11 +837,11 @@ 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
         | 
| 842 | 
            -
                ) -> PangeaResponse[ | 
| 844 | 
            +
                ) -> PangeaResponse[IPReputationBulkResult]:
         | 
| 843 845 | 
             
                    """
         | 
| 844 846 | 
             
                    Reputation V2
         | 
| 845 847 |  | 
| @@ -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,
         | 
| @@ -1195,7 +1197,7 @@ class UrlIntel(ServiceBase): | |
| 1195 1197 | 
             
                    verbose: Optional[bool] = None,
         | 
| 1196 1198 | 
             
                    raw: Optional[bool] = None,
         | 
| 1197 1199 | 
             
                    provider: Optional[str] = None,
         | 
| 1198 | 
            -
                ) -> PangeaResponse[ | 
| 1200 | 
            +
                ) -> PangeaResponse[URLReputationBulkResult]:
         | 
| 1199 1201 | 
             
                    """
         | 
| 1200 1202 | 
             
                    Reputation V2
         | 
| 1201 1203 |  | 
| @@ -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 |  |