880f89bf98
fix(keycape): NK-WP-0003-T07 — fix deployment image + add demo-app client
...
- deployment.yaml: image → 92.205.130.254:32166/coulomb/key-cape:latest
(Gitea OCI registry, delivered by KEY-WP-0002; imagePullPolicy: Always)
- k3s insecure registry hosts.toml: fixed server endpoint to http:// so
containerd does not attempt HTTPS against the plain-HTTP Gitea NodePort
- create-secrets.sh: add demo-app OIDC client (required for KeyCape to
start; also needed for T08 acceptance tests)
- keycape-config Secret updated in-place (no re-bootstrap needed)
KeyCape pod 1/1 Running; /healthz OK; OIDC discovery live at
https://kc.coulomb.social/.well-known/openid-configuration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-22 00:30:58 +00:00
f2f07871eb
fix(sso-mfa): commit T02–T06 fixes and workplan status updates
...
- authelia: users_filter uid→{username_attribute}, OIDC client secret
moved from env var to inline bcrypt hash in configmap (4.38 limitation)
- authelia: remove unsupported CLIENTS_0_SECRET_FILE env var
- lldap: drop runAsNonRoot/runAsUser (image init requires root)
- verify-t02: keycloak→keycape NetworkPolicy check rename
- workplan: T02/T03/T05/T06 marked done with notes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-21 20:25:03 +00:00
59ba9e6fe1
fix(creds-bootstrap): harden agent bootstrap for non-interactive execution
...
- creds-bootstrap-agent.sh: skip Phase 3 if all secrets already applied
(avoids CNPG SSL connection drops from repeated reconciliation)
- creds-bootstrap-agent.sh: wait for rollout to complete after restart
before running enckey/admin bootstrap (fixes race with old pod)
- creds-bootstrap-agent.sh: only restart privacyIDEA when Phase 3 ran
- create-pi-token.sh: use env-var + retry for token fetch (no heredoc
stdin; handles transient 500 from idle connection pool)
- create-pi-token.sh: create keycape-pi-token K8s Secret after fetching
- creds-verify.sh: map keycape-pi-token to secrets_applied.keycape
(not pi_admin_created, which caused spurious Phase 5 re-runs)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-21 12:11:13 +00:00
56036cd4be
chore(creds): bootstrap complete [agent NK-WP-0005]
2026-03-21 12:10:53 +00:00
329f086743
chore(creds): encrypted secrets [agent NK-WP-0005]
2026-03-21 12:09:53 +00:00
aa0edabb81
chore(creds): encrypted secrets [agent NK-WP-0005]
2026-03-21 11:43:02 +00:00
49ded70e4b
chore(creds): encrypted secrets [agent NK-WP-0005]
2026-03-21 11:37:13 +00:00
eb7c21a00c
chore(creds): encrypted secrets [agent NK-WP-0005]
2026-03-21 11:34:50 +00:00
152c2aac72
chore(creds): encrypted secrets [agent NK-WP-0005]
2026-03-21 11:24:38 +00:00
daeeb863cb
chore(creds): encrypted secrets [agent NK-WP-0005]
2026-03-21 11:22:53 +00:00
ca853a84b7
chore(creds): encrypted secrets [agent NK-WP-0005]
2026-03-21 10:59:13 +00:00
5d032db3dd
chore(creds): encrypted secrets [agent NK-WP-0005]
2026-03-21 10:51:47 +00:00
0ea05b302c
chore(creds): encrypted secrets [agent NK-WP-0005]
2026-03-21 10:50:22 +00:00
963a4700ef
chore(creds): encrypted secrets [agent NK-WP-0005]
2026-03-21 10:44:37 +00:00
33b9b93dba
chore(creds): encrypted secrets [agent NK-WP-0005]
2026-03-21 10:42:39 +00:00
f227dfbd3d
fix(privacyidea): add PI_ADDRESS/PI_PORT; switch readiness probe to tcpSocket
...
gpappsoft entrypoint requires PI_ADDRESS and PI_PORT env vars to build
the gunicorn bind argument. Without them the container crashes immediately.
/token/ returns 401 for unauthenticated GET requests so the httpGet
readiness probe was permanently failing. Switch to tcpSocket to match
the startup and liveness probes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-21 10:41:13 +00:00
9587d14803
fix(privacyidea): override PRIVACYIDEA_CONFIGFILE to use mounted pi.cfg
...
gpappsoft image sets PRIVACYIDEA_CONFIGFILE=/privacyidea/etc/pi.cfg
internally, causing it to ignore our mounted configmap at
/etc/privacyidea/pi.cfg and fall back to SQLite.
Override the env var so the entrypoint reads our pi.cfg, which points
to PostgreSQL via PI_SQLALCHEMY_DATABASE_URI from the secret.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-21 09:43:35 +00:00
bececac7b8
fix(privacyidea): correct image to ghcr.io/gpappsoft, port 5001→8080
...
privacyidea/privacyidea:3.12 and privacyidea/otpserver:3.12.2 do not
exist on Docker Hub. Correct image is ghcr.io/gpappsoft/privacyidea-docker:3.12.2
which listens on port 8080.
Update all port references: deployment, service, ingress, netpol-mfa,
netpol-sso (keycape→privacyIDEA egress rule).
Also: creds-bootstrap-agent.sh — restart privacyIDEA deployment after
applying new secrets so the pod picks up updated env vars.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-21 09:37:38 +00:00
95656f2324
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
6fdfe8a669
chore
2026-03-21 00:15:58 +00:00
01c8a07f3a
fix(sso-mfa): NK-WP-0003-T04 — correct privacyIDEA image and port
...
privacyidea/privacyidea:3.12 does not exist on Docker Hub.
Correct image: privacyidea/otpserver:3.12.2 (port 5001).
Updated files:
- deployment.yaml: image, containerPort, probes, service port
- ingress.yaml: backend service port
- netpol-mfa.yaml: ingress port + keycloak → keycape label
- netpol-sso.yaml: KeyCape egress port to privacyIDEA
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-20 23:54:18 +00:00
c10d7d2f8a
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
2bbe328aec
docs(sso-mfa): record T04 blocker — wrong image reference (ImagePullBackOff)
...
privacyidea/privacyidea:3.12 does not exist on Docker Hub. Pod is deployed
but stuck. Correct image reference must be identified before proceeding.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-20 17:16:35 +00:00
bee0936d5d
docs(sso-mfa): fix stale Keycloak refs and add T04 apply section to WORKPLAN
...
- README.md: ipAllowList → ipWhiteList (match Traefik v2 fix)
- verify-t04.sh: update success message (Keycloak → LLDAP+Authelia+KeyCape)
- WORKPLAN.md: add full T04 section with deliverables, pending steps, done-criteria
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-20 07:33:47 +00:00
a375b3814d
fix(sso-mfa): use ipWhiteList for Traefik v2 in LLDAP and privacyIDEA middleware
...
Traefik 2.10 (K3s 1.30 bundle) requires ipWhiteList, not ipAllowList.
Updated both middleware files and clarified comments to match cluster version.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-20 07:28:06 +00:00
6d25d088d7
feat(sso-mfa): T02/T03 live apply — age-encrypted secrets, CNPG cluster (NK-WP-0001-T02/T03)
...
- Add encrypt-secrets.sh / decrypt-secrets.sh: age-based secrets workflow
replaces KeePassXC dependency; encrypted .env.age files committed to repo
- Add bootstrap/secrets.enc/: all component secrets encrypted to age pubkey
- Fix .gitignore: allow secrets.enc/**/*.age while blocking plaintext
- Fix verify-t02.sh: update netpol names for Authelia+LLDAP+KeyCape stack
- Fix verify-t03.sh: remove keycloak_db/role checks; fix ((PASS++)) set-e bug
- Update postgresql/cluster.yaml: drop keycloak_db, bootstrap privacyidea_db only
- Update postgresql/create-secrets.sh: remove keycloak secret
- Fix netpol-databases.yaml: add port 8000 for CNPG instance manager HTTP API
- T02 COMPLETE: namespaces, network policies, cert-manager issuers applied
- T03 COMPLETE: CNPG operator installed, net-kingdom-pg cluster healthy
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-20 02:57:41 +00:00
6c062e1295
feat(sso-mfa): T07/T08 user mgmt, backups, DR & break-glass (NK-WP-0001-T07/T08)
...
T07 — User management & self-service:
- k8s/lldap/bootstrap-users.sh: creates net-kingdom-users and net-kingdom-admins
groups in LLDAP via GraphQL API; idempotent.
- k8s/lldap/break-glass.sh: creates break-glass bypass account in LLDAP,
sets BREAKGLASS_PASSWORD, assigns to net-kingdom-admins.
- k8s/verify-t07.sh: 6 checks — groups, break-glass, self-service portal,
KeyCape OIDC client registrations.
T08 — Backups, DR, break-glass:
- k8s/backup/cronjob-sqlite-backups.yaml: daily CronJobs for LLDAP SQLite,
Authelia SQLite (with scale-down/up RBAC), and privacyIDEA enckey backup.
7-day retention, 03:00/03:15/03:30 UTC staggered schedule.
- k8s/backup/DR-RUNBOOK.md: full restore runbook — scenarios, restore order,
LLDAP/Authelia/PI SQLite restore procedure, full node rebuild sequence,
offsite age-encrypted export.
- k8s/verify-t08.sh: 9 checks — CronJobs, RBAC, run history, backup files
on PVCs, DR runbook presence, offsite backup (manual confirmation).
- WORKPLAN.md: T07/T08 sections with done-criteria added.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-19 09:17:03 +00:00
69e900ddb1
feat(sso-mfa): T06 realm config & MFA flow manifests (NK-WP-0001-T06)
...
- k8s/privacyidea/bootstrap-realm.sh: creates LLDAP resolver
"lldap-netkingdom", the "netkingdom" default realm, TOTP self-enrollment
policy, and passthru authentication policy (phase-1 rollout).
- k8s/verify-t06.sh: verifies realm, resolver, LDAP user resolution,
KeyCape→privacyIDEA admin token, API connectivity, and policies.
- WORKPLAN.md: mark T05 done, add T06 section with done-criteria.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-19 09:04:07 +00:00
c0e17611cc
chore(sso-mfa): mark T05 complete in WORKPLAN.md
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-19 08:32:35 +00:00
0754dc32e6
feat(sso-mfa): T05 SSO stack pivot — Keycloak → Authelia + LLDAP + KeyCape (NK-WP-0001-T05)
...
Replaces the Keycloak+privacyIDEA SSO tier with the lightweight stack built
during KEY-WP-0001: Authelia (password frontend), LLDAP (directory), and
KeyCape (OIDC orchestration). privacyIDEA is retained as the MFA engine.
Stack:
kc.coulomb.social — KeyCape OIDC server (stateless, custom Go)
auth.coulomb.social — Authelia login portal (password auth → Authelia OIDC → KeyCape)
lldap.coulomb.social — LLDAP admin UI (IP-restricted)
pink.coulomb.social — privacyIDEA MFA engine (unchanged)
Changes:
- Remove sso-mfa/k8s/keycloak/ (7 files)
- Add sso-mfa/k8s/lldap/ (pvc, deployment, middleware, ingress, create-secrets, README)
- Add sso-mfa/k8s/authelia/ (pvc, configmap, deployment, ingress, create-secrets, README)
- Add sso-mfa/k8s/keycape/ (deployment, middleware, ingress, create-secrets, create-pi-token, README)
- Update network-policies/netpol-sso.yaml for new component topology
- Update verify-t05.sh: checks LLDAP + Authelia + KeyCape (23 checks)
- Update CONFIG.md: fix CP-NK-004 (KeyCape), add CP-NK-005 (Authelia), CP-NK-006 (LLDAP)
- Update bootstrap/gen-secrets.sh: add LLDAP/Authelia/KeyCape sections, remove Keycloak
- Update k8s/README.md: network policy table reflects new traffic paths
- Add sso-mfa/WORKPLAN.md: resumable task checklist
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-19 08:31:51 +00:00
d0ed7d9cd6
feat(sso-mfa): T05 Keycloak manifests (NK-WP-0001-T05)
...
Deploys Keycloak (SSO core) in the sso namespace.
Files:
sso-mfa/k8s/keycloak/pvc.yaml — keycloak-data PVC (build cache)
sso-mfa/k8s/keycloak/middleware.yaml — rate-limit, admin-allowlist, HSTS
sso-mfa/k8s/keycloak/deployment.yaml — Deployment + Service; init container
downloads privacyIDEA provider JAR
sso-mfa/k8s/keycloak/ingress.yaml — Ingress for kc.coulomb.social (CP-NK-004)
sso-mfa/k8s/keycloak/create-secrets.sh — keycloak-config Secret
sso-mfa/k8s/keycloak/bootstrap-realm.sh— hardens master realm, creates net-kingdom realm
sso-mfa/k8s/keycloak/README.md — apply order, custom image guide, DR
sso-mfa/k8s/verify-t05.sh — T05 done-criteria verification script
Config points added: CP-NK-004 (kc.coulomb.social), CP-NK-005 (provider JAR URL).
CP-NK-005 must be set before applying deployment.yaml.
Pending: apply to live cluster, set CP-NK-005, run bootstrap-realm.sh, verify-t05.sh.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-19 02:00:51 +00:00
1d94652ba1
feat(sso-mfa): T04 privacyIDEA manifests (NK-WP-0001-T04)
...
Deploy privacyIDEA (MFA core) in the mfa namespace:
- pvc.yaml: privacyidea-data (5Gi) and privacyidea-logs (2Gi)
- configmap.yaml: pi.cfg reading secrets from env vars
- deployment.yaml: Deployment + ClusterIP Service (port 8080)
- middleware.yaml: Traefik RateLimit + admin IP AllowList
- ingress.yaml: pink.coulomb.social (portal + admin), pink-account.coulomb.social (self-service)
- create-secrets.sh: creates privacyidea-config Secret
- enckey-bootstrap.sh: post-deploy key extraction + DR Secrets
- bootstrap-admin.sh: pi-admin, trigger-admin, privacyidea-trigger-admin Secret
- verify-t04.sh: 8-section done-criteria checker
Config points CP-NK-002 (pink.coulomb.social) and CP-NK-003
(pink-account.coulomb.social) registered in CONFIG.md.
pink = PrivacyIDEA Net Knights (project mnemonic).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-19 01:22:41 +00:00
8929bf65bc
feat(sso-mfa): T03 PostgreSQL manifests (NK-WP-0001-T03)
...
CloudNativePG Cluster CR (net-kingdom-pg, PostgreSQL 16) with two
application databases: keycloak_db (owner: keycloak) and privacyidea_db
(owner: privacyidea). Passwords managed continuously via managed.roles.
WAL archiving section stubbed and commented; activate when object storage
is available. ScheduledBackup CR included (daily 02:00 UTC, 7d retention).
Also: sync workplan status for T01 (Phase 0a done), T02 (manifests done),
T03 (manifests done, restore drill pending); close NK-WP-0002.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-05 09:22:13 +01:00
2ebb231f19
custodian integration and some cleanuo
2026-03-04 23:31:28 +01:00
ee794a61ab
feat(sso-mfa): T02 K8s foundations manifests (NK-WP-0001-T02)
...
namespaces/namespaces.yaml:
- sso, mfa, databases with net-kingdom/component labels for NetworkPolicy selectors
network-policies/{netpol-sso,netpol-mfa,netpol-databases}.yaml:
- Default-deny-all posture on all three namespaces
- sso: ingress from Traefik; egress to databases:5432 and mfa:8080
- mfa: ingress from Traefik + Keycloak; egress to databases:5432
- databases: ingress from sso/mfa + CNPG operator; egress to kube-dns + K8s API
- DNS (kube-system:53) allowed for all pods in all namespaces
cert-manager/issuers.yaml:
- selfsigned-issuer (ClusterIssuer) for internal/test use
- letsencrypt-prod (ClusterIssuer, HTTP-01/Traefik) — fill ACME_EMAIL before apply
cert-manager/test-certificate.yaml:
- 24h self-signed cert to smoke-test cert-manager
storage/verify-pvc.yaml:
- Test PVC + Pod to confirm default StorageClass provisioning
verify-t02.sh:
- Full verification script: namespaces, NetworkPolicies, issuers, certs, StorageClass
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-02 09:49:39 +01:00
c5761884f4
feat(sso-mfa): Phase 0a bootstrap tooling (NK-WP-0001-T01)
...
- sso-mfa/bootstrap/gen-secrets.sh: generates all pre-cluster secrets
(PI_SECRET_KEY, PI_PEPPER, DB passwords, Keycloak admin, break-glass)
into a structured secrets/ directory; prints summary with truncated values.
PI_ENCFILE deferred — must be generated inside the privacyIDEA container.
- sso-mfa/bootstrap/pack-bundle.sh: age-encrypts the secrets directory into
an offsite ops bundle.
- sso-mfa/bootstrap/README.md: KeePassXC group/entry structure, full workflow
(generate → KeePassXC → bundle → shred → PI_ENCFILE post-deploy).
- .gitignore: add sso-mfa/bootstrap/secrets/, *.age, *.kdbx.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-02 09:01:50 +01:00