Skip to content

Security hardening 2026 07 - #1

Merged
krlex merged 10 commits into
mainfrom
security-hardening-2026-07
Jul 16, 2026
Merged

Security hardening 2026 07#1
krlex merged 10 commits into
mainfrom
security-hardening-2026-07

Conversation

@krlex

@krlex krlex commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Motivation

Changes

Testing

  • Existing tests pass locally
  • New tests added (where applicable)
  • Manual verification documented above

Notes for reviewers

Checklist

  • Commits are signed with a real name and email
  • CHANGELOG.md updated (under ## [Unreleased])
  • Documentation updated (README / docs/ / Pages) if behavior changed
  • No secrets, credentials, or internal hostnames committed

krlex added 10 commits June 24, 2026 17:30
- No working secret defaults: postgres/SECRET_KEY/broadcast secrets are
  auto-generated (reused across upgrades via Secret lookup); admin password
  is required and install fails without it (H3).
- forail-task defaults to non-privileged, no host cgroup mount; opt in for
  the podman-in-pod path (H4).
- Session cookies Secure by default (M8); ALLOWED_HOSTS defaults to the
  ingress host instead of '*' (M9).
- Tiered NetworkPolicy (default-deny ingress + scoped allows so Postgres/Redis
  aren't reachable cluster-wide), gated behind networkPolicy.enabled=false
  since k3s flannel doesn't enforce policy (M11).
- podSecurityContext + per-workload securityContext values wired into web /
  frontend / assistant, empty by default pending per-image validation (M10).
- Flag the floating opa/otel :latest tags for pinning (L15).
The M9 hardening narrowed allowedHosts to the ingress host, but the
in-cluster liveness/readiness probes reach the app on 127.0.0.1. Django
rejects any Host not in ALLOWED_HOSTS with HTTP 400, so the probes failed
and the web pod crash-looped. Keep 127.0.0.1 and localhost listed.
The default instance group is a container group, so the scheduler submits
each job to receptor as the kubernetes-incluster-auth work type. Without a
matching work-kubernetes worktype receptor rejects the launch ("unknown
work type kubernetes-incluster-auth") and the job errors at 0s. authmethod
incluster uses the task pod's own ServiceAccount token.
Receptor lists/creates/deletes container-group job pods with the task pod's
ServiceAccount, so it needs pod RBAC in the release namespace. Without it
every launch fails ("pods is forbidden ... cannot list resource pods") and
the job stays pending. Adds a dedicated ServiceAccount plus a namespaced
Role/RoleBinding (pods, pods/log, pods/attach, pods/exec); both gated behind
serviceAccount.create / rbac.create.
serviceAccountName resolves the job-runner ServiceAccount (falls back to the
namespace default account when serviceAccount.create is false). MY_POD_NAMESPACE
is bound to the release namespace via the downward API so the container-group
scheduler launches job pods where the pod RBAC applies, not the cluster
"default" namespace.
Bind both backend deployments to the ServiceAccount that carries the pod RBAC
so the task scheduler (and receptor) can manage container-group job pods.
Keep the provisioning job on the same ServiceAccount as web/task for a
consistent identity across all backend pods.
@krlex
krlex merged commit 0845452 into main Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant