Aug 21 - Fernet key rotation
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
"""control0006_fernet_key_version
|
||||
|
||||
Adds the Fernet key-version stamp to the `tenants` table:
|
||||
- key_version INT NOT NULL DEFAULT 1
|
||||
|
||||
MT-23: credentials are encrypted under a single control-plane Fernet key, and
|
||||
before this there was no way to tell which rows had been re-encrypted after a
|
||||
key change — rotation was all-or-nothing and unverifiable. Stamping the version
|
||||
each time a row is written makes rotation progress a plain query:
|
||||
|
||||
SELECT COUNT(*) FROM tenants WHERE key_version < <current>;
|
||||
|
||||
Existing rows default to 1, which matches the single key in use before this
|
||||
migration, so nothing needs re-encrypting to adopt it.
|
||||
|
||||
Guarded by an INFORMATION_SCHEMA existence check, so re-running is safe.
|
||||
|
||||
Revision ID: control0006_fernet_key_ver
|
||||
Revises: control0005_superadmin_mfa
|
||||
Create Date: 2026-08-21
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
# NOTE: revision ids must fit VARCHAR(32) — 'control0006_fernet_key_ver' is 26.
|
||||
revision = 'control0006_fernet_key_ver'
|
||||
down_revision = 'control0005_superadmin_mfa'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def _column_exists(table, column):
|
||||
result = op.get_bind().execute(sa.text(
|
||||
"SELECT COUNT(*) FROM information_schema.COLUMNS "
|
||||
"WHERE TABLE_SCHEMA = DATABASE() "
|
||||
" AND TABLE_NAME = :tbl "
|
||||
" AND COLUMN_NAME = :col"
|
||||
), {'tbl': table, 'col': column})
|
||||
return result.scalar() > 0
|
||||
|
||||
|
||||
def upgrade():
|
||||
if not _column_exists('tenants', 'key_version'):
|
||||
op.add_column('tenants', sa.Column('key_version', sa.Integer(),
|
||||
nullable=False, server_default='1'))
|
||||
|
||||
|
||||
def downgrade():
|
||||
if _column_exists('tenants', 'key_version'):
|
||||
op.drop_column('tenants', 'key_version')
|
||||
Reference in New Issue
Block a user