generated from coulomb/repo-seed
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>
This commit is contained in:
145
sso-mfa/k8s/keycape/README.md
Normal file
145
sso-mfa/k8s/keycape/README.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# T05c — KeyCape (OIDC Orchestration Layer)
|
||||
|
||||
KeyCape is the stateless OIDC server that ties the stack together. It orchestrates
|
||||
the full authentication flow:
|
||||
1. User visits a registered application
|
||||
2. Application redirects to KeyCape (`kc.coulomb.social`) for login
|
||||
3. KeyCape redirects the browser to Authelia (`auth.coulomb.social`) for password auth
|
||||
4. Authelia validates the password against LLDAP and returns an authorization code
|
||||
5. KeyCape exchanges the code for user identity, then calls privacyIDEA for MFA
|
||||
6. On success, KeyCape issues a signed OIDC token to the application
|
||||
|
||||
KeyCape is stateless — all state lives in Authelia (sessions), LLDAP (users), and
|
||||
privacyIDEA (MFA tokens). No PVC is required.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- T04 complete (privacyIDEA is Running and bootstrapped — admin account + enckey done)
|
||||
- T05a complete (LLDAP is Running)
|
||||
- T05b complete (Authelia is Running)
|
||||
- KeyCape container image built and available (see "Building the image" below)
|
||||
- `bootstrap/gen-secrets.sh` run
|
||||
- `kubectl` configured with cluster access
|
||||
|
||||
## Building the image
|
||||
|
||||
KeyCape has no published image. Build it from the source repository and make it
|
||||
available to K3s before applying `deployment.yaml`.
|
||||
|
||||
### Option A — Local import into K3s (dev/single-node)
|
||||
|
||||
```bash
|
||||
cd ~/key-cape
|
||||
docker build -t keycape:v0.1 .
|
||||
|
||||
# Import directly into the K3s containerd runtime (no registry needed)
|
||||
docker save keycape:v0.1 | sudo k3s ctr images import -
|
||||
|
||||
# After import, set imagePullPolicy: Never in deployment.yaml
|
||||
# (the image is now in the K3s local store, not a registry)
|
||||
```
|
||||
|
||||
### Option B — Private registry (production)
|
||||
|
||||
```bash
|
||||
cd ~/key-cape
|
||||
docker build -t <registry>/keycape:v0.1 .
|
||||
docker push <registry>/keycape:v0.1
|
||||
|
||||
# Update the image field in deployment.yaml:
|
||||
# image: <registry>/keycape:v0.1
|
||||
# imagePullPolicy: IfNotPresent (default) is correct for registry images.
|
||||
```
|
||||
|
||||
After building, update `deployment.yaml` line:
|
||||
```yaml
|
||||
image: keycape:v0.1 # replace with your actual tag
|
||||
```
|
||||
|
||||
## Apply order
|
||||
|
||||
```bash
|
||||
# 1. Create Secrets (config.yaml + key.pem)
|
||||
# Run this AFTER T04 bootstrap if you want the privacyIDEA token included.
|
||||
# If T04 is not yet done, run it now and re-run after create-pi-token.sh.
|
||||
cd sso-mfa/k8s/keycape
|
||||
chmod +x create-secrets.sh create-pi-token.sh
|
||||
./create-secrets.sh
|
||||
|
||||
# 2. Apply manifests
|
||||
kubectl apply -f deployment.yaml
|
||||
kubectl apply -f middleware.yaml
|
||||
kubectl apply -f ingress.yaml
|
||||
|
||||
# 3. Wait for pod to be ready
|
||||
kubectl rollout status deployment/keycape -n sso --timeout=60s
|
||||
```
|
||||
|
||||
## Post-deploy: inject privacyIDEA admin token
|
||||
|
||||
If T04 was not complete when you ran `create-secrets.sh`, the privacyIDEA admin
|
||||
token is a placeholder. After T04 bootstrap is done:
|
||||
|
||||
```bash
|
||||
# 1. Fetch the token from privacyIDEA and store it
|
||||
chmod +x create-pi-token.sh
|
||||
./create-pi-token.sh
|
||||
|
||||
# 2. Re-run create-secrets.sh to update keycape-config with the real token
|
||||
./create-secrets.sh
|
||||
|
||||
# 3. Restart KeyCape to pick up the new Secret
|
||||
kubectl rollout restart deployment/keycape -n sso
|
||||
```
|
||||
|
||||
## OIDC client registration
|
||||
|
||||
Downstream applications are registered in the `clients:` block in
|
||||
`keycape/create-secrets.sh`. After editing:
|
||||
|
||||
```bash
|
||||
./create-secrets.sh # regenerates keycape-config Secret
|
||||
kubectl rollout restart deployment/keycape -n sso
|
||||
```
|
||||
|
||||
Example entry (public client, PKCE, for a SPA):
|
||||
```yaml
|
||||
clients:
|
||||
- clientId: "my-app"
|
||||
displayName: "My Application"
|
||||
redirectUris:
|
||||
- "https://my-app.coulomb.social/callback"
|
||||
allowedScopes: ["openid", "profile", "email", "groups"]
|
||||
grantTypes: ["authorization_code"]
|
||||
clientType: "public"
|
||||
```
|
||||
|
||||
## Secrets managed
|
||||
|
||||
| Secret name | Keys | Purpose |
|
||||
|-------------|------|---------|
|
||||
| `keycape-config` | `config.yaml` | Full KeyCape configuration (LLDAP URL + creds, Authelia URL + client secret, privacyIDEA URL + admin token, OIDC clients) |
|
||||
| | `key.pem` | RSA-2048 private key for signing OIDC tokens issued to downstream applications |
|
||||
| `keycape-pi-token` | `pi_admin_token` | privacyIDEA admin JWT — created by `create-pi-token.sh`, referenced in `config.yaml` |
|
||||
|
||||
Store `key.pem` in KeePassXC as a binary attachment. If it is lost, all active
|
||||
sessions become invalid (tokens cannot be verified) and all applications must
|
||||
re-authenticate.
|
||||
|
||||
## Verify
|
||||
|
||||
```bash
|
||||
# Pod status
|
||||
kubectl get pod -n sso -l app.kubernetes.io/name=keycape
|
||||
|
||||
# Health check
|
||||
kubectl run -n sso --rm -it kc-test --image=busybox --restart=Never \
|
||||
-- wget -qO- http://keycape.sso.svc.cluster.local:8080/healthz
|
||||
|
||||
# OIDC discovery (public endpoint)
|
||||
curl -s https://kc.coulomb.social/.well-known/openid-configuration | jq .
|
||||
|
||||
# Check issuer matches CP-NK-004
|
||||
curl -s https://kc.coulomb.social/.well-known/openid-configuration \
|
||||
| jq -r .issuer # should be: https://kc.coulomb.social
|
||||
```
|
||||
Reference in New Issue
Block a user