feat(creds): implement NK-WP-0004 Credential Management Foundation
- .sops.yaml + keys/age.pub: SOPS age encryption for all secrets/ paths
- .gitignore: broad secrets/ catch-all (any depth)
- .githooks/pre-commit: blocks unencrypted secrets/, *.env outside bootstrap/,
and known plaintext patterns (PI_SECRET_KEY=, LLDAP_JWT_SECRET=, etc.)
- Makefile: full credential lifecycle (creds-init/generate/bundle/apply/verify/
status/rotate) + SOPS helpers (sops-setup/edit/encrypt/decrypt/rotate/check-secrets)
+ hooks/hooks-test
- creds-apply.sh: runs create-secrets.sh in dependency order (postgresql → lldap →
authelia → privacyidea), skips keycape with printed instructions, updates state
- creds-verify.sh: checks all K8s secrets exist, updates creds-state.yaml
- creds-status.sh: human-readable state table from creds-state.yaml
- creds-rotate.sh: guided rotation for all 9 secret types with impact descriptions
and atomic multi-component update sequences
- creds-state.yaml: committable state file tracking generation, bundle, KeePassXC
confirmation, per-component apply status, enckey and pi-admin bootstrap flags
NK-WP-0003-T01 unblocked. /creds-bootstrap skill registered separately.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 23:39:35 +00:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
# creds-status.sh — print a human-readable credential state table.
|
|
|
|
|
#
|
|
|
|
|
# Usage:
|
feat(creds): NK-WP-0005 — agent-driven credential bootstrap
Implements all 7 tasks from NK-WP-0005:
T01: creds-state.yaml → schema_version: 2, agent_mode: true
Replaces keepass_confirmed with emergency_bundle_delivered,
adds phase tracking fields for fully automated flow.
T02: creds-bootstrap-agent.sh — single entrypoint for autonomous
bootstrap. 10 phases, idempotent re-runs via state file.
Only human touchpoint: emergency bundle confirmation gate.
T03: emergency-bundle.sh — assembles and displays emergency bundle
(age key + break-glass passwords + ops bundle location).
Writes temp file, shreds on confirmation, clears screen.
Supports --reprint for re-delivery.
T04: ~/.claude/commands/creds-init.md — /creds-init skill replaces
/creds-bootstrap. Fully autonomous execution via the agent.
T05: Makefile — creds-agent-init, creds-agent-status,
creds-emergency-reprint targets.
T06: creds-rotate.sh — --non-interactive flag for agent-driven
rotation. Auto-confirms all gates; tracks last_rotated_<key>
in creds-state.yaml. LLDAP web UI step prints warning in
non-interactive mode.
T07: canon/standards/credential-management_v0.2.md — updated
standard: KeePassXC removed from operational path, agent
bootstrap as Phase 0, emergency bundle section, prohibited
patterns updated.
Also: creds-status.sh handles both schema v1 (legacy) and v2.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 08:38:52 +00:00
|
|
|
# bash sso-mfa/bootstrap/creds-status.sh [state-file] [--v2]
|
feat(creds): implement NK-WP-0004 Credential Management Foundation
- .sops.yaml + keys/age.pub: SOPS age encryption for all secrets/ paths
- .gitignore: broad secrets/ catch-all (any depth)
- .githooks/pre-commit: blocks unencrypted secrets/, *.env outside bootstrap/,
and known plaintext patterns (PI_SECRET_KEY=, LLDAP_JWT_SECRET=, etc.)
- Makefile: full credential lifecycle (creds-init/generate/bundle/apply/verify/
status/rotate) + SOPS helpers (sops-setup/edit/encrypt/decrypt/rotate/check-secrets)
+ hooks/hooks-test
- creds-apply.sh: runs create-secrets.sh in dependency order (postgresql → lldap →
authelia → privacyidea), skips keycape with printed instructions, updates state
- creds-verify.sh: checks all K8s secrets exist, updates creds-state.yaml
- creds-status.sh: human-readable state table from creds-state.yaml
- creds-rotate.sh: guided rotation for all 9 secret types with impact descriptions
and atomic multi-component update sequences
- creds-state.yaml: committable state file tracking generation, bundle, KeePassXC
confirmation, per-component apply status, enckey and pi-admin bootstrap flags
NK-WP-0003-T01 unblocked. /creds-bootstrap skill registered separately.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 23:39:35 +00:00
|
|
|
# make creds-status
|
feat(creds): NK-WP-0005 — agent-driven credential bootstrap
Implements all 7 tasks from NK-WP-0005:
T01: creds-state.yaml → schema_version: 2, agent_mode: true
Replaces keepass_confirmed with emergency_bundle_delivered,
adds phase tracking fields for fully automated flow.
T02: creds-bootstrap-agent.sh — single entrypoint for autonomous
bootstrap. 10 phases, idempotent re-runs via state file.
Only human touchpoint: emergency bundle confirmation gate.
T03: emergency-bundle.sh — assembles and displays emergency bundle
(age key + break-glass passwords + ops bundle location).
Writes temp file, shreds on confirmation, clears screen.
Supports --reprint for re-delivery.
T04: ~/.claude/commands/creds-init.md — /creds-init skill replaces
/creds-bootstrap. Fully autonomous execution via the agent.
T05: Makefile — creds-agent-init, creds-agent-status,
creds-emergency-reprint targets.
T06: creds-rotate.sh — --non-interactive flag for agent-driven
rotation. Auto-confirms all gates; tracks last_rotated_<key>
in creds-state.yaml. LLDAP web UI step prints warning in
non-interactive mode.
T07: canon/standards/credential-management_v0.2.md — updated
standard: KeePassXC removed from operational path, agent
bootstrap as Phase 0, emergency bundle section, prohibited
patterns updated.
Also: creds-status.sh handles both schema v1 (legacy) and v2.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 08:38:52 +00:00
|
|
|
# make creds-agent-status
|
feat(creds): implement NK-WP-0004 Credential Management Foundation
- .sops.yaml + keys/age.pub: SOPS age encryption for all secrets/ paths
- .gitignore: broad secrets/ catch-all (any depth)
- .githooks/pre-commit: blocks unencrypted secrets/, *.env outside bootstrap/,
and known plaintext patterns (PI_SECRET_KEY=, LLDAP_JWT_SECRET=, etc.)
- Makefile: full credential lifecycle (creds-init/generate/bundle/apply/verify/
status/rotate) + SOPS helpers (sops-setup/edit/encrypt/decrypt/rotate/check-secrets)
+ hooks/hooks-test
- creds-apply.sh: runs create-secrets.sh in dependency order (postgresql → lldap →
authelia → privacyidea), skips keycape with printed instructions, updates state
- creds-verify.sh: checks all K8s secrets exist, updates creds-state.yaml
- creds-status.sh: human-readable state table from creds-state.yaml
- creds-rotate.sh: guided rotation for all 9 secret types with impact descriptions
and atomic multi-component update sequences
- creds-state.yaml: committable state file tracking generation, bundle, KeePassXC
confirmation, per-component apply status, enckey and pi-admin bootstrap flags
NK-WP-0003-T01 unblocked. /creds-bootstrap skill registered separately.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 23:39:35 +00:00
|
|
|
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
|
STATE_FILE="${1:-$SCRIPT_DIR/creds-state.yaml}"
|
|
|
|
|
|
feat(creds): NK-WP-0005 — agent-driven credential bootstrap
Implements all 7 tasks from NK-WP-0005:
T01: creds-state.yaml → schema_version: 2, agent_mode: true
Replaces keepass_confirmed with emergency_bundle_delivered,
adds phase tracking fields for fully automated flow.
T02: creds-bootstrap-agent.sh — single entrypoint for autonomous
bootstrap. 10 phases, idempotent re-runs via state file.
Only human touchpoint: emergency bundle confirmation gate.
T03: emergency-bundle.sh — assembles and displays emergency bundle
(age key + break-glass passwords + ops bundle location).
Writes temp file, shreds on confirmation, clears screen.
Supports --reprint for re-delivery.
T04: ~/.claude/commands/creds-init.md — /creds-init skill replaces
/creds-bootstrap. Fully autonomous execution via the agent.
T05: Makefile — creds-agent-init, creds-agent-status,
creds-emergency-reprint targets.
T06: creds-rotate.sh — --non-interactive flag for agent-driven
rotation. Auto-confirms all gates; tracks last_rotated_<key>
in creds-state.yaml. LLDAP web UI step prints warning in
non-interactive mode.
T07: canon/standards/credential-management_v0.2.md — updated
standard: KeePassXC removed from operational path, agent
bootstrap as Phase 0, emergency bundle section, prohibited
patterns updated.
Also: creds-status.sh handles both schema v1 (legacy) and v2.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 08:38:52 +00:00
|
|
|
# --v2 flag forces v2 display regardless of schema_version field
|
|
|
|
|
FORCE_V2=false
|
|
|
|
|
for arg in "$@"; do [[ "$arg" == "--v2" ]] && FORCE_V2=true; done
|
|
|
|
|
|
feat(creds): implement NK-WP-0004 Credential Management Foundation
- .sops.yaml + keys/age.pub: SOPS age encryption for all secrets/ paths
- .gitignore: broad secrets/ catch-all (any depth)
- .githooks/pre-commit: blocks unencrypted secrets/, *.env outside bootstrap/,
and known plaintext patterns (PI_SECRET_KEY=, LLDAP_JWT_SECRET=, etc.)
- Makefile: full credential lifecycle (creds-init/generate/bundle/apply/verify/
status/rotate) + SOPS helpers (sops-setup/edit/encrypt/decrypt/rotate/check-secrets)
+ hooks/hooks-test
- creds-apply.sh: runs create-secrets.sh in dependency order (postgresql → lldap →
authelia → privacyidea), skips keycape with printed instructions, updates state
- creds-verify.sh: checks all K8s secrets exist, updates creds-state.yaml
- creds-status.sh: human-readable state table from creds-state.yaml
- creds-rotate.sh: guided rotation for all 9 secret types with impact descriptions
and atomic multi-component update sequences
- creds-state.yaml: committable state file tracking generation, bundle, KeePassXC
confirmation, per-component apply status, enckey and pi-admin bootstrap flags
NK-WP-0003-T01 unblocked. /creds-bootstrap skill registered separately.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 23:39:35 +00:00
|
|
|
if [[ ! -f "$STATE_FILE" ]]; then
|
|
|
|
|
echo "ERROR: creds-state.yaml not found: $STATE_FILE" >&2
|
|
|
|
|
echo " This file is created at repo init — check your working directory." >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Simple key extractors (no yaml lib dependency)
|
|
|
|
|
top_val() { grep -E "^$1:" "$STATE_FILE" | sed 's/^[^:]*: *//' | sed 's/ *#.*//' | tr -d '"'; }
|
|
|
|
|
nested_val() { grep -E "^ $1:" "$STATE_FILE" | sed 's/^[^:]*: *//' | sed 's/ *#.*//' | tr -d '"'; }
|
|
|
|
|
|
|
|
|
|
status_icon() {
|
|
|
|
|
case "$1" in
|
|
|
|
|
true) echo "✔" ;;
|
|
|
|
|
false) echo "✗" ;;
|
|
|
|
|
null) echo "—" ;;
|
|
|
|
|
*) echo "?" ;;
|
|
|
|
|
esac
|
|
|
|
|
}
|
|
|
|
|
|
feat(creds): NK-WP-0005 — agent-driven credential bootstrap
Implements all 7 tasks from NK-WP-0005:
T01: creds-state.yaml → schema_version: 2, agent_mode: true
Replaces keepass_confirmed with emergency_bundle_delivered,
adds phase tracking fields for fully automated flow.
T02: creds-bootstrap-agent.sh — single entrypoint for autonomous
bootstrap. 10 phases, idempotent re-runs via state file.
Only human touchpoint: emergency bundle confirmation gate.
T03: emergency-bundle.sh — assembles and displays emergency bundle
(age key + break-glass passwords + ops bundle location).
Writes temp file, shreds on confirmation, clears screen.
Supports --reprint for re-delivery.
T04: ~/.claude/commands/creds-init.md — /creds-init skill replaces
/creds-bootstrap. Fully autonomous execution via the agent.
T05: Makefile — creds-agent-init, creds-agent-status,
creds-emergency-reprint targets.
T06: creds-rotate.sh — --non-interactive flag for agent-driven
rotation. Auto-confirms all gates; tracks last_rotated_<key>
in creds-state.yaml. LLDAP web UI step prints warning in
non-interactive mode.
T07: canon/standards/credential-management_v0.2.md — updated
standard: KeePassXC removed from operational path, agent
bootstrap as Phase 0, emergency bundle section, prohibited
patterns updated.
Also: creds-status.sh handles both schema v1 (legacy) and v2.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 08:38:52 +00:00
|
|
|
SCHEMA_VER="$(top_val schema_version)"
|
|
|
|
|
|
|
|
|
|
if [[ "$SCHEMA_VER" == "2" || "$FORCE_V2" == "true" ]]; then
|
|
|
|
|
# ── Schema v2: agent-driven model (NK-WP-0005) ────────────────────────────
|
|
|
|
|
echo "=== net-kingdom Credential State (v2 — agent mode) ==="
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
age_key="$(top_val age_key_present)"
|
|
|
|
|
secrets_gen="$(top_val secrets_generated)"
|
|
|
|
|
ops_bundle="$(top_val ops_bundle_created)"
|
|
|
|
|
ops_loc="$(top_val ops_bundle_location)"
|
|
|
|
|
emerg_delivered="$(top_val emergency_bundle_delivered)"
|
|
|
|
|
emerg_at="$(top_val emergency_bundle_delivered_at)"
|
|
|
|
|
bootstrap_complete="$(top_val bootstrap_complete)"
|
|
|
|
|
|
|
|
|
|
printf " %-32s %s\n" "age key present:" "$(status_icon "$age_key")"
|
|
|
|
|
printf " %-32s %s\n" "secrets generated:" "$(status_icon "$secrets_gen")"
|
|
|
|
|
printf " %-32s %s %s\n" "ops bundle created:" \
|
|
|
|
|
"$(status_icon "$ops_bundle")" \
|
|
|
|
|
"$([ "$ops_bundle" = "true" ] && echo "${ops_loc:-}" || true)"
|
|
|
|
|
printf " %-32s %s %s\n" "emergency bundle delivered:" \
|
|
|
|
|
"$(status_icon "$emerg_delivered")" \
|
|
|
|
|
"$([ "$emerg_delivered" = "true" ] && echo "at ${emerg_at:-<unknown>}" || echo "(pending human confirmation)")"
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
echo " Secrets applied:"
|
|
|
|
|
for component in postgres lldap authelia privacyidea keycape; do
|
|
|
|
|
val="$(nested_val "$component")"
|
|
|
|
|
printf " %-28s %s\n" "$component" "$(status_icon "$val")"
|
|
|
|
|
done
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
enckey="$(top_val enckey_bootstrapped)"
|
|
|
|
|
pi_admin="$(top_val pi_admin_created)"
|
|
|
|
|
|
|
|
|
|
printf " %-32s %s\n" "enckey bootstrapped:" "$(status_icon "$enckey")"
|
|
|
|
|
printf " %-32s %s\n" "pi-admin created:" "$(status_icon "$pi_admin")"
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
printf " %-32s %s\n" "bootstrap complete:" "$(status_icon "$bootstrap_complete")"
|
|
|
|
|
echo ""
|
|
|
|
|
echo "Run 'make creds-verify' to refresh secrets_applied state from the live cluster."
|
|
|
|
|
echo "Run 'make creds-agent-init' to resume bootstrap if not complete."
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
# ── Schema v1: human-as-operator model (NK-WP-0004, legacy) ──────────────
|
|
|
|
|
echo "=== net-kingdom Credential State (v1 — human mode) ==="
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
generated_at="$(top_val generated_at)"
|
|
|
|
|
bundle_at="$(top_val bundle_at)"
|
|
|
|
|
keepass_confirmed="$(top_val keepass_confirmed)"
|
|
|
|
|
|
|
|
|
|
printf " %-30s %s\n" "Generated at:" "${generated_at:-—}"
|
|
|
|
|
printf " %-30s %s\n" "Bundle at:" "${bundle_at:-—}"
|
|
|
|
|
printf " %-30s %s %s\n" "KeePassXC confirmed:" \
|
|
|
|
|
"$(status_icon "$keepass_confirmed")" \
|
|
|
|
|
"$([ "$keepass_confirmed" = "false" ] && echo "(set keepass_confirmed: true manually)" || true)"
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
echo " Secrets applied:"
|
|
|
|
|
for component in postgres lldap authelia privacyidea keycape; do
|
|
|
|
|
val="$(nested_val "$component")"
|
|
|
|
|
note=""
|
|
|
|
|
[[ "$component" == "keycape" && "$val" == "false" ]] && \
|
|
|
|
|
note=" (requires PI_ADMIN_TOKEN — post-T04)"
|
|
|
|
|
printf " %-28s %s%s\n" "$component" "$(status_icon "$val")" "$note"
|
|
|
|
|
done
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
enckey="$(top_val enckey_bootstrapped)"
|
|
|
|
|
pi_admin="$(top_val pi_admin_created)"
|
|
|
|
|
|
|
|
|
|
printf " %-30s %s%s\n" "enckey bootstrapped:" \
|
|
|
|
|
"$(status_icon "$enckey")" \
|
|
|
|
|
"$([ "$enckey" = "false" ] && echo " ← TIME-SENSITIVE once pod is live" || true)"
|
|
|
|
|
printf " %-30s %s\n" "pi-admin created:" "$(status_icon "$pi_admin")"
|
|
|
|
|
|
|
|
|
|
echo ""
|
|
|
|
|
echo "Run 'make creds-verify' to refresh state from the live cluster."
|
|
|
|
|
fi
|