pangea-sdk 3.8.0b1__py3-none-any.whl → 5.4.0b1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. pangea/__init__.py +1 -1
  2. pangea/asyncio/file_uploader.py +1 -1
  3. pangea/asyncio/request.py +56 -34
  4. pangea/asyncio/services/__init__.py +4 -0
  5. pangea/asyncio/services/ai_guard.py +75 -0
  6. pangea/asyncio/services/audit.py +192 -31
  7. pangea/asyncio/services/authn.py +187 -109
  8. pangea/asyncio/services/authz.py +285 -0
  9. pangea/asyncio/services/base.py +21 -2
  10. pangea/asyncio/services/embargo.py +2 -2
  11. pangea/asyncio/services/file_scan.py +24 -9
  12. pangea/asyncio/services/intel.py +108 -34
  13. pangea/asyncio/services/prompt_guard.py +73 -0
  14. pangea/asyncio/services/redact.py +72 -4
  15. pangea/asyncio/services/sanitize.py +217 -0
  16. pangea/asyncio/services/share.py +246 -73
  17. pangea/asyncio/services/vault.py +1710 -750
  18. pangea/crypto/rsa.py +135 -0
  19. pangea/deep_verify.py +7 -1
  20. pangea/dump_audit.py +9 -8
  21. pangea/request.py +87 -59
  22. pangea/response.py +49 -31
  23. pangea/services/__init__.py +4 -0
  24. pangea/services/ai_guard.py +128 -0
  25. pangea/services/audit/audit.py +205 -42
  26. pangea/services/audit/models.py +56 -8
  27. pangea/services/audit/signing.py +6 -5
  28. pangea/services/audit/util.py +3 -3
  29. pangea/services/authn/authn.py +140 -70
  30. pangea/services/authn/models.py +167 -11
  31. pangea/services/authz.py +400 -0
  32. pangea/services/base.py +39 -8
  33. pangea/services/embargo.py +2 -2
  34. pangea/services/file_scan.py +32 -15
  35. pangea/services/intel.py +157 -32
  36. pangea/services/prompt_guard.py +83 -0
  37. pangea/services/redact.py +152 -4
  38. pangea/services/sanitize.py +371 -0
  39. pangea/services/share/share.py +683 -107
  40. pangea/services/vault/models/asymmetric.py +120 -18
  41. pangea/services/vault/models/common.py +439 -141
  42. pangea/services/vault/models/keys.py +94 -0
  43. pangea/services/vault/models/secret.py +27 -3
  44. pangea/services/vault/models/symmetric.py +68 -22
  45. pangea/services/vault/vault.py +1690 -749
  46. pangea/tools.py +6 -7
  47. pangea/utils.py +16 -27
  48. pangea/verify_audit.py +270 -83
  49. {pangea_sdk-3.8.0b1.dist-info → pangea_sdk-5.4.0b1.dist-info}/METADATA +43 -35
  50. pangea_sdk-5.4.0b1.dist-info/RECORD +60 -0
  51. {pangea_sdk-3.8.0b1.dist-info → pangea_sdk-5.4.0b1.dist-info}/WHEEL +1 -1
  52. pangea_sdk-3.8.0b1.dist-info/RECORD +0 -50
pangea/services/base.py CHANGED
@@ -1,23 +1,40 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+ from __future__ import annotations
3
4
 
4
5
  import copy
5
6
  import logging
6
7
  from typing import Dict, Optional, Type, Union
7
8
 
9
+ from typing_extensions import TypeVar
10
+
8
11
  from pangea.asyncio.request import PangeaRequestAsync
9
12
  from pangea.config import PangeaConfig
10
13
  from pangea.exceptions import AcceptedRequestException
11
14
  from pangea.request import PangeaRequest
12
15
  from pangea.response import AttachedFile, PangeaResponse, PangeaResponseResult
13
16
 
17
+ TResult = TypeVar("TResult", bound=PangeaResponseResult, default=PangeaResponseResult)
18
+
14
19
 
15
20
  class ServiceBase(object):
16
21
  service_name: str = "base"
17
22
 
18
23
  def __init__(
19
- self, token, config: Optional[PangeaConfig] = None, logger_name: str = "pangea", config_id: Optional[str] = None
20
- ):
24
+ self,
25
+ token: str,
26
+ config: PangeaConfig | None = None,
27
+ logger_name: str = "pangea",
28
+ config_id: str | None = None,
29
+ ) -> None:
30
+ """
31
+ Initializes a new Pangea service client.
32
+
33
+ Args:
34
+ token: Pangea API token.
35
+ config: Configuration.
36
+ logger_name: Logger name.
37
+ """
21
38
  if not token:
22
39
  raise Exception("No token provided")
23
40
 
@@ -30,11 +47,11 @@ class ServiceBase(object):
30
47
  self.request.set_extra_headers(extra_headers)
31
48
 
32
49
  @property
33
- def token(self):
50
+ def token(self) -> str:
34
51
  return self._token
35
52
 
36
53
  @token.setter
37
- def token(self, value):
54
+ def token(self, value: str) -> None:
38
55
  self._token = value
39
56
 
40
57
  @property
@@ -55,15 +72,16 @@ class ServiceBase(object):
55
72
  exception: Optional[AcceptedRequestException] = None,
56
73
  response: Optional[PangeaResponse] = None,
57
74
  request_id: Optional[str] = None,
58
- result_class: Union[Type[PangeaResponseResult], Type[Dict]] = dict,
59
- ) -> PangeaResponse:
75
+ result_class: Type[TResult] = PangeaResponseResult, # type: ignore[assignment]
76
+ ) -> PangeaResponse[TResult]:
60
77
  """
61
78
  Poll result
62
79
 
63
80
  Returns request's result that has been accepted by the server
64
81
 
65
82
  Args:
66
- exception (AcceptedRequestException): Exception raise by SDK on the call that is been processed.
83
+ exception: Exception that was previously raised by the SDK on a call
84
+ that is being processed.
67
85
 
68
86
  Returns:
69
87
  PangeaResponse
@@ -83,5 +101,18 @@ class ServiceBase(object):
83
101
  else:
84
102
  raise AttributeError("Need to set exception, response or request_id")
85
103
 
86
- def download_file(self, url: str, filename: Optional[str] = None) -> AttachedFile:
104
+ def download_file(self, url: str, filename: str | None = None) -> AttachedFile:
105
+ """
106
+ Download file
107
+
108
+ Download a file from the specified URL and save it with the given
109
+ filename.
110
+
111
+ Args:
112
+ url: URL of the file to download
113
+ filename: Name to save the downloaded file as. If not provided, the
114
+ filename will be determined from the Content-Disposition header or
115
+ the URL.
116
+ """
117
+
87
118
  return self.request.download_file(url=url, filename=filename)
@@ -103,7 +103,7 @@ class Embargo(ServiceBase):
103
103
  response = embargo.ip_check("190.6.64.94")
104
104
  """
105
105
  input = IPCheckRequest(ip=ip)
106
- return self.request.post("v1/ip/check", EmbargoResult, data=input.dict())
106
+ return self.request.post("v1/ip/check", EmbargoResult, data=input.model_dump())
107
107
 
108
108
  def iso_check(self, iso_code: str) -> PangeaResponse[EmbargoResult]:
109
109
  """
@@ -130,4 +130,4 @@ class Embargo(ServiceBase):
130
130
  response = embargo.iso_check("CU")
131
131
  """
132
132
  input = ISOCheckRequest(iso_code=iso_code)
133
- return self.request.post("v1/iso/check", result_class=EmbargoResult, data=input.dict())
133
+ return self.request.post("v1/iso/check", result_class=EmbargoResult, data=input.model_dump())
@@ -11,22 +11,25 @@ from pangea.utils import FileUploadParams, get_file_upload_params
11
11
 
12
12
 
13
13
  class FileScanRequest(APIRequestModel):
14
- """
15
- File Scan request data
16
-
17
- provider (str, optional): Provider of the information. Default provider defined by the configuration.
18
- verbose (bool, optional): Echo back the parameters of the API in the response
19
- raw (bool, optional): Return additional details from the provider.
20
- """
14
+ """File Scan request data."""
21
15
 
22
16
  verbose: Optional[bool] = None
17
+ """Echo back the parameters of the API in the response."""
18
+
23
19
  raw: Optional[bool] = None
20
+ """Return additional details from the provider."""
21
+
24
22
  provider: Optional[str] = None
23
+ """Provider of the information. Default provider defined by the configuration."""
24
+
25
25
  size: Optional[int] = None
26
26
  crc32c: Optional[str] = None
27
27
  sha256: Optional[str] = None
28
28
  source_url: Optional[str] = None
29
+ """A URL where the file to be scanned can be downloaded."""
30
+
29
31
  transfer_method: TransferMethod = TransferMethod.POST_URL
32
+ """The transfer method used to upload the file data."""
30
33
 
31
34
 
32
35
  class FileScanData(PangeaResponseResult):
@@ -71,7 +74,6 @@ class FileScan(ServiceBase):
71
74
  """
72
75
 
73
76
  service_name = "file-scan"
74
- version = "v1"
75
77
 
76
78
  def file_scan(
77
79
  self,
@@ -92,12 +94,14 @@ class FileScan(ServiceBase):
92
94
  OperationId: file_scan_post_v1_scan
93
95
 
94
96
  Args:
95
- file (io.BufferedReader, optional): file to be scanned (should be opened with read permissions and in binary format)
96
97
  file_path (str, optional): filepath to be opened and scanned
98
+ file (io.BufferedReader, optional): file to be scanned (should be opened with read permissions and in binary format)
97
99
  verbose (bool, optional): Echo the API parameters in the response
98
100
  raw (bool, optional): Include raw data from this provider
99
101
  provider (str, optional): Scan file using this provider
100
102
  sync_call (bool, optional): True to wait until server returns a result, False to return immediately and retrieve result asynchronously
103
+ transfer_method (TransferMethod, optional): Transfer method used to upload the file data.
104
+ source_url (str, optional): A URL where the Pangea APIs can fetch the contents of the input file.
101
105
 
102
106
  Raises:
103
107
  PangeaAPIException: If an API Error happens
@@ -118,6 +122,15 @@ class FileScan(ServiceBase):
118
122
  print(f"\\t{err.detail} \\n")
119
123
  """
120
124
 
125
+ if transfer_method == TransferMethod.SOURCE_URL and source_url is None:
126
+ raise ValueError("`source_url` argument is required when using `TransferMethod.SOURCE_URL`.")
127
+
128
+ if source_url is not None and transfer_method != TransferMethod.SOURCE_URL:
129
+ raise ValueError(
130
+ "`transfer_method` should be `TransferMethod.SOURCE_URL` when using the `source_url` argument."
131
+ )
132
+
133
+ files: Optional[List[Tuple]] = None
121
134
  if file or file_path:
122
135
  if file_path:
123
136
  file = open(file_path, "rb")
@@ -128,9 +141,9 @@ class FileScan(ServiceBase):
128
141
  size = params.size
129
142
  else:
130
143
  crc, sha, size = None, None, None
131
- files: List[Tuple] = [("upload", ("filename", file, "application/octet-stream"))]
132
- else:
133
- raise ValueError("Need to set file_path or file arguments")
144
+ files = [("upload", ("filename", file, "application/octet-stream"))]
145
+ elif source_url is None:
146
+ raise ValueError("Need to set one of `file_path`, `file`, or `source_url` arguments.")
134
147
 
135
148
  input = FileScanRequest(
136
149
  verbose=verbose,
@@ -142,8 +155,12 @@ class FileScan(ServiceBase):
142
155
  transfer_method=transfer_method,
143
156
  source_url=source_url,
144
157
  )
145
- data = input.dict(exclude_none=True)
146
- return self.request.post("v1/scan", FileScanResult, data=data, files=files, poll_result=sync_call)
158
+ data = input.model_dump(exclude_none=True)
159
+ try:
160
+ return self.request.post("v1/scan", FileScanResult, data=data, files=files, poll_result=sync_call)
161
+ finally:
162
+ if file_path and file:
163
+ file.close()
147
164
 
148
165
  def request_upload_url(
149
166
  self,
@@ -164,7 +181,7 @@ class FileScan(ServiceBase):
164
181
  input.sha256 = params.sha256_hex
165
182
  input.size = params.size
166
183
 
167
- data = input.dict(exclude_none=True)
184
+ data = input.model_dump(exclude_none=True)
168
185
  return self.request.request_presigned_url("v1/scan", FileScanResult, data=data)
169
186
 
170
187