Skip to content

Commit 3815a70

Browse files
committed
fix encrypted tests
1 parent 4ef6b84 commit 3815a70

File tree

6 files changed

+86
-27
lines changed

6 files changed

+86
-27
lines changed

.evergreen/run-tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ set -eux
66
/opt/python/3.10/bin/python3 -m venv venv
77
. venv/bin/activate
88
python -m pip install -U pip
9+
pip install ".[encryption]"
910
pip install -e .
1011

1112
# Install django and test dependencies

.github/workflows/mongodb_settings.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import os
22

3+
from pymongo.encryption_options import AutoEncryptionOpts
4+
35
from django_mongodb_backend import parse_uri
46

57
if mongodb_uri := os.getenv("MONGODB_URI"):
@@ -27,6 +29,35 @@
2729
},
2830
}
2931

32+
DATABASES["encrypted"] = {
33+
"ENGINE": "django_mongodb_backend",
34+
"NAME": "djangotests-encrypted",
35+
"OPTIONS": {
36+
"auto_encryption_opts": AutoEncryptionOpts(
37+
key_vault_namespace="my_encrypted_database.keyvault",
38+
kms_providers={"local": {"key": os.urandom(96)}},
39+
)
40+
},
41+
"KMS_PROVIDERS": {},
42+
"KMS_CREDENTIALS": {},
43+
}
44+
45+
46+
class EncryptedRouter:
47+
def allow_migrate(self, db, app_label, model_name=None, **hints):
48+
# The encryption_ app's models are only created in the encrypted database.
49+
if app_label == "encryption_":
50+
return db == "encrypted"
51+
# Don't create other app's models in the encrypted database.
52+
if db == "encrypted":
53+
return False
54+
return None
55+
56+
def kms_provider(self, model, **hints):
57+
return "local"
58+
59+
60+
DATABASE_ROUTERS = [EncryptedRouter()]
3061
DEFAULT_AUTO_FIELD = "django_mongodb_backend.fields.ObjectIdAutoField"
3162
PASSWORD_HASHERS = ("django.contrib.auth.hashers.MD5PasswordHasher",)
3263
SECRET_KEY = "django_tests_secret_key"

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
- name: install django-mongodb-backend
2929
run: |
3030
pip3 install --upgrade pip
31+
pip3 install ".[encryption]"
3132
pip3 install -e .
3233
- name: Checkout Django
3334
uses: actions/checkout@v4

.github/workflows/test-python.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
- name: install django-mongodb-backend
2929
run: |
3030
pip3 install --upgrade pip
31+
pip3 install ".[encryption]"
3132
pip3 install -e .
3233
- name: Checkout Django
3334
uses: actions/checkout@v4

tests/encryption_/routers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ class TestEncryptedRouter:
1010

1111
def allow_migrate(self, db, app_label, model_name=None, model=None, **hints):
1212
if model:
13-
return db == ("other" if has_encrypted_fields(model) else "default")
13+
return db == ("encrypted" if has_encrypted_fields(model) else "default")
1414
return db == "default"
1515

1616
def db_for_read(self, model, **hints):
1717
if has_encrypted_fields(model):
18-
return "other"
18+
return "encrypted"
1919
return "default"
2020

2121
db_for_write = db_for_read

tests/encryption_/tests.py

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,19 @@
2929
"bsonType": "string",
3030
"path": "cc_type",
3131
"queries": {"queryType": "equality"},
32-
"keyId": Binary(b" \x901\x89\x1f\xafAX\x9b*\xb1\xc7\xc5\xfdl\xa4", 4),
32+
# "keyId": Binary(b" \x901\x89\x1f\xafAX\x9b*\xb1\xc7\xc5\xfdl\xa4", 4),
3333
},
3434
{
3535
"bsonType": "long",
3636
"path": "cc_number",
3737
"queries": {"queryType": "equality"},
38-
"keyId": Binary(b"\x97\xb4\x9d\xb8\xd5\xa6Ay\x85\xfe\x00\xc0\xd4{\xa2\xff", 4),
38+
# "keyId": Binary(b"\x97\xb4\x9d\xb8\xd5\xa6Ay\x85\xfe\x00\xc0\xd4{\xa2\xff", 4),
3939
},
4040
{
4141
"bsonType": "decimal",
4242
"path": "account_balance",
4343
"queries": {"queryType": "range"},
44-
"keyId": Binary(b"\xcc\x01-s\xea\xd9B\x8d\x80\xd7\xf8!n\xc6\xf5U", 4),
44+
# "keyId": Binary(b"\xcc\x01-s\xea\xd9B\x8d\x80\xd7\xf8!n\xc6\xf5U", 4),
4545
},
4646
]
4747
},
@@ -51,31 +51,31 @@
5151
"bsonType": "string",
5252
"path": "ssn",
5353
"queries": {"queryType": "equality"},
54-
"keyId": Binary(b"\x14F\x89\xde\x8d\x04K7\xa9\x9a\xaf_\xca\x8a\xfb&", 4),
54+
# "keyId": Binary(b"\x14F\x89\xde\x8d\x04K7\xa9\x9a\xaf_\xca\x8a\xfb&", 4),
5555
},
5656
{
5757
"bsonType": "date",
5858
"path": "birth_date",
5959
"queries": {"queryType": "range"},
60-
"keyId": Binary(b"@\xdd\xb4\xd2%\xc2B\x94\xb5\x07\xbc(ER[s", 4),
60+
# "keyId": Binary(b"@\xdd\xb4\xd2%\xc2B\x94\xb5\x07\xbc(ER[s", 4),
6161
},
6262
{
6363
"bsonType": "binData",
6464
"path": "profile_picture",
6565
"queries": {"queryType": "equality"},
66-
"keyId": Binary(b"Q\xa2\xebc!\xecD,\x8b\xe4$\xb6ul9\x9a", 4),
66+
# "keyId": Binary(b"Q\xa2\xebc!\xecD,\x8b\xe4$\xb6ul9\x9a", 4),
6767
},
6868
{
6969
"bsonType": "int",
7070
"path": "patient_age",
7171
"queries": {"queryType": "range"},
72-
"keyId": Binary(b"\ro\x80\x1e\x8e1K\xde\xbc_\xc3bi\x95\xa6j", 4),
72+
# "keyId": Binary(b"\ro\x80\x1e\x8e1K\xde\xbc_\xc3bi\x95\xa6j", 4),
7373
},
7474
{
7575
"bsonType": "double",
7676
"path": "weight",
7777
"queries": {"queryType": "range"},
78-
"keyId": Binary(b"\x9b\xfd:n\xe1\xd0N\xdd\xb3\xe7e)\x06\xea\x8a\x1d", 4),
78+
# "keyId": Binary(b"\x9b\xfd:n\xe1\xd0N\xdd\xb3\xe7e)\x06\xea\x8a\x1d", 4),
7979
},
8080
]
8181
},
@@ -85,33 +85,50 @@
8585
"bsonType": "int",
8686
"path": "patient_id",
8787
"queries": {"queryType": "equality"},
88-
"keyId": Binary(b"\x8ft\x16:\x8a\x91D\xc7\x8a\xdf\xe5O\n[\xfd\\", 4),
88+
# "keyId": Binary(b"\x8ft\x16:\x8a\x91D\xc7\x8a\xdf\xe5O\n[\xfd\\", 4),
8989
},
9090
{
9191
"bsonType": "string",
9292
"path": "patient_name",
93-
"keyId": Binary(b"<\x9b\xba\xeb:\xa4@m\x93\x0e\x0c\xcaN\x03\xfb\x05", 4),
93+
# "keyId": Binary(b"<\x9b\xba\xeb:\xa4@m\x93\x0e\x0c\xcaN\x03\xfb\x05", 4),
9494
},
9595
{
9696
"bsonType": "string",
9797
"path": "patient_notes",
9898
"queries": {"queryType": "equality"},
99-
"keyId": Binary(b"\x01\xe7\xd1isnB$\xa9(gwO\xca\x10\xbd", 4),
99+
# "keyId": Binary(b"\x01\xe7\xd1isnB$\xa9(gwO\xca\x10\xbd", 4),
100100
},
101101
{
102102
"bsonType": "date",
103103
"path": "registration_date",
104104
"queries": {"queryType": "equality"},
105-
"keyId": Binary(b"F\xfb\xae\x82\xd5\x9a@\xee\xbfJ\xaf#\x9c:-I", 4),
105+
# "keyId": Binary(b"F\xfb\xae\x82\xd5\x9a@\xee\xbfJ\xaf#\x9c:-I", 4),
106106
},
107107
{
108108
"bsonType": "bool",
109109
"path": "is_active",
110110
"queries": {"queryType": "equality"},
111-
"keyId": Binary(b"\xb2\xb5\xc4K53A\xda\xb9V\xa6\xa9\x97\x94\xea;", 4),
111+
# "keyId": Binary(b"\xb2\xb5\xc4K53A\xda\xb9V\xa6\xa9\x97\x94\xea;", 4),
112112
},
113+
{"bsonType": "string", "path": "email", "queries": {"queryType": "equality"}},
113114
]
114115
},
116+
"encryption__patientportaluser": {
117+
"fields": [
118+
{"bsonType": "string", "path": "ip_address", "queries": {"queryType": "equality"}},
119+
{"bsonType": "string", "path": "url", "queries": {"queryType": "equality"}},
120+
]
121+
},
122+
"encryption__encryptednumbers": {
123+
"fields": [
124+
{"bsonType": "int", "path": "pos_bigint", "queries": {"queryType": "equality"}},
125+
{"bsonType": "int", "path": "pos_smallint", "queries": {"queryType": "equality"}},
126+
{"bsonType": "int", "path": "smallint", "queries": {"queryType": "equality"}},
127+
]
128+
},
129+
"encryption__appointment": {
130+
"fields": [{"bsonType": "date", "path": "time", "queries": {"queryType": "equality"}}]
131+
},
115132
}
116133

117134

@@ -144,7 +161,7 @@ def reload_module(module):
144161
)
145162
@override_settings(DATABASE_ROUTERS=[TestEncryptedRouter()])
146163
class EncryptedFieldTests(TransactionTestCase):
147-
databases = {"default", "other"}
164+
databases = {"default", "encrypted"}
148165
available_apps = ["django_mongodb_backend", "encryption_"]
149166

150167
def setUp(self):
@@ -259,7 +276,7 @@ def test_get_encrypted_fields_map(self):
259276
},
260277
}
261278
self.maxDiff = None
262-
with connections["other"].schema_editor() as editor:
279+
with connections["encrypted"].schema_editor() as editor:
263280
db_table = self.patient._meta.db_table
264281
self.assertEqual(
265282
editor._get_encrypted_fields_map(self.patient),
@@ -272,11 +289,18 @@ def test_show_schema_map(self):
272289
call_command(
273290
"showschemamap",
274291
"--database",
275-
"other",
292+
"encrypted",
276293
verbosity=0,
277294
stdout=out,
278295
)
279-
self.assertEqual(json_util.dumps(EXPECTED_ENCRYPTED_FIELDS_MAP, indent=2), out.getvalue())
296+
# Remove keyIds since they are different for each run.
297+
output_json = json_util.loads(out.getvalue())
298+
for table in output_json:
299+
for field in output_json[table]["fields"]:
300+
del field["keyId"]
301+
# TODO: probably we don't need to test the entire mapping, otherwise it
302+
# requires updates every time a new model or field is added!
303+
self.assertEqual(EXPECTED_ENCRYPTED_FIELDS_MAP, output_json)
280304

281305
def test_set_encrypted_fields_map_in_client(self):
282306
# TODO: Create new client with and without schema map provided then
@@ -315,16 +339,17 @@ def test_patientrecord(self):
315339
self.assertTrue(PatientRecord.objects.filter(weight__gte=175.0).exists())
316340

317341
# Test encrypted patient record in unencrypted database.
318-
conn_params = connections["other"].get_connection_params()
342+
conn_params = connections["encrypted"].get_connection_params()
319343
if conn_params.pop("auto_encryption_opts", False):
320344
# Call MongoClient instead of get_new_connection because
321345
# get_new_connection will return the encrypted connection
322346
# from the connection pool.
323-
connection = pymongo.MongoClient(**conn_params)
324-
patientrecords = connection["test_other"].encryption__patientrecord.find()
325-
ssn = patientrecords[0]["ssn"]
326-
self.assertTrue(isinstance(ssn, Binary))
327-
connection.close()
347+
with pymongo.MongoClient(**conn_params) as new_connection:
348+
patientrecords = new_connection[
349+
"test_django_encrypted"
350+
].encryption__patientrecord.find()
351+
ssn = patientrecords[0]["ssn"]
352+
self.assertTrue(isinstance(ssn, Binary))
328353

329354
def test_patient(self):
330355
self.assertEqual(
@@ -343,9 +368,9 @@ def test_patient(self):
343368
)
344369

345370
# Test decrypted patient record in encrypted database.
346-
patients = connections["other"].database.encryption__patient.find()
371+
patients = connections["encrypted"].database.encryption__patient.find()
347372
self.assertEqual(len(list(patients)), 1)
348-
records = connections["other"].database.encryption__patientrecord.find()
373+
records = connections["encrypted"].database.encryption__patientrecord.find()
349374
self.assertTrue("__safeContent__" in records[0])
350375

351376

0 commit comments

Comments
 (0)