docs/architecture/security.md
Simon Bärlocher 345cf4b319
docs: add architecture section and overhaul top-level README
- Move Simon's architecture documentation into architecture/
  (setup, variables, topology, dns, deploy, security, operations
  plus index and glossary). All cross-repo references point at
  https://git.digitalboard.ch/Digitalboard/{reference-ansible,dns-zones}
  via absolute URLs so the docs remain navigable from any context.
- Rewrite README.md as a documentation hub: introduction, platform
  Mermaid overview, comparison of the three repos
  (docs / digitalboard.core / reference-ansible) and a full table of
  contents covering architecture, contributing, infrastructure,
  keycloak, ms-entra and troubleshooting.

Addresses the open items from the WKS PoC review (2026-05-26):
docs README begrüssungstext + Übersichtsgrafik + Verlinkung der
beiden anderen Repos, sowie das Verschieben der Architektur-Doku.
2026-05-28 14:25:27 +02:00

71 lines
3.7 KiB
Markdown

<!-- markdownlint-disable MD013 MD060 MD051 -->
# Security and demo-only defaults
← Back to [Architecture index](README.md)
> This repo is explicitly designed for **demo setups**. All default
> values in the roles are insecure and are overridden in `demo-*`
> inventories via Bao lookups or host_vars. For production deployments
> the hardening block further down also applies.
## Secret pattern (Bao lookup)
```yaml
# group_vars/.../<service>.yml or host_vars/.../<service>.yml
authentik_secret_key: "{{ lookup('community.hashi_vault.hashi_vault',
vault_mount + '/data/authentik:secret_key',
url=vault_addr) }}"
```
- `vault_mount` and `vault_addr` come from
[group_vars/all/vault.yml](https://git.digitalboard.ch/Digitalboard/reference-ansible/src/branch/main/inventories/demo-gymburgdorf/group_vars/all/vault.yml).
- KV-v2 paths require an explicit `/data/` segment — Ansible does not
resolve this automatically.
- `vault_mount` is unique per inventory (`demo-gymburgdorf`,
`demo-phbern`, …) → tenant isolation in Bao via mount + policy.
## Demo-only defaults — override required
These defaults in `digitalboard.core` are insecure. In any
**production-grade** deployment they must be overridden via Bao lookup
or host_var:
| Variable | Default | Where to override |
|---|---|---|
| `keycloak_admin_password` | `changeme` | host_vars `keycloak_servers` |
| `keycloak_postgres_password` | `changeme` | same |
| `authentik_secret_key` | `changeme-generate-a-random-string` | `host_vars/application/authentik.yml` |
| `authentik_postgres_password` | `changeme` | same |
| `nextcloud_admin_password` | `admin` | `host_vars/application/nextcloud.yml` |
| `nextcloud_postgres_password` | `changeme` | same |
| `nextcloud_s3_key` / `nextcloud_s3_secret` | `changeme` / `changeme` | same |
| `garage_webui_password` | `admin` | `host_vars/storage/garage.yml` |
| `garage_rpc_secret` | `0123…cdef` (64-hex constant) | same |
| `garage_admin_token` | identical to `rpc_secret` | same |
| `garage_metrics_token` | identical to `rpc_secret` | same |
> **Convention:** every value listed above **must** have a Bao lookup
> in `demo-*/host_vars/.../...yml` before the inventory is considered
> deploy-ready.
## Threat boundaries (current demo state)
| Boundary | Status | Notes |
|---|---|---|
| DMZ ↔ Backend (172.16.9 ↔ 172.16.19) | **Plaintext HTTP** | Auth bearers, OIDC codes, session cookies travel unencrypted. Fine for demo; for prod use mTLS or a WireGuard overlay. |
| Host firewall | **missing** | The `base` role does not install UFW/nftables. Segmentation relies on the hypervisor/VLAN. |
| SSH | `ansible_user: root` | No bastion, no jump host. Key distribution out-of-band. |
| Authentik SPOF | **accepted** | IdP and SP services share the same host (`application`). An Authentik outage means a login outage including the LDAP outpost. No break-glass path. |
| ACME TSIG key | Bao lookup (in Ansible), **plaintext in [`knot.conf`](https://git.digitalboard.ch/Digitalboard/dns-zones/src/branch/main/knot/knot.conf)** on `ns1` side | One TSIG key per demo tenant, scoped via Knot ACL `update-owner-name` to the tenant's ACME sub-tree. Rotation is manual and must be done on both sides simultaneously (Bao + `knot.conf` + `knotc zone-reload`). |
| Backup / DR | **out of scope** | Garage `replication_factor: 1` (default), no Postgres backup job, no Bao snapshot cron. |
## To adapt for production, add
- Host firewall (extend the `base` role or add a dedicated `firewall`
role).
- mTLS or WireGuard between DMZ and backend.
- Authentik on a separate host with a recovery admin token.
- Bao policies per inventory mount (read-only for the deploy token,
write-only for the bootstrap job).
- Backup cron for Postgres + Garage + Bao.
- SSH bastion + key rotation.