nucliadb-utils 5.0.0.post641__py3-none-any.whl → 5.0.0.post642__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.
- nucliadb_utils/encryption/__init__.py +81 -0
- nucliadb_utils/encryption/settings.py +39 -0
- nucliadb_utils/utilities.py +19 -0
- {nucliadb_utils-5.0.0.post641.dist-info → nucliadb_utils-5.0.0.post642.dist-info}/METADATA +3 -3
- {nucliadb_utils-5.0.0.post641.dist-info → nucliadb_utils-5.0.0.post642.dist-info}/RECORD +8 -6
- {nucliadb_utils-5.0.0.post641.dist-info → nucliadb_utils-5.0.0.post642.dist-info}/WHEEL +0 -0
- {nucliadb_utils-5.0.0.post641.dist-info → nucliadb_utils-5.0.0.post642.dist-info}/top_level.txt +0 -0
- {nucliadb_utils-5.0.0.post641.dist-info → nucliadb_utils-5.0.0.post642.dist-info}/zip-safe +0 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
# Copyright (C) 2021 Bosutech XXI S.L.
|
2
|
+
#
|
3
|
+
# nucliadb is offered under the AGPL v3.0 and as commercial software.
|
4
|
+
# For commercial licensing, contact us at info@nuclia.com.
|
5
|
+
#
|
6
|
+
# AGPL:
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Affero General Public License as
|
9
|
+
# published by the Free Software Foundation, either version 3 of the
|
10
|
+
# License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Affero General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Affero General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
import base64
|
21
|
+
import binascii
|
22
|
+
|
23
|
+
import nacl.exceptions
|
24
|
+
import nacl.secret
|
25
|
+
import nacl.utils
|
26
|
+
|
27
|
+
from nucliadb_telemetry.metrics import Observer
|
28
|
+
|
29
|
+
|
30
|
+
class DecryptionError(Exception): ...
|
31
|
+
|
32
|
+
|
33
|
+
class DecryptionDataError(DecryptionError): ...
|
34
|
+
|
35
|
+
|
36
|
+
endecryptor_observer = Observer(
|
37
|
+
"endecryptor",
|
38
|
+
error_mappings={
|
39
|
+
"DecryptionError": DecryptionError,
|
40
|
+
"DecryptionDataError": DecryptionDataError,
|
41
|
+
},
|
42
|
+
labels={"operation": ""},
|
43
|
+
)
|
44
|
+
|
45
|
+
|
46
|
+
class EndecryptorUtility:
|
47
|
+
"""
|
48
|
+
Utility class for encryption and decryption of sensitive data using the nacl library.
|
49
|
+
"""
|
50
|
+
|
51
|
+
def __init__(self, secret_key: bytes):
|
52
|
+
try:
|
53
|
+
self.box = nacl.secret.SecretBox(secret_key)
|
54
|
+
except nacl.exceptions.TypeError as ex:
|
55
|
+
raise ValueError("Invalid secret key") from ex
|
56
|
+
|
57
|
+
@classmethod
|
58
|
+
def from_b64_encoded_secret_key(cls, encoded_secret_key: str):
|
59
|
+
try:
|
60
|
+
secret_key = base64.b64decode(encoded_secret_key)
|
61
|
+
except binascii.Error as ex:
|
62
|
+
raise ValueError("Invalid base64 encoding") from ex
|
63
|
+
return cls(secret_key=secret_key)
|
64
|
+
|
65
|
+
@endecryptor_observer.wrap({"operation": "encrypt"})
|
66
|
+
def encrypt(self, text: str) -> str:
|
67
|
+
text_bytes = text.encode()
|
68
|
+
encrypted = self.box.encrypt(text_bytes)
|
69
|
+
return encrypted.hex()
|
70
|
+
|
71
|
+
@endecryptor_observer.wrap({"operation": "decrypt"})
|
72
|
+
def decrypt(self, encrypted_text: str) -> str:
|
73
|
+
try:
|
74
|
+
encrypted = nacl.utils.EncryptedMessage.fromhex(encrypted_text)
|
75
|
+
except ValueError as ex:
|
76
|
+
raise DecryptionDataError("Error decrypting the message") from ex
|
77
|
+
try:
|
78
|
+
decrypted_bytes = self.box.decrypt(encrypted)
|
79
|
+
except nacl.exceptions.CryptoError as ex:
|
80
|
+
raise DecryptionError("Error decrypting the message") from ex
|
81
|
+
return decrypted_bytes.decode()
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Copyright (C) 2021 Bosutech XXI S.L.
|
2
|
+
#
|
3
|
+
# nucliadb is offered under the AGPL v3.0 and as commercial software.
|
4
|
+
# For commercial licensing, contact us at info@nuclia.com.
|
5
|
+
#
|
6
|
+
# AGPL:
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Affero General Public License as
|
9
|
+
# published by the Free Software Foundation, either version 3 of the
|
10
|
+
# License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Affero General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Affero General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
from typing import Optional
|
20
|
+
|
21
|
+
from pydantic import Field
|
22
|
+
from pydantic_settings import BaseSettings
|
23
|
+
|
24
|
+
|
25
|
+
class EncryptionSettings(BaseSettings):
|
26
|
+
encryption_secret_key: Optional[str] = Field(
|
27
|
+
default=None,
|
28
|
+
title="Encryption Secret Key",
|
29
|
+
description="""Secret key used for encryption and decryption of sensitive data in the database.
|
30
|
+
The key must be a 32-byte string, base64 encoded. You can generate a new key with the following unix command:
|
31
|
+
head -c 32 /dev/urandom | base64
|
32
|
+
""",
|
33
|
+
examples=[
|
34
|
+
"6TGjSkvX6qkFOo/BJKl5OY1fwJoWnMaSVI7VOJjU07Y=",
|
35
|
+
],
|
36
|
+
)
|
37
|
+
|
38
|
+
|
39
|
+
settings = EncryptionSettings()
|
nucliadb_utils/utilities.py
CHANGED
@@ -34,6 +34,8 @@ from nucliadb_utils.audit.stream import StreamAuditStorage
|
|
34
34
|
from nucliadb_utils.cache.nats import NatsPubsub
|
35
35
|
from nucliadb_utils.cache.pubsub import PubSubDriver
|
36
36
|
from nucliadb_utils.cache.settings import settings as cache_settings
|
37
|
+
from nucliadb_utils.encryption import EndecryptorUtility
|
38
|
+
from nucliadb_utils.encryption.settings import settings as encryption_settings
|
37
39
|
from nucliadb_utils.exceptions import ConfigurationError
|
38
40
|
from nucliadb_utils.indexing import IndexingUtility
|
39
41
|
from nucliadb_utils.nats import NatsConnectionManager
|
@@ -78,6 +80,7 @@ class Utility(str, Enum):
|
|
78
80
|
LOCAL_STORAGE = "local_storage"
|
79
81
|
NUCLIA_STORAGE = "nuclia_storage"
|
80
82
|
MAINDB_DRIVER = "driver"
|
83
|
+
ENDECRYPTOR = "endecryptor"
|
81
84
|
|
82
85
|
|
83
86
|
def get_utility(ident: Union[Utility, str]):
|
@@ -406,3 +409,19 @@ def has_feature(
|
|
406
409
|
if X_ACCOUNT_TYPE_HEADER in headers:
|
407
410
|
context["account_type"] = headers[X_ACCOUNT_TYPE_HEADER]
|
408
411
|
return get_feature_flags().enabled(name, default=default, context=context)
|
412
|
+
|
413
|
+
|
414
|
+
def get_endecryptor() -> EndecryptorUtility:
|
415
|
+
util = get_utility(Utility.ENDECRYPTOR)
|
416
|
+
if util is not None:
|
417
|
+
return util
|
418
|
+
if encryption_settings.encryption_secret_key is None:
|
419
|
+
raise ConfigurationError("Encryption secret key not configured")
|
420
|
+
try:
|
421
|
+
util = EndecryptorUtility.from_b64_encoded_secret_key(encryption_settings.encryption_secret_key)
|
422
|
+
except ValueError as ex:
|
423
|
+
raise ConfigurationError(
|
424
|
+
"Invalid encryption key. Must be a base64 encoded 32-byte string"
|
425
|
+
) from ex
|
426
|
+
set_utility(Utility.ENDECRYPTOR, util)
|
427
|
+
return util
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: nucliadb_utils
|
3
|
-
Version: 5.0.0.
|
3
|
+
Version: 5.0.0.post642
|
4
4
|
Home-page: https://nuclia.com
|
5
5
|
License: BSD
|
6
6
|
Classifier: Development Status :: 4 - Beta
|
@@ -23,8 +23,8 @@ Requires-Dist: PyNaCl
|
|
23
23
|
Requires-Dist: pyjwt >=2.4.0
|
24
24
|
Requires-Dist: memorylru >=1.1.2
|
25
25
|
Requires-Dist: mrflagly
|
26
|
-
Requires-Dist: nucliadb-protos >=5.0.0.
|
27
|
-
Requires-Dist: nucliadb-telemetry >=5.0.0.
|
26
|
+
Requires-Dist: nucliadb-protos >=5.0.0.post642
|
27
|
+
Requires-Dist: nucliadb-telemetry >=5.0.0.post642
|
28
28
|
Provides-Extra: cache
|
29
29
|
Requires-Dist: redis >=4.3.4 ; extra == 'cache'
|
30
30
|
Requires-Dist: orjson >=3.6.7 ; extra == 'cache'
|
@@ -16,7 +16,7 @@ nucliadb_utils/settings.py,sha256=AaOtQZVRqRcMnUyN1l1MpR10lANaDT2uPrbhmTyn6uk,76
|
|
16
16
|
nucliadb_utils/signals.py,sha256=JRNv2y9zLtBjOANBf7krGfDGfOc9qcoXZ6N1nKWS2FE,2674
|
17
17
|
nucliadb_utils/store.py,sha256=kQ35HemE0v4_Qg6xVqNIJi8vSFAYQtwI3rDtMsNy62Y,890
|
18
18
|
nucliadb_utils/transaction.py,sha256=mwcI3aIHAvU5KOGqd_Uz_d1XQzXhk_-NWY8NqU1lfb0,7307
|
19
|
-
nucliadb_utils/utilities.py,sha256=
|
19
|
+
nucliadb_utils/utilities.py,sha256=ABcv4PwRYlrFOFOJF-1TU8PVbmW548g7scs-dsEJDp0,14955
|
20
20
|
nucliadb_utils/audit/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
|
21
21
|
nucliadb_utils/audit/audit.py,sha256=dn5ZnCVQUlCcvdjzaORghbrjk9QgVGrtkfIftq30Bp8,2819
|
22
22
|
nucliadb_utils/audit/basic.py,sha256=NViey6mKbCXqRTLDBX2xNTcCg9I-2e4oB2xkekuhDvM,3392
|
@@ -26,6 +26,8 @@ nucliadb_utils/cache/exceptions.py,sha256=Zu-O_-0-yctOEgoDGI92gPzWfBMRrpiAyESA62
|
|
26
26
|
nucliadb_utils/cache/nats.py,sha256=-AjCfkFgKVdJUlGR0hT9JDSNkPVFg4S6w9eW-ZIcXPM,7037
|
27
27
|
nucliadb_utils/cache/pubsub.py,sha256=l8i_RwRf7OPzfmPy-gyn66xgYFs5aHidCIjEaU9VOHE,1654
|
28
28
|
nucliadb_utils/cache/settings.py,sha256=WVeHOE6Re5i4k2hUHdFKfkoL4n83v_Z6UPBK6GHYb8g,1059
|
29
|
+
nucliadb_utils/encryption/__init__.py,sha256=oav6jFOTGgmIen88sdmy-bCK-uj1tyDt2hr7lB2YKik,2690
|
30
|
+
nucliadb_utils/encryption/settings.py,sha256=yF2AW6c_mu0yWbBn1grAERDAqDvKIpXqQnwD0OFmROI,1467
|
29
31
|
nucliadb_utils/fastapi/__init__.py,sha256=itSI7dtTwFP55YMX4iK7JzdMHS5CQVUiB1XzQu4UBh8,833
|
30
32
|
nucliadb_utils/fastapi/openapi.py,sha256=b0pLuri0QuzQd0elDyOVXM42YYmES_cmT-jEfsQ1G6Y,1737
|
31
33
|
nucliadb_utils/fastapi/run.py,sha256=n6vOX64QqF1I5n4UlKnpm_ZJ24rmwfRGi-J9YMGpZzA,3631
|
@@ -58,8 +60,8 @@ nucliadb_utils/tests/indexing.py,sha256=YW2QhkhO9Q_8A4kKWJaWSvXvyQ_AiAwY1VylcfVQ
|
|
58
60
|
nucliadb_utils/tests/local.py,sha256=c3gZJJWmvOftruJkIQIwB3q_hh3uxEhqGIAVWim1Bbk,1343
|
59
61
|
nucliadb_utils/tests/nats.py,sha256=Tosonm9A9cusImyji80G4pgdXEHNVPaCLT5TbFK_ra0,7543
|
60
62
|
nucliadb_utils/tests/s3.py,sha256=YB8QqDaBXxyhHonEHmeBbRRDmvB7sTOaKBSi8KBGokg,2330
|
61
|
-
nucliadb_utils-5.0.0.
|
62
|
-
nucliadb_utils-5.0.0.
|
63
|
-
nucliadb_utils-5.0.0.
|
64
|
-
nucliadb_utils-5.0.0.
|
65
|
-
nucliadb_utils-5.0.0.
|
63
|
+
nucliadb_utils-5.0.0.post642.dist-info/METADATA,sha256=Pvc_Ts0moq5GdYijN-wBnOI7u5to8ZqGAdl4Vqwve1g,2078
|
64
|
+
nucliadb_utils-5.0.0.post642.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
|
65
|
+
nucliadb_utils-5.0.0.post642.dist-info/top_level.txt,sha256=fE3vJtALTfgh7bcAWcNhcfXkNPp_eVVpbKK-2IYua3E,15
|
66
|
+
nucliadb_utils-5.0.0.post642.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
67
|
+
nucliadb_utils-5.0.0.post642.dist-info/RECORD,,
|
File without changes
|
{nucliadb_utils-5.0.0.post641.dist-info → nucliadb_utils-5.0.0.post642.dist-info}/top_level.txt
RENAMED
File without changes
|
File without changes
|