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
SHELL := /usr/bin/env bash
.DEFAULT_GOAL := help
# Operator age public key — used as bundle encryption recipient
OPERATOR_AGE_PUBKEY := $( shell cat keys/age.pub 2>/dev/null | tr -d '[:space:]' )
2026-06-01 21:20:53 +02:00
SECURITY_BOOTSTRAP_METADATA ?= $( if $( METADATA) ,$( METADATA) ,.local/security-bootstrap.json)
SECURITY_BOOTSTRAP_HOST ?= $( if $( HOST) ,$( HOST) ,127.0.0.1)
SECURITY_BOOTSTRAP_PORT ?= $( if $( PORT) ,$( PORT) ,8876)
2026-06-02 00:24:18 +02:00
OPENBAO_RESTORE_EVIDENCE ?= /tmp/netkingdom-openbao-restore-drill/evidence.json
OPENBAO_EMERGENCY_EVIDENCE ?= /tmp/netkingdom-openbao-emergency-drill/evidence.json
2026-06-03 01:50:29 +02:00
BOOTSTRAP_CLEANUP_EVIDENCE ?= /tmp/netkingdom-bootstrap-cleanup/evidence.json
LIFECYCLE_FLOW_EVIDENCE ?= /tmp/netkingdom-lifecycle-flow/evidence.json
ONBOARDING_DRY_RUN_EVIDENCE ?= /tmp/netkingdom-onboarding-dry-run/evidence.json
2026-06-02 00:24:18 +02:00
RAILIANCE_PLATFORM_PATH ?= ../railiance-platform
2026-08-23 13:24:55 +02:00
KEY_CAPE_PATH ?= ../key-cape
2026-06-02 01:11:42 +02:00
CUSTODY_ROSTER ?= .local/custody-roster.json
CUSTODY_ROSTER_SIGNATURE ?= .local/custody-roster.json.sig
CUSTODY_ROSTER_ALLOWED_SIGNERS ?= .local/custody-roster.allowed_signers
CUSTODY_ROSTER_SIGNING_KEY ?= $( HOME) /.ssh/id_custodian_agent
CUSTODY_ROSTER_SIGNING_PRINCIPAL ?= platform-custodian
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
# ── Help ──────────────────────────────────────────────────────────────────────
help : ## Show this help
@echo "net-kingdom — available targets"
@echo ""
@grep -E '^[a-zA-Z0-9_-]+:.*?## ' $( MAKEFILE_LIST) \
| sort \
| awk 'BEGIN {FS = ":.*?## "}; {printf " %-28s %s\n", $$1, $$2}'
# ── Git hooks ─────────────────────────────────────────────────────────────────
hooks : ## Configure git to use repo-local hooks (.githooks)
@mkdir -p .githooks
git config core.hooksPath .githooks
@test -f .githooks/pre-commit \
|| ( echo "ERROR: .githooks/pre-commit not found" ; exit 1)
chmod +x .githooks/pre-commit
@echo "✔ git hooks enabled (.githooks/pre-commit is active)"
hooks-test : ## Test that the pre-commit hook blocks plaintext secrets
@mkdir -p sso-mfa/bootstrap/secrets/_hooktest
@echo 'PI_SECRET_KEY=deadbeef' > sso-mfa/bootstrap/secrets/_hooktest/test.env
@git add sso-mfa/bootstrap/secrets/_hooktest/test.env 2>/dev/null || true
@if git commit -m "TEST: hook must block this" 2>/dev/null; then \
echo "FAIL: hook did NOT block plaintext commit" ; \
git reset --soft HEAD~1 2>/dev/null || true; \
else \
echo "✔ Hook blocked plaintext as expected" ; \
fi
@git restore --staged sso-mfa/bootstrap/secrets/_hooktest/test.env 2>/dev/null || true
@rm -rf sso-mfa/bootstrap/secrets/_hooktest
# ── SOPS / age ────────────────────────────────────────────────────────────────
2026-06-14 19:51:05 +02:00
sops-setup : ## Legacy dev-local setup: copy age key to SOPS default path
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
@mkdir -p ~/.config/sops/age
@if [ [ -f ~/.config/age/key.txt ] ] ; then \
cp -n ~/.config/age/key.txt ~/.config/sops/age/keys.txt || true; \
chmod 600 ~/.config/sops/age/keys.txt; \
echo "✔ SOPS key ready at ~/.config/sops/age/keys.txt" ; \
elif [ [ -f ~/.config/sops/age/keys.txt ] ] ; then \
echo "✔ SOPS key already present at ~/.config/sops/age/keys.txt" ; \
else \
echo "ERROR: age key not found at ~/.config/age/key.txt" ; \
echo " Generate one with: age-keygen -o ~/.config/age/key.txt" ; \
exit 1; \
fi
sops-edit : ## Edit an encrypted file with SOPS: make sops-edit FILE=secrets/foo.yaml
@[ [ -n " $( FILE) " ] ] || ( echo "Usage: make sops-edit FILE=secrets/path/to/file.yaml" ; exit 1)
sops $( FILE)
sops-encrypt : ## Encrypt a file in place: make sops-encrypt FILE=secrets/foo.yaml
@[ [ -n " $( FILE) " ] ] || ( echo "Usage: make sops-encrypt FILE=secrets/path/to/file.yaml" ; exit 1)
sops --encrypt --in-place $( FILE)
@echo " ✔ Encrypted $( FILE) "
sops-decrypt : ## Decrypt a file to stdout (never writes plaintext to disk): make sops-decrypt FILE=secrets/foo.yaml
@[ [ -n " $( FILE) " ] ] || ( echo "Usage: make sops-decrypt FILE=secrets/path/to/file.yaml" ; exit 1)
sops -d $( FILE)
sops-rotate : ## Rotate SOPS recipients after updating .sops.yaml: make sops-rotate FILE=secrets/foo.yaml
@[ [ -n " $( FILE) " ] ] || ( echo "Usage: make sops-rotate FILE=secrets/path/to/file.yaml" ; exit 1)
sops --rotate --in-place $( FILE)
@echo " ✔ Recipients rotated for $( FILE) "
2026-06-14 19:51:05 +02:00
sops-custody-check : ## Validate a custody age key against keys/age.pub without keeping it on disk
@bash sso-mfa/bootstrap/sops-custody-unlock.sh \
--expected-recipient " $( OPERATOR_AGE_PUBKEY) " \
--check-only
sops-custody-shell : ## Open a shell with a temporary SOPS_AGE_KEY_FILE from custody material
@bash sso-mfa/bootstrap/sops-custody-unlock.sh \
--expected-recipient " $( OPERATOR_AGE_PUBKEY) "
sops-custody-run : ## Run COMMAND with a temporary custody age key: make sops-custody-run COMMAND='make -C ../inter-hub recovery-drill'
@[ [ -n " $( COMMAND) " ] ] || ( echo "Usage: make sops-custody-run COMMAND='make -C ../inter-hub recovery-drill'" ; exit 1)
@COMMAND= '$(COMMAND)' bash sso-mfa/bootstrap/sops-custody-unlock.sh \
--expected-recipient " $( OPERATOR_AGE_PUBKEY) " \
-- bash -lc " $$ COMMAND "
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
check-secrets : ## Fail if any file under secrets/ is not SOPS-encrypted
@echo "Checking for unencrypted files under secrets/..."
@bad= 0; \
while IFS = read -r f; do \
[ [ -z " $$ f " ] ] && continue ; \
if grep -qE '^[[:space:]]*sops:[[:space:]]*$$|"sops"[[:space:]]*:' " $$ f " 2>/dev/null; then \
continue ; \
fi ; \
case " $$ f " in *.age| *.gpg) continue ; ; esac ; \
echo " UNENCRYPTED: $$ f " ; bad = 1; \
2026-07-02 22:08:33 +02:00
done < <( git ls-files --others --cached 'secrets' 2>/dev/null | grep -v '/$$' ) ; \
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 [ [ " $$ bad " -ne 0 ] ] ; then \
echo "" ; \
echo "ERROR: Unencrypted secret(s) detected. Encrypt with: sops --encrypt --in-place <file>" ; \
exit 1; \
fi ; \
echo "✔ All secrets/ files appear SOPS-encrypted"
# ── Credential lifecycle ──────────────────────────────────────────────────────
creds-init : sops -setup hooks ## One-time setup: verify prerequisites, configure SOPS and git hooks
@echo "=== creds-init: checking prerequisites ==="
@command -v age >/dev/null 2>& 1 || ( echo "ERROR: age not installed (apt install age)" ; exit 1)
@command -v sops >/dev/null 2>& 1 || ( echo "ERROR: sops not installed (see https://github.com/getsops/sops/releases)" ; exit 1)
@command -v kubectl >/dev/null 2>& 1 \
&& echo "✔ kubectl found" \
|| echo "WARN: kubectl not found (required for creds-apply/verify)"
@test -f ~/.config/sops/age/keys.txt \
|| ( echo "ERROR: age key not found — run 'make sops-setup' after placing your key at ~/.config/age/key.txt" ; exit 1)
@echo ""
@echo "✔ creds-init complete. Next: make creds-generate"
creds-generate : ## Generate all service secrets and print KeePassXC entry guide
@command -v openssl >/dev/null 2>& 1 || ( echo "ERROR: openssl not found" ; exit 1)
cd sso-mfa/bootstrap && bash gen-secrets.sh
@sed -i " s|^generated_at: .*|generated_at: $$ (date -Iseconds)| " sso-mfa/bootstrap/creds-state.yaml
@echo ""
@echo "State: generated_at updated in sso-mfa/bootstrap/creds-state.yaml"
@echo "Next : enter values into KeePassXC, then set keepass_confirmed: true"
@echo " Run 'make creds-bundle' to create an encrypted offsite backup."
creds-bundle : ## Age-encrypt the ops bundle for offsite storage
@[ [ -n " $( OPERATOR_AGE_PUBKEY) " ] ] \
|| ( echo "ERROR: keys/age.pub not found — cannot determine encryption recipient" ; exit 1)
@[ [ -d sso-mfa/bootstrap/secrets ] ] \
|| ( echo "ERROR: sso-mfa/bootstrap/secrets/ not found — run 'make creds-generate' first" ; exit 1)
cd sso-mfa/bootstrap && bash pack-bundle.sh secrets " $( OPERATOR_AGE_PUBKEY) "
@sed -i " s|^bundle_at: .*|bundle_at: $$ (date -Iseconds)| " sso-mfa/bootstrap/creds-state.yaml
@echo ""
@echo "State: bundle_at updated in sso-mfa/bootstrap/creds-state.yaml"
@echo "Store the .tar.age bundle offsite (external drive, encrypted cloud, second location)."
creds-apply : ## Apply all create-secrets.sh scripts to the cluster in dependency order
bash sso-mfa/bootstrap/creds-apply.sh
creds-verify : ## Check all expected K8s secrets exist and update creds-state.yaml
bash sso-mfa/bootstrap/creds-verify.sh
creds-status : ## Print human-readable credential state from creds-state.yaml
bash sso-mfa/bootstrap/creds-status.sh
creds-rotate : ## Guided rotation for one secret: make creds-rotate SECRET=<name>
@[ [ -n " $( SECRET) " ] ] \
|| ( echo "Usage: make creds-rotate SECRET=<name>" ; \
echo "" ; \
echo "Known secrets:" ; \
echo " PI_SECRET_KEY PI_PEPPER PI_DB_PASSWORD LLDAP_JWT_SECRET" ; \
echo " LLDAP_LDAP_USER_PASS AUTHELIA_SESSION_SECRET" ; \
echo " AUTHELIA_KEYCAPE_CLIENT_SECRET KEYCAPE_RSA_KEY" ; \
echo " BREAKGLASS_PASSWORD" ; \
exit 1)
SECRET = $( SECRET) bash sso-mfa/bootstrap/creds-rotate.sh
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
## ── Agent-driven credential lifecycle (NK-WP-0005) ──────────────────────────
creds-agent-init : ## Fully automated credential bootstrap — generates, encrypts, injects, delivers emergency bundle
@bash sso-mfa/bootstrap/creds-bootstrap-agent.sh
creds-agent-status : ## Show current v2 bootstrap state (agent mode)
@bash sso-mfa/bootstrap/creds-status.sh --v2
creds-emergency-reprint : ## Re-deliver emergency bundle (if lost/stolen — reprints, rotates nothing)
@bash sso-mfa/bootstrap/emergency-bundle.sh --reprint
2026-07-02 11:01:34 +02:00
openbao-init-unseal : ## SOPS-held OpenBao init/unseal (NET-WP-0020 T2; requires sops-held-automation model selected)
@bash sso-mfa/bootstrap/openbao-init-unseal.sh
openbao-init-unseal-dry-run : ## Dry-run the SOPS-held OpenBao init/unseal path
@bash sso-mfa/bootstrap/openbao-init-unseal.sh --dry-run
2026-08-23 12:40:52 +02:00
iam-profile-conformance-test : ## Run current IAM Profile conformance fixture tests
2026-05-22 14:35:31 +02:00
python3 -m pytest tools/iam-profile-conformance/tests
2026-05-22 14:49:25 +02:00
playbook-contract-test : ## Run Playbook Capability Contract fixture tests
python3 -m pytest tools/playbook-capability-contract/tests
2026-08-23 12:40:52 +02:00
security-scenario-composer-test : ## Run deterministic security scenario composer tests
python3 -m pytest tools/security-scenario-composer/tests
security-scenario-compose-c0 : ## Compose the plan-only C0 local-identity reference
python3 tools/security-scenario-composer/security_scenario_composer.py \
--scenario examples/security-scenarios/c0-local-identity.yaml \
capabilities/playbooks/net-kingdom.local-identity.yaml
2026-08-23 13:24:55 +02:00
security-scenario-compose-lightweight : ## Compose plan-only KeyCape C1+C2b from owner declarations
python3 tools/security-scenario-composer/security_scenario_composer.py \
--scenario examples/security-scenarios/c1-c2b-key-cape.yaml \
$( KEY_CAPE_PATH) /capabilities/playbooks/key-cape.lightweight-sso.yaml \
$( KEY_CAPE_PATH) /capabilities/playbooks/key-cape.privacyidea-token-authority.yaml
2026-08-23 13:16:34 +02:00
posture-feedback-test : ## Run deterministic posture-feedback tests
python3 -m pytest tools/posture-feedback/tests tools/tenancy-posture/test_validate.py
posture-feedback-reference : ## Emit the proposal-only reference report at its fixed example time
python3 tools/posture-feedback/posture_feedback.py \
--as-of 2026-08-23T12:00:00Z \
--horizon-days 14 \
--fail-on none \
examples/posture-feedback/expired-e2.yaml
feat(NET-WP-0018-T07): add automated tests for bootstrap UI sections and runbooks
- Created tools/security-bootstrap-console/tests/test_security_bootstrap_console.py (pytest-based, 8 tests covering templates (incl. 0019 dry-run fields), runbook_payloads (T06 entry), audit_core_posture, etc. per layered spec + 0019 note)
- Makefile: added security-bootstrap-console-test (pytest), security-bootstrap-scripts-syntax (bash -n for key sh scripts like dry-run-nonroot-user.sh); integrated into .PHONY and bootstrap lists
- Updated workplan T07 status done + detailed note with pragmatic refs
- Tests pass (python -m pytest)
- Commit + will sync/fix/progress
- Covers console UI, validators, 0019 polish artifacts (orchestrator, cmds, claims, evidence) as required for T07
T07 complete. 6/9 now.
2026-06-03 17:28:21 +02:00
security-bootstrap-console-test : ## Run automated tests for bootstrap console UI/sections/runbooks (NET-WP-0018-T07)
python3 -m pytest tools/security-bootstrap-console/tests
# Syntax check for key bootstrap helper scripts (part of T07 layered tests)
security-bootstrap-scripts-syntax : ## Shell syntax check for bootstrap scripts
bash -n sso-mfa/k8s/lldap/dry-run-nonroot-user.sh
bash -n sso-mfa/k8s/lldap/create-user.sh
bash -n sso-mfa/k8s/lldap/break-glass.sh || true # may have env assumptions
@echo "✔ bootstrap scripts syntax OK"
2026-06-04 00:25:45 +02:00
security-bootstrap-validate-keycape-client : ## Validate KeyCape OpenBao client definition+deployment (T08)
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
--metadata " $( SECURITY_BOOTSTRAP_METADATA) " \
validate-keycape-client || true
2026-06-01 21:20:53 +02:00
security-bootstrap-console : security -bootstrap -metadata -init ## Show guided security bootstrap status and safe actions
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
--metadata " $( SECURITY_BOOTSTRAP_METADATA) " \
status
2026-05-24 09:26:02 +02:00
security-bootstrap-king-kit : ## Print the king credential kit checklist
python3 tools/security-bootstrap-console/security_bootstrap_console.py king-kit
2026-06-01 21:20:53 +02:00
security-bootstrap-validate-kit : ## Validate non-secret king credential metadata
2026-05-24 09:26:02 +02:00
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
2026-06-01 21:20:53 +02:00
--metadata " $( SECURITY_BOOTSTRAP_METADATA) " \
2026-05-24 09:26:02 +02:00
validate-king-kit
2026-06-02 00:24:18 +02:00
security-bootstrap-validate-t02 : ## Validate NET-WP-0017-T02 OpenBao audit/recovery gates
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
--metadata " $( SECURITY_BOOTSTRAP_METADATA) " \
validate-t02 \
--railiance-path " $( RAILIANCE_PLATFORM_PATH) " \
--restore-evidence " $( OPENBAO_RESTORE_EVIDENCE) " \
2026-06-02 01:11:42 +02:00
--emergency-evidence " $( OPENBAO_EMERGENCY_EVIDENCE) " \
--custody-roster " $( CUSTODY_ROSTER) " \
--custody-roster-signature " $( CUSTODY_ROSTER_SIGNATURE) " \
--custody-roster-allowed-signers " $( CUSTODY_ROSTER_ALLOWED_SIGNERS) "
2026-06-03 01:50:29 +02:00
security-bootstrap-validate-cleanup : ## Validate NET-WP-0017-T03/T04 cleanup and taint evidence
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
--metadata " $( SECURITY_BOOTSTRAP_METADATA) " \
validate-cleanup \
--evidence " $( BOOTSTRAP_CLEANUP_EVIDENCE) "
security-bootstrap-validate-lifecycle-flow : ## Validate NET-WP-0017-T05 lifecycle operator-flow evidence
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
validate-lifecycle-flow \
--evidence " $( LIFECYCLE_FLOW_EVIDENCE) "
security-bootstrap-validate-onboarding-dry-run : ## Validate NET-WP-0017-T06 non-root onboarding dry-run evidence
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
validate-onboarding-dry-run \
--evidence " $( ONBOARDING_DRY_RUN_EVIDENCE) "
2026-06-02 01:11:42 +02:00
security-bootstrap-custody-roster-template : ## Print a non-secret two-of-three custody roster template
python3 tools/security-bootstrap-console/security_bootstrap_console.py custody-roster-template
2026-06-03 01:50:29 +02:00
security-bootstrap-cleanup-evidence-template : ## Print non-secret NET-WP-0017-T03/T04 cleanup and taint evidence JSON template
python3 tools/security-bootstrap-console/security_bootstrap_console.py cleanup-evidence-template
2026-06-03 01:55:43 +02:00
security-bootstrap-lifecycle-flow-template : ## Print non-secret NET-WP-0017-T05 lifecycle operator-flow evidence JSON template
python3 tools/security-bootstrap-console/security_bootstrap_console.py lifecycle-flow-template
security-bootstrap-lifecycle-guide : ## Print the practical T05 operator flow guide (onboard/lock/offboard/review/fabric-admin with previews + commands)
python3 tools/security-bootstrap-console/security_bootstrap_console.py lifecycle-guide
2026-06-03 02:11:56 +02:00
security-bootstrap-onboarding-dry-run-template : ## Print non-secret NET-WP-0017-T06 onboarding dry-run evidence JSON template (use to start T06 evidence after running the lifecycle flow)
python3 tools/security-bootstrap-console/security_bootstrap_console.py onboarding-dry-run-template
2026-06-03 02:17:55 +02:00
security-bootstrap-onboarding-dry-run : ## Run the T06 non-root dry-run orchestrator (see sso-mfa/k8s/lldap/dry-run-nonroot-user.sh and NET-WP-0019). Usage: make ... SUBJECT=foo EMAIL=foo@ex.com DISPLAY="Foo"
@cd sso-mfa/k8s/lldap && \
./dry-run-nonroot-user.sh $( or $( SUBJECT) ,t06-dryrun) $( or $( EMAIL) ,t06-dryrun@coulomb.social) " $( or $( DISPLAY) ,T06 Dry Run User) " --actor user --scope none
security-bootstrap-lifecycle-cleanup-dryrun-users : ## Clean up dry-run/test users by pattern (NET-WP-0019 T04). Usage: make ... PATTERN=t06-*
@cd sso-mfa/k8s/lldap && \
./dry-run-nonroot-user.sh --cleanup-only " $( or $( PATTERN) ,t06-*) "
2026-06-02 01:11:42 +02:00
security-bootstrap-validate-custody-roster : ## Validate and verify the signed local custody roster
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
validate-custody-roster \
--roster " $( CUSTODY_ROSTER) " \
--signature " $( CUSTODY_ROSTER_SIGNATURE) " \
--allowed-signers " $( CUSTODY_ROSTER_ALLOWED_SIGNERS) "
security-bootstrap-sign-custody-roster : ## Sign the ignored local custody roster with an SSH signing key
@mkdir -p " $$ (dirname " $( CUSTODY_ROSTER_ALLOWED_SIGNERS) ")"
@printf '%s ' " $( CUSTODY_ROSTER_SIGNING_PRINCIPAL) " > " $( CUSTODY_ROSTER_ALLOWED_SIGNERS) "
@cat " $( CUSTODY_ROSTER_SIGNING_KEY) .pub " >> " $( CUSTODY_ROSTER_ALLOWED_SIGNERS) "
ssh-keygen -Y sign \
-f " $( CUSTODY_ROSTER_SIGNING_KEY) " \
-n netkingdom-custody-roster \
" $( CUSTODY_ROSTER) "
@if [ [ " $( CUSTODY_ROSTER_SIGNATURE) " != " $( CUSTODY_ROSTER) .sig " ] ] ; then \
cp " $( CUSTODY_ROSTER) .sig " " $( CUSTODY_ROSTER_SIGNATURE) " ; \
fi
2026-06-02 00:24:18 +02:00
2026-06-01 21:20:53 +02:00
security-bootstrap-approve-custody : ## Approve custody mode metadata: make security-bootstrap-approve-custody ARGS="--mfa-enrolled-confirmed --mfa-enrollment-source identity-provider --recovery-confirmed --custody-packet-prepared --no-secret-capture-confirmed"
2026-05-24 09:26:02 +02:00
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
2026-06-01 21:20:53 +02:00
--metadata " $( SECURITY_BOOTSTRAP_METADATA) " \
2026-05-24 09:26:02 +02:00
approve-custody-mode \
--mode " $( if $( MODE) ,$( MODE) ,temporary-single-king) " \
$( ARGS)
security-bootstrap-custody-packet : ## Print a blank offline custody packet template
python3 tools/security-bootstrap-console/security_bootstrap_console.py custody-packet
security-bootstrap-openbao-preflight : ## Show safe OpenBao preflight commands
python3 tools/security-bootstrap-console/security_bootstrap_console.py openbao-preflight \
--railiance-path ../railiance-platform
2026-06-18 00:51:48 +02:00
security-bootstrap-openbao-unseal-custody-models : ## List OpenBao unseal custody models and implementation status
python3 tools/security-bootstrap-console/security_bootstrap_console.py openbao-unseal-custody-models
security-bootstrap-select-openbao-unseal-custody-model : security -bootstrap -metadata -init ## Select implemented unseal model (blocks planned): make ... MODEL=sops-held-automation
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
--metadata " $( SECURITY_BOOTSTRAP_METADATA) " \
select -openbao-unseal-custody-model \
--model " $( if $( MODEL) ,$( MODEL) ,sops-held-automation) "
2026-07-02 22:08:33 +02:00
security-bootstrap-select-deployment-profile : security -bootstrap -metadata -init ## Select deployment profile (production blocks sops-held-automation): make ... PROFILE=production
@[ [ -n " $( PROFILE) " ] ] || ( echo "Usage: make security-bootstrap-select-deployment-profile PROFILE=lab|production" ; exit 1)
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
--metadata " $( SECURITY_BOOTSTRAP_METADATA) " \
select -deployment-profile --profile " $( PROFILE) "
security-bootstrap-openbao-ceremony-record-template : ## Print non-secret attended OpenBao ceremony record template
python3 tools/security-bootstrap-console/security_bootstrap_console.py openbao-ceremony-record-template
security-bootstrap-validate-openbao-ceremony-record : ## Validate non-secret attended ceremony record: make ... [EVIDENCE=.local/openbao-ceremony-record.json]
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
validate-openbao-ceremony-record \
--evidence " $( if $( EVIDENCE) ,$( EVIDENCE) ,.local/openbao-ceremony-record.json) "
2026-06-01 21:20:53 +02:00
security-bootstrap-metadata-init : ## Create durable local non-secret bootstrap metadata if missing
@mkdir -p " $$ (dirname " $( SECURITY_BOOTSTRAP_METADATA) ")"
@if [ [ -f " $( SECURITY_BOOTSTRAP_METADATA) " ] ] ; then \
echo " ✔ Metadata already exists: $( SECURITY_BOOTSTRAP_METADATA) " ; \
elif [ [ -f /tmp/net-kingdom-security-bootstrap.json ] ] ; then \
cp /tmp/net-kingdom-security-bootstrap.json " $( SECURITY_BOOTSTRAP_METADATA) " ; \
echo " ✔ Imported previous /tmp bootstrap metadata to $( SECURITY_BOOTSTRAP_METADATA) " ; \
else \
python3 tools/security-bootstrap-console/security_bootstrap_console.py metadata-template \
> " $( SECURITY_BOOTSTRAP_METADATA) " ; \
echo " ✔ Created metadata: $( SECURITY_BOOTSTRAP_METADATA) " ; \
fi
security-bootstrap-ui : security -bootstrap -metadata -init ## Serve local custody approval UI on localhost:8876: make security-bootstrap-ui
2026-05-24 09:26:02 +02:00
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
2026-06-01 21:20:53 +02:00
--metadata " $( SECURITY_BOOTSTRAP_METADATA) " \
2026-05-24 09:26:02 +02:00
web-ui \
2026-06-01 21:20:53 +02:00
--host " $( SECURITY_BOOTSTRAP_HOST) " \
--port " $( SECURITY_BOOTSTRAP_PORT) "
2026-05-24 09:26:02 +02:00
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
.PHONY : help hooks hooks -test sops -setup sops -edit sops -encrypt sops -decrypt sops -rotate \
check-secrets creds-init creds-generate creds-bundle creds-apply creds-verify \
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
creds-status creds-rotate \
2026-05-22 14:35:31 +02:00
creds-agent-init creds-agent-status creds-emergency-reprint \
2026-07-02 11:01:34 +02:00
openbao-init-unseal openbao-init-unseal-dry-run \
2026-08-23 13:16:34 +02:00
iam-profile-conformance-test playbook-contract-test posture-feedback-test \
2026-08-23 13:24:55 +02:00
posture-feedback-reference security-scenario-compose-lightweight \
feat(NET-WP-0018-T07): add automated tests for bootstrap UI sections and runbooks
- Created tools/security-bootstrap-console/tests/test_security_bootstrap_console.py (pytest-based, 8 tests covering templates (incl. 0019 dry-run fields), runbook_payloads (T06 entry), audit_core_posture, etc. per layered spec + 0019 note)
- Makefile: added security-bootstrap-console-test (pytest), security-bootstrap-scripts-syntax (bash -n for key sh scripts like dry-run-nonroot-user.sh); integrated into .PHONY and bootstrap lists
- Updated workplan T07 status done + detailed note with pragmatic refs
- Tests pass (python -m pytest)
- Commit + will sync/fix/progress
- Covers console UI, validators, 0019 polish artifacts (orchestrator, cmds, claims, evidence) as required for T07
T07 complete. 6/9 now.
2026-06-03 17:28:21 +02:00
security-bootstrap-console-test security-bootstrap-scripts-syntax \
2026-05-24 09:26:02 +02:00
security-bootstrap-console security-bootstrap-king-kit \
2026-06-02 00:24:18 +02:00
security-bootstrap-validate-kit security-bootstrap-validate-t02 \
2026-06-03 01:50:29 +02:00
security-bootstrap-validate-cleanup \
security-bootstrap-validate-lifecycle-flow \
security-bootstrap-validate-onboarding-dry-run \
2026-06-04 00:25:45 +02:00
security-bootstrap-validate-keycape-client \
2026-06-02 01:11:42 +02:00
security-bootstrap-custody-roster-template \
2026-06-03 01:50:29 +02:00
security-bootstrap-cleanup-evidence-template \
2026-06-03 01:55:43 +02:00
security-bootstrap-lifecycle-flow-template \
security-bootstrap-lifecycle-guide \
2026-06-03 02:11:56 +02:00
security-bootstrap-onboarding-dry-run-template \
2026-06-03 02:17:55 +02:00
security-bootstrap-onboarding-dry-run \
security-bootstrap-lifecycle-cleanup-dryrun-users \
2026-06-02 01:11:42 +02:00
security-bootstrap-validate-custody-roster \
security-bootstrap-sign-custody-roster \
2026-06-02 00:24:18 +02:00
security-bootstrap-approve-custody \
2026-05-24 09:26:02 +02:00
security-bootstrap-custody-packet security-bootstrap-openbao-preflight \
2026-07-02 22:08:33 +02:00
security-bootstrap-openbao-unseal-custody-models \
security-bootstrap-select-openbao-unseal-custody-model \
security-bootstrap-select-deployment-profile \
security-bootstrap-openbao-ceremony-record-template \
security-bootstrap-validate-openbao-ceremony-record \
feat(NET-WP-0018-T07): add automated tests for bootstrap UI sections and runbooks
- Created tools/security-bootstrap-console/tests/test_security_bootstrap_console.py (pytest-based, 8 tests covering templates (incl. 0019 dry-run fields), runbook_payloads (T06 entry), audit_core_posture, etc. per layered spec + 0019 note)
- Makefile: added security-bootstrap-console-test (pytest), security-bootstrap-scripts-syntax (bash -n for key sh scripts like dry-run-nonroot-user.sh); integrated into .PHONY and bootstrap lists
- Updated workplan T07 status done + detailed note with pragmatic refs
- Tests pass (python -m pytest)
- Commit + will sync/fix/progress
- Covers console UI, validators, 0019 polish artifacts (orchestrator, cmds, claims, evidence) as required for T07
T07 complete. 6/9 now.
2026-06-03 17:28:21 +02:00
security-bootstrap-metadata-init security-bootstrap-ui \
2026-06-04 00:25:45 +02:00
security-bootstrap-console-test security-bootstrap-scripts-syntax \
security-bootstrap-validate-keycape-client