feat(gateway): PAM auth against host — close #1010

Adds opt-in HTTP Basic auth to the hive-gateway backed by the host PAM
stack + group membership check.

New binary `hive-gateway-auth` (hive-c0re workspace):
- Axum HTTP service on 127.0.0.1:7002 (host loopback)
- Decodes Basic credentials, authenticates via pam_unix.so
- Checks membership in `hyperhive-operator` group (or custom)
- Returns 200 / 401 / 403; nginx `auth_request` consumes these

New options under `services.hyperhive.gateway.auth`:
- `enable`      — off by default
- `port`        — auth service port (default 7002)
- `realm`       — WWW-Authenticate realm string (default "hyperhive")
- `group`       — required host group (default "hyperhive-operator")
- `pamService`  — PAM service name (default "hive-gateway")

Host-side NixOS wiring:
- `users.groups.hyperhive-operator` declared when default group used
- `/etc/pam.d/hive-gateway` emitted via `security.pam.services`
- `systemd.services.hive-gateway-auth` runs the auth binary as root
  (needs /etc/shadow access for pam_unix.so)

Gateway container nginx wiring:
- `location = /__hive_gateway_auth` — internal proxy to auth service
- `auth_request /__hive_gateway_auth` on the `"/"` proxy location
- `@hive_auth_required` named location adds WWW-Authenticate: Basic
  header on 401 so browsers display a login prompt

Workspace deps: pam = "0.8"; flake.nix: linux-pam added to
nativeBuildInputs so pkg-config can find libpam at build time.
This commit is contained in:
atlas 2026-06-01 22:35:11 +02:00
commit d4409b27a3
6 changed files with 550 additions and 37 deletions

View file

@ -16,6 +16,7 @@ must_use_candidate = "allow"
[workspace.dependencies]
anyhow = "1"
pam = "0.8"
axum = { version = "0.8", features = ["ws"] }
base64 = "0.22"
clap = { version = "4", features = ["derive"] }