#!/bin/bash # Gemeinsame Hilfsfunktionen beider Spiegel-Container: den EXTERN erzeugten # Signing-Key aus dem read-only gemounteten $GPG_SOURCE uebernehmen und # pruefen, ob damit unbeaufsichtigt signiert werden kann. # # ACHTUNG: identische Kopie in dnf-mirror/gpg-import.sh - Aenderungen bitte in # beiden pflegen. (Getrennte Build-Kontexte je Image; ein gemeinsamer Kontext # wuerde das Schluesselverzeichnis ./gpg in den Build-Kontext ziehen.) # Die Dateien, die ein GnuPG-Homedir ausmachen. Bewusst eine feste Liste statt # "cp -a .": im Quellverzeichnis liegen oft noch die Agent-Sockets # (S.gpg-agent & Co.) und Lock-Dateien eines gpg-agent, der auf dem HOST # lief/laeuft. Die haben im Container nichts verloren. GPG_HOME_ENTRIES=(pubring.kbx pubring.gpg secring.gpg trustdb.gpg \ private-keys-v1.d openpgp-revocs.d public-keys.d) import_shared_gpg() { if [ ! -d "$GPG_SOURCE" ]; then echo "[gpg] FEHLER: $GPG_SOURCE ist nicht gemountet - fehlt der Ordner ./gpg?" >&2 return 1 fi rm -rf "$GNUPGHOME" mkdir -p "$GNUPGHOME" chmod 700 "$GNUPGHOME" local entry copied=0 for entry in "${GPG_HOME_ENTRIES[@]}"; do [ -e "$GPG_SOURCE/$entry" ] || continue # Kein "|| true": schlaegt das Kopieren des Schluesselmaterials fehl, # soll das laut und sofort auffallen statt spaeter als "Key nicht # gefunden". cp -a "$GPG_SOURCE/$entry" "$GNUPGHOME/" copied=1 done if [ "$copied" -eq 0 ]; then echo "[gpg] FEHLER: in $GPG_SOURCE liegt kein GnuPG-Schluesselbund." >&2 echo "[gpg] Erwartet wird der INHALT eines GnuPG-Homedirs (pubring.kbx," >&2 echo "[gpg] private-keys-v1.d, ...), nicht z.B. eine exportierte .asc-Datei." >&2 echo "[gpg] Tatsaechlicher Inhalt:" >&2 ls -la "$GPG_SOURCE" >&2 return 1 fi chmod -R go-rwx "$GNUPGHOME" # Signiert wird unbeaufsichtigt, also nie ein Pinentry-Fenster erwarten. echo "allow-loopback-pinentry" > "$GNUPGHOME/gpg-agent.conf" echo "pinentry-mode loopback" > "$GNUPGHOME/gpg.conf" } # Listet die im Homedir tatsaechlich vorhandenen geheimen Schluessel als # " " - genau das, was als GPG_KEY_ID in die .env gehoert. list_available_secret_keys() { gpg --batch --list-secret-keys --with-colons 2>/dev/null | awk -F: ' $1 == "sec" { want = 1; fpr = ""; next } $1 == "fpr" && want { fpr = $10; want = 0; next } $1 == "uid" && fpr != "" { print " " fpr " " $10; fpr = ""; next } ' } # Prueft nicht nur, OB der Key da ist, sondern ob damit auch wirklich # unbeaufsichtigt signiert werden kann - ein passphrasegeschuetzter Key faellt # sonst erst mitten im ersten Sync-Lauf auf. require_usable_signing_key() { if ! gpg --batch --list-secret-keys "$GPG_KEY_ID" >/dev/null 2>&1; then echo "[gpg] FEHLER: kein geheimer Schluessel '$GPG_KEY_ID' in ./gpg gefunden." >&2 local available available="$(list_available_secret_keys)" if [ -n "$available" ]; then echo "[gpg] Vorhanden sind:" >&2 echo "$available" >&2 echo "[gpg] Einen dieser Fingerprints als GPG_KEY_ID in die .env eintragen." >&2 else echo "[gpg] Der Schluesselbund enthaelt ueberhaupt keinen GEHEIMEN Schluessel" >&2 echo "[gpg] (nur oeffentliche?). private-keys-v1.d/ pruefen - dort muss" >&2 echo "[gpg] mindestens eine .key-Datei liegen." >&2 fi return 1 fi local err err="$(printf 'signing-selftest' \ | gpg --batch --yes --local-user "$GPG_KEY_ID" --detach-sign --output /dev/null - 2>&1)" && { echo "[gpg] Gemeinsamen Signing-Key '$GPG_KEY_ID' uebernommen, Testsignatur ok." return 0 } echo "[gpg] FEHLER: Schluessel '$GPG_KEY_ID' ist da, aber Signieren schlaegt fehl:" >&2 echo "$err" >&2 echo "[gpg] Haeufigste Ursache: der Key hat eine Passphrase. Unbeaufsichtigtes" >&2 echo "[gpg] Signieren braucht einen Key OHNE Passphrase (siehe README)." >&2 return 1 }