-
Notifications
You must be signed in to change notification settings - Fork 687
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
Refactor encryption logic to fix type-checking and improve tests (CryptoUtil 3/3) #6160
Refactor encryption logic to fix type-checking and improve tests (CryptoUtil 3/3) #6160
Conversation
644e3e2
to
adeb4a6
Compare
_default_encryption_mgr: Optional["EncryptionManager"] = None | ||
|
||
|
||
class EncryptionManager: |
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.
Not sure about this name... open to changing it.
app.crypto_util = CryptoUtil( | ||
securedrop_root=config.SECUREDROP_ROOT, | ||
gpg_key_dir=config.GPG_KEY_DIR, | ||
) |
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 main goal of this PR: removing app.crypto_util
.
securedrop_root=config.SECUREDROP_ROOT, | ||
gpg_key_dir=config.GPG_KEY_DIR, | ||
) | ||
app.storage = Storage(config.STORE_DIR, config.TEMP_DIR) |
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.
Storage
no longer needs the config.JOURNALIST_KEY
.
# where files and directories are sent to be securely deleted | ||
self.__shredder_path = os.path.abspath(os.path.join(self.__storage_path, "../shredder")) | ||
if not os.path.exists(self.__shredder_path): | ||
os.makedirs(self.__shredder_path, mode=0o700) | ||
|
||
# crash if we don't have a way to securely remove files | ||
if not rm.check_secure_delete_capability(): | ||
raise AssertionError("Secure file deletion is not possible.") |
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.
Moved from CryptoUtil to here.
adeb4a6
to
c9578ac
Compare
This pull request introduces 1 alert when merging 8f3c8e5 into f34565d - view on LGTM.com new alerts:
|
69aba24
to
6132be7
Compare
6132be7
to
18d7a57
Compare
securedrop/tests/conftest.py
Outdated
journalist_secret_key_path = Path(__file__).parent / "files" / "test_journalist_key.sec" | ||
journalist_secret_key = journalist_secret_key_path.read_text() | ||
gpg.import_keys(journalist_secret_key) | ||
|
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.
Important change here: the journalist's private/secret key is no longer imported by default.
Having the journalist secret key available in GPG was making the test suite behave differently compared to web app. For example, data in tests could get decrypted using the journalist secret key instead of the expected source key.
|
||
The journalist secret key is removed at the end of this context manager in order to not impact | ||
other decryption-related tests. | ||
""" |
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.
import_journalist_private_key()
can be used when the journalist secret key needs to be available for a specific test.
7bb4b3b
to
8f39600
Compare
8f39600
to
9834cad
Compare
4222ede
to
7a6bb0f
Compare
# Reduce source GPG key length to speed up tests at the expense of security | ||
with mock.patch.object( | ||
EncryptionManager, "GPG_KEY_LENGTH", PropertyMock(return_value=1024) | ||
): |
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.
Moved from CryptoUtil to the test suite.
|
||
# And the source or anyone else is NOT able to decrypt the message | ||
# For GPG 2.1+, a non-null passphrase _must_ be passed to decrypt() | ||
assert not encryption_mgr._gpg.decrypt(encrypted_message, passphrase="test 123").ok |
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.
Example of a new test that ensures that only the right user/key can decrypt some data.
7a6bb0f
to
859fbf1
Compare
@@ -0,0 +1,351 @@ | |||
import typing |
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.
Coverage report:
---------- coverage: platform linux, python 3.8.10-final-0 -----------
Name Stmts Miss Branch BrPart Cover
------------------------------------------------------------------------
encryption.py 123 9 28 4 91%
I ran the tests locally and also manually tested the app ( |
859fbf1
to
6fa34d0
Compare
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.
- no issues found in code review
- tests pass in staging env
- upgrade scenario is successful and tests pass against upgrade env
- manual tests of affected functionality look good.
LGTM, thanks for this!
Status
Ready.
Description of Changes
This is the last PR for refactoring CryptoUtil and fixing type-checking, as described in #5599.
More specifically:
encrypt()
anddecrypt()
) by making them private. Instead, only higher-level, public methods can be used such asencrypt_source_file()
,decrypt_journalist_reply()
, etc.encrypt()
ordecrypt()
, for example by providing the wrong fingerprints.