- hostfeatures.lua: replace basic-auth-only enforcement with a combined
apply_auth() that allows if EITHER basic auth OR a valid SSO session passes.
A "Basic" Authorization header takes the basic path (401 on failure);
otherwise a browser is 302'd to /__proxy_auth/start. SSO sessions are read
straight from Redis (proxy_SsoSession_<sid>, sid from the __proxy_sso cookie,
character-restricted) and matched to the host.
- proxy.conf: add a /__proxy_auth/ location (outside the gate) that forwards to
the nodejs app so the OIDC flow can run and set the cookie on every host.
- nginx.conf: add the proxy_auth_backend upstream (defaults to 127.0.0.1:3000).
Needs live verification on an OpenResty box (no Lua/nginx runtime in CI here).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bump proxy_cache_valid from 10m to 48h and match proxy_cache_path
`inactive` (must be >= the TTL or entries evict before expiring).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Every proxied request flows through one shared OpenResty location whose
behavior is chosen at request time from the host's Redis hash. Add per-host
controls as new Host fields enforced in Lua rather than static nginx config
(which can't key off a per-request variable):
- Rate limiting: per-client-IP token bucket via resty.limit.req
(ratelimit_enabled/rate/burst), backed by a new `ratelimit` shared dict.
- Response caching: opt-in per host via a global proxy_cache zone gated by
$skip_cache (respcache_enabled). Off by default; upstream Cache-Control
still honored.
- Custom/security headers: req_headers (upstream) + resp_headers (client) and
hsts_enabled, applied in access/header_filter phases.
- IP allow/deny CIDR lists via resty.ipmatcher (deny wins; non-empty allow is
default-deny).
New ops/nginx_conf/hostfeatures.lua holds the enforcement; proxy.conf's
access_by_lua string becomes a block that calls it, plus a header_filter block.
nodejs/utils/host_features.js is the pure, unit-tested normalize/validate layer
(header/CIDR parsing, range clamping, injection-safe values) applied in
routes/host.js and mirrored by the hosts.ejs edit form. install.sh gains the
ipmatcher rock, the cache dir, and the hostfeatures.lua symlink.
Per-host cache TTL is intentionally deferred (global default only) — see the
plan's limitations.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>