Overview
在本教程中,您可以学习;了解如何在 Django应用程序中使用Queryable Encryption (QE)。
MongoDB 的Queryable Encryption功能通过自动加密敏感数据来帮助保护敏感数据,同时仍然允许应用程序与加密数据进行交互。在本教程中,您可以通过在应用程序设置中启用加密并选择要加密的模型字段学习;了解如何将Queryable Encryption与 Django MongoDB后端结合使用。
先决条件
在开始本教程之前,请完成以下先决任务:
创建MongoDB Atlas帐户并配置集群。确保您的集群在MongoDB Server7.0 或更高版本上运行。要学习;了解更多信息,请参阅 MongoDB入门指南。
下载自动加密共享库。要查看说明,请参阅《安装和配置查询分析组件》指南。这些说明展示了如何导航到MongoDB下载中心并填写下载库所需的表格。
安装Python3.10 或更高版本。
Tutorial
在本教程中,您将创建一个使用 Django MongoDB后端的Queryable Encryption应用程序。该应用程序安全地处理医疗记录:它对敏感医疗信息进行加密、解密和查询。
设置您的项目
按照本节中的步骤安装项目依赖项、配置环境并创建应用程序结构。
安装带有 QE 依赖项的 Django MongoDB后端。
选择与操作系统对应的标签页,运行以下命令激活虚拟环境,安装 Django MongoDB后端,并安装Queryable Encryption依赖项:
python -m venv venv source venv/bin/activate pip install 'django-mongodb-backend[encryption]'
python -m venv venv . venv\Scripts\activate pip install 'django-mongodb-backend[encryption]'
pip install 'django-mongodb-backend[encryption]' 命令会安装 Django MongoDB后端、最新的PyMongo版本以及所需的Python依赖项。
注意
适用于 v6.0.1
Queryable Encryption需要 Django MongoDB后端 v6.0.1 或更高版本。前面的命令会安装所需的版本。
Include your app in your project.
导航到 django_qe目录中的 settings.py文件,并编辑 INSTALLED_APPS 设置以类似于以下代码:
INSTALLED_APPS = [ 'medical_records.apps.MedicalRecordsConfig', 'django_qe.apps.MongoAdminConfig', 'django_qe.apps.MongoAuthConfig', 'django_qe.apps.MongoContentTypesConfig', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django_mongodb_backend', ]
此设置可确保在您的项目中启用 medical_records应用。
连接并启用加密
设置项目后,请按照本节中的步骤连接到MongoDB并创建存储加密数据的模型。
配置Queryable Encryption。
在 settings.py文件中,您可以在 DATABASES 设置中指定 encrypted 密钥,以启用Queryable Encryption并设立密钥管理系统 (KMS)提供商。 Django MongoDB后端支持 AWS、 Azure、 GCP、KMIP 和本地KMS提供商。
警告
本地集合扫描存储
如果您将客户主密钥(集合扫描 )存储在本地,请勿在生产环境中使用此应用程序。如果没有远程KMS,您可能会面临未经授权访问权限加密密钥或丢失解密数据所需密钥的风险。
选择与您的KMS对应的标签页,然后修改 DATABASES 设置以类似于以下示例:
DATABASES = { 'default': { # ... Your default configuration }, 'encrypted': { 'ENGINE': 'django_mongodb_backend', 'HOST': '<connection string>', 'NAME': 'medical_records', # ... 'OPTIONS': { 'auto_encryption_opts': AutoEncryptionOpts( key_vault_namespace='medical_records.__keyVault', kms_providers={ 'local': { # Generated by os.urandom(96) 'key': ( b'-\xc3\x0c\xe3\x93\xc3\x8b\xc0\xf8\x12\xc5#b' b'\x19\xf3\xbc\xccR\xc8\xedI\xda\\ \xfb\x9cB' b'\x7f\xab5\xe7\xb5\xc9x\xb8\xd4d\xba\xdc\x9c' b'\x9a\xdb9J]\xe6\xce\x104p\x079q.=\xeb\x9dK*' b'\x97\xea\xf8\x1e\xc3\xd49K\x18\x81\xc3\x1a"' b'\xdc\x00U\xc4u"X\xe7xy\xa5\xb2\x0e\xbc\xd6+-' b'\x80\x03\xef\xc2\xc4\x9bU' ) }, }, crypt_shared_lib_path='<Automatic Encryption Shared Library path>', crypt_shared_lib_required=True, ) }, }, }
将以下占位符值替换为:
<connection string>:与您在default键中指定的连接字符串相同<Automatic Encryption Shared Library path>:自动加密共享库的完整路径
DATABASES = { 'default': { # ... Your default configuration }, 'encrypted': { 'ENGINE': 'django_mongodb_backend', 'HOST': '<connection string>', 'NAME': 'medical_records', # ... 'OPTIONS': { 'auto_encryption_opts': AutoEncryptionOpts( key_vault_namespace='medical_records.__keyVault', kms_providers={ 'aws': { 'accessKeyId': '<AWS Access Key ID>', 'secretAccessKey': '<AWS Secret Access Key>', }, }, crypt_shared_lib_path='<Automatic Encryption Shared Library path>', crypt_shared_lib_required=True, ) }, 'KMS_CREDENTIALS': { 'aws': { 'key': '<AWS Key ARN>', 'region': '<AWS Key Region>', }, }, }, }
将以下占位符值替换为:
<connection string>:与您在default键中指定的连接字符串相同<AWS Access Key ID>:您的Amazon Web Services访问密钥ID<AWS Secret Access Key>:您的Amazon Web Services秘密访问权限密钥<Automatic Encryption Shared Library path>:自动加密共享库的完整路径<AWS Key ARN>:AWS 客户的Amazon资源名称。<AWS Key Region>:您的 AWS地区,例如'us-east-1'
DATABASES = { 'default': { # ... Your default configuration }, 'encrypted': { 'ENGINE': 'django_mongodb_backend', 'HOST': '<connection string>', 'NAME': 'medical_records', # ... 'OPTIONS': { 'auto_encryption_opts': AutoEncryptionOpts( key_vault_namespace='medical_records.__keyVault', kms_providers={ 'azure': { 'tenantId': '<Azure Tenant ID>', 'clientId': '<Azure Client ID>', 'clientSecret': '<Azure Client Secret>', }, }, crypt_shared_lib_path='<Automatic Encryption Shared Library path>', crypt_shared_lib_required=True, ) }, 'KMS_CREDENTIALS': { 'azure': { 'keyVaultEndpoint': '<Azure Key Vault Endpoint>', 'keyName': '<Azure Key Name>', # Optional: 'keyVersion': '<Azure Key Version>', }, }, }, }
将以下占位符值替换为:
<connection string>:与您在default键中指定的连接字符串相同<Azure Tenant ID>:您的Azure Active Directory 租户ID<Azure Client ID>:您的Azure应用程序客户端ID<Azure Client Secret>: Your Azure application client secret<Automatic Encryption Shared Library path>:自动加密共享库的完整路径<Azure Key Vault Endpoint>:您的Azure Key Vault端点URL。<Azure Key Name>: The name of your key in Azure Key Vault<Azure Key Version>:(可选)要使用的密钥版本
DATABASES = { 'default': { # ... Your default configuration }, 'encrypted': { 'ENGINE': 'django_mongodb_backend', 'HOST': '<connection string>', 'NAME': 'medical_records', # ... 'OPTIONS': { 'auto_encryption_opts': AutoEncryptionOpts( key_vault_namespace='medical_records.__keyVault', kms_providers={ 'gcp': { 'email': '<GCP Service Account Email>', 'privateKey': '<GCP Service Account Private Key>', }, }, crypt_shared_lib_path='<Automatic Encryption Shared Library path>', crypt_shared_lib_required=True, ) }, 'KMS_CREDENTIALS': { 'gcp': { 'projectId': '<GCP Project ID>', 'location': '<GCP Key Ring Location>', 'keyRing': '<GCP Key Ring Name>', 'keyName': '<GCP Key Name>', }, }, }, }
将以下占位符值替换为:
<connection string>:与您在default键中指定的连接字符串相同<GCP Service Account Email>:您的 Google Cloud 服务帐号电子邮件<GCP Service Account Private Key>:您的 Google Cloud 服务帐号私钥<Automatic Encryption Shared Library path>:自动加密共享库的完整路径<GCP Project ID>:您的 Google Cloud项目ID<GCP Key Ring Location>:密钥环的位置,例如'global'<GCP Key Ring Name>:密钥环的名称<GCP Key Name>:密钥的名称
DATABASES = { 'default': { # ... Your default configuration }, 'encrypted': { 'ENGINE': 'django_mongodb_backend', 'HOST': '<connection string>', 'NAME': 'medical_records', # ... 'OPTIONS': { 'auto_encryption_opts': AutoEncryptionOpts( key_vault_namespace='medical_records.__keyVault', kms_providers={ 'kmip': { 'endpoint': '<KMIP Server Endpoint>', }, }, crypt_shared_lib_path='<Automatic Encryption Shared Library path>', crypt_shared_lib_required=True, ) }, 'KMS_CREDENTIALS': { 'kmip': { # Optional: 'keyId': '<KMIP Key Identifier>', }, }, }, }
将以下占位符值替换为:
<connection string>:与您在default键中指定的连接字符串相同。<KMIP Server Endpoint>:KMIP服务器端点及其端口,例如'example.com:443'。<Automatic Encryption Shared Library path>:自动加密共享库的完整路径。<KMIP Key Identifier>:(可选)96 字节 KMIP 密钥数据托管对象的 KMIP 唯一标识符。如果省略此值,Django MongoDB后端将创建一个随机的 96 字节对象。
This code connects to the encrypted medical_records database, stores your data keys in the medical_records.__keyVault collection, and configures your KMS provider.
将操作路由到加密数据库。
在 medical_records目录中,创建名为 routers.py 的文件并将以下代码粘贴到其中:
class EncryptedRouter: def allow_migrate(self, db, app_label, model_name=None, **hints): # Create medical_records models only in the encrypted database. if app_label == "medical_records": return db == "encrypted" # Don't create collections for other apps in the encrypted db. if db == "encrypted": return False return None def db_for_read(self, model, **hints): # All reads and writes for medical_records models go to the encrypted db. if model._meta.app_label == "medical_records": return "encrypted" return None db_for_write = db_for_read
此文件将 medical_records应用程序中所有模型的数据库操作路由到加密的medical_records数据库。
然后,导航到 settings.py文件并将 DATABASE_ROUTERS 设置替换为以下代码,以添加自定义路由器:
DATABASE_ROUTERS = [ 'django_mongodb_backend.routers.MongoRouter', 'medical_records.routers.EncryptedRouter', ]
创建存储加密字段的模型。
In your medical_records directory, navigate to the models.py file and paste the following code:
from django.db import models from django_mongodb_backend.models import EmbeddedModel from django_mongodb_backend.fields import ( EmbeddedModelField, EncryptedCharField, EncryptedEmbeddedModelField, ) class Patient(models.Model): patient_name = models.CharField(max_length=255) patient_id = models.BigIntegerField() patient_record = EmbeddedModelField("PatientRecord") class Meta: db_table = "patients" def __str__(self): return f"{self.patient_name} ({self.patient_id})" class PatientRecord(EmbeddedModel): ssn = EncryptedCharField(max_length=11, queries={"queryType": "equality"}) billing = EncryptedEmbeddedModelField("Billing") bill_amount = models.DecimalField(max_digits=10, decimal_places=2) class Billing(EmbeddedModel): cc_type = models.CharField(max_length=50) cc_number = models.CharField(max_length=20)
This code creates a Patient model, which corresponds to the patients collection in your medical_records database. It also creates two embedded models, PatientRecord and Billing, to represent nested fields in the collection.
该代码配置以下加密字段:
patient_record.ssn:针对相等查询进行加密和配置patient_record.billing.cc_type:已加密,但不可查询patient_record.billing.cc_number:已加密,但不可查询
执行加密操作
配置应用程序和数据库连接后,请按照本节中的步骤插入和查询加密文档。
插入加密数据。
在Shell中运行以下命令,创建 Patient实例,并将相应的加密文档插入数据库:
billing = Billing(cc_type="Visa", cc_number="4111111111111111") record = PatientRecord(ssn="987-65-4320", billing=billing, bill_amount=1500) patient = Patient.objects.create( name="John Doe", patient_id=12345678, patient_record=record )
medical_records.patients如果导航到MongoDB Atlas上的 集合,则可以看到文档的patient_record.ssn 和patient_record.billing 字段已加密。
后续步骤
恭喜完成Queryable Encryption教程!您现在拥有一个示例Django应用程序,它使用Queryable Encryption自动加密和解密文档字段。您的应用程序会在服务器端加密敏感数据,并在客户端端查询数据。
要学习;了解有关Queryable Encryption和 Django MongoDB后端的更多信息,请访问以下资源:
在MongoDB Server手册中查看更多驾驶员Queryable Encryption教程。
在API文档中了解详情有关使用 Django MongoDB后端Queryable Encryption 的更多信息