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

@ -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()