Files
homelab/scripts/ci/make-diag-kubeconfig.sh
claude-botandClaude Fable 5 90aeaf1ef8 feat(ci-agents): give triage/fix agents verified read-only live diagnostics
Both wrong assessments (#249 openbao 'sealed', #250 three untested
hypotheses while one 'kubectl logs' showed the 401) share one root
cause: the agents diagnose blind, so they narrate plausible fiction.
Labeling unverified claims (previous commit) treats the symptom; this
gives them the means to verify:

- kubernetes/apps/monitoring/ci-diagnostics-rbac.yaml: ServiceAccount
  ci-diagnostics with a read-only ClusterRole (workloads, events,
  pods/log, Flux/ESO/cert-manager/monitoring/ceph CRDs — NO secrets)
  plus a namespaced services/proxy Role for the Prometheus and
  Alertmanager HTTP APIs.
- scripts/ci/make-diag-kubeconfig.sh: mints a 1h token per run from
  the admin kubeconfig (no new long-lived secret), builds
  .ci-diag/kubeconfig, copies the static kubectl binary for the
  jq-only ci-claude image, smoke-tests with the restricted identity,
  and degrades to snapshot-only mode when the SA isn't reconciled.
- alert-monitor.yml / issue-fix.yml: agents get exactly one extra tool,
  Bash(./.ci-diag/kubectl:*) — prefix match forbids pipes and any other
  binary; RBAC forbids mutation and secret reads.
- prompts: verification is now mandatory, not aspirational — 'a
  hypothesis you could have settled with one read-only command but
  didn't is a defect in your output'; fix agent must test the issue's
  claims before building on them; minimal-quote rule against dumping
  logs into public issues.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NV7bZzZLeoFUEdAeCSLEei
2026-07-16 10:30:29 +02:00

43 lines
2.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Build .ci-diag/ in the CI workspace: a short-lived, least-privilege
# kubeconfig (ServiceAccount monitoring/ci-diagnostics, RBAC in
# kubernetes/apps/monitoring/ci-diagnostics-rbac.yaml) plus a copy of the
# kubectl binary, so a later ci-claude step (which ships no kubectl) can run
# read-only live diagnostics as ./.ci-diag/kubectl.
#
# Requires the admin kubeconfig at ~/.kube/config (fetch-kubeconfig.sh).
# Degrades gracefully: if the ServiceAccount does not exist yet (RBAC not
# reconciled), it prints a warning and exits 0 — agents then run in
# snapshot-only mode.
set -euo pipefail
DIAG_DIR=".ci-diag"
mkdir -p "$DIAG_DIR"
if ! TOKEN=$(kubectl -n monitoring create token ci-diagnostics --duration=1h 2>/dev/null); then
echo "WARNING: could not mint a ci-diagnostics token (ServiceAccount missing" \
"or no permission) — no $DIAG_DIR/kubeconfig, agents run snapshot-only."
exit 0
fi
SERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
kubectl config view --minify --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' \
| base64 -d > "$DIAG_DIR/ca.crt"
KC="$DIAG_DIR/kubeconfig"
kubectl --kubeconfig="$KC" config set-cluster homelab \
--server="$SERVER" --certificate-authority="$DIAG_DIR/ca.crt" --embed-certs=true >/dev/null
kubectl --kubeconfig="$KC" config set-credentials ci-diagnostics --token="$TOKEN" >/dev/null
kubectl --kubeconfig="$KC" config set-context diag --cluster=homelab --user=ci-diagnostics >/dev/null
kubectl --kubeconfig="$KC" config use-context diag >/dev/null
chmod 600 "$KC"
rm -f "$DIAG_DIR/ca.crt"
cp "$(command -v kubectl)" "$DIAG_DIR/kubectl"
# Smoke-test with the restricted identity so a broken RBAC surfaces HERE,
# in the pipeline log, not as a confusing tool failure inside the agent.
KUBECONFIG="$KC" "$DIAG_DIR/kubectl" get ns >/dev/null \
&& echo "diag kubeconfig OK (SA ci-diagnostics, 1h token)" \
|| { echo "WARNING: diag kubeconfig smoke test failed — removing it; agents run snapshot-only."; rm -f "$KC"; }