fix(security): enforce audited account, network and resource boundaries

Implement B01-B06 with regression coverage and retained validation evidence. Preserve the production ingress preflight; F04 runtime verification remains open.
This commit is contained in:
cesnimda
2026-09-09 18:21:47 +02:00
parent 7d641edc7b
commit 0954876295
116 changed files with 10101 additions and 122 deletions
+23 -8
View File
@@ -77,17 +77,32 @@ PostgreSQL is not implemented. Do not configure or recommend it without first ad
## Deployment flow
Production automation always selects `docker-compose.yml` explicitly. Local development must add
`docker-compose.dev.yml`; never add that file to a production command. The base configuration has no
host bindings for frontend, backend, ai-service, or bundled Ollama.
`docker-compose.dev.yml`; never add that file to a production command. The effective base configuration
publishes **frontend 3000 → 80** on all host interfaces for the recorded Traefik host-port dependency.
Backend, ai-service and bundled Ollama have no host-port bindings. CORS and Docker service names are
not network isolation. The backend also joins the operator-managed `jobtracker_shared` network for
existing service dependencies; its membership and other host services need operator inspection.
The external Traefik configuration is operator-owned and is not stored here. Before deployment it
must route only the exact host from `APP_PUBLIC_BASE_URL` to frontend port 80 on
`jobtracker_shared`, terminate TLS, replace `X-Forwarded-For` and `X-Forwarded-Proto=https`, and
expose no direct application or Ollama host ports.
must route only the exact host from `APP_PUBLIC_BASE_URL` to the recorded frontend host port 3000,
terminate TLS, and replace `X-Forwarded-For` with one client IP and `X-Forwarded-Proto=https`.
Do not migrate to container routing or bind port 3000 to loopback without verifying where Traefik runs.
Host firewall/Docker forwarding rules must restrict ingress appropriately; their existence is unproven.
Nginx independently rejects non-canonical Hosts except `/health`, forwards Traefik's sanitized
single-hop values, and reaches the backend only over `WEB_PROXY_SUBNET`. The backend fails startup
if forwarded-header trust is enabled without a valid known CIDR.
Nginx requires `INGRESS_PROXY_CIDRS` (space-separated observed Traefik peer CIDRs, preferably /32 or
/128), rejects other peers before serving application routes, rejects missing scheme/IP and forwarding
chains, and emits normalized forwarding metadata. It rejects non-canonical Hosts except the default
server's liveness-only `/health`. The backend trusts only `WEB_PROXY_SUBNET` and one hop. Never trust a
NAT/gateway address shared by both Traefik and untrusted callers. If peer identity cannot distinguish
them, stop rollout and establish a verified host binding/firewall or dedicated proxy route first.
Deployment requires Python 3 (standard library) and Docker Compose's JSON config support. The new
`scripts/validate-ingress.py` preflight checks the **rendered** production configuration before normal
deployment backup/build/replacement; backup-only runs remain independent of the new ingress setting.
CI runs `python3 scripts/test-ingress.py` without needing a Docker engine. Empty/missing peer values
fail safely; do not copy synthetic addresses from tests into production. Runtime/container verification
is still pending locally due to Docker Desktop failure. See the [B06 report and operator checks](../docs/audits/2026-09-07/validation/b06-completion.md)
before deploying this change. No production verification is implied by configuration tests.
1. push to `main`
2. Gitea Actions runs tests
3. if green, workflow uploads repo to server