secret.yaml 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. # App secrets (task 46). PLACEHOLDERS ONLY — never commit real values.
  2. #
  3. # Consumption: the Deployment and the migrate Job project every key below into
  4. # a tmpfs volume at `/run/secrets` (`defaultMode: 0400`, group 65532 via the
  5. # pod `fsGroup`) and read them through `*_FILE` variables, so no secret enters
  6. # the process environment (`/proc/self/environ`, children, crash dumps,
  7. # `docker inspect`):
  8. #
  9. # token-pepper -> D_OAUTH_TOKEN_PEPPER_FILE
  10. # totp-encryption-key -> D_OAUTH_TOTP_ENCRYPTION_KEY_FILE
  11. # pii-encryption-key -> D_OAUTH_PII_ENCRYPTION_KEY_FILE
  12. # database-password -> D_OAUTH_DATABASE__PASSWORD_FILE
  13. # redis-password -> D_OAUTH_REDIS__PASSWORD_FILE
  14. #
  15. # The PII key is MANDATORY: the server refuses to start without it. Unlike the
  16. # always-required keys above, the PREVIOUS PII/TOTP keys are OPTIONAL and are
  17. # projected only during a rotation window; `scripts/check_manifests.py` enforces
  18. # the mandatory projection and, when a workload references a previous-key
  19. # `*_FILE`, that its basename is actually projected here.
  20. #
  21. # The passwordless DSNs (host/user/db/sslmode and the Redis address) are
  22. # non-secret and live in `configmap.yaml`; only the passwords are here. A
  23. # `kubectl exec` into a running pod therefore reads no credential from the
  24. # environment — only the 0400 files, which the container user already holds.
  25. # `scripts/check_manifests.py` fails the build if a workload injects any secret
  26. # through a `secretKeyRef` env instead.
  27. #
  28. # In-cluster Redis is expected to run with AUTH (`requirepass`); the password
  29. # is injected into the bare `redis://host:port` URL at connect time. A Redis
  30. # deployment without AUTH must enable it, or the workload fails closed on the
  31. # missing password file.
  32. #
  33. # Production rule: this file's keys are replaced by the secret manager
  34. # (external-secrets / sealed-secrets / vault agent). The manifests only ever
  35. # reference keys, never values; `scripts/check_manifests.py` fails the build
  36. # if a placeholder leaks outside this file, if a PEM block appears in any
  37. # manifest, or if a secret-shaped key lands in the ConfigMap.
  38. #
  39. # To provision: `kubectl create secret generic d-oauth-secrets -n d-oauth
  40. # --from-literal=database-password='...' --from-literal=redis-password='...'
  41. # ...` (or the external-secret equivalent), then delete this placeholder
  42. # file from the applied set.
  43. apiVersion: v1
  44. kind: Secret
  45. metadata:
  46. name: d-oauth-secrets
  47. namespace: d-oauth
  48. labels:
  49. app.kubernetes.io/name: d-oauth-server
  50. app.kubernetes.io/part-of: d-oauth
  51. type: Opaque
  52. stringData:
  53. # Postgres password, split out of the passwordless DSN in configmap.yaml.
  54. database-password: "REPLACE_ME__postgres-password"
  55. # Redis AUTH password, injected into the bare redis:// URL at connect time.
  56. redis-password: "REPLACE_ME__redis-password"
  57. # 256-bit server-side pepper for opaque-token hashing. Losing it invalidates
  58. # every live token; rotate per docs/OPERATIONS.md.
  59. token-pepper: "REPLACE_ME__at-least-32-bytes-of-random"
  60. # 256-bit key encrypting TOTP secrets at rest.
  61. totp-encryption-key: "REPLACE_ME__at-least-32-bytes-of-random"
  62. # 256-bit master key encrypting PII fields at rest (mandatory). Losing it
  63. # makes every sealed PII value unreadable; rotate per docs/OPERATIONS.md
  64. # (retaining the previous key until `pii rotate` completes).
  65. pii-encryption-key: "REPLACE_ME__at-least-32-bytes-of-random"