This commit is contained in:
2026-08-20 01:10:22 +02:00
parent 1229bb0cb5
commit 13547fb083
2 changed files with 41 additions and 12 deletions

View File

@ -1,6 +1,14 @@
--- ---
# Mit `ansible-vault encrypt group_vars/vault.yml` verschluesseln, NIEMALS # Mit `ansible-vault encrypt group_vars/vault.yml` verschluesseln, NIEMALS
# im Klartext committen (siehe Konzept 6.4/7.3). # 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" vault_jumphost_initial_admin_password: "CHANGE_ME_STRONG_PASSWORD"

View File

@ -16,21 +16,40 @@ from pathlib import Path
def _read_credential(name: str, env_fallback: str | None = None, *, required: bool = True) -> bytes | None: 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") cred_dir = os.environ.get("CREDENTIALS_DIRECTORY")
raw: bytes | None = None
if cred_dir: if cred_dir:
cred_path = Path(cred_dir) / name cred_path = Path(cred_dir) / name
if cred_path.exists(): if cred_path.exists():
return cred_path.read_bytes().strip() raw = cred_path.read_bytes().strip()
if env_fallback and env_fallback in os.environ: if raw is None and env_fallback and env_fallback in os.environ:
return os.environ[env_fallback].encode() raw = os.environ[env_fallback].strip().encode()
if required: 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( raise RuntimeError(
f"Secret '{name}' weder ueber systemd-creds noch ueber Env-Variable " f"Secret '{name}' ist kein gueltiger Hex-String (erwartet z.B. das "
f"'{env_fallback}' verfuegbar. In Produktion MUSS dies ueber " f"Ergebnis von `openssl rand -hex 32`)."
f"systemd LoadCredentialEncrypted= bereitgestellt werden." ) from exc
)
return None
@dataclass @dataclass
@ -70,6 +89,8 @@ class Settings:
if len(self.kek) != 32: if len(self.kek) != 32:
raise RuntimeError("KEK muss genau 32 Bytes (256 Bit) lang sein.") 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() settings = Settings()