From 13547fb08392fb4c92f3ccef4d08bf7acb044b9c Mon Sep 17 00:00:00 2001 From: Midas Wollinger Date: Thu, 20 Aug 2026 01:10:22 +0200 Subject: [PATCH] fix 11 --- .../inventory/group_vars/vault.yml.example | 12 +++++- app/config.py | 41 ++++++++++++++----- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/ansible/inventory/group_vars/vault.yml.example b/ansible/inventory/group_vars/vault.yml.example index 8d1971b..2a0d4dc 100644 --- a/ansible/inventory/group_vars/vault.yml.example +++ b/ansible/inventory/group_vars/vault.yml.example @@ -1,6 +1,14 @@ --- # Mit `ansible-vault encrypt group_vars/vault.yml` verschluesseln, NIEMALS # im Klartext committen (siehe Konzept 6.4/7.3). -vault_jumphost_kek: "CHANGE_ME_32_BYTES_HEX_0123456789abcdef0123456789abcdef" -vault_jumphost_session_secret: "CHANGE_ME_32_BYTES_HEX_0123456789abcdef0123456789abcdef" +# +# vault_jumphost_kek / vault_jumphost_session_secret MUESSEN je ein +# 64-Zeichen-Hex-String sein (= 32 Byte / 256 Bit Rohentropie nach dem +# Hex-Dekodieren durch app/config.py). Erzeugen mit z.B.: +# openssl rand -hex 32 +# Ein zu kurzer/langer oder nicht-hexadezimaler Wert fuehrt beim Start der +# jumphost-app zu "KEK muss genau 32 Bytes (256 Bit) lang sein." bzw. der +# analogen Fehlermeldung fuer das Session-Secret. +vault_jumphost_kek: "CHANGE_ME_RUN_openssl_rand_-hex_32" +vault_jumphost_session_secret: "CHANGE_ME_RUN_openssl_rand_-hex_32" vault_jumphost_initial_admin_password: "CHANGE_ME_STRONG_PASSWORD" diff --git a/app/config.py b/app/config.py index 46595c3..9169044 100644 --- a/app/config.py +++ b/app/config.py @@ -16,21 +16,40 @@ from pathlib import Path def _read_credential(name: str, env_fallback: str | None = None, *, required: bool = True) -> bytes | None: - """Liest ein Secret aus $CREDENTIALS_DIRECTORY (systemd-creds) oder Fallback-Env.""" + """Liest ein Secret aus $CREDENTIALS_DIRECTORY (systemd-creds) oder Fallback-Env. + + Der Wert wird als Hex-String erwartet (z.B. per `openssl rand -hex 32` + erzeugt) und hier zu den zugrundeliegenden Rohbytes dekodiert -- passend + zum selben Format, das auch fuer JUMPHOST_DEV_KEK/JUMPHOST_DEV_SESSION_SECRET + im development-Zweig unten verwendet wird (s. Konzept 6.4). Vorher wurde + dieser Wert hier NICHT dekodiert, sondern roh als Bytes interpretiert -- + das fuehrte bei einem korrekt per `openssl rand -hex 32` erzeugten + 64-Zeichen-Hex-String (= 32 Byte Entropie) zu einer 64-Byte-Rohlaenge und + damit zum Fehler "KEK muss genau 32 Bytes lang sein". + """ cred_dir = os.environ.get("CREDENTIALS_DIRECTORY") + raw: bytes | None = None if cred_dir: cred_path = Path(cred_dir) / name if cred_path.exists(): - return cred_path.read_bytes().strip() - if env_fallback and env_fallback in os.environ: - return os.environ[env_fallback].encode() - if required: + raw = cred_path.read_bytes().strip() + if raw is None and env_fallback and env_fallback in os.environ: + raw = os.environ[env_fallback].strip().encode() + if raw is None: + if required: + raise RuntimeError( + f"Secret '{name}' weder ueber systemd-creds noch ueber Env-Variable " + f"'{env_fallback}' verfuegbar. In Produktion MUSS dies ueber " + f"systemd LoadCredentialEncrypted= bereitgestellt werden." + ) + return None + try: + return bytes.fromhex(raw.decode("ascii")) + except (ValueError, UnicodeDecodeError) as exc: raise RuntimeError( - f"Secret '{name}' weder ueber systemd-creds noch ueber Env-Variable " - f"'{env_fallback}' verfuegbar. In Produktion MUSS dies ueber " - f"systemd LoadCredentialEncrypted= bereitgestellt werden." - ) - return None + f"Secret '{name}' ist kein gueltiger Hex-String (erwartet z.B. das " + f"Ergebnis von `openssl rand -hex 32`)." + ) from exc @dataclass @@ -70,6 +89,8 @@ class Settings: if len(self.kek) != 32: raise RuntimeError("KEK muss genau 32 Bytes (256 Bit) lang sein.") + if len(self.session_secret) != 32: + raise RuntimeError("Session-Secret muss genau 32 Bytes (256 Bit) lang sein.") settings = Settings()