Files
ACORE/core/utils/crypto.py
T
lokses 38c8e35a51 Security hardening: обязательный ключ шифрования, fail-closed токены, права API
- FIELD_ENCRYPTION_KEY: production требует явный ключ (ImproperlyConfigured
  при пустом), local — fallback на SECRET_KEY с предупреждением (crypto.py)
- MATTERMOST_INTERACTIVE_TOKEN: fail-closed токен для интерактивных кнопок
  Mattermost (bot_service task-done URL + проверка в mattermost views)
- Ужесточение прав API (employees/visit_manager) + тесты
  (employees, mattermost_connector, visit_manager)
- .env.example с описанием переменных; правки шаблонов (index/dislocation/pharmacies)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 12:23:28 +03:00

33 lines
960 B
Python

import base64
import hashlib
import logging
from django.conf import settings
from cryptography.fernet import Fernet
logger = logging.getLogger(__name__)
_warned_fallback = False
def _get_fernet() -> Fernet:
global _warned_fallback
key_source = getattr(settings, 'FIELD_ENCRYPTION_KEY', None) or ''
if not key_source:
key_source = settings.SECRET_KEY
if not _warned_fallback:
logger.warning(
'FIELD_ENCRYPTION_KEY is not set — falling back to SECRET_KEY. '
'Set a dedicated key in .env (production requires it).'
)
_warned_fallback = True
derived_key = base64.urlsafe_b64encode(hashlib.sha256(key_source.encode()).digest())
return Fernet(derived_key)
def encrypt_secret(plain: str) -> str:
return _get_fernet().encrypt(plain.encode()).decode()
def decrypt_secret(cipher: str) -> str:
return _get_fernet().decrypt(cipher.encode()).decode()