net-kingdom/sso-mfa/k8s/authelia/README.md
tegwick 2f1e6c3369
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 11s
Fix plus-address sign-in and finish NK-WP-0041
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0e31f-2bcc-7051-a050-70d8cb2dfa49
2026-09-27 16:05:03 +02:00

148 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# T05b — Authelia (Authentication Frontend)
Exercise status: unknown for the procedures in this runbook; no per-procedure successful-run receipt with operator attribution was established in the 2026-09-05 review. See [procedure inventory](../../../docs/attended-procedure-inventory.md).
Authelia is the password-authentication frontend for the net-kingdom SSO stack.
It acts as an upstream OIDC provider for KeyCape: users are redirected here to
enter their password; Authelia validates credentials against LLDAP and returns
an authorization code to KeyCape, which then performs the MFA step via privacyIDEA.
**Important:** Authelia's access control policy is set to `one_factor` (password only).
MFA is handled exclusively by KeyCape + privacyIDEA. Do not change this to `two_factor`.
## Prerequisites
- T05a complete (LLDAP is Running and healthy, application groups created)
- `bootstrap/gen-secrets.sh` run and `secrets/authelia/secrets.env` populated in KeePassXC
- `kubectl` configured with cluster access
## Apply order
```bash
# 1. Create K8s Secret
cd sso-mfa/k8s/authelia
chmod +x create-secrets.sh
./create-secrets.sh
# 2. Apply manifests (order matters)
kubectl apply -f pvc.yaml
kubectl apply -f configmap.yaml
kubectl apply -f deployment.yaml
kubectl apply -f ingress.yaml
# 3. Wait for pod to be ready
# The startup probe allows 90 s for the initial LLDAP connection.
kubectl rollout status deployment/authelia -n sso --timeout=120s
```
## Configuration
All non-sensitive configuration is in `configmap.yaml` (mounted as `configuration.yml`).
Sensitive values are injected via `*_FILE` environment variables pointing to
Secret-mounted files (see `deployment.yaml` env section).
Key config points:
- `authentication_backend.ldap.url` — points to LLDAP cluster-internal service
- `identity_providers.oidc.clients[0].redirect_uris` — must match CP-NK-004 (`kc.coulomb.social`)
- `session.domain` — set to parent domain `coulomb.social` so cookies are valid across
both `auth.coulomb.social` and `kc.coulomb.social`
- `default_redirection_url` — `https://users.coulomb.social` when the visitor
opened the portal with no follow-up. A provided `rd` still wins
- `access_control.default_policy: one_factor` — fleet default; MFA is not Authelia’s job
- `access_control.rules` — domain allowlists by LLDAP group (see below)
### Domain rules (app operator groups)
Authelia evaluates `rules` top-down; **first match wins**. A rule that matches
`domain` but not `subject` is skipped, so non-members would fall through to
`default_policy` and stay allowed unless a later domain-only `deny` rule exists.
Pattern used for activity-core public hosts (NK-WP-0021):
```yaml
access_control:
default_policy: one_factor
rules:
- domain: app.example.com
subject: "group:app-operators"
policy: one_factor
- domain: app.example.com
policy: deny
```
| Host | Required LLDAP group |
|------|----------------------|
| `activity.coulomb.social` | `activity-core-operators` |
| `temporal.coulomb.social` | `activity-core-operators` |
Membership: `sso-mfa/k8s/lldap/OPERATOR-GROUPS.md`. Do **not** set `two_factor`
on these rules. Do **not** invent KeyCape OIDC clients for Traefik ForwardAuth
apps — the edge already calls Authelia `/api/verify`.
## Secrets managed
| Secret name | Keys | Purpose |
|-------------|------|---------|
| `authelia-secrets` | `jwt_secret` | Session JWT signing |
| | `session_secret` | Session cookie encryption |
| | `storage_encryption_key` | SQLite database encryption |
| | `ldap_password` | LDAP bind password (= `LLDAP_LDAP_USER_PASS`) |
| | `oidc_hmac_secret` | OIDC HMAC signing |
| | `oidc_issuer_private_key` | RSA-2048 private key for OIDC token signing |
| | `keycape_client_secret_hash` | Bcrypt hash of `AUTHELIA_KEYCAPE_CLIENT_SECRET` |
`create-secrets.sh` reads plaintext values from `secrets/authelia/secrets.env` and
`secrets/lldap/secrets.env`. It generates the bcrypt hash on the fly (requires
`python3+bcrypt` or `apache2-utils`). The RSA OIDC private key is generated
automatically if `AUTHELIA_OIDC_PRIVATE_KEY_FILE` is not set.
## Storage
`authelia-data` PVC (1 Gi, ReadWriteOnce) holds:
- `db.sqlite3` — SQLite database (user sessions, regulation data)
- `notification.txt` — notification log (filesystem notifier)
Back this PVC up alongside the LLDAP PVC.
## Verify
```bash
# Pod status
kubectl get pod -n sso -l app.kubernetes.io/name=authelia
# Health check
kubectl run -n sso --rm -it auth-test --image=busybox --restart=Never \
-- wget -qO- http://authelia.sso.svc.cluster.local:9091/api/health
# OIDC discovery (should return issuer + endpoints)
curl -s https://auth.coulomb.social/.well-known/openid-configuration | jq .
```
## 4.39 compatibility and regression check
KeyCape needs `preferred_username` in the signed upstream ID token for its
directory and MFA lookup. Authelia 4.39 requires the explicit `keycape`
claims policy in `configmap.yaml`; deploy it together with the pinned image.
KeyCape's in-cluster token requests must also carry the public HTTPS forwarded
scheme and host (KeyCape `3b0446e` or later). Neither a health check nor an
authorization redirect exercises these requirements.
Run the isolated token regression with an Authelia 4.39.28 binary and Python
`requests`, `PyYAML`, and `cryptography` installed:
```bash
python3 sso-mfa/k8s/authelia/tests/probe_claims.py --authelia-bin /path/to/authelia
```
It uses disposable local users, keys and SQLite databases, checks real signed
authorization-code tokens with and without the policy, and terminates the
scratch processes. It uses a file backend, so it does not prove LDAP email
lookup. Live acceptance also requires a fresh plus-addressed email sign-in
through KeyCape to both Vergabe and the account portal, with successful
callback and token issuance evidence.
Before a 4.38 → 4.39 rollout, stop Authelia and preserve the SQLite database
and any sidecar files. Keep the previous ConfigMap and image reference too.
Rollback requires stopping 4.39 and restoring all three: database, ConfigMap,
and image. The migrated database and 4.39 claims policy cannot be used by
4.38. See `NK-WP-0041` for the exercised rollout and backup receipt.