Skip to content

Commit 13ed19a

Browse files
committed
Misc updates
- Add mongocryptd to atlas CI - Doc updates - Remove custom db_type, not needed after #414 - SupportsQueryableEncryptionTests require MongoDB 8 - Update test model names prefix and suffix
1 parent 324c959 commit 13ed19a

File tree

12 files changed

+275
-149
lines changed

12 files changed

+275
-149
lines changed

.github/workflows/encrypted_settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"auto_encryption_opts": AutoEncryptionOpts(
1111
key_vault_namespace="my_encrypted_database.keyvault",
1212
kms_providers={"local": {"key": os.urandom(96)}},
13-
crypt_shared_lib_path="lib/mongo_crypt_v1.so",
13+
# crypt_shared_lib_path="lib/mongo_crypt_v1.so",
1414
),
1515
"directConnection": True,
1616
},

.github/workflows/test-python-atlas.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,27 @@ jobs:
5656
- name: Start local Atlas
5757
working-directory: .
5858
run: bash .github/workflows/start_local_atlas.sh mongodb/mongodb-atlas-local:8.0.15
59+
60+
- name: Install mongosh
61+
run: |
62+
wget -q https://downloads.mongodb.com/compass/mongosh-2.2.10-linux-x64.tgz
63+
tar -xzf mongosh-*-linux-x64.tgz
64+
sudo cp mongosh-*-linux-x64/bin/mongosh /usr/local/bin/
65+
mongosh --version
66+
- name: Install mongocryptd from Enterprise tarball
67+
run: |
68+
curl -sSL -o mongodb-enterprise.tgz "https://downloads.mongodb.com/linux/mongodb-linux-x86_64-enterprise-ubuntu2204-8.0.15.tgz"
69+
tar -xzf mongodb-enterprise.tgz
70+
sudo cp mongodb-linux-x86_64-enterprise-ubuntu2204-8.0.15/bin/mongocryptd /usr/local/bin/
71+
- name: Start mongocryptd
72+
run: |
73+
nohup mongocryptd --logpath=/tmp/mongocryptd.log &
74+
- name: Verify MongoDB installation
75+
run: |
76+
mongosh --eval 'db.runCommand({ connectionStatus: 1 })'
77+
- name: Verify mongocryptd is running
78+
run: |
79+
pgrep mongocryptd
5980
- name: Run tests
6081
run: python3 django_repo/tests/runtests_.py
6182
permissions:

django_mongodb_backend/fields/encryption.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
class EncryptedEmbeddedModelField(EmbeddedModelField):
77
encrypted = True
88

9-
def db_type(self, connection):
10-
return "object"
11-
129

1310
class EncryptedFieldMixin:
1411
encrypted = True

docs/howto/queryable-encryption.rst

Lines changed: 144 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Encryption in your Django project.
1414
.. admonition:: MongoDB requirements
1515

1616
Queryable Encryption can be used with MongoDB replica sets or sharded
17-
clusters running version 7.0 or later. Standalone instances are not
17+
clusters running version 8.0 or later. Standalone instances are not
1818
supported. The following table summarizes which MongoDB server products
1919
support each Queryable Encryption mechanism.
2020

@@ -51,21 +51,36 @@ encryption keys.
5151
5252
import os
5353
54-
from django_mongodb_backend import parse_uri
5554
from pymongo.encryption_options import AutoEncryptionOpts
5655
5756
DATABASES = {
58-
# ...
59-
"encrypted": parse_uri(
60-
DATABASE_URL,
61-
options={
57+
"default": {
58+
"ENGINE": "django_mongodb_backend",
59+
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
60+
"NAME": "my_database",
61+
"USER": "my_user",
62+
"PASSWORD": "my_password",
63+
"PORT": 27017,
64+
"OPTIONS": {
65+
"retryWrites": "true",
66+
"w": "majority",
67+
"tls": "false",
68+
},
69+
},
70+
"encrypted": {
71+
"ENGINE": "django_mongodb_backend",
72+
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
73+
"NAME": "encrypted",
74+
"USER": "my_user",
75+
"PASSWORD": "my_password",
76+
"PORT": 27017,
77+
"OPTIONS": {
6278
"auto_encryption_opts": AutoEncryptionOpts(
63-
key_vault_namespace="keyvault.keyvault",
79+
key_vault_namespace="encrypted.keyvault",
6480
kms_providers={"local": {"key": os.urandom(96)}},
6581
)
6682
},
67-
db_name="encrypted",
68-
),
83+
},
6984
}
7085
7186
Configuring the ``DATABASE_ROUTERS`` setting
@@ -88,10 +103,15 @@ configure a custom router for Queryable Encryption:
88103
Encryption.
89104
"""
90105
106+
def db_for_read(self, model, **hints):
107+
if model._meta.app_label == "myapp":
108+
return "encrypted"
109+
return None
110+
111+
db_for_write = db_for_read
112+
91113
def allow_migrate(self, db, app_label, model_name=None, **hints):
92-
# The patientdata app's models are only created in the encrypted
93-
# database.
94-
if app_label == "patientdata":
114+
if app_label == "myapp":
95115
return db == "encrypted"
96116
# Don't create other app's models in the encrypted database.
97117
if db == "encrypted":
@@ -132,15 +152,19 @@ Example of KMS configuration with AWS KMS:
132152

133153
.. code-block:: python
134154
135-
from django_mongodb_backend import parse_uri
136155
from pymongo.encryption_options import AutoEncryptionOpts
137156
138157
DATABASES = {
139-
"encrypted": parse_uri(
140-
DATABASE_URL,
141-
options={
158+
"encrypted": {
159+
"ENGINE": "django_mongodb_backend",
160+
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
161+
"NAME": "encrypted",
162+
"USER": "my_user",
163+
"PASSWORD": "my_password",
164+
"PORT": 27017,
165+
"OPTIONS": {
142166
"auto_encryption_opts": AutoEncryptionOpts(
143-
key_vault_namespace="keyvault.keyvault",
167+
key_vault_namespace="encrypted.keyvault",
144168
kms_providers={
145169
"aws": {
146170
"accessKeyId": "your-access-key-id",
@@ -149,14 +173,12 @@ Example of KMS configuration with AWS KMS:
149173
},
150174
)
151175
},
152-
db_name="encrypted",
153-
),
154-
}
155-
156-
DATABASES["encrypted"]["KMS_CREDENTIALS"] = {
157-
"aws": {
158-
"key": os.getenv("AWS_KEY_ARN", ""),
159-
"region": os.getenv("AWS_KEY_REGION", ""),
176+
"KMS_CREDENTIALS": {
177+
"aws": {
178+
"key": os.getenv("AWS_KEY_ARN", ""),
179+
"region": os.getenv("AWS_KEY_REGION", ""),
180+
},
181+
},
160182
},
161183
}
162184
@@ -208,6 +230,57 @@ If you do not want to use the data keys created by Django MongoDB Backend (when
208230
In this scenario, Django MongoDB Backend will use the newly created data keys
209231
to create collections for models with encrypted fields.
210232

233+
Here is an example of how to configure the
234+
``encrypted_fields_map`` in your Django settings:
235+
236+
.. code-block:: python
237+
238+
from pymongo.encryption_options import AutoEncryptionOpts
239+
from bson import json_util
240+
241+
DATABASES = {
242+
"encrypted": {
243+
"ENGINE": "django_mongodb_backend",
244+
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
245+
"NAME": "encrypted",
246+
"USER": "my_user",
247+
"PASSWORD": "my_password",
248+
"PORT": 27017,
249+
"OPTIONS": {
250+
"auto_encryption_opts": AutoEncryptionOpts(
251+
key_vault_namespace="encrypted.keyvault",
252+
kms_providers={
253+
"aws": {
254+
"accessKeyId": "your-access-key-id",
255+
"secretAccessKey": "your-secret-access-key",
256+
}
257+
},
258+
encrypted_fields_map=json_util.loads(
259+
"""{
260+
"encrypt_patient": {
261+
"fields": [
262+
{
263+
"bsonType": "string",
264+
"path": "patient_record.ssn",
265+
"keyId": {
266+
"$binary": {
267+
"base64": "2MA29LaARIOqymYHGmi2mQ==",
268+
"subType": "04"
269+
}
270+
},
271+
"queries": {
272+
"queryType": "equality"
273+
}
274+
},
275+
]
276+
}
277+
}"""
278+
),
279+
)
280+
},
281+
},
282+
}
283+
211284
Configuring the Automatic Encryption Shared Library
212285
===================================================
213286

@@ -218,25 +291,62 @@ to perform automatic encryption.
218291
You can :ref:`download the shared library
219292
<manual:qe-csfle-shared-library-download>` from the
220293
:ref:`manual:enterprise-official-packages` and configure it in your Django
221-
settings as follows:
294+
settings using the ``crypt_shared_lib_path`` option in
295+
:class:`pymongo.encryption_options.AutoEncryptionOpts`. The following example
296+
shows how to configure the shared library in your Django settings:
222297

223298
.. code-block:: python
224299
225-
from django_mongodb_backend import parse_uri
226300
from pymongo.encryption_options import AutoEncryptionOpts
227301
228302
DATABASES = {
229-
"encrypted": parse_uri(
230-
DATABASE_URL,
231-
options={
303+
"encrypted": {
304+
"ENGINE": "django_mongodb_backend",
305+
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
306+
"NAME": "encrypted",
307+
"USER": "my_user",
308+
"PASSWORD": "my_password",
309+
"PORT": 27017,
310+
"OPTIONS": {
232311
"auto_encryption_opts": AutoEncryptionOpts(
233-
key_vault_namespace="keyvault.keyvault",
234-
kms_providers={"local": {"key": os.urandom(96)}},
312+
key_vault_namespace="encrypted.keyvault",
313+
kms_providers={
314+
"aws": {
315+
"accessKeyId": "your-access-key-id",
316+
"secretAccessKey": "your-secret-access-key",
317+
}
318+
},
319+
encrypted_fields_map=json_util.loads(
320+
"""{
321+
"encrypt_patient": {
322+
"fields": [
323+
{
324+
"bsonType": "string",
325+
"path": "patient_record.ssn",
326+
"keyId": {
327+
"$binary": {
328+
"base64": "2MA29LaARIOqymYHGmi2mQ==",
329+
"subType": "04"
330+
}
331+
},
332+
"queries": {
333+
"queryType": "equality"
334+
}
335+
},
336+
]
337+
}
338+
}"""
339+
),
235340
crypt_shared_lib_path="/path/to/mongo_crypt_shared_v1.dylib",
236341
)
237342
},
238-
db_name="encrypted",
239-
),
343+
"KMS_CREDENTIALS": {
344+
"aws": {
345+
"key": os.getenv("AWS_KEY_ARN", ""),
346+
"region": os.getenv("AWS_KEY_REGION", ""),
347+
},
348+
},
349+
},
240350
}
241351
242352
You are now ready to :doc:`start developing applications

docs/ref/django-admin.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Available commands
1717
``showencryptedfieldsmap``
1818
--------------------------
1919

20-
.. versionadded:: 5.2.2
20+
.. versionadded:: 5.2.3
2121

2222
.. django-admin:: showencryptedfieldsmap
2323

docs/ref/models/encrypted-fields.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Django MongoDB Backend supports :doc:`manual:core/queryable-encryption`.
99
See :doc:`/howto/queryable-encryption` for more information on how to use
1010
Queryable Encryption with Django MongoDB Backend.
1111

12-
See the :doc:`Queryable Encryption topic </topics/queryable-encryption>` for
12+
See the :doc:`/topics/queryable-encryption` topic guide for
1313
more information on developing applications with Queryable Encryption.
1414

1515
The following fields are supported by Django MongoDB Backend for use with

docs/topics/queryable-encryption.rst

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ For example, to find a patient by their SSN, you can do the following::
106106
'Bob'
107107

108108

109-
QuerySet Limitations
109+
QuerySet limitations
110110
~~~~~~~~~~~~~~~~~~~~
111111

112112
When using Django QuerySets with MongoDB Queryable Encryption, it’s important to
@@ -128,8 +128,6 @@ be done client-side after decryption. Key limitations include:
128128
- **No joins on encrypted fields** – Filtering across relationships using
129129
encrypted foreign keys is unsupported because matching must happen
130130
client-side.
131-
- **Admin/debug limitations** – You’ll need to integrate client-side decryption
132-
for Django admin or tools, otherwise you’ll see ciphertext.
133131

134132
In short, when working with Queryable Encryption, design your queries to use
135133
exact matches only on encrypted fields, and plan to handle any sorting or

tests/backend_/test_features.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,24 +69,24 @@ def non_enterprise_response(command):
6969
raise Exception("Unexpected command")
7070

7171
def test_supported_on_atlas(self):
72-
"""Supported on MongoDB 7.0+ Atlas replica set or sharded cluster."""
72+
"""Supported on MongoDB 8.0+ Atlas replica set or sharded cluster."""
7373
with (
7474
patch(
7575
"pymongo.synchronous.database.Database.command", wraps=self.non_enterprise_response
7676
),
7777
patch("django.db.connection.features.supports_atlas_search", True),
7878
patch("django.db.connection.features._supports_transactions", True),
79-
patch("django.db.connection.features.is_mongodb_7_0", True),
79+
patch("django.db.connection.features.is_mongodb_8_0", True),
8080
):
8181
self.assertIs(connection.features.supports_queryable_encryption, True)
8282

8383
def test_supported_on_enterprise(self):
84-
"""Supported on MongoDB 7.0+ Enterprise replica set or sharded cluster."""
84+
"""Supported on MongoDB 8.0+ Enterprise replica set or sharded cluster."""
8585
with (
8686
patch("pymongo.synchronous.database.Database.command", wraps=self.enterprise_response),
8787
patch("django.db.connection.features.supports_atlas_search", False),
8888
patch("django.db.connection.features._supports_transactions", True),
89-
patch("django.db.connection.features.is_mongodb_7_0", True),
89+
patch("django.db.connection.features.is_mongodb_8_0", True),
9090
):
9191
self.assertIs(connection.features.supports_queryable_encryption, True)
9292

@@ -98,7 +98,7 @@ def test_atlas_or_enterprise_required(self):
9898
),
9999
patch("django.db.connection.features.supports_atlas_search", False),
100100
patch("django.db.connection.features._supports_transactions", True),
101-
patch("django.db.connection.features.is_mongodb_7_0", True),
101+
patch("django.db.connection.features.is_mongodb_8_0", True),
102102
):
103103
self.assertIs(connection.features.supports_queryable_encryption, False)
104104

@@ -111,16 +111,16 @@ def test_transactions_required(self):
111111
patch("pymongo.synchronous.database.Database.command", wraps=self.enterprise_response),
112112
patch("django.db.connection.features.supports_atlas_search", False),
113113
patch("django.db.connection.features._supports_transactions", False),
114-
patch("django.db.connection.features.is_mongodb_7_0", True),
114+
patch("django.db.connection.features.is_mongodb_8_0", True),
115115
):
116116
self.assertIs(connection.features.supports_queryable_encryption, False)
117117

118-
def test_mongodb_7_0_required(self):
119-
"""Not supported on MongoDB < 7.0"""
118+
def test_mongodb_8_0_required(self):
119+
"""Not supported on MongoDB < 8.0"""
120120
with (
121121
patch("pymongo.synchronous.database.Database.command", wraps=self.enterprise_response),
122122
patch("django.db.connection.features.supports_atlas_search", False),
123123
patch("django.db.connection.features._supports_transactions", True),
124-
patch("django.db.connection.features.is_mongodb_7_0", False),
124+
patch("django.db.connection.features.is_mongodb_8_0", False),
125125
):
126126
self.assertIs(connection.features.supports_queryable_encryption, False)

0 commit comments

Comments
 (0)