feat(openzaak): real secrets + TLS for the production OpenZaak harness (WP-55)
CI / changes (push) Successful in 8s
CI / lint (push) Successful in 12s
CI / frontend (push) Successful in 14s
CI / storybook-a11y (push) Successful in 17s
CI / backend (push) Successful in 1m51s
CI / semgrep (push) Successful in 1m13s
CI / e2e (push) Successful in 2m56s
CI / api-client-drift (push) Successful in 1m41s
CI / changes (push) Successful in 8s
CI / lint (push) Successful in 12s
CI / frontend (push) Successful in 14s
CI / storybook-a11y (push) Successful in 17s
CI / backend (push) Successful in 1m51s
CI / semgrep (push) Successful in 1m13s
CI / e2e (push) Successful in 2m56s
CI / api-client-drift (push) Successful in 1m41s
docker-compose.openzaak.prod.yml layers real SECRET_KEY/DB password/site
domain/allowed-hosts (all required, fail-fast via ${VAR:?...}) on top of the
WP-54 dev harness, switches Postgres off trust auth, and sets IS_HTTPS for a
front-facing reverse-proxy TLS setup. The ZGW client secret lives inside a
file setup_configuration reads rather than a compose env var, so it's
templated (data.prod.yaml.template, no secret) and rendered host-side via
render-prod-secrets.sh into a gitignored data.prod.yaml, mounted over the
container's dev data.yaml. ZgwOptions.cs already binds from IConfiguration,
so the BFF side needed no code change.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -50,6 +50,40 @@ up, so it never runs where the harness doesn't exist.
|
||||
docker compose -f docker-compose.openzaak.yml down -v
|
||||
```
|
||||
|
||||
## Production (WP-55)
|
||||
|
||||
This dev harness stays dev-only: hardcoded `SECRET_KEY`, `POSTGRES_HOST_AUTH_METHOD=trust`,
|
||||
`IS_HTTPS: 'no'`, a client secret checked into `setup_configuration/data.yaml`. A real
|
||||
deployment layers `docker-compose.openzaak.prod.yml` on top instead of replacing anything:
|
||||
|
||||
```bash
|
||||
export OPENZAAK_SECRET_KEY=... # Django SECRET_KEY — generate, don't reuse the dev value
|
||||
export OPENZAAK_DB_PASSWORD=... # postgres password (switches auth off `trust`)
|
||||
export OPENZAAK_SITE_DOMAIN=... # e.g. open-zaak.example.org — no scheme/port
|
||||
export OPENZAAK_ALLOWED_HOSTS=... # Django ALLOWED_HOSTS, usually the same domain
|
||||
export OPENZAAK_CLIENT_ID=... # the BFF's OpenZaak client id (ZgwOptions:ClientId)
|
||||
export OPENZAAK_CLIENT_SECRET=... # the BFF's JWT signing secret (ZgwOptions:Secret)
|
||||
export OPENZAAK_APPLICATIE_UUID=$(uuidgen)
|
||||
|
||||
./render-prod-secrets.sh # writes the gitignored setup_configuration/data.prod.yaml
|
||||
docker compose -f docker-compose.openzaak.yml -f docker-compose.openzaak.prod.yml up -d
|
||||
```
|
||||
|
||||
Every one of those env vars is `${VAR:?...}`-checked — compose (and `render-prod-secrets.sh`
|
||||
for the client secret) refuses to start rather than silently falling back to a dev-looking
|
||||
default. There is no env var that "means insecure default"; if it's unset, it's a hard error.
|
||||
|
||||
**TLS**: OpenZaak itself does no certificate handling. Put a reverse proxy/ingress (the same
|
||||
one fronting the BFF) in front of `web`'s `:8000`, terminate TLS there, and forward to
|
||||
`http://web:8000` over the compose network. `IS_HTTPS: 'yes'` in the prod override only tells
|
||||
Django it's being served over HTTPS (secure cookies, `SECURE_*` redirects) — it does not open
|
||||
a TLS listener itself.
|
||||
|
||||
The BFF side needs no code change: `ZgwOptions` already binds `ClientId`/`Secret`/the base
|
||||
URLs from `IConfiguration`, so pointing it at a production OpenZaak is a config change
|
||||
(`Zgw:ClientId`/`Zgw:Secret`/`Zgw:ZrcBaseUrl` etc. via env vars or a secrets manager), not an
|
||||
app change.
|
||||
|
||||
## What's in here / what isn't
|
||||
|
||||
- `docker-compose.openzaak.yml` — postgres (postgis), redis, a one-shot `web-init` (runs
|
||||
@@ -72,3 +106,11 @@ docker compose -f docker-compose.openzaak.yml down -v
|
||||
`procesType` on the public VNG selectielijst API).
|
||||
- **Not here**: Documenten (DRC) / Notificaties (NRC) content — add if a later WP needs to prove
|
||||
those round-trips against a live instance too (WP-51/52 are fixture-tested today).
|
||||
- `docker-compose.openzaak.prod.yml` (WP-55) — production overrides layered on top of
|
||||
`docker-compose.openzaak.yml`: real `SECRET_KEY`/DB password/site domain/allowed-hosts from
|
||||
required env vars (fails fast if unset), password DB auth instead of `trust`, `IS_HTTPS: 'yes'`.
|
||||
Adds no image/service of its own — see "Production" above for the full flow.
|
||||
- `setup_configuration/data.prod.yaml.template` (WP-55) — the prod counterpart of `data.yaml`
|
||||
with no secret in it (`${OPENZAAK_CLIENT_SECRET}` etc. as placeholders); `render-prod-secrets.sh`
|
||||
fills it in to the gitignored `data.prod.yaml`, which the prod compose override mounts over
|
||||
the container's `data.yaml`.
|
||||
|
||||
Reference in New Issue
Block a user