boma/docs/security/service-checklist.md
sjat 2f4218814a Reconcile image pinning to a tiered tag@digest rule
Resolve the conflict between ADR-011 (tags-not-digests) and the security work
(digest pinning) with one coherent rule that respects ADR-011's stateless/stateful
split:

- Stateful → pin `tag@digest` (readable tag + integrity digest): legible diffs AND
  tamper-evidence. Snapshots cover broken updates; the digest covers swapped images.
- Stateless → rolling tags (latest/stable); digest-pinning would defeat the rolling
  design. Integrity rests on official/verified images + disposability.

Aligned across ADR-011 (decision 2), ADR-004 (image management), ADR-002
(supply-chain row), accepted-risk R1, the service checklist, and TODO 15.6.
TODO 16.7 marked decided.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 19:21:36 +02:00

53 lines
2.4 KiB
Markdown

# Per-service security checklist
The bar every service (a per-service role — ADR-004) must clear **before deploy**,
especially anything reachable beyond its own host. Established by **ADR-002**
(Security baseline and strategy); referenced from `docs/runbooks/new-role.md`.
Enforced manually in review today; the planned `/security-review` skill (see
`docs/TODO.md`) will automate the check.
Treat each item as must-pass **unless** a deviation is recorded in
`docs/security/accepted-risks.md` with a rationale and a revisit trigger.
This checklist is the generic **bar**. Each service answers it in its own
`roles/<service>/SECURITY.md` (the "Checklist status" section), created from
`docs/security/service-security-template.md` — see ADR-004.
## Secrets & credentials
- [ ] All secrets live in an encrypted `vault.yml` (`vault.<service>.<key>`); none in
plaintext files, templates, or Compose env literals
- [ ] No default or vendor-shipped credentials remain — admin passwords/tokens are
generated and stored in vault
- [ ] Nothing secret is baked into an image or committed to git (gitleaks must pass)
## Least privilege
- [ ] Container runs as a non-root user where the image supports it
- [ ] No `privileged: true` and no host network mode unless explicitly justified
- [ ] Only the volumes/paths the service needs are mounted; read-only where possible
- [ ] Linux capabilities dropped to what's required (no blanket grants)
## Network & exposure
- [ ] Every listening port is declared in `group_vars` firewall definitions — never
opened ad-hoc on a host
- [ ] The service is not published directly to a LAN/WAN port if it can sit behind the
reverse proxy instead
- [ ] Anything reachable beyond the `srv` VLAN is behind the reverse proxy **with
authentication** (and TLS)
- [ ] Inter-service reach follows least privilege — no broad `srv``srv` access where a
single declared dependency suffices
## Updates & provenance
- [ ] Image pinned per ADR-011's tiered rule — stateful: `tag@digest`; stateless: rolling tag (`latest`/`stable`) acceptable
- [ ] The update path is known — how this service gets patched
## Operability (security-adjacent)
- [ ] Logs go somewhere reviewable (central aggregation when available)
- [ ] Backup/restore is covered if the service holds state
> Deviations are allowed but must be **conscious**: record them in
> `docs/security/accepted-risks.md`, don't leave them implicit.