Files
2026-09-07 11:55:21 +02:00

96 lines
4.0 KiB
Bash
Executable File

#!/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
# "<fingerprint> <uid>" - 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
}