Jul 2nd - Optimized code 3
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
"""
|
||||
Symmetric encryption for secrets stored in SystemSetting (currently just
|
||||
the IMAP mailbox password used by email ingestion).
|
||||
|
||||
The Fernet key is derived from SECRET_KEY rather than a separately managed
|
||||
key, so no extra key-rotation story is needed for a single-tenant on-prem
|
||||
app — rotating SECRET_KEY (which already invalidates sessions) also
|
||||
invalidates encrypted secrets, which is an acceptable trade-off here.
|
||||
"""
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
|
||||
from cryptography.fernet import Fernet, InvalidToken
|
||||
from flask import current_app
|
||||
|
||||
|
||||
def _fernet() -> Fernet:
|
||||
secret = current_app.config['SECRET_KEY'].encode()
|
||||
key = base64.urlsafe_b64encode(hashlib.sha256(secret).digest())
|
||||
return Fernet(key)
|
||||
|
||||
|
||||
def encrypt_secret(plain: str) -> str:
|
||||
"""Encrypt a secret for storage. Empty input passes through unchanged."""
|
||||
if not plain:
|
||||
return ''
|
||||
return _fernet().encrypt(plain.encode()).decode()
|
||||
|
||||
|
||||
def decrypt_secret(stored: str) -> str:
|
||||
"""Decrypt a secret previously written by encrypt_secret().
|
||||
|
||||
Falls back to returning the value unchanged if it isn't a valid Fernet
|
||||
token. This covers values saved before encryption was introduced, so
|
||||
existing configurations (e.g. email ingestion set up before this change)
|
||||
keep working without a manual data migration — the value is simply
|
||||
re-encrypted the next time it's saved through the settings form.
|
||||
"""
|
||||
if not stored:
|
||||
return ''
|
||||
try:
|
||||
return _fernet().decrypt(stored.encode()).decode()
|
||||
except (InvalidToken, ValueError):
|
||||
return stored
|
||||
@@ -295,7 +295,8 @@ def _run_ingestion(app):
|
||||
host = _get_setting('email_ingestion_host', '')
|
||||
port = int(_get_setting('email_ingestion_port', '993'))
|
||||
username = _get_setting('email_ingestion_user', '')
|
||||
password = _get_setting('email_ingestion_password', '')
|
||||
from app.services.crypto_service import decrypt_secret
|
||||
password = decrypt_secret(_get_setting('email_ingestion_password', ''))
|
||||
folder = _get_setting('email_ingestion_folder', 'INBOX')
|
||||
move_to = _get_setting('email_ingestion_move_to', 'Processed')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user