Skip to content

Commit 5f01a82

Browse files
aclark4lifetimgraham
authored andcommitted
Update docs
1 parent 0154ca4 commit 5f01a82

File tree

3 files changed

+125
-138
lines changed

3 files changed

+125
-138
lines changed

docs/howto/queryable-encryption.rst

Lines changed: 98 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,36 @@ Installation
2424
============
2525

2626
In addition to the :doc:`installation </intro/install>` and :doc:`configuration
27-
</intro/configure>` steps for Django MongoDB Backend, Queryable
28-
Encryption requires encryption support and a Key Management Service (KMS).
27+
</intro/configure>` steps required to use Django MongoDB Backend, Queryable
28+
Encryption has additional dependencies. You can install these dependencies
29+
by using the ``encryption`` extra when installing ``django-mongodb-backend``:
2930

30-
You can install encryption support with the following command::
31+
.. code-block:: console
3132
32-
pip install django-mongodb-backend[encryption]
33+
$ pip install django-mongodb-backend[encryption]
3334
3435
.. _qe-configuring-databases-setting:
3536

3637
Configuring the ``DATABASES`` setting
3738
=====================================
3839

39-
In addition to :ref:`configuring-databases-setting`, you must also configure an
40-
encrypted database in your :setting:`django:DATABASES` setting.
40+
In addition to the :ref:`database settings <configuring-databases-setting>`
41+
required to use Django MongoDB Backend, Queryable Encryption requires you to
42+
configure a separate encrypted database connection in your
43+
:setting:`django:DATABASES` setting.
4144

42-
This database will be used to store encrypted fields in your models. The
43-
following example shows how to configure an encrypted database using the
44-
:class:`AutoEncryptionOpts <pymongo.encryption_options.AutoEncryptionOpts>` from the
45-
:mod:`encryption_options <pymongo.encryption_options>` module.
45+
.. admonition:: Encrypted database
4646

47-
This example uses a local KMS provider and a key vault namespace for storing
48-
encryption keys.
47+
An encrypted database is a separate database connection in your
48+
:setting:`django:DATABASES` setting that is configured to use PyMongo's
49+
:class:`automatic encryption
50+
<pymongo.encryption_options.AutoEncryptionOpts>`.
51+
52+
The following example shows how to
53+
configure an encrypted database using the :class:`AutoEncryptionOpts
54+
<pymongo.encryption_options.AutoEncryptionOpts>` from the
55+
:mod:`encryption_options <pymongo.encryption_options>` module with a local KMS
56+
provider and encryption keys stored in the ``encryption.__keyVault`` collection.
4957

5058
.. code-block:: python
5159
@@ -58,19 +66,12 @@ encryption keys.
5866
"ENGINE": "django_mongodb_backend",
5967
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
6068
"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+
# ...
6970
},
7071
"encrypted": {
7172
"ENGINE": "django_mongodb_backend",
7273
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
73-
"NAME": "encrypted",
74+
"NAME": "my_database_encrypted",
7475
"USER": "my_user",
7576
"PASSWORD": "my_password",
7677
"PORT": 27017,
@@ -83,55 +84,69 @@ encryption keys.
8384
},
8485
}
8586
87+
.. admonition:: Local KMS provider key
88+
89+
In the example above, a random key is generated for the local KMS provider
90+
using ``os.urandom(96)``. In a production environment, you should securely
91+
:ref:`store and manage your encryption keys
92+
<manual:qe-fundamentals-kms-providers>`.
93+
8694
.. _qe-configuring-database-routers-setting:
8795

8896
Configuring the ``DATABASE_ROUTERS`` setting
8997
============================================
9098

91-
Similar to :ref:`configuring-database-routers-setting` for using :doc:`embedded
92-
models </topics/embedded-models>`, to use Queryable Encryption you must also
93-
configure the :setting:`django:DATABASE_ROUTERS` setting to route queries to the
94-
encrypted database.
99+
Similar to configuring the :ref:`DATABASE_ROUTERS
100+
<configuring-database-routers-setting>` setting for
101+
:doc:`embedded models </topics/embedded-models>`, Queryable Encryption
102+
requires a :setting:`DATABASE_ROUTERS <django:DATABASE_ROUTERS>` setting to
103+
route database operations to the encrypted database.
95104

96-
This is done by adding a custom router that routes queries to the encrypted
97-
database based on the model's metadata. The following example shows how to
98-
configure a custom router for Queryable Encryption:
105+
The following example shows how to configure a router for the "myapp"
106+
application that routes database operations to the encrypted database for all
107+
models in that application. The router also specifies the :ref:`KMS provider
108+
<qe-configuring-kms>` to use.
99109

100110
.. code-block:: python
101111
112+
# myapp/routers.py
102113
class EncryptedRouter:
103-
"""
104-
A router for routing queries to the encrypted database for Queryable
105-
Encryption.
106-
"""
107-
108-
def db_for_read(self, model, **hints):
109-
if model._meta.app_label == "myapp":
110-
return "encrypted"
111-
return None
112-
113-
db_for_write = db_for_read
114-
115114
def allow_migrate(self, db, app_label, model_name=None, **hints):
116115
if app_label == "myapp":
117116
return db == "encrypted"
118-
# Don't create other app's models in the encrypted database.
117+
# Prevent migrations on the encrypted database for other apps
119118
if db == "encrypted":
120119
return False
121120
return None
122121
122+
def db_for_read(self, model, **hints):
123+
if model._meta.app_label == "myapp":
124+
return "encrypted"
125+
return None
126+
123127
def kms_provider(self, model, **hints):
124128
return "local"
125129
130+
db_for_write = db_for_read
131+
132+
Then in your Django settings, add the custom database router to the
133+
:setting:`django:DATABASE_ROUTERS` setting:
126134

127-
DATABASE_ROUTERS = [EncryptedRouter]
135+
.. code-block:: python
136+
137+
# settings.py
138+
DATABASE_ROUTERS = ["myapp.routers.EncryptedRouter"]
128139
129140
.. _qe-configuring-kms:
130141

131142
Configuring the Key Management Service (KMS)
132143
============================================
133144

134-
To use Queryable Encryption, you must configure a Key Management Service (KMS).
145+
To use Queryable Encryption, you must configure a Key Management Service (KMS)
146+
to store and manage your encryption keys. Django MongoDB Backend allows you to
147+
configure multiple KMS providers and select the appropriate provider for each
148+
model using a custom database router.
149+
135150
The KMS is responsible for managing the encryption keys used to encrypt and
136151
decrypt data. The following table summarizes the available KMS configuration
137152
options followed by an example of how to use them.
@@ -142,38 +157,33 @@ options followed by an example of how to use them.
142157
| | :setting:`django:DATABASES` setting. |
143158
+-------------------------------------------------------------------------+--------------------------------------------------------+
144159
| :class:`kms_providers <pymongo.encryption_options.AutoEncryptionOpts>` | A dictionary of KMS provider credentials used to |
145-
| | access the KMS with |
146-
| | :setting:`KMS_CREDENTIALS <DATABASE-KMS-CREDENTIALS>`. |
160+
| | access the KMS with ``kms_provider``. |
147161
+-------------------------------------------------------------------------+--------------------------------------------------------+
148-
| ``kms_provider`` | A single KMS provider name |
162+
| :ref:`kms_provider <qe-configuring-database-routers-setting>` | A single KMS provider name |
149163
| | configured in your custom database |
150164
| | router. |
151165
+-------------------------------------------------------------------------+--------------------------------------------------------+
152166

153-
Example of KMS configuration with AWS KMS:
167+
Example of KMS configuration with ``aws`` in your :class:`kms_providers
168+
<pymongo.encryption_options.AutoEncryptionOpts>` setting:
154169

155170
.. code-block:: python
156171
157172
from pymongo.encryption_options import AutoEncryptionOpts
158173
159174
DATABASES = {
160175
"encrypted": {
161-
"ENGINE": "django_mongodb_backend",
162-
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
163-
"NAME": "encrypted",
164-
"USER": "my_user",
165-
"PASSWORD": "my_password",
166-
"PORT": 27017,
176+
# ...
167177
"OPTIONS": {
168178
"auto_encryption_opts": AutoEncryptionOpts(
169-
key_vault_namespace="encryption.__keyVault",
179+
# ...
170180
kms_providers={
171181
"aws": {
172182
"accessKeyId": "your-access-key-id",
173183
"secretAccessKey": "your-secret-access-key",
174-
}
184+
},
175185
},
176-
)
186+
),
177187
},
178188
"KMS_CREDENTIALS": {
179189
"aws": {
@@ -184,6 +194,10 @@ Example of KMS configuration with AWS KMS:
184194
},
185195
}
186196
197+
In your :ref:`custom database router <qe-configuring-database-routers-setting>`,
198+
specify the KMS provider to use for the models in your application:
199+
200+
.. code-block:: python
187201
188202
class EncryptedRouter:
189203
# ...
@@ -192,25 +206,25 @@ Example of KMS configuration with AWS KMS:
192206
193207
.. _qe-configuring-encrypted-fields-map:
194208

195-
Configuring the ``encrypted_fields_map``
196-
========================================
209+
Configuring the ``encrypted_fields_map`` option
210+
===============================================
197211

198-
When you :ref:`configure an encrypted database connection
199-
<qe-configuring-databases-setting>` without specifying an
212+
When you configure the :ref:`DATABASES <qe-configuring-databases-setting>`
213+
setting for Queryable Encryption *without* specifying an
200214
``encrypted_fields_map``, Django MongoDB Backend will create encrypted
201-
collections for you when you run ``python manage.py migrate --database
202-
encrypted``.
215+
collections, including encryption keys, when you :ref:`run migrations for models
216+
that have encrypted fields <qe-migrations>`.
203217

204-
Encryption keys for encrypted fields are stored in the key vault
205-
:ref:`specified in the Django settings <qe-configuring-kms>`. To see the keys
206-
created by Django MongoDB Backend, along with the entire schema, you can run the
218+
Encryption keys for encrypted fields are stored in the key vault specified in
219+
the :ref:`DATABASES <qe-configuring-kms>` setting. To see the keys created by
220+
Django MongoDB Backend, along with the entire schema, you can run the
207221
:djadmin:`showencryptedfieldsmap` command::
208222

209223
$ python manage.py showencryptedfieldsmap --database encrypted
210224

211-
Use the output of the :djadmin:`showencryptedfieldsmap` command to set the
212-
``encrypted_fields_map`` in
213-
:class:`pymongo.encryption_options.AutoEncryptionOpts` in your Django settings.
225+
Use the output of :djadmin:`showencryptedfieldsmap` to set the
226+
``encrypted_fields_map`` in :class:`AutoEncryptionOpts
227+
<pymongo.encryption_options.AutoEncryptionOpts>` in your Django settings.
214228

215229
.. code-block:: python
216230
@@ -219,21 +233,10 @@ Use the output of the :djadmin:`showencryptedfieldsmap` command to set the
219233
220234
DATABASES = {
221235
"encrypted": {
222-
"ENGINE": "django_mongodb_backend",
223-
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
224-
"NAME": "encrypted",
225-
"USER": "my_user",
226-
"PASSWORD": "my_password",
227-
"PORT": 27017,
236+
# ...
228237
"OPTIONS": {
229238
"auto_encryption_opts": AutoEncryptionOpts(
230-
key_vault_namespace="encryption.__keyVault",
231-
kms_providers={
232-
"aws": {
233-
"accessKeyId": "your-access-key-id",
234-
"secretAccessKey": "your-secret-access-key",
235-
}
236-
},
239+
# ...
237240
encrypted_fields_map=json_util.loads(
238241
"""{
239242
"encrypt_patient": {
@@ -260,6 +263,13 @@ Use the output of the :djadmin:`showencryptedfieldsmap` command to set the
260263
},
261264
}
262265
266+
267+
.. admonition:: Security consideration
268+
269+
Supplying an encrypted fields map provides more security than relying on an
270+
encrypted fields map obtained from the server. It protects against a
271+
malicious server advertising a false encrypted fields map.
272+
263273
Configuring the Automatic Encryption Shared Library
264274
===================================================
265275

@@ -275,60 +285,25 @@ You can :ref:`download the shared library
275285
<manual:qe-csfle-shared-library-download>` from the
276286
:ref:`manual:enterprise-official-packages` and configure it in your Django
277287
settings using the ``crypt_shared_lib_path`` option in
278-
:class:`pymongo.encryption_options.AutoEncryptionOpts`. The following example
279-
shows how to configure the shared library in your Django settings:
288+
:class:`AutoEncryptionOpts <pymongo.encryption_options.AutoEncryptionOpts>`.
289+
290+
The following example shows how to configure the shared library in your Django
291+
settings:
280292

281293
.. code-block:: python
282294
283295
from pymongo.encryption_options import AutoEncryptionOpts
284296
285297
DATABASES = {
286298
"encrypted": {
287-
"ENGINE": "django_mongodb_backend",
288-
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
289-
"NAME": "encrypted",
290-
"USER": "my_user",
291-
"PASSWORD": "my_password",
292-
"PORT": 27017,
299+
# ...
293300
"OPTIONS": {
294301
"auto_encryption_opts": AutoEncryptionOpts(
295-
key_vault_namespace="encryption.__keyVault",
296-
kms_providers={
297-
"aws": {
298-
"accessKeyId": "your-access-key-id",
299-
"secretAccessKey": "your-secret-access-key",
300-
}
301-
},
302-
encrypted_fields_map=json_util.loads(
303-
"""{
304-
"encrypt_patient": {
305-
"fields": [
306-
{
307-
"bsonType": "string",
308-
"path": "patient_record.ssn",
309-
"keyId": {
310-
"$binary": {
311-
"base64": "2MA29LaARIOqymYHGmi2mQ==",
312-
"subType": "04"
313-
}
314-
},
315-
"queries": {
316-
"queryType": "equality"
317-
}
318-
},
319-
]
320-
}
321-
}"""
322-
),
302+
# ...
323303
crypt_shared_lib_path="/path/to/mongo_crypt_shared_v1.dylib",
324304
)
325305
},
326-
"KMS_CREDENTIALS": {
327-
"aws": {
328-
"key": os.getenv("AWS_KEY_ARN", ""),
329-
"region": os.getenv("AWS_KEY_REGION", ""),
330-
},
331-
},
306+
# ...
332307
},
333308
}
334309

docs/ref/models/encrypted-fields.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ for use with Queryable Encryption.
7272
| ``EncryptedObjectIdField`` | :class:`~.fields.ObjectIdField` |
7373
+----------------------------------------+------------------------------------------------------+
7474

75-
The following fields are supported by Django MongoDB Backend but not by
76-
Queryable Encryption.
75+
The following fields are supported by Django MongoDB Backend but not supported
76+
by Queryable Encryption.
7777

7878
+--------------------------------------+--------------------------------------------------------------------------------------------------------------------+
7979
| Field | Limitation |

0 commit comments

Comments
 (0)