-
Notifications
You must be signed in to change notification settings - Fork 26
INTPYTHON-527 Add Queryable Encryption support #329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
django_mongodb_backend/management/commands/get_encrypted_fields_map.py
Outdated
Show resolved
Hide resolved
django_mongodb_backend/management/commands/get_encrypted_fields_map.py
Outdated
Show resolved
Hide resolved
django_mongodb_backend/management/commands/get_encrypted_fields_map.py
Outdated
Show resolved
Hide resolved
django_mongodb_backend/management/commands/get_encrypted_fields_map.py
Outdated
Show resolved
Hide resolved
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
Encrypted fields map | ||
~~~~~~~~~~~~~~~~~~~~ | ||
|
||
In addition to the :ref:`settings described in the how-to guide | ||
<queryable-encryption-settings>` you will need to provide a | ||
``encrypted_fields_map`` to the ``AutoEncryptionOpts``. | ||
|
||
You can use the :djadmin:`showencryptedfieldsmap` management command to generate | ||
the schema map for your encrypted fields and then use the results in your | ||
settings:: | ||
|
||
python manage.py showencryptedfieldsmap --database=encrypted |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're missing the step on defining your models (consolidate from topic guide?), then makemigrations
and migrate
. Otherwise showencryptedfieldsmap
may crash without any keyIds to retrieve?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed and no, it should return "no keys found"
25b7e8b
to
2469f84
Compare
cd8aa5c
to
62db35a
Compare
QE Doc flow - Three top level (or close to it) docs - How to guide on QE configuration - QE field guide (moved out of model field ref to its own section) - Topic guide on QE usage
- Planning to finish QE setup in the how-to doc then switch back to the topic doc to explain the workflow.
In the QE topics guide I'm going to explain how to develop a patient model similar to the Python QE tutorial and the encryption test suite. If embedding were possible now, I could present the same example. Since embedded models are a WIP I may either: - design the guide to work around that issue - design the guide to anticipate resolution of that issue In ether case, I'll try to wrap this 24-48 hour docs jam having covered everything I know about QE and Django and having presented it to Django folks in a way we can support.
- Configuring the encrypted_fields_map section
21c237e
to
cd035eb
Compare
- Configuring the Automatic Encryption Shared Library
…map.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements comprehensive Queryable Encryption support for the Django MongoDB Backend, enabling developers to use encrypted fields in Django models while maintaining the ability to query on encrypted data.
Key changes:
- Added encrypted field types that extend Django's standard fields with encryption capabilities
- Implemented automatic encrypted collection creation with proper schema generation
- Added management command for viewing and managing encrypted field mappings
Reviewed Changes
Copilot reviewed 31 out of 32 changed files in this pull request and generated 5 comments.
Show a summary per file
File | Description |
---|---|
django_mongodb_backend/fields/encryption.py |
Implements EncryptedFieldMixin and all encrypted field variants |
django_mongodb_backend/schema.py |
Adds encrypted collection creation and encrypted fields map generation |
django_mongodb_backend/management/commands/showencryptedfieldsmap.py |
Management command for displaying encrypted field mappings |
django_mongodb_backend/features.py |
Adds feature detection for Queryable Encryption support |
tests/encryption_/ |
Comprehensive test suite for encrypted fields and functionality |
docs/source/ |
Complete documentation for setup and usage |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
options = client._options | ||
auto_encryption_opts = options.auto_encryption_opts | ||
kms_provider = router.kms_provider(model) | ||
master_key = self.connection.settings_dict.get("KMS_CREDENTIALS").get(kms_provider) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code will raise an AttributeError if 'KMS_CREDENTIALS' is not in settings_dict, as .get() returns None and then .get() is called on None. Should use: master_key = self.connection.settings_dict.get("KMS_CREDENTIALS", {}).get(kms_provider)
master_key = self.connection.settings_dict.get("KMS_CREDENTIALS").get(kms_provider) | |
master_key = self.connection.settings_dict.get("KMS_CREDENTIALS", {}).get(kms_provider) |
Copilot uses AI. Check for mistakes.
if not model_name: | ||
return None | ||
try: | ||
model = apps.get_model(app_label, model_name) | ||
except LookupError: | ||
return None | ||
return False if issubclass(model, EmbeddedModel) else None | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is defined at module level but references 'self' as if it's a method. It should either be a standalone function without 'self' parameter or be properly defined as a method within a class.
# This function is intended to be monkey-patched as a method of ConnectionRouter. |
Copilot uses AI. Check for mistakes.
def _compare_output(self, json1, json2): | ||
# Remove keyIds since they are different for each run. | ||
for field in json2["fields"]: | ||
del field["keyId"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using del
on a dictionary key that might not exist will raise a KeyError. Should use field.pop("keyId", None)
to safely remove the key if it exists, similar to line 62 in test_schema.py.
del field["keyId"] | |
field.pop("keyId", None) |
Copilot uses AI. Check for mistakes.
else: | ||
db.create_collection(db_table) | ||
|
||
def _get_encrypted_fields_map(self, model, client, create_data_keys=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method signature is inconsistent with its usage. At line 448, it's called with auto_encryption_opts
as the third parameter, but the method signature expects create_data_keys
as the third parameter. This will cause incorrect behavior.
Copilot uses AI. Check for mistakes.
|
||
class Patient(models.Model): | ||
name = models.CharField(max_length=255) | ||
ssn = models.EncryptedCharField(max_length=11, queries={"queryType": "equality"}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect import reference. Should be EncryptedCharField
from django_mongodb_backend.fields
, not models.EncryptedCharField
. The import at line 71 shows the correct import path.
ssn = models.EncryptedCharField(max_length=11, queries={"queryType": "equality"}) | |
ssn = EncryptedCharField(max_length=11, queries={"queryType": "equality"}) |
Copilot uses AI. Check for mistakes.
Previous attempts and additional context here: