pangea-sdk 3.8.0b4__py3-none-any.whl → 3.9.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 +14 -19
- pangea/asyncio/services/__init__.py +0 -2
- pangea/asyncio/services/audit.py +160 -14
- pangea/asyncio/services/authn.py +118 -79
- pangea/asyncio/services/authz.py +35 -50
- pangea/asyncio/services/intel.py +4 -4
- pangea/asyncio/services/redact.py +56 -2
- pangea/asyncio/services/vault.py +115 -4
- pangea/request.py +24 -21
- pangea/response.py +27 -28
- pangea/services/__init__.py +0 -2
- pangea/services/audit/audit.py +161 -16
- pangea/services/audit/models.py +53 -5
- pangea/services/authn/authn.py +77 -36
- pangea/services/authn/models.py +79 -0
- pangea/services/authz.py +47 -54
- pangea/services/base.py +23 -6
- pangea/services/file_scan.py +1 -0
- pangea/services/intel.py +2 -2
- pangea/services/redact.py +122 -2
- pangea/services/vault/models/common.py +115 -0
- pangea/services/vault/vault.py +117 -6
- pangea/utils.py +19 -91
- {pangea_sdk-3.8.0b4.dist-info → pangea_sdk-3.9.0.dist-info}/METADATA +6 -15
- pangea_sdk-3.9.0.dist-info/RECORD +46 -0
- 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_sdk-3.8.0b4.dist-info → pangea_sdk-3.9.0.dist-info}/WHEEL +0 -0
@@ -22,6 +22,8 @@ class KeyPurpose(str, enum.Enum):
|
|
22
22
|
SIGNING = "signing"
|
23
23
|
ENCRYPTION = "encryption"
|
24
24
|
JWT = "jwt"
|
25
|
+
FPE = "fpe"
|
26
|
+
"""Format-preserving encryption."""
|
25
27
|
|
26
28
|
def __str__(self):
|
27
29
|
return str(self.value)
|
@@ -84,6 +86,11 @@ class SymmetricAlgorithm(str, enum.Enum):
|
|
84
86
|
AES128_CBC = "AES-CBC-128"
|
85
87
|
AES256_CBC = "AES-CBC-256"
|
86
88
|
AES = "AES-CFB-128" # deprecated, use AES128_CFB instead
|
89
|
+
AES128_FF3_1_BETA = "AES-FF3-1-128-BETA"
|
90
|
+
"""128-bit encryption using the FF3-1 algorithm."""
|
91
|
+
|
92
|
+
AES256_FF3_1_BETA = "AES-FF3-1-256-BETA"
|
93
|
+
"""256-bit encryption using the FF3-1 algorithm."""
|
87
94
|
|
88
95
|
def __str__(self):
|
89
96
|
return str(self.value)
|
@@ -427,3 +434,111 @@ class EncryptStructuredResult(PangeaResponseResult, Generic[TDict]):
|
|
427
434
|
|
428
435
|
structured_data: TDict
|
429
436
|
"""Encrypted structured data."""
|
437
|
+
|
438
|
+
|
439
|
+
class TransformAlphabet(str, enum.Enum):
|
440
|
+
"""Set of characters to use for format-preserving encryption (FPE)."""
|
441
|
+
|
442
|
+
NUMERIC = "numeric"
|
443
|
+
"""Numeric (0-9)."""
|
444
|
+
|
445
|
+
ALPHA_LOWER = "alphalower"
|
446
|
+
"""Lowercase alphabet (a-z)."""
|
447
|
+
|
448
|
+
ALPHA_UPPER = "alphaupper"
|
449
|
+
"""Uppercase alphabet (A-Z)."""
|
450
|
+
|
451
|
+
ALPHANUMERIC_LOWER = "alphanumericlower"
|
452
|
+
"""Lowercase alphabet with numbers (a-z, 0-9)."""
|
453
|
+
|
454
|
+
ALPHANUMERIC_UPPER = "alphanumericupper"
|
455
|
+
"""Uppercase alphabet with numbers (A-Z, 0-9)."""
|
456
|
+
|
457
|
+
ALPHANUMERIC = "alphanumeric"
|
458
|
+
"""Alphanumeric (a-z, A-Z, 0-9)."""
|
459
|
+
|
460
|
+
def __str__(self) -> str:
|
461
|
+
return str(self.value)
|
462
|
+
|
463
|
+
def __repr__(self) -> str:
|
464
|
+
return str(self.value)
|
465
|
+
|
466
|
+
|
467
|
+
class EncryptTransformRequest(APIRequestModel):
|
468
|
+
id: str
|
469
|
+
"""The item ID."""
|
470
|
+
|
471
|
+
plain_text: str
|
472
|
+
"""A message to be encrypted."""
|
473
|
+
|
474
|
+
alphabet: TransformAlphabet
|
475
|
+
"""Set of characters to use for format-preserving encryption (FPE)."""
|
476
|
+
|
477
|
+
tweak: Optional[str] = None
|
478
|
+
"""
|
479
|
+
User provided tweak string. If not provided, a random string will be
|
480
|
+
generated and returned. The user must securely store the tweak source which
|
481
|
+
will be needed to decrypt the data.
|
482
|
+
"""
|
483
|
+
|
484
|
+
version: Optional[int] = None
|
485
|
+
"""The item version."""
|
486
|
+
|
487
|
+
|
488
|
+
class EncryptTransformResult(PangeaResponseResult):
|
489
|
+
id: str
|
490
|
+
"""The item ID."""
|
491
|
+
|
492
|
+
version: int
|
493
|
+
"""The item version."""
|
494
|
+
|
495
|
+
algorithm: str
|
496
|
+
"""The algorithm of the key."""
|
497
|
+
|
498
|
+
cipher_text: str
|
499
|
+
"""The encrypted message."""
|
500
|
+
|
501
|
+
tweak: str
|
502
|
+
"""
|
503
|
+
User provided tweak string. If not provided, a random string will be
|
504
|
+
generated and returned. The user must securely store the tweak source which
|
505
|
+
will be needed to decrypt the data.
|
506
|
+
"""
|
507
|
+
|
508
|
+
alphabet: str
|
509
|
+
"""Set of characters to use for format-preserving encryption (FPE)."""
|
510
|
+
|
511
|
+
|
512
|
+
class DecryptTransformRequest(APIRequestModel):
|
513
|
+
id: str
|
514
|
+
"""The item ID."""
|
515
|
+
|
516
|
+
cipher_text: str
|
517
|
+
"""A message encrypted by Vault."""
|
518
|
+
|
519
|
+
tweak: str
|
520
|
+
"""
|
521
|
+
User provided tweak string. If not provided, a random string will be
|
522
|
+
generated and returned. The user must securely store the tweak source which
|
523
|
+
will be needed to decrypt the data.
|
524
|
+
"""
|
525
|
+
|
526
|
+
alphabet: TransformAlphabet
|
527
|
+
"""Set of characters to use for format-preserving encryption (FPE)."""
|
528
|
+
|
529
|
+
version: Optional[int] = None
|
530
|
+
"""The item version."""
|
531
|
+
|
532
|
+
|
533
|
+
class DecryptTransformResult(PangeaResponseResult):
|
534
|
+
id: str
|
535
|
+
"""The item ID."""
|
536
|
+
|
537
|
+
version: int
|
538
|
+
"""The item version."""
|
539
|
+
|
540
|
+
algorithm: str
|
541
|
+
"""The algorithm of the key."""
|
542
|
+
|
543
|
+
plain_text: str
|
544
|
+
"""Decrypted message."""
|
pangea/services/vault/vault.py
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
from __future__ import annotations
|
4
|
+
|
3
5
|
import datetime
|
4
6
|
from typing import Dict, Optional, Union
|
5
7
|
|
8
|
+
from pangea.config import PangeaConfig
|
6
9
|
from pangea.response import PangeaResponse
|
7
10
|
from pangea.services.base import ServiceBase
|
8
11
|
from pangea.services.vault.models.asymmetric import (
|
@@ -17,6 +20,8 @@ from pangea.services.vault.models.asymmetric import (
|
|
17
20
|
)
|
18
21
|
from pangea.services.vault.models.common import (
|
19
22
|
AsymmetricAlgorithm,
|
23
|
+
DecryptTransformRequest,
|
24
|
+
DecryptTransformResult,
|
20
25
|
DeleteRequest,
|
21
26
|
DeleteResult,
|
22
27
|
EncodedPrivateKey,
|
@@ -24,6 +29,8 @@ from pangea.services.vault.models.common import (
|
|
24
29
|
EncodedSymmetricKey,
|
25
30
|
EncryptStructuredRequest,
|
26
31
|
EncryptStructuredResult,
|
32
|
+
EncryptTransformRequest,
|
33
|
+
EncryptTransformResult,
|
27
34
|
FolderCreateRequest,
|
28
35
|
FolderCreateResult,
|
29
36
|
GetRequest,
|
@@ -50,6 +57,7 @@ from pangea.services.vault.models.common import (
|
|
50
57
|
SymmetricAlgorithm,
|
51
58
|
Tags,
|
52
59
|
TDict,
|
60
|
+
TransformAlphabet,
|
53
61
|
UpdateRequest,
|
54
62
|
UpdateResult,
|
55
63
|
)
|
@@ -98,10 +106,24 @@ class Vault(ServiceBase):
|
|
98
106
|
|
99
107
|
def __init__(
|
100
108
|
self,
|
101
|
-
token,
|
102
|
-
config=None,
|
103
|
-
logger_name="pangea",
|
104
|
-
):
|
109
|
+
token: str,
|
110
|
+
config: PangeaConfig | None = None,
|
111
|
+
logger_name: str = "pangea",
|
112
|
+
) -> None:
|
113
|
+
"""
|
114
|
+
Vault client
|
115
|
+
|
116
|
+
Initializes a new Vault client.
|
117
|
+
|
118
|
+
Args:
|
119
|
+
token: Pangea API token.
|
120
|
+
config: Configuration.
|
121
|
+
logger_name: Logger name.
|
122
|
+
|
123
|
+
Examples:
|
124
|
+
config = PangeaConfig(domain="pangea_domain")
|
125
|
+
vault = Vault(token="pangea_token", config=config)
|
126
|
+
"""
|
105
127
|
super().__init__(token, config, logger_name)
|
106
128
|
|
107
129
|
# Delete endpoint
|
@@ -1216,7 +1238,7 @@ class Vault(ServiceBase):
|
|
1216
1238
|
Args:
|
1217
1239
|
id (str): The item ID.
|
1218
1240
|
structured_data (dict): Structured data for applying bulk operations.
|
1219
|
-
filter (str
|
1241
|
+
filter (str): A filter expression for applying bulk operations to the data field.
|
1220
1242
|
version (int, optional): The item version. Defaults to the current version.
|
1221
1243
|
additional_data (str, optional): User provided authentication data.
|
1222
1244
|
|
@@ -1265,7 +1287,7 @@ class Vault(ServiceBase):
|
|
1265
1287
|
Args:
|
1266
1288
|
id (str): The item ID.
|
1267
1289
|
structured_data (dict): Structured data to decrypt.
|
1268
|
-
filter (str
|
1290
|
+
filter (str): A filter expression for applying bulk operations to the data field.
|
1269
1291
|
version (int, optional): The item version. Defaults to the current version.
|
1270
1292
|
additional_data (str, optional): User provided authentication data.
|
1271
1293
|
|
@@ -1294,3 +1316,92 @@ class Vault(ServiceBase):
|
|
1294
1316
|
EncryptStructuredResult,
|
1295
1317
|
data=input.dict(exclude_none=True),
|
1296
1318
|
)
|
1319
|
+
|
1320
|
+
def encrypt_transform(
|
1321
|
+
self,
|
1322
|
+
id: str,
|
1323
|
+
plain_text: str,
|
1324
|
+
alphabet: TransformAlphabet,
|
1325
|
+
tweak: str | None = None,
|
1326
|
+
version: int | None = None,
|
1327
|
+
) -> PangeaResponse[EncryptTransformResult]:
|
1328
|
+
"""
|
1329
|
+
Encrypt transform
|
1330
|
+
|
1331
|
+
Encrypt using a format-preserving algorithm (FPE).
|
1332
|
+
|
1333
|
+
OperationId: vault_post_v1_key_encrypt_transform
|
1334
|
+
|
1335
|
+
Args:
|
1336
|
+
id: The item ID.
|
1337
|
+
plain_text: A message to be encrypted.
|
1338
|
+
alphabet: Set of characters to use for format-preserving encryption (FPE).
|
1339
|
+
tweak: User provided tweak string. If not provided, a random string will be generated and returned.
|
1340
|
+
version: The item version. Defaults to the current version.
|
1341
|
+
|
1342
|
+
Raises:
|
1343
|
+
PangeaAPIException: If an API error happens.
|
1344
|
+
|
1345
|
+
Returns:
|
1346
|
+
A `PangeaResponse` containing the encrypted message.
|
1347
|
+
|
1348
|
+
Examples:
|
1349
|
+
vault.encrypt_transform(
|
1350
|
+
id="pvi_[...]",
|
1351
|
+
plain_text="message to encrypt",
|
1352
|
+
alphabet=TransformAlphabet.ALPHANUMERIC,
|
1353
|
+
tweak="MTIzMTIzMT==",
|
1354
|
+
)
|
1355
|
+
"""
|
1356
|
+
|
1357
|
+
input = EncryptTransformRequest(
|
1358
|
+
id=id,
|
1359
|
+
plain_text=plain_text,
|
1360
|
+
tweak=tweak,
|
1361
|
+
alphabet=alphabet,
|
1362
|
+
version=version,
|
1363
|
+
)
|
1364
|
+
return self.request.post(
|
1365
|
+
"v1/key/encrypt/transform",
|
1366
|
+
EncryptTransformResult,
|
1367
|
+
data=input.dict(exclude_none=True),
|
1368
|
+
)
|
1369
|
+
|
1370
|
+
def decrypt_transform(
|
1371
|
+
self, id: str, cipher_text: str, tweak: str, alphabet: TransformAlphabet, version: int | None = None
|
1372
|
+
) -> PangeaResponse[DecryptTransformResult]:
|
1373
|
+
"""
|
1374
|
+
Decrypt transform
|
1375
|
+
|
1376
|
+
Decrypt using a format-preserving algorithm (FPE).
|
1377
|
+
|
1378
|
+
OperationId: vault_post_v1_key_decrypt_transform
|
1379
|
+
|
1380
|
+
Args:
|
1381
|
+
id: The item ID.
|
1382
|
+
cipher_text: A message encrypted by Vault.
|
1383
|
+
tweak: User provided tweak string.
|
1384
|
+
alphabet: Set of characters to use for format-preserving encryption (FPE).
|
1385
|
+
version: The item version. Defaults to the current version.
|
1386
|
+
|
1387
|
+
Raises:
|
1388
|
+
PangeaAPIException: If an API error happens.
|
1389
|
+
|
1390
|
+
Returns:
|
1391
|
+
A `PangeaResponse` containing the decrypted message.
|
1392
|
+
|
1393
|
+
Examples:
|
1394
|
+
vault.decrypt_transform(
|
1395
|
+
id="pvi_[...]",
|
1396
|
+
cipher_text="encrypted message",
|
1397
|
+
tweak="MTIzMTIzMT==",
|
1398
|
+
alphabet=TransformAlphabet.ALPHANUMERIC,
|
1399
|
+
)
|
1400
|
+
"""
|
1401
|
+
|
1402
|
+
input = DecryptTransformRequest(id=id, cipher_text=cipher_text, tweak=tweak, alphabet=alphabet, version=version)
|
1403
|
+
return self.request.post(
|
1404
|
+
"v1/key/decrypt/transform",
|
1405
|
+
DecryptTransformResult,
|
1406
|
+
data=input.dict(exclude_none=True),
|
1407
|
+
)
|
pangea/utils.py
CHANGED
@@ -4,8 +4,7 @@ import datetime
|
|
4
4
|
import io
|
5
5
|
import json
|
6
6
|
from collections import OrderedDict
|
7
|
-
from hashlib import
|
8
|
-
from typing import Union
|
7
|
+
from hashlib import new, sha1, sha256, sha512
|
9
8
|
|
10
9
|
from google_crc32c import Checksum as CRC32C # type: ignore[import]
|
11
10
|
from pydantic import BaseModel
|
@@ -31,8 +30,8 @@ def default_encoder(obj) -> str:
|
|
31
30
|
return str(obj)
|
32
31
|
|
33
32
|
|
34
|
-
def str2str_b64(data: str):
|
35
|
-
return base64.b64encode(data.encode(
|
33
|
+
def str2str_b64(data: str, encoding: str = "utf-8") -> str:
|
34
|
+
return base64.b64encode(data.encode(encoding)).decode("ascii")
|
36
35
|
|
37
36
|
|
38
37
|
def dict_order_keys(data: dict) -> OrderedDict:
|
@@ -77,97 +76,33 @@ def canonicalize(data: dict) -> str:
|
|
77
76
|
return str(data)
|
78
77
|
|
79
78
|
|
80
|
-
def hash_sha256(
|
81
|
-
# Return
|
82
|
-
|
83
|
-
if isinstance(input, io.BufferedReader):
|
84
|
-
input.seek(0) # restart reading
|
85
|
-
while True:
|
86
|
-
chunk = input.read(1024 * 1024)
|
87
|
-
if not chunk:
|
88
|
-
break
|
89
|
-
hash.update(chunk)
|
79
|
+
def hash_sha256(data: str) -> str:
|
80
|
+
# Return sha256 hash in hex format
|
81
|
+
return sha256(data.encode("ascii")).hexdigest()
|
90
82
|
|
91
|
-
input.seek(0) # restart reading
|
92
|
-
else:
|
93
|
-
hash.update(input) # type: ignore
|
94
|
-
|
95
|
-
return hash.hexdigest()
|
96
|
-
|
97
|
-
|
98
|
-
def hash_sha1(input: Union[str, io.BufferedReader]) -> str:
|
99
|
-
# Return SHA1 hash in hex format
|
100
|
-
hash = sha1()
|
101
|
-
if isinstance(input, io.BufferedReader):
|
102
|
-
input.seek(0) # restart reading
|
103
|
-
while True:
|
104
|
-
chunk = input.read(1024 * 1024)
|
105
|
-
if not chunk:
|
106
|
-
break
|
107
|
-
hash.update(chunk)
|
108
83
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
return hash
|
84
|
+
def hash_256_filepath(filepath: str) -> str:
|
85
|
+
data = open(filepath, "rb")
|
86
|
+
hash = sha256(data.read()).hexdigest()
|
87
|
+
data.close()
|
88
|
+
return hash
|
114
89
|
|
115
90
|
|
116
|
-
def
|
117
|
-
# Return
|
118
|
-
|
119
|
-
if isinstance(input, io.BufferedReader):
|
120
|
-
input.seek(0) # restart reading
|
121
|
-
while True:
|
122
|
-
chunk = input.read(1024 * 1024)
|
123
|
-
if not chunk:
|
124
|
-
break
|
125
|
-
hash.update(chunk)
|
91
|
+
def hash_sha1(data: str) -> str:
|
92
|
+
# Return sha1 hash in hex format
|
93
|
+
return sha1(data.encode("ascii")).hexdigest()
|
126
94
|
|
127
|
-
input.seek(0) # restart reading
|
128
|
-
else:
|
129
|
-
hash.update(input) # type: ignore
|
130
95
|
|
131
|
-
|
96
|
+
def hash_sha512(data: str) -> str:
|
97
|
+
# Return sha512 hash in hex format
|
98
|
+
return sha512(data.encode("ascii")).hexdigest()
|
132
99
|
|
133
100
|
|
134
|
-
def hash_ntlm(data: str)
|
135
|
-
#
|
101
|
+
def hash_ntlm(data: str):
|
102
|
+
# Calculate the NTLM hash
|
136
103
|
return new("md4", data.encode("utf-16le")).hexdigest()
|
137
104
|
|
138
105
|
|
139
|
-
def hash_md5(input: Union[str, io.BufferedReader]) -> str:
|
140
|
-
# Return MD5 hash in hex format
|
141
|
-
hash = md5()
|
142
|
-
if isinstance(input, io.BufferedReader):
|
143
|
-
input.seek(0) # restart reading
|
144
|
-
|
145
|
-
while True:
|
146
|
-
chunk = input.read(1024 * 1024)
|
147
|
-
if not chunk:
|
148
|
-
break
|
149
|
-
hash.update(chunk)
|
150
|
-
|
151
|
-
input.seek(0) # restart reading
|
152
|
-
else:
|
153
|
-
hash.update(input) # type: ignore
|
154
|
-
|
155
|
-
return hash.hexdigest()
|
156
|
-
|
157
|
-
|
158
|
-
def get_crc32c(data: str) -> str:
|
159
|
-
crc = CRC32C()
|
160
|
-
crc.update(data)
|
161
|
-
return crc.hexdigest().decode("utf-8")
|
162
|
-
|
163
|
-
|
164
|
-
def hash_256_filepath(filepath: str) -> str:
|
165
|
-
data = open(filepath, "rb")
|
166
|
-
hash = sha256(data.read()).hexdigest()
|
167
|
-
data.close()
|
168
|
-
return hash
|
169
|
-
|
170
|
-
|
171
106
|
def get_prefix(hash: str, len: int = 5):
|
172
107
|
return hash[0:len]
|
173
108
|
|
@@ -197,10 +132,3 @@ def get_file_upload_params(file: io.BufferedReader) -> FileUploadParams:
|
|
197
132
|
|
198
133
|
file.seek(0) # restart reading
|
199
134
|
return FileUploadParams(crc_hex=crc.hexdigest().decode("utf-8"), sha256_hex=sha.hexdigest(), size=size)
|
200
|
-
|
201
|
-
|
202
|
-
def get_file_size(file: io.BufferedReader) -> int:
|
203
|
-
file.seek(0, io.SEEK_END)
|
204
|
-
size = file.tell()
|
205
|
-
file.seek(0) # restart reading
|
206
|
-
return size
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pangea-sdk
|
3
|
-
Version: 3.
|
3
|
+
Version: 3.9.0
|
4
4
|
Summary: Pangea API SDK
|
5
5
|
Home-page: https://pangea.cloud/docs/sdk/python/
|
6
6
|
License: MIT
|
@@ -18,13 +18,14 @@ Classifier: Topic :: Software Development
|
|
18
18
|
Classifier: Topic :: Software Development :: Libraries
|
19
19
|
Requires-Dist: aiohttp (>=3.8.6,<4.0.0)
|
20
20
|
Requires-Dist: asyncio (>=3.4.3,<4.0.0)
|
21
|
-
Requires-Dist: cryptography (>=42.0.
|
21
|
+
Requires-Dist: cryptography (>=42.0.7,<43.0.0)
|
22
22
|
Requires-Dist: deprecated (>=1.2.14,<2.0.0)
|
23
23
|
Requires-Dist: google-crc32c (>=1.5.0,<2.0.0)
|
24
|
-
Requires-Dist: pydantic (>=1.10.
|
24
|
+
Requires-Dist: pydantic (>=1.10.15,<2.0.0)
|
25
25
|
Requires-Dist: python-dateutil (>=2.9.0,<3.0.0)
|
26
26
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
27
27
|
Requires-Dist: requests-toolbelt (>=1.0.0,<2.0.0)
|
28
|
+
Requires-Dist: typing-extensions (>=4.7.1,<5.0.0)
|
28
29
|
Project-URL: Repository, https://github.com/pangeacyber/pangea-python/tree/main/packages/pangea-sdk
|
29
30
|
Description-Content-Type: text/markdown
|
30
31
|
|
@@ -70,13 +71,13 @@ compatibility guarantees as stable releases. [Beta changelog](https://github.com
|
|
70
71
|
Via pip:
|
71
72
|
|
72
73
|
```bash
|
73
|
-
$ pip3 install pangea-sdk==3.8.
|
74
|
+
$ pip3 install pangea-sdk==3.8.0b2
|
74
75
|
```
|
75
76
|
|
76
77
|
Via poetry:
|
77
78
|
|
78
79
|
```bash
|
79
|
-
$ poetry add pangea-sdk==3.8.
|
80
|
+
$ poetry add pangea-sdk==3.8.0b2
|
80
81
|
```
|
81
82
|
|
82
83
|
## Usage
|
@@ -142,16 +143,6 @@ if __name__ == "__main__":
|
|
142
143
|
asyncio.run(main())
|
143
144
|
```
|
144
145
|
|
145
|
-
|
146
|
-
<a name="beta-releases"></a>
|
147
|
-
|
148
|
-
## Beta releases
|
149
|
-
|
150
|
-
Pre-release versions may be available with the `beta` denotation in the version
|
151
|
-
number. These releases serve to preview beta services and APIs. Per Semantic
|
152
|
-
Versioning, they are considered unstable and do not carry the same compatibility
|
153
|
-
guarantees as stable releases.
|
154
|
-
|
155
146
|
## Secure Audit Log - Integrity Tools
|
156
147
|
|
157
148
|
The Python Pangea SDK also includes some extra features to validate Audit Service log's integrity. Here we explain how to run them.
|
@@ -0,0 +1,46 @@
|
|
1
|
+
pangea/__init__.py,sha256=xVt29HqH0NMwg6j3N6C8FwhZHWN8XdEvbDgAxvq2tAo,200
|
2
|
+
pangea/asyncio/request.py,sha256=uvx9d1hmYhGKvbI4ecj6kIagGhPn_4bKmHN062Zz35c,17089
|
3
|
+
pangea/asyncio/services/__init__.py,sha256=hmySN2LoXYpHzSKLVSdVjMbpGXi5Z5iNx-fJ2Fc8W6I,320
|
4
|
+
pangea/asyncio/services/audit.py,sha256=9WFr_hiGMuMtp21aBtNd0iMK06De_QwjvpZJ-tBYjNY,25615
|
5
|
+
pangea/asyncio/services/authn.py,sha256=UTjEf_QMqS0ZThZwamZYg3NE_qCCqv7bQg5PBPnAC8M,45413
|
6
|
+
pangea/asyncio/services/authz.py,sha256=2S-O6T2p_x8DIaU1frF3KE8tlmepfFvN1OZNJY_fftA,9068
|
7
|
+
pangea/asyncio/services/base.py,sha256=4FtKtlq74NmE9myrgIt9HMA6JDnP4mPZ6krafWr286o,2663
|
8
|
+
pangea/asyncio/services/embargo.py,sha256=8WguyWZUaGVwGpNzic5h8QzLueirA9WpBBik4mpCTeA,3056
|
9
|
+
pangea/asyncio/services/file_scan.py,sha256=WIKYjUNCIx6jF0vQ-KnsKYBcZh53Q5rmccTlsTPP_rY,6301
|
10
|
+
pangea/asyncio/services/intel.py,sha256=-0xAfnlAgNH774XRHX1-zIv2nr1Xra7X8tLhuCArQhE,37647
|
11
|
+
pangea/asyncio/services/redact.py,sha256=QOJax94O2Sd20zwzrymf4HJ9CFHUJhoMa2jayc5qkcY,7225
|
12
|
+
pangea/asyncio/services/vault.py,sha256=pGO2vQK9t0xKzuBvy5GT5mnJckudAl6ng9Vj3Vxdq1I,50897
|
13
|
+
pangea/audit_logger.py,sha256=gRkCfUUT5LDNaycwxkhZUySgY47jDfn1ZeKOul4XCQI,3842
|
14
|
+
pangea/config.py,sha256=mQUu8GX_6weIuv3vjNdG5plppXskXYASmxMWtFQh-hc,1662
|
15
|
+
pangea/deep_verify.py,sha256=mocaGbC6XLbMTVWxTpMv4oJtXGPWpT-SbFqT3obpiZs,8443
|
16
|
+
pangea/deprecated.py,sha256=IjFYEVvY1E0ld0SMkEYC1o62MAleX3nnT1If2dFVbHo,608
|
17
|
+
pangea/dump_audit.py,sha256=8KrTOP64D28RFv1mvOOxe0fxlRZi8PtwnEZfvabglNA,7019
|
18
|
+
pangea/exceptions.py,sha256=OBtzUECpNa6vNp8ySkHC-tm4QjFRCOAHBkMHqzAlOu8,5656
|
19
|
+
pangea/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
+
pangea/request.py,sha256=ZcK49SgCPvGwPGrY63UmiTo-xELu2ryPvALmPxPXkGI,24298
|
21
|
+
pangea/response.py,sha256=egyLcl0FxEDmTrbRjHuB_DvxipfTXG0ExUS1yLBss-M,6828
|
22
|
+
pangea/services/__init__.py,sha256=iAIa1kk_C0EHBsSn2XP3QT-bOZNGwMBPUcO2JoI-9cE,278
|
23
|
+
pangea/services/audit/audit.py,sha256=jRjx8wNb75kqclcpPZRpBbl4FhNhuh-LzIE2lR2gEhY,38754
|
24
|
+
pangea/services/audit/exceptions.py,sha256=bhVuYe4ammacOVxwg98CChxvwZf5FKgR2DcgqILOcwc,471
|
25
|
+
pangea/services/audit/models.py,sha256=2yEss7ZyeJ-5Sz896MrPUgVzw3LeL2qVLDHaEJqlFaM,14668
|
26
|
+
pangea/services/audit/signing.py,sha256=pOjw60BIYDcg3_5YKDCMWZUaapsEZpCHaFhyFu7TEgc,5567
|
27
|
+
pangea/services/audit/util.py,sha256=C6KAdu6qhValmNrIMUPLdAW0SCiLwcDd5euXti_63Og,7596
|
28
|
+
pangea/services/authn/authn.py,sha256=NBaEduKx9bN68MnPOSGF-tOwhwqpWXLq0l0OFf8sjKg,44394
|
29
|
+
pangea/services/authn/models.py,sha256=9TvJixFoC1SsyC1rAzRMDIuCEV1iGsPZefENS89SdJU,19878
|
30
|
+
pangea/services/authz.py,sha256=jCxuseTV5gvZ6YxeBH5LGsIlF7CKXOyijkAVV9esYf8,11747
|
31
|
+
pangea/services/base.py,sha256=lwhHoe5Juy28Ir3Mfj2lHdM58gxZRaxa2SRFi4_DBRw,3453
|
32
|
+
pangea/services/embargo.py,sha256=WFqBreGU1FPgOSabIIkWCrXBvquYN958Un7h9P1aHSI,3885
|
33
|
+
pangea/services/file_scan.py,sha256=tWR4D672Lxk_btSA1NcuUFkajbEhiCGMoTMm2bGtCj4,6942
|
34
|
+
pangea/services/intel.py,sha256=t8SksNsh-r1JjLN3if4yNmx711hNjQ_1YzCX-96_xv0,51645
|
35
|
+
pangea/services/redact.py,sha256=84nTdo3rIsbiK3q7LAvQIKtj3LYO8MTrRcTW9X4tr9c,11447
|
36
|
+
pangea/services/vault/models/asymmetric.py,sha256=ac2Exc66elXxO-HxBqtvLPQWNI7y_00kb6SVqBPKecA,1450
|
37
|
+
pangea/services/vault/models/common.py,sha256=o2gO6hzifNAFrLDr0QeEZqAcdXid52pdAy057Dic2dQ,13988
|
38
|
+
pangea/services/vault/models/secret.py,sha256=cLgEj-_BeGkB4-pmSeTkWVyasFbaJwcEltIEcOyf1U8,481
|
39
|
+
pangea/services/vault/models/symmetric.py,sha256=5N2n6FDStB1CLPfpd4p-6Ig__Nt-EyurhjCWfEyws2k,1330
|
40
|
+
pangea/services/vault/vault.py,sha256=Wn3qNCvCtK0MfZgriu8NwN4pHNJ8x2fsqilKJ-D0LKA,50644
|
41
|
+
pangea/tools.py,sha256=sa2pSz-L8tB6GcZg6lghsmm8w0qMQAIkzqcv7dilU6Q,6429
|
42
|
+
pangea/utils.py,sha256=nTrw0lcw4s0R2m_LFIoypFU4ilsBfjV1eCf_bTjJ-Lo,3489
|
43
|
+
pangea/verify_audit.py,sha256=QthhKzFlIQwoEyjBLojcX4uHGaN3EEGomx-IC5e3L0E,10756
|
44
|
+
pangea_sdk-3.9.0.dist-info/METADATA,sha256=Z6SzAotPRtxmjXppLOpJWB2ScRrFnW5RD_QtStU9E8w,7464
|
45
|
+
pangea_sdk-3.9.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
46
|
+
pangea_sdk-3.9.0.dist-info/RECORD,,
|
pangea/asyncio/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
from .file_uploader import FileUploaderAsync
|
pangea/asyncio/file_uploader.py
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
# Copyright 2022 Pangea Cyber Corporation
|
2
|
-
# Author: Pangea Cyber Corporation
|
3
|
-
import io
|
4
|
-
import logging
|
5
|
-
from typing import Dict, Optional
|
6
|
-
|
7
|
-
from pangea.asyncio.request import PangeaRequestAsync
|
8
|
-
from pangea.request import PangeaConfig
|
9
|
-
from pangea.response import TransferMethod
|
10
|
-
|
11
|
-
|
12
|
-
class FileUploaderAsync:
|
13
|
-
def __init__(self) -> None:
|
14
|
-
self.logger = logging.getLogger("pangea")
|
15
|
-
self._request: PangeaRequestAsync = PangeaRequestAsync(
|
16
|
-
config=PangeaConfig(),
|
17
|
-
token="",
|
18
|
-
service="FileUploader",
|
19
|
-
logger=self.logger,
|
20
|
-
)
|
21
|
-
|
22
|
-
async def upload_file(
|
23
|
-
self,
|
24
|
-
url: str,
|
25
|
-
file: io.BufferedReader,
|
26
|
-
transfer_method: TransferMethod = TransferMethod.PUT_URL,
|
27
|
-
file_details: Optional[Dict] = None,
|
28
|
-
) -> None:
|
29
|
-
if transfer_method == TransferMethod.PUT_URL:
|
30
|
-
files = [("file", ("filename", file, "application/octet-stream"))]
|
31
|
-
await self._request.put_presigned_url(url=url, files=files) # type: ignore[arg-type]
|
32
|
-
elif transfer_method == TransferMethod.POST_URL:
|
33
|
-
files = [("file", ("filename", file, "application/octet-stream"))]
|
34
|
-
await self._request.post_presigned_url(url=url, data=file_details, files=files) # type: ignore[arg-type]
|
35
|
-
else:
|
36
|
-
raise ValueError(f"Transfer method not supported: {transfer_method}")
|
37
|
-
|
38
|
-
async def close(self) -> None:
|
39
|
-
await self._request.session.close()
|