Feature/profile cipher for securing data#1225
Conversation
This is for properly encrypting sensitive User data (creds for external services).
We'll store the cipher in the Session and not as a runtime property of the Profile, because the cipher must persist across requests. Because there are several signal receivers associate with the encryption of sensitive data, we'll just put the cipher create code in signals.py as well.
the Fernet instance can't be serialized to be saved in the session. So, we just save the key and use it to instantiate a new Fernet instance when we need it.
or rather don't update the session hash to perserve the login session. The user will have to log back in. This is to trigger the UserSession object creation to maintain encrypted database fields across password changes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This reverts commit 92b757d1b22598b2ad27407a42f8fa026987e28b.
They have moved to session_utils.py and these fuctions generally deal with encryptioning fields and that mechanism uses sessions to keep track of things across HTTP requests.
When the user changes their password good practice is to call update_session_auth_hash to keep them logged in. This create a new Session object. That means that the old UserSession object gets deleted on CASCADE. This create a new UserSession, linking the User with their new Session. Previously, the call to update_session_auth_hash was in dispatch(), but now it's here in form_valid().
This makes it match the urlpattern; also make sure it's an int.
This makes it match the urlpattern; also make sure it's an int.
This has been addressed in the latest commits. We now clear a User's encrypted fields if and Admin changes their password. Upon that password change, the data in those fields became irretrievable and stale. So, it makes sense to clear it out. Also, added a confirmation and warning to the admin that encrypted fields for the User would be cleared out. |
This simplifies the encrypted property-containing class
defintition to this:
class MyModel(EncryptableModelMixin, models.Model):
_encyrpted_api_key = models.BinaryField(null=True)
EncryptedProperty('_encrypted_api_key')
You still have to instantiate a cipher and attach it to the
the Model before you set/get, but there's no getting aournd that.
This has been refactored away. Encrypting a Model field no longer requires changes to the AppConfig |
jchate6
left a comment
There was a problem hiding this comment.
Sorry, ran out of time. Will finish the review on the rest of the code next week, but didn't want to leave you hanging for tomorrow!
Adds two helper fuctions (get and set) that encapulate the logic for - geting the User's encryption key - creating the Fernet cipher - attatching the cipher to the Model instance - removing the cipher when finished.
This clarifies the contract between the mixin and it's Model and also simplifies the logic in session_utils.py. It does introduce an documentation issue that EncrtypableModelMixin subclasses MUST NOT then have their own user OneToOneField.
| else: | ||
| return reverse_lazy('user-update', kwargs={'pk': self.request.user.id}) | ||
|
|
||
| def get_context_data(self, **kwargs): |
There was a problem hiding this comment.
This is a work around for a bug with the user-update page where the "user" value in the context is set to the user being edited rather than the current user, so that even the name in the top right of the navbar temporarily gets set to that user than the currently logged in user. We should probably fix this, but who has the time. (and I doubt many people will notice.)
jchate6
left a comment
There was a problem hiding this comment.
I have made a few commits for little things. do a pull before any other changes.
I'm also unclear on the local imports but it's not enough to hold this up any more.
this was necessary before the refactor of these functions to session_utils.py, but not after
This PR covers the signals, utility functions, and other changes required to store sensitive data, encrypted in the TOMToolkit database. See tom_eso for an example of how to use it. Briefly,
UserSessionis updated intom_base.view.UserUpdateView.signals.pylooks for saves to the User model and calls out tosession_utils.pyto keep the EncryptedBinaryFields up-to-date.tom_common.test.py