Skip to content

Commit 371d983

Browse files
committed
Doc updates
1 parent 012ea2d commit 371d983

File tree

1 file changed

+85
-118
lines changed

1 file changed

+85
-118
lines changed

docs/howto/queryable-encryption.rst

Lines changed: 85 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ 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
3233
pip install django-mongodb-backend[encryption]
3334
@@ -36,16 +37,23 @@ You can install encryption support with the following command::
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
@@ -70,7 +78,7 @@ encryption keys.
7078
"encrypted": {
7179
"ENGINE": "django_mongodb_backend",
7280
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
73-
"NAME": "encrypted",
81+
"NAME": "my_database_encrypted",
7482
"USER": "my_user",
7583
"PASSWORD": "my_password",
7684
"PORT": 27017,
@@ -83,63 +91,77 @@ encryption keys.
8391
},
8492
}
8593
94+
.. admonition:: Local KMS provider key
95+
96+
In the example above, a random key is generated for the local KMS provider
97+
using ``os.urandom(96)``. In a production environment, you should securely
98+
store and manage your encryption keys.
99+
86100
.. _qe-configuring-database-routers-setting:
87101

88102
Configuring the ``DATABASE_ROUTERS`` setting
89103
============================================
90104

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.
105+
Similar to configuring the :ref:`DATABASE_ROUTERS
106+
<configuring-database-routers-setting>` setting for
107+
:doc:`embedded models </topics/embedded-models>`, Queryable Encryption
108+
requires a :setting:`DATABASE_ROUTERS <django:DATABASE_ROUTERS>` setting to
109+
route database operations to the encrypted database.
95110

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:
111+
The following example shows how to configure a router for the "myapp"
112+
application that routes database operations to the encrypted database for all
113+
models in that application. The router also specifies the :ref:`KMS provider
114+
<qe-configuring-kms>` to use.
99115

100116
.. code-block:: python
101117
118+
# myapp/routers.py
102119
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-
115120
def allow_migrate(self, db, app_label, model_name=None, **hints):
116121
if app_label == "myapp":
117122
return db == "encrypted"
118-
# Don't create other app's models in the encrypted database.
123+
# Prevent migrations on the encrypted database for other apps
119124
if db == "encrypted":
120125
return False
121126
return None
122127
128+
def db_for_read(self, model, **hints):
129+
if model._meta.app_label == "myapp":
130+
return "encrypted"
131+
return None
132+
123133
def kms_provider(self, model, **hints):
124134
return "local"
125135
136+
db_for_write = db_for_read
137+
126138
127-
DATABASE_ROUTERS = [EncryptedRouter]
139+
Then in your Django settings, add the custom router to the
140+
:setting:`django:DATABASE_ROUTERS` setting:
141+
142+
.. code-block:: python
143+
144+
# settings.py
145+
DATABASE_ROUTERS = ["myapp.routers.EncryptedRouter"]
128146
129147
.. _qe-configuring-kms:
130148

131149
Configuring the Key Management Service (KMS)
132150
============================================
133151

134-
To use Queryable Encryption, you must configure a Key Management Service (KMS).
152+
To use Queryable Encryption, you must configure a Key Management Service (KMS)
153+
to store and manage your encryption keys. Django MongoDB Backend allows you to
154+
configure multiple KMS providers and select the appropriate provider for each
155+
model using a custom database router.
156+
135157
The KMS is responsible for managing the encryption keys used to encrypt and
136158
decrypt data. The following table summarizes the available KMS configuration
137159
options followed by an example of how to use them.
138160

139161
+-------------------------------------------------------------------------+--------------------------------------------------------+
140162
| :setting:`KMS_CREDENTIALS <DATABASE-KMS-CREDENTIALS>` | A dictionary of Key Management Service (KMS) |
141-
| | credentials configured in the |
142-
| | :setting:`django:DATABASES` setting. |
163+
| | credentials configured in an inner option of the |
164+
| | encrypted :setting:`django:DATABASES` setting. |
143165
+-------------------------------------------------------------------------+--------------------------------------------------------+
144166
| :class:`kms_providers <pymongo.encryption_options.AutoEncryptionOpts>` | A dictionary of KMS provider credentials used to |
145167
| | access the KMS with |
@@ -158,23 +180,7 @@ Example of KMS configuration with AWS KMS:
158180
159181
DATABASES = {
160182
"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,
167-
"OPTIONS": {
168-
"auto_encryption_opts": AutoEncryptionOpts(
169-
key_vault_namespace="encryption.__keyVault",
170-
kms_providers={
171-
"aws": {
172-
"accessKeyId": "your-access-key-id",
173-
"secretAccessKey": "your-secret-access-key",
174-
}
175-
},
176-
)
177-
},
183+
# ...
178184
"KMS_CREDENTIALS": {
179185
"aws": {
180186
"key": os.getenv("AWS_KEY_ARN", ""),
@@ -195,22 +201,22 @@ Example of KMS configuration with AWS KMS:
195201
Configuring the ``encrypted_fields_map``
196202
========================================
197203

198-
When you :ref:`configure an encrypted database connection
199-
<qe-configuring-databases-setting>` without specifying an
204+
When you configure the :ref:`DATABASES <qe-configuring-databases-setting>`
205+
setting for Queryable Encryption *without* specifying an
200206
``encrypted_fields_map``, Django MongoDB Backend will create encrypted
201-
collections for you when you run ``python manage.py migrate --database
202-
encrypted``.
207+
collections, including data keys, when you run ``python manage.py migrate
208+
--database encrypted``.
203209

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
210+
Encryption keys for encrypted fields are stored in the key vault specified in
211+
the :ref:`DATABASES <qe-configuring-kms>` setting. To see the keys created by
212+
Django MongoDB Backend, along with the entire schema, you can run the
207213
:djadmin:`showencryptedfieldsmap` command::
208214

209215
$ python manage.py showencryptedfieldsmap --database encrypted
210216

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.
217+
Use the output of :djadmin:`showencryptedfieldsmap` to set the
218+
``encrypted_fields_map`` in :class:`AutoEncryptionOpts
219+
<pymongo.encryption_options.AutoEncryptionOpts>` in your Django settings.
214220

215221
.. code-block:: python
216222
@@ -219,21 +225,10 @@ Use the output of the :djadmin:`showencryptedfieldsmap` command to set the
219225
220226
DATABASES = {
221227
"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,
228+
# ...
228229
"OPTIONS": {
229230
"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-
},
231+
# ...
237232
encrypted_fields_map=json_util.loads(
238233
"""{
239234
"encrypt_patient": {
@@ -260,6 +255,13 @@ Use the output of the :djadmin:`showencryptedfieldsmap` command to set the
260255
},
261256
}
262257
258+
259+
.. admonition:: Security consideration
260+
261+
Supplying an encrypted fields map provides more security than relying on an
262+
encrypted fields map obtained from the server. It protects against a
263+
malicious server advertising a false encrypted fields map.
264+
263265
Configuring the Automatic Encryption Shared Library
264266
===================================================
265267

@@ -271,60 +273,25 @@ You can :ref:`download the shared library
271273
<manual:qe-csfle-shared-library-download>` from the
272274
:ref:`manual:enterprise-official-packages` and configure it in your Django
273275
settings using the ``crypt_shared_lib_path`` option in
274-
:class:`pymongo.encryption_options.AutoEncryptionOpts`. The following example
275-
shows how to configure the shared library in your Django settings:
276+
:class:`AutoEncryptionOpts <pymongo.encryption_options.AutoEncryptionOpts>`.
277+
278+
The following example shows how to configure the shared library in your Django
279+
settings:
276280

277281
.. code-block:: python
278282
279283
from pymongo.encryption_options import AutoEncryptionOpts
280284
281285
DATABASES = {
282286
"encrypted": {
283-
"ENGINE": "django_mongodb_backend",
284-
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
285-
"NAME": "encrypted",
286-
"USER": "my_user",
287-
"PASSWORD": "my_password",
288-
"PORT": 27017,
287+
# ...
289288
"OPTIONS": {
290289
"auto_encryption_opts": AutoEncryptionOpts(
291-
key_vault_namespace="encryption.__keyVault",
292-
kms_providers={
293-
"aws": {
294-
"accessKeyId": "your-access-key-id",
295-
"secretAccessKey": "your-secret-access-key",
296-
}
297-
},
298-
encrypted_fields_map=json_util.loads(
299-
"""{
300-
"encrypt_patient": {
301-
"fields": [
302-
{
303-
"bsonType": "string",
304-
"path": "patient_record.ssn",
305-
"keyId": {
306-
"$binary": {
307-
"base64": "2MA29LaARIOqymYHGmi2mQ==",
308-
"subType": "04"
309-
}
310-
},
311-
"queries": {
312-
"queryType": "equality"
313-
}
314-
},
315-
]
316-
}
317-
}"""
318-
),
290+
# ...
319291
crypt_shared_lib_path="/path/to/mongo_crypt_shared_v1.dylib",
320292
)
321293
},
322-
"KMS_CREDENTIALS": {
323-
"aws": {
324-
"key": os.getenv("AWS_KEY_ARN", ""),
325-
"region": os.getenv("AWS_KEY_REGION", ""),
326-
},
327-
},
294+
# ...
328295
},
329296
}
330297

0 commit comments

Comments
 (0)