chore(k8s): live config values in overlay, script to fill missing secrets
- overlays/encry configmaps now carry the live cluster values (runbook step 1) plus OIDC_CLIENT_ID; kubectl diff against the cluster is empty. - deploy/k8s/scripts/ensure-secrets.sh adds missing secret keys without touching existing ones (random encryption keys, empty Open-Meteo key, TELEGRAM_BOT_TOKEN=dummy) and never prints values. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
dd1eecdfa0
commit
6e3e9aee9b
3 files changed
+86
-7
No files matched your search
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env bash
|
||||
# Ergaenzt fehlende Schluessel in den ApiCore-Secrets, ohne vorhandene Werte
|
||||
# zu aendern. Gibt nur Schluesselnamen aus, nie Werte. Mehrfach ausfuehrbar.
|
||||
#
|
||||
# bash deploy/k8s/scripts/ensure-secrets.sh # Namespace apicore
|
||||
# bash deploy/k8s/scripts/ensure-secrets.sh --dry-run # nur anzeigen
|
||||
#
|
||||
# Werte:
|
||||
# - MFA_/WEBHOOK_/BACKUP_ENCRYPTION_KEY: zufaellig (48 Byte, base64url). Die
|
||||
# App verlangt mindestens 32 Zeichen; "dummy" wuerde den Start abbrechen.
|
||||
# Diese Schluessel nie wieder aendern ohne *_PREVIOUS (sonst sind MFA-
|
||||
# Geheimnisse, Webhook-Secrets und Backups nicht mehr lesbar). Sichern!
|
||||
# - OPEN_METEO_API_KEY: leer = freie Open-Meteo-API (ein Fantasiewert wuerde
|
||||
# die kostenpflichtige API mit falschem Schluessel ansprechen).
|
||||
# - TELEGRAM_BOT_TOKEN (Secret apicore-telegram, nur Worker): "dummy". Die App
|
||||
# erkennt ein ungueltiges Format und schaltet Telegram ab, bis das echte
|
||||
# Token von BotFather eingetragen ist.
|
||||
set -euo pipefail
|
||||
|
||||
NS="${NAMESPACE:-apicore}"
|
||||
DRY_RUN=false
|
||||
[[ "${1:-}" == "--dry-run" ]] && DRY_RUN=true
|
||||
|
||||
random_key() {
|
||||
node -e "process.stdout.write(require('crypto').randomBytes(48).toString('base64url'))"
|
||||
}
|
||||
|
||||
existing_keys() {
|
||||
kubectl get secret "$1" -n "$NS" -o jsonpath='{.data}' 2>/dev/null \
|
||||
| node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{try{console.log(Object.keys(JSON.parse(s||'{}')).join('\n'))}catch{}})"
|
||||
}
|
||||
|
||||
# ensure_keys <secret> <key> <random|empty|dummy> [<key> <mode> ...]
|
||||
ensure_keys() {
|
||||
local secret="$1"; shift
|
||||
local have
|
||||
have="$(existing_keys "$secret")"
|
||||
local patch="{}" added=()
|
||||
while (($#)); do
|
||||
local key="$1" mode="$2"; shift 2
|
||||
if grep -qx "$key" <<<"$have"; then
|
||||
continue
|
||||
fi
|
||||
local value
|
||||
case "$mode" in
|
||||
random) value="$(random_key)" ;;
|
||||
empty) value="" ;;
|
||||
dummy) value="dummy" ;;
|
||||
esac
|
||||
patch="$(KEY="$key" VALUE="$value" PATCH="$patch" node -e "const p=JSON.parse(process.env.PATCH);p.stringData=p.stringData||{};p.stringData[process.env.KEY]=process.env.VALUE;process.stdout.write(JSON.stringify(p))")"
|
||||
added+=("$key")
|
||||
done
|
||||
if ((${#added[@]} == 0)); then
|
||||
echo "$secret: alle Schluessel vorhanden"
|
||||
return
|
||||
fi
|
||||
if $DRY_RUN; then
|
||||
echo "$secret: wuerde ergaenzen: ${added[*]}"
|
||||
return
|
||||
fi
|
||||
if ! kubectl get secret "$secret" -n "$NS" >/dev/null 2>&1; then
|
||||
kubectl create secret generic "$secret" -n "$NS" >/dev/null
|
||||
fi
|
||||
kubectl patch secret "$secret" -n "$NS" --type merge -p "$patch" >/dev/null
|
||||
echo "$secret: ergaenzt: ${added[*]}"
|
||||
}
|
||||
|
||||
ensure_keys apicore-backend-secret \
|
||||
MFA_ENCRYPTION_KEY random \
|
||||
WEBHOOK_ENCRYPTION_KEY random \
|
||||
BACKUP_ENCRYPTION_KEY random \
|
||||
OPEN_METEO_API_KEY empty
|
||||
|
||||
ensure_keys apicore-telegram \
|
||||
TELEGRAM_BOT_TOKEN dummy
|
||||
|
||||
echo "Fertig. Laufende Pods lesen neue Werte erst nach einem Neustart."
|
||||
Reference in new issue
Block a user