@@ -24,28 +24,36 @@ Installation
2424============
2525
2626In 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
3637Configuring 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,134 +84,138 @@ 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
8896Configuring 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
126131
127- DATABASE_ROUTERS = [EncryptedRouter]
132+ Then in your Django settings, add the custom database router to the
133+ :setting: `django:DATABASE_ROUTERS ` setting:
134+
135+ .. code-block :: python
136+
137+ # settings.py
138+ DATABASE_ROUTERS = [" myapp.routers.EncryptedRouter" ]
128139
129140 .. _qe-configuring-kms :
130141
131142Configuring 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+
135150The KMS is responsible for managing the encryption keys used to encrypt and
136151decrypt data. The following table summarizes the available KMS configuration
137152options followed by an example of how to use them.
138153
139- +-------------------------------------------------------------------------+--------------------------------------------------------+
140- | :setting: `KMS_CREDENTIALS <DATABASE-KMS-CREDENTIALS> ` | A dictionary of Key Management Service (KMS) |
141- | | credentials configured in the |
142- | | :setting: `django:DATABASES ` setting. |
143154+-------------------------------------------------------------------------+--------------------------------------------------------+
144155| :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> `. |
156+ | | access the KMS with ``kms_provider ``. |
147157+-------------------------------------------------------------------------+--------------------------------------------------------+
148- | `` kms_provider `` | A single KMS provider name |
158+ | :ref: ` kms_provider < qe-configuring-database-routers-setting >` | A single KMS provider name |
149159| | configured in your custom database |
150160| | router. |
151161+-------------------------------------------------------------------------+--------------------------------------------------------+
152162
153- Example of KMS configuration with AWS KMS:
163+ Example of KMS configuration with ``aws `` in your :class: `kms_providers
164+ <pymongo.encryption_options.AutoEncryptionOpts> ` setting:
154165
155166.. code-block :: python
156167
157168 from pymongo.encryption_options import AutoEncryptionOpts
158169
159170 DATABASES = {
160171 " 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 ,
172+ # ...
167173 " OPTIONS" : {
168174 " auto_encryption_opts" : AutoEncryptionOpts(
169- key_vault_namespace = " encryption.__keyVault " ,
175+ # ...
170176 kms_providers = {
171177 " aws" : {
172- " accessKeyId " : " your-access-key-id " ,
173- " secretAccessKey " : " your-secret-access-key " ,
174- }
178+ " key " : os.getenv( " AWS_KEY_ARN " , " " ) ,
179+ " region " : os.getenv( " AWS_KEY_REGION " , " " ) ,
180+ },
175181 },
176- )
177- },
178- " KMS_CREDENTIALS" : {
179- " aws" : {
180- " key" : os.getenv(" AWS_KEY_ARN" , " " ),
181- " region" : os.getenv(" AWS_KEY_REGION" , " " ),
182- },
182+ ),
183183 },
184184 },
185185 }
186186
187187
188+ In your :ref: `custom database router <qe-configuring-database-routers-setting >`,
189+ specify the KMS provider to use for the models in your application:
190+
191+ .. code-block :: python
192+
188193 class EncryptedRouter :
189194 # ...
190195 def kms_provider (self , model , ** hints ):
191196 return " aws"
192197
193198 .. _qe-configuring-encrypted-fields-map :
194199
195- Configuring the ``encrypted_fields_map ``
196- ========================================
200+ Configuring the ``encrypted_fields_map `` option
201+ ===============================================
197202
198- When you :ref: `configure an encrypted database connection
199- <qe-configuring-databases- setting>` without specifying an
203+ When you configure the :ref: `DATABASES < qe-configuring-databases-setting >`
204+ setting for Queryable Encryption * without * specifying an
200205``encrypted_fields_map ``, Django MongoDB Backend will create encrypted
201- collections for you when you run `` python manage.py migrate --database
202- encrypted ` `.
206+ collections, including encryption keys, when you :ref: ` run migrations for models
207+ that have encrypted fields <qe-migrations> `.
203208
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
209+ Encryption keys for encrypted fields are stored in the key vault specified in
210+ the :ref: `DATABASES <qe-configuring-kms >` setting . To see the keys created by
211+ Django MongoDB Backend, along with the entire schema, you can run the
207212:djadmin: `showencryptedfieldsmap ` command::
208213
209214 $ python manage.py showencryptedfieldsmap --database encrypted
210215
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.
216+ Use the output of :djadmin: `showencryptedfieldsmap ` to set the
217+ ``encrypted_fields_map `` in :class: ` AutoEncryptionOpts
218+ < pymongo.encryption_options.AutoEncryptionOpts> ` in your Django settings.
214219
215220.. code-block :: python
216221
@@ -219,21 +224,10 @@ Use the output of the :djadmin:`showencryptedfieldsmap` command to set the
219224
220225 DATABASES = {
221226 " 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 ,
227+ # ...
228228 " OPTIONS" : {
229229 " 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- },
230+ # ...
237231 encrypted_fields_map = json_util.loads(
238232 """ {
239233 "encrypt_patient": {
@@ -260,6 +254,13 @@ Use the output of the :djadmin:`showencryptedfieldsmap` command to set the
260254 },
261255 }
262256
257+
258+ .. admonition :: Security consideration
259+
260+ Supplying an encrypted fields map provides more security than relying on an
261+ encrypted fields map obtained from the server. It protects against a
262+ malicious server advertising a false encrypted fields map.
263+
263264Configuring the Automatic Encryption Shared Library
264265===================================================
265266
@@ -271,60 +272,25 @@ You can :ref:`download the shared library
271272<manual:qe-csfle-shared-library-download>` from the
272273:ref: `manual:enterprise-official-packages ` and configure it in your Django
273274settings 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:
275+ :class: `AutoEncryptionOpts <pymongo.encryption_options.AutoEncryptionOpts> `.
276+
277+ The following example shows how to configure the shared library in your Django
278+ settings:
276279
277280.. code-block :: python
278281
279282 from pymongo.encryption_options import AutoEncryptionOpts
280283
281284 DATABASES = {
282285 " 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 ,
286+ # ...
289287 " OPTIONS" : {
290288 " 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- ),
289+ # ...
319290 crypt_shared_lib_path = " /path/to/mongo_crypt_shared_v1.dylib" ,
320291 )
321292 },
322- " KMS_CREDENTIALS" : {
323- " aws" : {
324- " key" : os.getenv(" AWS_KEY_ARN" , " " ),
325- " region" : os.getenv(" AWS_KEY_REGION" , " " ),
326- },
327- },
293+ # ...
328294 },
329295 }
330296
0 commit comments