Шифрование секретов ConnectorConfig (password/token) в БД
- EncryptedCharField (core/models/fields.py): прозрачное Fernet-шифрование на границе с БД, читатели и админка не меняются - ConnectorConfig.password/token переведены на EncryptedCharField, колонки расширены под шифртекст - Миграция 0004: расширение колонок -> шифрование существующих значений -> смена типа - FIELD_ENCRYPTION_KEY в settings (default = SECRET_KEY); на проде задавать отдельно ДО migrate Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
from django.db import models
|
||||
|
||||
from core.utils.crypto import encrypt_secret, decrypt_secret
|
||||
|
||||
|
||||
class EncryptedCharField(models.CharField):
|
||||
"""CharField, который хранит значение в БД в зашифрованном виде (Fernet).
|
||||
|
||||
Для приложения поле ведёт себя как обычная строка: чтение отдаёт открытый
|
||||
текст, запись сохраняет шифртекст. Шифрование выполняется на границе с БД,
|
||||
поэтому читатели (`cfg.password`, `cfg.token`) и админка изменений не требуют.
|
||||
|
||||
Шифртекст длиннее исходного текста (~1.4×) плюс постоянный оверхед Fernet,
|
||||
поэтому колонку нужно объявлять с запасом по `max_length`.
|
||||
"""
|
||||
|
||||
def get_db_prep_save(self, value, connection):
|
||||
value = super().get_db_prep_save(value, connection)
|
||||
if value in (None, ''):
|
||||
return value
|
||||
return encrypt_secret(value)
|
||||
|
||||
def from_db_value(self, value, expression, connection):
|
||||
if value in (None, ''):
|
||||
return value
|
||||
try:
|
||||
return decrypt_secret(value)
|
||||
except Exception:
|
||||
# Значение записано до включения шифрования — вернуть как есть.
|
||||
return value
|
||||
Reference in New Issue
Block a user