11import copy
2+ import os
23import time
4+ from pathlib import Path
5+ from urllib .parse import urlencode
36
47import django
58from django .conf import settings
811from django .utils .functional import SimpleLazyObject
912from django .utils .text import format_lazy
1013from django .utils .version import get_version_tuple
14+ from pymongo .encryption_options import AutoEncryptionOpts
1115from pymongo .uri_parser import parse_uri as pymongo_parse_uri
1216
1317
@@ -28,6 +32,62 @@ def check_django_compatability():
2832 )
2933
3034
35+ # Queryable Encryption-related functions based on helpers from Python Queryable
36+ # Encryption Tutorial
37+ # https://github.com/mongodb/docs/tree/master/source/includes/qe-tutorials/python/
38+ def _get_kms_provider_credentials (kms_provider_name ):
39+ """
40+ "A KMS is a remote service that securely stores and manages your encryption keys."
41+
42+ Via https://www.mongodb.com/docs/manual/core/queryable-encryption/quick-start/
43+
44+ Here we check the provider name and return the appropriate credentials.
45+ """
46+ # TODO: Add support for other KMS providers.
47+ if kms_provider_name == "local" :
48+ if not Path ("./customer-master-key.txt" ).exists :
49+ try :
50+ path = "customer-master-key.txt"
51+ file_bytes = os .urandom (96 )
52+ with Path .open (path , "wb" ) as f :
53+ f .write (file_bytes )
54+ except Exception as e :
55+ raise Exception (
56+ "Unable to write Customer Master Key to file due to the following error: "
57+ ) from e
58+
59+ try :
60+ path = "./customer-master-key.txt"
61+ with Path .open (path , "rb" ) as f :
62+ local_master_key = f .read ()
63+ if len (local_master_key ) != 96 :
64+ raise Exception ("Expected the customer master key file to be 96 bytes." )
65+ return {
66+ "local" : {"key" : local_master_key },
67+ }
68+ except Exception as e :
69+ raise Exception (
70+ "Unable to read Customer Master Key from file due to the following error: "
71+ ) from e
72+ else :
73+ raise ValueError (
74+ "Unrecognized value for kms_provider_name encountered while retrieving KMS credentials."
75+ )
76+
77+
78+ def get_auto_encryption_options (kms_provider_name ):
79+ key_vault_database_name = "encryption"
80+ key_vault_collection_name = "__keyVault"
81+ key_vault_namespace = f"{ key_vault_database_name } .{ key_vault_collection_name } "
82+ kms_provider_credentials = _get_kms_provider_credentials (kms_provider_name )
83+ auto_encryption_opts = AutoEncryptionOpts (
84+ kms_provider_credentials ,
85+ key_vault_namespace ,
86+ crypt_shared_lib_path = os .environ .get ("SHARED_LIB_PATH" ),
87+ )
88+ return urlencode (auto_encryption_opts )
89+
90+
3191def parse_uri (uri , * , db_name = None , test = None ):
3292 """
3393 Convert the given uri into a dictionary suitable for Django's DATABASES
0 commit comments