openova/products/catalyst/chart/templates/serviceaccount-cutover-driver.yaml
e3mrah b52fc45c37
fix(bp-catalyst-platform): cutover-driver RBAC dual-mode render (#830) (#839)
Chart 1.3.2 shipped serviceaccount-cutover-driver.yaml +
clusterrole-cutover-driver.yaml + clusterrolebinding-cutover-driver.yaml
with `{{ .Release.Namespace }}` directives that rendered fine via Helm
on Sovereigns but BROKE the Kustomize-mode contabo-mkt deploy: the
directives made Kustomize parse the files as invalid YAML and silently
skip them. Worse, the new files were never added to templates/
kustomization.yaml's resources list.

Result on contabo: catalyst-api Pod's spec.serviceAccountName references
a non-existent SA — the Pod fails ContainerCreating with the same RBAC
forbidden error #830 was meant to fix.

Fix:
  - Strip `{{ .Release.Namespace }}` directives from the SA + ClusterRole
    files. metadata.namespace auto-fills from Helm's --namespace flag
    and from Kustomize's `namespace:` directive.
  - For ClusterRoleBinding: Helm does NOT auto-inject subjects[0].
    namespace the way it does metadata.namespace, so the apiserver
    rejects bindings without it. Split into two files:
      * clusterrolebinding-cutover-driver.yaml — Helm-only, uses
        {{ .Release.Namespace }} (correctly resolves to catalyst-system
        on Sovereigns).
      * clusterrolebinding-cutover-driver-kustomize.yaml — Kustomize-
        only, omits subjects[0].namespace and relies on Kustomize's
        native injection (resolves to `catalyst` on contabo).
    The .helmignore excludes the Kustomize-only file from Sovereign
    chart packaging; templates/kustomization.yaml's resources list
    references the Kustomize-only file, NOT the Helm-only one.
  - Add the new RBAC files to templates/kustomization.yaml's resources
    list so contabo's Flux Kustomization actually renders them.

Verified live with `helm template` (subjects[0].namespace=catalyst-system)
and `kubectl kustomize` (subjects[0].namespace=catalyst).

Bumps bp-catalyst-platform 1.3.2 → 1.3.3.

Issue: openova-io/openova#830 (Bug 1 follow-up)

Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 23:54:03 +04:00

53 lines
2.7 KiB
YAML

# ServiceAccount used by the catalyst-api Pod to drive the
# self-sovereignty cutover endpoint (issue #792).
#
# After handover, catalyst-api on the Sovereign cluster handles
# POST /api/v1/sovereign/cutover/start. The handler:
# - reads the cutover-step PodSpec ConfigMaps in the `catalyst` namespace
# (selected by app.kubernetes.io/part-of=self-sovereign-cutover)
# - stamps batchv1.Job objects from those PodSpecs in the same namespace
# - patches the self-sovereign-cutover-status ConfigMap as each step
# transitions, recording state machine progress
# - watches Job status to completion / Failed
# - inspects DaemonSet readiness for daemonset-wait steps
#
# catalyst-api itself runs in:
# - `catalyst` namespace on contabo-mkt (deployed via Kustomize from
# ./products/catalyst/chart/templates with namespace: catalyst).
# - `catalyst-system` namespace on Sovereigns (deployed via Helm with
# targetNamespace: catalyst-system from the bp-catalyst-platform OCI
# chart).
# Both deployment paths fill in metadata.namespace automatically (Helm
# from --namespace, Kustomize from its namespace: directive). The same
# auto-fill propagates into ClusterRoleBinding subjects[0].namespace —
# verified with kubectl kustomize on a fixture binding (PR #831 follow-up
# after Kustomize-mode contabo deploy dropped this resource because the
# original {{ .Release.Namespace }} directive made Kustomize parse the
# file as invalid YAML and silently skip it).
#
# NOTE — DUAL-MODE CONTRACT (api-deployment.yaml has the canonical
# explanation): every file in this directory is consumed BOTH by Helm
# (per-Sovereign install) AND by Kustomize (contabo via flux Kustomization
# at path: ./products/catalyst/chart/templates). Helm template syntax
# (double-curly directives) here breaks the Kustomize build. Hence NO
# Helm directives in this file at all — namespace auto-fills, no other
# Helm context is needed.
#
# Why a dedicated SA (not `default`):
# - The proof loop on otech102 surfaced a 502 status-read-failed:
# "User \"system:serviceaccount:catalyst-system:default\" cannot get
# resource \"configmaps\" in API group \"\" in the namespace \"catalyst\""
# because no Role/ClusterRole was bound to the default SA. Granting
# cluster-scope cutover-driver verbs to the default SA would leak
# those permissions to every other Pod in catalyst-system.
# - Per docs/INVIOLABLE-PRINCIPLES.md #10 (least privilege), bespoke
# workload SAs are the canonical pattern. This SA is referenced
# explicitly in api-deployment.yaml's spec.serviceAccountName.
apiVersion: v1
kind: ServiceAccount
metadata:
name: catalyst-api-cutover-driver
labels:
app.kubernetes.io/name: catalyst-api
app.kubernetes.io/component: cutover-driver-sa