{{- /*
Catalyst auto-unseal RBAC — bp-openbao (issue #316, bug fix issue #598).

ServiceAccount + RoleBindings used by the post-install Jobs that run
`bao operator init` and bootstrap the Kubernetes auth method.

Permissions required (least-privilege):
  - get/list/delete on the seed Secret in the openbao namespace
    (init-job consumes the seed and deletes it on success).
  - get on Pods in the openbao namespace (the Job polls the
    StatefulSet readiness before calling `bao operator init`).
  - tokenreviews.authentication.k8s.io: create — required by OpenBao's
    Kubernetes auth method to validate ServiceAccount tokens. Bound at
    cluster scope via the standard `system:auth-delegator` ClusterRole.
    This binding is permanent (it's how OpenBao authenticates ESO at
    runtime, not a one-shot init step) so it lives outside the Helm
    hook lifecycle.

RBAC resources are NOT Helm hooks (issue #598 root cause fix):
  The SA/Role/RoleBinding must NOT have hook-delete-policy so they
  persist for the Job container to use. Previously they had
  `hook-delete-policy: before-hook-creation,hook-succeeded` — the
  `hook-succeeded` clause caused Helm to delete the SA immediately
  after the weight-0 hook "succeeded", before the weight-5 init Job
  pod could start (Job pod needs the SA to exist for token mount).
  Making them regular Helm-managed resources (no hook annotations)
  ensures they exist for the full duration of the install/upgrade and
  for idempotent re-runs.

Skip-render pattern (per #402 lesson, never use `{{ fail }}`): when
`autoUnseal.enabled=false` this entire file emits nothing — `helm
template` with default values stays clean.
*/}}
{{- $au := .Values.autoUnseal | default dict -}}
{{- if $au.enabled -}}
---
# ServiceAccount used by the init + auth-bootstrap Jobs. Lives in the
# openbao namespace alongside the StatefulSet. NOT a hook — must persist
# for the Job container's SA token mount (issue #598).
apiVersion: v1
kind: ServiceAccount
metadata:
  name: openbao-auto-unseal
  namespace: {{ .Release.Namespace | quote }}
  labels:
    catalyst.openova.io/blueprint: bp-openbao
    catalyst.openova.io/component: openbao-auto-unseal
---
# Role: read+delete the seed Secret, get/list Pods to poll readiness.
# NOT a hook — persists for life of the Helm release (issue #598).
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: openbao-auto-unseal
  namespace: {{ .Release.Namespace | quote }}
  labels:
    catalyst.openova.io/blueprint: bp-openbao
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list", "delete"]
    resourceNames:
      - {{ (($au.seedSecret).name) | default "openbao-recovery-seed" | quote }}
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list"]
  # CREATE rule — Kubernetes RBAC does NOT enforce resourceNames on
  # the "create" verb (the resource has no name yet at admission time,
  # so there's nothing to filter against). Splitting create into its
  # own rule WITHOUT resourceNames is the documented k8s pattern and
  # is required for the init Job's POST to /secrets to succeed.
  #
  # The 1.x history of this chart had `verbs: ["create", "get", "patch",
  # "update"]` with resourceNames set — every fresh init's POST
  # silently 403'd and the PUT fallback then silently failed (busybox
  # wget has no --method flag), so the openbao-unseal-keys Secret was
  # never written and every retry hit the idempotent FATAL. Caught
  # live across otech22..otech40 with chart 1.2.9's trace capture.
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["create"]
  # MUTATION rule — once the Secret exists, restrict subsequent
  # GET/PATCH/UPDATE/DELETE to only the well-known names this Job is
  # allowed to touch. Newly added secrets in the namespace remain
  # invisible to the Job SA.
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "patch", "update", "delete"]
    resourceNames:
      - openbao-init-marker
      # openbao-unseal-keys: persisted unseal-key set used by the init
      # Job's idempotent-resume path (issue #539). Required so the Job
      # can both write the keys on fresh init and re-read them on a
      # later retry when the vault is initialised but still sealed.
      - openbao-unseal-keys
      # openbao-init-trace: every init script run uploads its full
      # set -x trace to this Secret on EXIT, so the FIRST run's logs
      # survive subsequent container restarts that quickly hit the
      # idempotent FATAL. Recovery diagnostic only — contains no
      # secret material itself, but treating it as a Secret keeps it
      # under the same RBAC umbrella.
      - openbao-init-trace
      # openbao-root-token: transient Secret that init-job writes the
      # root_token into so auth-bootstrap (the next post-install hook)
      # can authenticate against bao. auth-bootstrap REVOKES the token
      # and DELETES this Secret on completion so the privileged token
      # never persists past the install window. RBAC mutation/delete
      # is intentionally scoped to this name.
      - openbao-root-token
---
# RoleBinding — NOT a hook (issue #598).
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: openbao-auto-unseal
  namespace: {{ .Release.Namespace | quote }}
  labels:
    catalyst.openova.io/blueprint: bp-openbao
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: openbao-auto-unseal
subjects:
  - kind: ServiceAccount
    name: openbao-auto-unseal
    namespace: {{ .Release.Namespace | quote }}
{{- if (($au.kubernetesAuth).enabled) }}
---
# ─── OpenBao runtime: token-reviewer ClusterRoleBinding ──────────────────
# OpenBao's Kubernetes auth method validates incoming ServiceAccount JWTs
# by calling tokenreviews.authentication.k8s.io. The OpenBao server pod
# (NOT the init Job) needs system:auth-delegator at cluster scope.
#
# This binding is NOT a Helm hook — it's permanent infrastructure that
# stays in place for the life of the OpenBao install. Hook lifecycle
# would tear it down on upgrade and break ESO auth in the gap window.
#
# Subject: the upstream openbao chart's ServiceAccount, named
# `<release>-openbao` per upstream convention (releaseName=openbao →
# `openbao` SA).
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: {{ printf "%s-openbao-auth-delegator" .Release.Name | quote }}
  labels:
    catalyst.openova.io/blueprint: bp-openbao
    catalyst.openova.io/component: openbao-token-reviewer
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
  - kind: ServiceAccount
    name: {{ .Release.Name | quote }}
    namespace: {{ .Release.Namespace | quote }}
{{- end }}
{{- end }}
