Skip to content

Commit 5bb54db

Browse files
committed
INTPYTHON-527 Add Queryable Encryption support
1 parent b8efc93 commit 5bb54db

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

django_mongodb_backend/utils.py

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from django.utils.functional import SimpleLazyObject
99
from django.utils.text import format_lazy
1010
from django.utils.version import get_version_tuple
11+
from pymongo.encryption_options import AutoEncryptionOpts
1112
from pymongo.uri_parser import parse_uri as pymongo_parse_uri
1213

1314

@@ -28,7 +29,52 @@ def check_django_compatability():
2829
)
2930

3031

31-
def parse_uri(uri, *, db_name=None, test=None):
32+
def get_auto_encryption_opts(crypt_shared_lib_path=None, kms_providers=None):
33+
key_vault_database_name = "encryption"
34+
key_vault_collection_name = "__keyVault"
35+
key_vault_namespace = f"{key_vault_database_name}.{key_vault_collection_name}"
36+
return AutoEncryptionOpts(
37+
key_vault_namespace=key_vault_namespace,
38+
kms_providers=kms_providers,
39+
crypt_shared_lib_path=crypt_shared_lib_path,
40+
)
41+
42+
43+
# This file is intended for local testing only.
44+
# The returned key is hard-coded and should NOT be used in production.
45+
46+
47+
def get_customer_master_key():
48+
"""
49+
Returns a 96-byte local master key for use with MongoDB Client-Side Field Level Encryption.
50+
51+
For local testing purposes only. In production, use a secure KMS like AWS, Azure, GCP, or KMIP.
52+
53+
Returns:
54+
bytes: A 96-byte key.
55+
"""
56+
# WARNING: This is a static key for testing only.
57+
# Generate with: os.urandom(96)
58+
return bytes.fromhex(
59+
"000102030405060708090a0b0c0d0e0f"
60+
"101112131415161718191a1b1c1d1e1f"
61+
"202122232425262728292a2b2c2d2e2f"
62+
"303132333435363738393a3b3c3d3e3f"
63+
"404142434445464748494a4b4c4d4e4f"
64+
"505152535455565758595a5b5c5d5e5f"
65+
)
66+
67+
68+
def get_kms_providers():
69+
"""
70+
Return the KMS providers for the MongoDB client.
71+
"""
72+
if not settings.KMS_PROVIDERS:
73+
raise ImproperlyConfigured("You must set KMS_PROVIDERS in your Django settings.")
74+
return settings.KMS_PROVIDERS
75+
76+
77+
def parse_uri(uri, *, db_name=None, test=None, options=None):
3278
"""
3379
Convert the given uri into a dictionary suitable for Django's DATABASES
3480
setting.
@@ -48,14 +94,17 @@ def parse_uri(uri, *, db_name=None, test=None):
4894
db_name = db_name or uri["database"]
4995
if not db_name:
5096
raise ImproperlyConfigured("You must provide the db_name parameter.")
97+
opts = uri.get("options")
98+
if options:
99+
opts = {**opts, **options}
51100
settings_dict = {
52101
"ENGINE": "django_mongodb_backend",
53102
"NAME": db_name,
54103
"HOST": host,
55104
"PORT": port,
56105
"USER": uri.get("username"),
57106
"PASSWORD": uri.get("password"),
58-
"OPTIONS": uri.get("options"),
107+
"OPTIONS": opts,
59108
}
60109
if "authSource" not in settings_dict["OPTIONS"] and uri["database"]:
61110
settings_dict["OPTIONS"]["authSource"] = uri["database"]

tests/backend_/utils/test_parse_uri.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from django.core.exceptions import ImproperlyConfigured
55
from django.test import SimpleTestCase
66

7-
from django_mongodb_backend import parse_uri
7+
from django_mongodb_backend import get_auto_encryption_opts, parse_uri
88

99

1010
class ParseURITests(SimpleTestCase):
@@ -94,3 +94,13 @@ def test_invalid_credentials(self):
9494
def test_no_scheme(self):
9595
with self.assertRaisesMessage(pymongo.errors.InvalidURI, "Invalid URI scheme"):
9696
parse_uri("cluster0.example.mongodb.net")
97+
98+
def test_options(self):
99+
settings_dict = parse_uri(
100+
"mongodb://cluster0.example.mongodb.net/myDatabase",
101+
options={"auto_encryption_opts": get_auto_encryption_opts()},
102+
)
103+
self.assertIsInstance(
104+
settings_dict["OPTIONS"]["auto_encryption_opts"],
105+
pymongo.encryption_options.AutoEncryptionOpts,
106+
)

0 commit comments

Comments
 (0)