c77ff07ce9
Remediation of the 2026-05-12/13 audits (78 findings + cluster gaps), tracked in deploy-k3s/SECURITY.md, plus fixes from two independent post-remediation reviews. Auth & sessions: - SHA-256 hashed auth-token storage (C1); prior-token cache eviction on re-login (MEDIUM-1) - local Google JWKS verification, iss/aud/exp checks (C2/C3) - constant-time login + generic errors (L1/LIVE-L11/LIVE-L13) - per-account login lockout keyed on distinct source IPs (M5/MEDIUM-3) - verified-email gating, login rate limiting (LIVE-L19, H1-H3) IAP & webhooks: - Apple/Google cross-account replay protection (C5/C6/C10/C13, H5/H6) - migrations 000003-000006 (token hashing, IAP replay, audit_log + webhook_event_log table creation, append-only audit log) Authorization & races: - file-ownership owner-OR-member fix (C7), atomic share-code join (C9/H9), device-token reassignment (C8/LOW-3) Secrets & deploy: - secrets file-mounted at /etc/honeydue/secrets, not env (F8); Redis password out of the ConfigMap (HIGH-1); B2 keys reconciled - digest-pinned images, admin ingress hardening, CSP/HSTS, /metrics lockdown; kubeconfig 0600, etcd secrets-encryption, fail2ban + unattended-upgrades at provision; secret-rotation runbook Build, vet, and the full test suite (incl. -race) pass; the goose migration chain is verified against PostgreSQL 16. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
115 lines
3.4 KiB
YAML
115 lines
3.4 KiB
YAML
# Traefik CRD middleware for rate limiting
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: rate-limit
|
|
namespace: honeydue
|
|
spec:
|
|
rateLimit:
|
|
average: 100
|
|
burst: 200
|
|
period: 1m
|
|
|
|
---
|
|
# Security headers
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: security-headers
|
|
namespace: honeydue
|
|
spec:
|
|
headers:
|
|
frameDeny: true
|
|
contentTypeNosniff: true
|
|
# browserXssFilter removed (audit L7): it emits the deprecated
|
|
# X-XSS-Protection header, which can itself introduce XSS in legacy
|
|
# browsers. Modern browsers ignore it.
|
|
referrerPolicy: "strict-origin-when-cross-origin"
|
|
customResponseHeaders:
|
|
X-Content-Type-Options: "nosniff"
|
|
X-Frame-Options: "DENY"
|
|
# HSTS: 2-year max-age + preload (audit L5/CODE-L3). After this is
|
|
# live on api/admin/app, submit myhoneydue.com to hstspreload.org.
|
|
Strict-Transport-Security: "max-age=63072000; includeSubDomains; preload"
|
|
# Cross-origin isolation (audit F9). COEP (require-corp) is omitted —
|
|
# it commonly breaks third-party embeds; add only after testing.
|
|
Cross-Origin-Opener-Policy: "same-origin"
|
|
Cross-Origin-Resource-Policy: "same-origin"
|
|
# Content-Security-Policy is intentionally NOT set here — the Go API
|
|
# sets a CSP in internal/router/router.go that permits Google Fonts
|
|
# for the landing page. Two CSP headers would intersect and break it.
|
|
# admin and web apps set their own CSP via Next.js middleware.
|
|
Permissions-Policy: "camera=(), microphone=(), geolocation=()"
|
|
X-Permitted-Cross-Domain-Policies: "none"
|
|
|
|
---
|
|
# Cloudflare IP allowlist (restrict origin to Cloudflare only)
|
|
# https://www.cloudflare.com/ips-v4 and /ips-v6
|
|
# Update periodically: curl -s https://www.cloudflare.com/ips-v4 && curl -s https://www.cloudflare.com/ips-v6
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: cloudflare-only
|
|
namespace: honeydue
|
|
spec:
|
|
ipAllowList:
|
|
sourceRange:
|
|
# Cloudflare IPv4 ranges
|
|
- 173.245.48.0/20
|
|
- 103.21.244.0/22
|
|
- 103.22.200.0/22
|
|
- 103.31.4.0/22
|
|
- 141.101.64.0/18
|
|
- 108.162.192.0/18
|
|
- 190.93.240.0/20
|
|
- 188.114.96.0/20
|
|
- 197.234.240.0/22
|
|
- 198.41.128.0/17
|
|
- 162.158.0.0/15
|
|
- 104.16.0.0/13
|
|
- 104.24.0.0/14
|
|
- 172.64.0.0/13
|
|
- 131.0.72.0/22
|
|
# Cloudflare IPv6 ranges
|
|
- 2400:cb00::/32
|
|
- 2606:4700::/32
|
|
- 2803:f800::/32
|
|
- 2405:b500::/32
|
|
- 2405:8100::/32
|
|
- 2a06:98c0::/29
|
|
- 2c0f:f248::/32
|
|
|
|
---
|
|
# Admin basic auth — additional auth layer for admin panel
|
|
# Secret created by 02-setup-secrets.sh from config.yaml credentials
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: admin-auth
|
|
namespace: honeydue
|
|
spec:
|
|
basicAuth:
|
|
secret: admin-basic-auth
|
|
realm: "honeyDue Admin"
|
|
|
|
---
|
|
# Strict rate limit for auth endpoints (audit F10 / LIVE-L12).
|
|
# Applied via the honeydue-api-auth Ingress to login / register /
|
|
# forgot-password / reset-password / join-with-code. depth: 2 makes the
|
|
# limiter key on the real client IP rather than the Cloudflare edge IP
|
|
# (request path: client -> Cloudflare -> Traefik). This is the edge half;
|
|
# the per-account lockout in the Go app is the robust half.
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: auth-rate-limit
|
|
namespace: honeydue
|
|
spec:
|
|
rateLimit:
|
|
average: 5
|
|
burst: 10
|
|
period: 1m
|
|
sourceCriterion:
|
|
ipStrategy:
|
|
depth: 2
|