feat: database migration to hold onion cert metadata
This commit is contained in:
parent
e5976c4739
commit
675a7341eb
1 changed files with 94 additions and 0 deletions
|
@ -0,0 +1,94 @@
|
|||
"""onion certificate metadata
|
||||
|
||||
Revision ID: c14f25f364c5
|
||||
Revises: 13b1d64f134a
|
||||
Create Date: 2024-12-06 14:14:45.796762
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import String, LargeBinary, DateTime, Integer, table, column
|
||||
|
||||
from app.util.x509 import validate_tls_keys, extract_sans
|
||||
|
||||
revision = 'c14f25f364c5'
|
||||
down_revision = '13b1d64f134a'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
with op.batch_alter_table('onion', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('cert_expiry', sa.DateTime(timezone=True), nullable=True))
|
||||
batch_op.add_column(sa.Column('cert_sans', sa.String(), nullable=True))
|
||||
|
||||
connection = op.get_bind()
|
||||
onion_table = table(
|
||||
'onion',
|
||||
column('id', Integer), # Primary key
|
||||
column('description', String(255)),
|
||||
column('added', DateTime),
|
||||
column('updated', DateTime),
|
||||
column('destroyed', DateTime),
|
||||
column('group_id', Integer),
|
||||
column('domain_name', String(255)),
|
||||
column('onion_public_key', LargeBinary),
|
||||
column('onion_private_key', LargeBinary),
|
||||
column('tls_public_key', LargeBinary),
|
||||
column('tls_private_key', LargeBinary),
|
||||
column('cert_expiry', DateTime(timezone=True)), # New column
|
||||
column('cert_sans', String), # New column
|
||||
)
|
||||
|
||||
rows = connection.execute(sa.select(
|
||||
onion_table.c.id,
|
||||
onion_table.c.tls_public_key,
|
||||
onion_table.c.tls_private_key
|
||||
)).fetchall()
|
||||
|
||||
updates = []
|
||||
for row in rows:
|
||||
# validate_tls_keys only returns the SANs if you validate the name
|
||||
chain, _, tls_errors = validate_tls_keys(
|
||||
row.tls_private_key.decode('utf-8'), row.tls_public_key.decode('utf-8'), True,
|
||||
True, ""
|
||||
)
|
||||
|
||||
if tls_errors:
|
||||
connection.close()
|
||||
with op.batch_alter_table('onion', schema=None) as batch_op:
|
||||
batch_op.drop_column('cert_expiry')
|
||||
batch_op.drop_column('cert_sans')
|
||||
|
||||
raise RuntimeError(f"TLS key error for onion {row.id}: {tls_errors}")
|
||||
|
||||
cert_expiry = chain[0].not_valid_after if chain else None
|
||||
cert_sans = extract_sans(chain[0])
|
||||
|
||||
updates.append({
|
||||
'id': row.id,
|
||||
'cert_expiry': cert_expiry,
|
||||
'cert_sans': ",".join(cert_sans)
|
||||
})
|
||||
|
||||
for update in updates:
|
||||
connection.execute(
|
||||
sa.text(
|
||||
"UPDATE onion SET cert_expiry = :cert_expiry, cert_sans = :cert_sans WHERE id = :id"
|
||||
),
|
||||
{
|
||||
'cert_expiry': update['cert_expiry'],
|
||||
'cert_sans': update['cert_sans'],
|
||||
'id': update['id']
|
||||
}
|
||||
)
|
||||
|
||||
with op.batch_alter_table('onion', schema=None) as batch_op:
|
||||
batch_op.alter_column('cert_expiry', existing_type=sa.DateTime(timezone=True), nullable=False)
|
||||
batch_op.alter_column('cert_sans', existing_type=sa.String(), nullable=False)
|
||||
|
||||
|
||||
def downgrade():
|
||||
with op.batch_alter_table('onion', schema=None) as batch_op:
|
||||
batch_op.drop_column('cert_sans')
|
||||
batch_op.drop_column('cert_expiry')
|
Loading…
Add table
Add a link
Reference in a new issue