generated from coulomb/repo-seed
- 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>
189 lines
5.5 KiB
Markdown
189 lines
5.5 KiB
Markdown
# T04 — Phase 3: Deploy privacyIDEA
|
|
|
|
Phase 3 of NK-WP-0001: deploys the MFA core (privacyIDEA) in the `mfa` namespace.
|
|
|
|
**Hostnames (config points CP-NK-002 / CP-NK-003):**
|
|
- `pink.coulomb.social` — main portal and API
|
|
- `pink-account.coulomb.social` — self-service token portal
|
|
|
|
**Prerequisites:**
|
|
- T02 complete: `mfa` namespace and NetworkPolicies applied, cert-manager running.
|
|
- T03 complete: PostgreSQL cluster `net-kingdom-pg` in `databases` namespace is Ready.
|
|
- T01 Phase 0a complete: `gen-secrets.sh` run, all secrets in KeePassXC.
|
|
|
|
---
|
|
|
|
## Apply order
|
|
|
|
### Step 1 — Create the config Secret
|
|
|
|
```bash
|
|
cd sso-mfa/k8s/privacyidea
|
|
chmod +x create-secrets.sh enckey-bootstrap.sh bootstrap-admin.sh
|
|
./create-secrets.sh
|
|
```
|
|
|
|
Creates `privacyidea-config` in the `mfa` namespace (PI_SECRET_KEY, PI_PEPPER,
|
|
PI_SQLALCHEMY_DATABASE_URI).
|
|
|
|
---
|
|
|
|
### Step 2 — Apply manifests
|
|
|
|
```bash
|
|
# From sso-mfa/k8s/privacyidea/
|
|
kubectl apply -f pvc.yaml
|
|
kubectl apply -f configmap.yaml
|
|
kubectl apply -f middleware.yaml
|
|
kubectl apply -f deployment.yaml
|
|
kubectl apply -f ingress.yaml
|
|
```
|
|
|
|
**Wait for the pod to reach Running state** (DB migrations run on first start —
|
|
allow up to 3 minutes):
|
|
|
|
```bash
|
|
kubectl get pods -n mfa -w
|
|
# Expected: privacyidea-<hash> 1/1 Running
|
|
```
|
|
|
|
If the pod is stuck in `Init` or `CrashLoopBackOff`, check logs:
|
|
```bash
|
|
kubectl logs -n mfa -l app.kubernetes.io/name=privacyidea --previous
|
|
```
|
|
|
|
Common causes:
|
|
- `privacyidea-config` Secret missing → run `create-secrets.sh`
|
|
- PostgreSQL not reachable → verify T03, check NetworkPolicies
|
|
- Wrong DB password → re-run `create-secrets.sh` with corrected secrets
|
|
|
|
---
|
|
|
|
### Step 3 — Extract key material and create DR Secrets
|
|
|
|
Run **once** after the pod reaches `Running`:
|
|
|
|
```bash
|
|
./enckey-bootstrap.sh
|
|
```
|
|
|
|
This generates RSA audit keys (if not already created), extracts the encryption
|
|
key and audit keys from the pod, and creates two K8s Secrets as disaster-recovery
|
|
copies:
|
|
- `privacyidea-enckey`
|
|
- `privacyidea-auditkeys`
|
|
|
|
Follow the printed instructions to store the key files in KeePassXC, then shred
|
|
the local copies.
|
|
|
|
---
|
|
|
|
### Step 4 — Bootstrap admin accounts
|
|
|
|
```bash
|
|
./bootstrap-admin.sh
|
|
```
|
|
|
|
Creates `pi-admin` (full admin) and `trigger-admin` (triggerchallenge only).
|
|
Also creates the `privacyidea-trigger-admin` K8s Secret used by Keycloak in T05.
|
|
|
|
**Immediately after the script completes:**
|
|
1. Log in to `https://pink.coulomb.social` as `pi-admin`.
|
|
2. Navigate to **Users → pi-admin → Enroll token** and enroll a TOTP or hardware token.
|
|
3. Log out, log back in — the MFA challenge must appear.
|
|
4. Verify the `trigger-admin-rights` policy at Config → Policies.
|
|
|
|
---
|
|
|
|
### Step 5 — Verify
|
|
|
|
```bash
|
|
cd sso-mfa/k8s
|
|
chmod +x verify-t04.sh
|
|
./verify-t04.sh
|
|
```
|
|
|
|
---
|
|
|
|
## Container port note
|
|
|
|
The deployment uses `containerPort: 8080`. The official `privacyidea/privacyidea`
|
|
image uses nginx internally; the default nginx port may be 80 depending on the
|
|
image version.
|
|
|
|
**If the pod starts but requests return "connection refused":**
|
|
```bash
|
|
# Check what port the container actually listens on:
|
|
kubectl exec -n mfa <pod> -- ss -tlnp | grep LISTEN
|
|
```
|
|
|
|
If the container uses port 80, update:
|
|
1. `deployment.yaml`: `containerPort: 80`, Service `targetPort: 80`
|
|
2. `sso-mfa/k8s/network-policies/netpol-mfa.yaml`: `port: 80` in privacyIDEA rules
|
|
3. Reapply both files.
|
|
|
|
---
|
|
|
|
## NetworkPolicy design
|
|
|
|
privacyIDEA sits entirely behind the NetworkPolicies applied in T02 (netpol-mfa.yaml):
|
|
|
|
| Source | Destination | Port | Purpose |
|
|
|--------|-------------|------|---------|
|
|
| Traefik (kube-system) | privacyIDEA (mfa) | 8080 | User-facing portal |
|
|
| Keycloak (sso) | privacyIDEA (mfa) | 8080 | Provider API (triggerchallenge) |
|
|
| privacyIDEA (mfa) | PostgreSQL (databases) | 5432 | Database |
|
|
|
|
Outbound to anything other than PostgreSQL and kube-dns is denied.
|
|
|
|
---
|
|
|
|
## Post-deploy steps (after verify-t04.sh passes)
|
|
|
|
### Rate limiting adjustment
|
|
|
|
The default rate limit (20 req/min, burst 5) is conservative. If Keycloak's
|
|
triggerchallenge calls trigger false positives (HTTP 429), raise the average
|
|
in `middleware.yaml` and reapply. Alternatively, the Keycloak-to-PI path is
|
|
cluster-internal and not subject to the Ingress middleware.
|
|
|
|
### Admin WebUI IP restriction
|
|
|
|
Update `middleware.yaml` `privacyidea-admin-allowlist.spec.ipWhiteList.sourceRange`
|
|
to your actual VPN/office CIDRs and reapply:
|
|
|
|
```bash
|
|
kubectl apply -f middleware.yaml
|
|
```
|
|
|
|
### Self-service portal
|
|
|
|
Enable the self-service portal policy in privacyIDEA:
|
|
Config → Policies → New policy:
|
|
- Scope: `user`
|
|
- Action: `enrollTOTP`, `enrollHOTP`, or token types you want users to manage
|
|
- URL for self-service: `https://pink-account.coulomb.social`
|
|
|
|
---
|
|
|
|
## Disaster recovery
|
|
|
|
If the `privacyidea-data` PVC is lost:
|
|
|
|
1. Create a new PVC with `pvc.yaml`.
|
|
2. Restore enckey and audit keys from KeePassXC:
|
|
```bash
|
|
# Copy pi.enc and private/public.pem from KeePassXC into a temporary pod
|
|
kubectl run restore-helper --image=busybox -n mfa --restart=Never -- sleep 3600
|
|
kubectl cp ./pi.enc mfa/restore-helper:/etc/privacyidea/enckey
|
|
kubectl cp ./private.pem mfa/restore-helper:/etc/privacyidea/private.pem
|
|
kubectl cp ./public.pem mfa/restore-helper:/etc/privacyidea/public.pem
|
|
kubectl delete pod -n mfa restore-helper
|
|
```
|
|
Or, if the K8s Secrets survived (created by `enckey-bootstrap.sh`):
|
|
```bash
|
|
kubectl get secret privacyidea-enckey -n mfa -o jsonpath='{.data.enckey}' | base64 -d > pi.enc
|
|
```
|
|
3. Restart the privacyIDEA deployment — it will run DB migrations and use the
|
|
restored key material.
|