Skip to content

Commit a566237

Browse files
committed
Code review fixes (1/x)
1 parent bf1e6d7 commit a566237

File tree

12 files changed

+110
-97
lines changed

12 files changed

+110
-97
lines changed

.github/workflows/mongodb_settings.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
),
4040
"directConnection": True,
4141
},
42-
"KMS_PROVIDERS": {},
4342
"KMS_CREDENTIALS": {},
4443
}
4544

django_mongodb_backend/management/commands/showencryptedfieldsmap.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,16 @@ def add_arguments(self, parser):
2626

2727
def handle(self, *args, **options):
2828
db = options["database"]
29-
create = options.get("create", False)
29+
create_data_keys = options.get("create_new_keys", False)
3030
connection = connections[db]
3131
client = connection.connection
3232
encrypted_fields_map = {}
3333
auto_encryption_opts = getattr(client._options, "auto_encryption_opts", None)
3434
for app_config in apps.get_app_configs():
3535
for model in router.get_migratable_models(app_config, db):
3636
if model_has_encrypted_fields(model):
37-
from_db = not create
3837
fields = connection.schema_editor()._get_encrypted_fields_map(
39-
model, client, auto_encryption_opts, from_db=from_db
38+
model, client, auto_encryption_opts, create_data_keys=create_data_keys
4039
)
4140
encrypted_fields_map[model._meta.db_table] = fields
4241
self.stdout.write(json_util.dumps(encrypted_fields_map, indent=2))

django_mongodb_backend/schema.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,6 @@ def _field_should_have_unique(self, field):
423423
# The _id column is automatically unique.
424424
return db_type and field.unique and field.column != "_id"
425425

426-
427426
def _create_collection(self, model):
428427
"""
429428
Create a collection for the model with the encrypted fields. If
@@ -456,7 +455,9 @@ def _create_collection(self, model):
456455
else:
457456
db.create_collection(db_table)
458457

459-
def _get_encrypted_fields_map(self, model, client, auto_encryption_opts, from_db=False):
458+
def _get_encrypted_fields_map(
459+
self, model, client, auto_encryption_opts, create_data_keys=False
460+
):
460461
connection = self.connection
461462
fields = model._meta.fields
462463
kms_provider = router.kms_provider(model)
@@ -474,7 +475,7 @@ def _get_encrypted_fields_map(self, model, client, auto_encryption_opts, from_db
474475
for field in fields:
475476
if getattr(field, "encrypted", False):
476477
key_alt_name = f"{db_table}_{field.column}"
477-
if from_db:
478+
if not create_data_keys:
478479
key_doc = key_vault_collection.find_one({"keyAltNames": key_alt_name})
479480
if not key_doc:
480481
raise ValueError(f"No key found in keyvault for keyAltName={key_alt_name}")

docs/source/howto/queryable-encryption.rst

Lines changed: 62 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,50 @@
22
Configuring Queryable Encryption
33
================================
44

5+
.. versionadded:: 5.2.0b2
6+
7+
.. admonition:: Queryable Encryption Compatibility
8+
9+
You can use Queryable Encryption on a MongoDB 7.0 or later replica
10+
set or sharded cluster, but not a standalone instance.
11+
:ref:`This table <manual:qe-compatibility-reference>` shows which MongoDB
12+
server products support which Queryable Encryption mechanisms.
13+
514
.. _server-side-queryable-encryption:
615

716
Configuring Queryable Encryption in Django is similar to
817
:doc:`manual:core/queryable-encryption/quick-start` but with some additional
918
steps required for Django.
1019

11-
Server-side Queryable Encryption
12-
--------------------------------
13-
14-
Server-side Queryable Encryption allows you to begin developing applications
15-
without needing to define the encrypted fields map at the time of connection
16-
to the database.
17-
18-
.. admonition:: What about client-side Queryable Encryption?
19-
20-
For configuration of client-side Queryable Encryption,
21-
please refer to this :ref:`see below <client-side-queryable-encryption>`.
22-
2320
Prerequisites
2421
-------------
2522

26-
In addition to :doc:`installing </intro/install>` and
27-
:doc:`configuring </intro/configure>` Django MongoDB Backend,
28-
you will need to install PyMongo with Queryable Encryption support::
23+
In addition to :doc:`installing </intro/install>` and :doc:`configuring
24+
</intro/configure>` Django MongoDB Backend, you will need to install some
25+
additional packages to use Queryable Encryption. This can be done with the
26+
optional dependency ``encryption`` in the ``django-mongodb-backend`` package.
2927

3028
pip install django-mongodb-backend[encryption]
3129

32-
.. admonition:: Queryable Encryption Compatibility
30+
.. _server-side-queryable-encryption-settings:
3331

34-
You can use Queryable Encryption on a MongoDB 7.0 or later replica
35-
set or sharded cluster, but not a standalone instance.
36-
:ref:`This table <manual:qe-compatibility-reference>` shows which MongoDB
37-
server products support which Queryable Encryption mechanisms.
32+
Server-side Queryable Encryption
33+
--------------------------------
3834

39-
.. _server-side-queryable-encryption-settings:
35+
Queryable Encryption is considered "server-side" when the encrypted fields map
36+
is not known at the time of connection to the database and this approach allows
37+
you to begin developing applications without needing to define the encrypted
38+
fields map at the time of connection to the database.
4039

4140
Settings
4241
--------
4342

44-
Queryable Encryption in Django requires the use of an additional encrypted
45-
database and Key Management Service (KMS) credentials as well as an encrypted
46-
database router. Here's how to set it up in your Django settings.
43+
Due to a limited set of
44+
:doc:`manual:core/queryable-encryption/reference/supported-operations`, a second
45+
encrypted database and corresponding database router are needed to use Queryable
46+
Encryption in Django, as well as a KMS provider and credentials.
4747

48-
::
48+
Here's how to set it up in your Django settings::
4949

5050
from django_mongodb_backend import parse_uri
5151
from pymongo.encryption_options import AutoEncryptionOpts
@@ -55,26 +55,28 @@ database router. Here's how to set it up in your Django settings.
5555
DATABASE_URL,
5656
db_name="my_database",
5757
),
58-
}
59-
60-
DATABASES["encrypted"] = {
61-
"ENGINE": "django_mongodb_backend",
62-
"NAME": "my_encrypted_database",
63-
"OPTIONS": {
64-
"auto_encryption_opts": AutoEncryptionOpts(
65-
key_vault_namespace="my_encrypted_database.keyvault",
66-
kms_providers={"local": {"key": os.urandom(96)}},
67-
),
68-
"directConnection": True,
69-
},
70-
"KMS_PROVIDERS": {},
71-
"KMS_CREDENTIALS": {},
58+
"encrypted": parse_uri(
59+
DATABASE_URL,
60+
options: {
61+
"auto_encryption_opts": AutoEncryptionOpts(
62+
key_vault_namespace="my_encrypted_database.keyvault",
63+
kms_providers={"local": {"key": os.urandom(96)}},
64+
),
65+
},
66+
db_name="my_encrypted_database",
67+
"KMS_CREDENTIALS": {},
68+
),
7269
}
7370

7471
class EncryptedRouter:
72+
"""
73+
A database router for an encrypted database to be used with a
74+
"patientdata" app that contains models with encrypted fields.
75+
"""
76+
7577
def allow_migrate(self, db, app_label, model_name=None, **hints):
76-
# The encryption_ app's models are only created in the encrypted database.
77-
if app_label == "encryption_":
78+
# The patientdata app's models are only created in the encrypted database.
79+
if app_label == "patientdata":
7880
return db == "encrypted"
7981
# Don't create other app's models in the encrypted database.
8082
if db == "encrypted":
@@ -87,7 +89,7 @@ database router. Here's how to set it up in your Django settings.
8789
DATABASE_ROUTERS = [EncryptedRouter()]
8890

8991
You are now ready to use server-side :doc:`Queryable Encryption
90-
</topics/queryable-encryption>` in your Django project.
92+
</topics/queryable-encryption>`.
9193

9294
.. admonition:: KMS providers and credentials
9395

@@ -100,37 +102,35 @@ You are now ready to use server-side :doc:`Queryable Encryption
100102
:doc:`manual:core/queryable-encryption/fundamentals/keys-key-vaults`
101103
for information on creating and managing data encryption keys.
102104

105+
You can also refer to the `Python Queryable Encryption Tutorial
106+
<https://github.com/mongodb/docs/tree/adad2b1ae41ec81a6e5682842850030813adc1e5/source/includes/qe-tutorials/python>`_.
107+
103108
.. _client-side-queryable-encryption:
104109

105110
Client-side Queryable Encryption
106111
--------------------------------
107112

108-
In the :ref:`section above <server-side-queryable-encryption-settings>`,
109-
server-side Queryable Encryption configuration is covered.
110-
111-
Client side Queryable Encryption configuration requires that the entire
112-
encrypted fields map be known at the time of client connection.
113+
Queryable Encryption is considered "client-side" when the encrypted fields map
114+
is known at the time of connection to the database. This approach can be used
115+
when you have finished development and you have a fixed set of encrypted fields
116+
that you want to use in your production environment.
113117

114118
Encrypted fields map
115119
~~~~~~~~~~~~~~~~~~~~
116120

117-
In addition to the
118-
:ref:`settings described in the how-to guide <server-side-queryable-encryption-settings>`,
119-
you will need to provide a ``encrypted_fields_map`` to the
120-
``AutoEncryptionOpts``.
121+
In addition to the :ref:`settings described in the how-to guide
122+
<server-side-queryable-encryption-settings>` you will need to provide a
123+
``encrypted_fields_map`` to the ``AutoEncryptionOpts``.
121124

122-
Fortunately, this is easy to do with Django MongoDB Backend. You can use
123-
the ``showencryptedfieldsmap`` management command to generate the schema map
124-
for your encrypted fields, and then use the results in your settings.
125-
126-
To generate the encrypted fields map, run the following command in your Django
127-
project::
125+
You can use the ``showencryptedfieldsmap`` management command to generate the
126+
schema map for your encrypted fields and then use the results in your settings::
128127

129128
python manage.py showencryptedfieldsmap
130129

131-
.. note:: The ``showencryptedfieldsmap`` command is only available if you
132-
have the ``django_mongodb_backend`` app included in the
133-
:setting:`INSTALLED_APPS` setting.
130+
.. admonition:: Didn't work?
131+
132+
If you get the error ``Unknown command: 'createcachecollection'``, ensure
133+
``"django_mongodb_backend"`` is in your :setting:`INSTALLED_APPS` setting.
134134

135135
Settings
136136
~~~~~~~~
@@ -162,6 +162,5 @@ Now include the generated schema map in your Django settings::
162162
163163
}
164164

165-
You are now ready to use client-side
166-
:doc:`Queryable Encryption </topics/queryable-encryption>`
167-
in your Django project.
165+
You are now ready to use client-side :doc:`Queryable Encryption
166+
</topics/queryable-encryption>`.

docs/source/ref/django-admin.rst

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,19 @@ Available commands
1717
``showencryptedfieldsmap``
1818
--------------------------
1919

20+
.. versionadded:: 5.2.0b2
21+
2022
.. django-admin:: showencryptedfieldsmap
2123

22-
Show mapping of models and their encrypted fields.
24+
This command shows the mapping of encrypted fields to attributes including
25+
data type, data keys and query types. Defaults to showing existing keys from
26+
the configured key vault.
2327

2428
.. django-admin-option:: --database DATABASE
2529

26-
Specifies the database to use.
27-
Defaults to ``default``.
30+
Specifies the database to use. Defaults to ``default``.
2831

2932
.. django-admin-option:: --create-new-keys
3033

31-
If specified, creates the data keys instead of getting them from the
32-
database.
34+
If specified, this option will create new encryption keys for use in
35+
production workflows.

docs/source/ref/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ API reference
1111
database
1212
django-admin
1313
utils
14+
settings

docs/source/ref/models/fields.rst

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,12 @@ These indexes use 0-based indexing.
415415
Encrypted fields
416416
----------------
417417

418-
Encrypted fields are used to store sensitive data with MongoDB's Queryable
419-
Encryption feature. They are subclasses of Django's built-in fields, and
420-
they encrypt the data before storing it in the database.
418+
.. versionadded:: 5.2.0b2
419+
420+
Encrypted fields are subclasses of Django's built-in fields and can be used to
421+
store sensitive data with MongoDB's :ref:`Queryable Encryption
422+
<server-side-queryable-encryption>` feature. They are subclasses of Django's
423+
built-in fields before storing it in the database.
421424

422425
+----------------------------------------+------------------------------------------------------+
423426
| Encrypted Field | Django Field |
@@ -459,13 +462,15 @@ they encrypt the data before storing it in the database.
459462

460463
.. admonition:: Unsupported fields
461464

462-
The following fields are supported by Django MongoDB Backend but are not supported by
463-
Queryable Encryption.
465+
The following fields are supported by Django MongoDB Backend but are not
466+
supported by Queryable Encryption.
464467

465-
:class:`~django.db.models.SlugField`
468+
:class:`~django.db.models.SlugField` - Queryable Encryption does not
469+
:doc:`support unique indexes on encrypted fields
470+
<manual:core/queryable-encryption/reference/limitations>`.
466471

467-
EncryptedFieldMixin
468-
-------------------
472+
``EncryptedFieldMixin``
473+
-----------------------
469474

470475
You can use the ``EncryptedFieldMixin`` to create your own encrypted fields. This mixin
471476
supports the use of a ``queries`` argument in the field definition to specify query type

docs/source/ref/settings.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
========
2+
Settings
3+
========
4+
5+
Core Settings
6+
=============
7+
8+
Here's a list of settings available in Django MongoDB Backend and their default
9+
values.

docs/source/topics/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ know:
99
:maxdepth: 2
1010

1111
embedded-models
12+
queryable-encryption
1213
transactions
1314
known-issues
14-
queryable-encryption

docs/source/topics/queryable-encryption.rst

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ Let's consider this example::
2020

2121

2222
class Patient(models.Model):
23-
ssn = EncryptedCharField(max_length=11, queries={"queryType":
24-
"equality"})
23+
ssn = EncryptedCharField(
24+
max_length=11, queries={"queryType": "equality"}
25+
)
2526

2627
def __str__(self):
2728
return self.ssn
@@ -39,11 +40,6 @@ unencrypted client connection, the patient data looks like this:
3940
ssn: Binary.createFromBase64('DkrbD67ejkt2u…', 6),
4041
}
4142
42-
.. admonition:: List of encrypted fields
43-
44-
See the full list of :ref:`encrypted fields <encrypted-fields>` in the
45-
:doc:`Model field reference </ref/models/fields>`.
46-
4743
You can query encrypted fields using a
4844
:ref:`manual:qe-supported-query-operators` which must be specified in the
4945
field definition. For example, to query the ``ssn`` field for equality, you
@@ -66,3 +62,10 @@ looks like this:
6662
ssn: '123-45-6789',
6763
__safeContent__: [b'\xe0)NOFB\x9a,\x08\xd7\xdd\xb8\xa6\xba$…']
6864
}
65+
66+
.. admonition:: List of encrypted fields
67+
68+
See the full list of :ref:`encrypted fields <encrypted-fields>` in the
69+
:doc:`/ref/models/fields`. Also see
70+
:doc:`manual:core/queryable-encryption/features` for an explanation of
71+
encrypted field data.

0 commit comments

Comments
 (0)