62c4e742ab
CRITICAL: - C-1: LDAP tls_verify Default False → True (MITM-Schutz) - C-2: TOTP-Secret Fernet-verschlüsselt in DB (statt Plaintext) - core/crypto.py: encrypt_value() / decrypt_value() helper - Migration 0026: totp_secret VARCHAR(64→500), ldap tls_verify default=true - _totp_plain() helper mit Legacy-Fallback für bestehende Werte HIGH: - H-1: Kiosk Nonce-Cache asyncio.Lock (Race Condition behoben) - H-2: File-Upload-Limit 10 MB (import_kimai.py + users.py CSV-Import) - H-3: CORS allow_methods/allow_headers explizit eingeschränkt (war *) - H-4: TrustedHostMiddleware aktiviert wenn ALLOWED_HOSTS gesetzt MEDIUM: - M-1: IP-Logging nutzt X-Forwarded-For hinter nginx-Proxy - M-4: Audit-Log für password_changed, totp_enabled, totp_disabled - M-5: CalDAV verify_ssl in Production erzwungen (_effective_verify_ssl) 152/152 Tests grün Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
69 lines
2.3 KiB
Python
69 lines
2.3 KiB
Python
"""Security-Fixes: LDAP tls_verify default=True, totp_secret column length 500
|
|
|
|
Revision ID: 0026
|
|
Revises: 0025
|
|
Create Date: 2026-05-24
|
|
|
|
Änderungen:
|
|
- ldap_configs.tls_verify: DEFAULT False → DEFAULT True
|
|
Neue Konfigurationen werden mit TLS-Verifikation angelegt.
|
|
BESTEHENDE Einträge mit tls_verify=False werden NICHT automatisch geändert,
|
|
da dies laufende LDAP-Verbindungen unterbrechen könnte.
|
|
Admins müssen ihre LDAP-Konfiguration manuell prüfen.
|
|
|
|
- users.totp_secret: VARCHAR(64) → VARCHAR(500)
|
|
Fernet-verschlüsselte Secrets sind länger als 64 Zeichen (~180 Zeichen).
|
|
Bestehende Plaintext-Secrets (falls vorhanden) müssen manuell verschlüsselt
|
|
werden; nach dieser Migration werden neue Secrets automatisch verschlüsselt.
|
|
WICHTIG: Nach dem Deployment müssen bestehende TOTP-Nutzer ihr 2FA neu einrichten
|
|
(altes Plaintext-Secret nicht mehr kompatibel mit neuem Decrypt-Flow).
|
|
Alternativ: vor dem Deployment `migrate_totp_secrets.py` ausführen (TODO).
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
revision = "0026"
|
|
down_revision = "0025"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
# ── C-1: LDAP tls_verify Default auf True ────────────────────────────────
|
|
op.alter_column(
|
|
"ldap_configs",
|
|
"tls_verify",
|
|
server_default=sa.text("true"),
|
|
existing_type=sa.Boolean(),
|
|
existing_nullable=False,
|
|
)
|
|
|
|
# ── C-2: totp_secret Column-Länge für Fernet-Token ───────────────────────
|
|
op.alter_column(
|
|
"users",
|
|
"totp_secret",
|
|
existing_type=sa.String(64),
|
|
type_=sa.String(500),
|
|
existing_nullable=True,
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
# totp_secret zurück auf 64 (ggf. Datenverlust bei Fernet-verschlüsselten Werten)
|
|
op.alter_column(
|
|
"users",
|
|
"totp_secret",
|
|
existing_type=sa.String(500),
|
|
type_=sa.String(64),
|
|
existing_nullable=True,
|
|
)
|
|
|
|
# LDAP tls_verify Default zurück auf False
|
|
op.alter_column(
|
|
"ldap_configs",
|
|
"tls_verify",
|
|
server_default=sa.text("false"),
|
|
existing_type=sa.Boolean(),
|
|
existing_nullable=False,
|
|
)
|