Phase 1 (author-only): Flux + SOPS bootstrap + interface wiring (T-1.4)
bootstrap/sops (age-keygen refusing in-repo, .sops.yaml, install-age-key.sh glue installing the sops-age Secret) + bootstrap/flux (bootstrap.sh: flux install -> apply -k clusters/dev; decryption/url patches). PM wiring: place .sops.yaml at repo root (SOPS walks to root); inline the 3 flux patches into clusters/dev (avoids kustomize ../ load-restriction). clusters/dev builds with decryption enabled; full CI gate PASS. No key material; nothing executed. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
1 parent
0e901f135c
commit
84a2d762f0
12 files changed
+573
-4
No files matched your search
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
# bootstrap/sops/install-age-key.sh — install the age PRIVATE key into the cluster as the
|
||||
# `sops-age` Secret in flux-system, so Flux can decrypt SOPS-encrypted manifests (ADR-0007,
|
||||
# R-SEC-01). This is the scripted form of the runbook in age-key-secret.md, and the entrypoint
|
||||
# the Ansible flux_bootstrap role calls (flux_bootstrap_sops_cmd) BEFORE bootstrap.sh.
|
||||
#
|
||||
# The private key NEVER lives in git. It is read from AGE_KEY_FILE (default: the standard sops
|
||||
# age path) and passed to kubectl from a file (not argv). Run at bootstrap by the OPERATOR — not
|
||||
# by any agent, and not during author-only Phase 1.
|
||||
set -euo pipefail
|
||||
AGE_KEY_FILE="${AGE_KEY_FILE:-${HOME}/.config/sops/age/keys.txt}"
|
||||
NAMESPACE="${FLUX_NAMESPACE:-flux-system}"
|
||||
SECRET_NAME="${SOPS_SECRET_NAME:-sops-age}"
|
||||
|
||||
[ -f "$AGE_KEY_FILE" ] || { echo "ERROR: age key not found at ${AGE_KEY_FILE} — run age-keygen.sh first." >&2; exit 1; }
|
||||
grep -q 'AGE-SECRET-KEY-' "$AGE_KEY_FILE" || { echo "ERROR: ${AGE_KEY_FILE} contains no AGE-SECRET-KEY." >&2; exit 1; }
|
||||
|
||||
kubectl get namespace "$NAMESPACE" >/dev/null 2>&1 || kubectl create namespace "$NAMESPACE"
|
||||
|
||||
# Flux reads keys ending in `.agekey` from the sops-age Secret. Idempotent create-or-update;
|
||||
# the key is streamed from the file, never placed on the command line / in shell history.
|
||||
kubectl create secret generic "$SECRET_NAME" \
|
||||
--namespace "$NAMESPACE" \
|
||||
--from-file=age.agekey="$AGE_KEY_FILE" \
|
||||
--dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
echo "Installed Secret ${NAMESPACE}/${SECRET_NAME} for Flux SOPS decryption."
|
||||
Reference in new issue
Block a user