# Prerequisites – two Kubernetes Secrets must exist in the infra namespace:
#
#   1. vault-root-token
#        key: token   → the Vault root token (created after `vault operator init`)
#
#   2. vault-oidc-credentials
#        key: clientSecret → the Keycloak client secret for the "vault" OIDC client
#
# This Job runs as an ArgoCD PostSync hook so it fires on every sync of the
# raw-resources-infra application. Because selfHeal is enabled, ArgoCD will
# re-sync (and re-run this Job) any time the Job resource is removed, which
# effectively covers Vault restarts that trigger a pod replacement.
#
# What the Job configures (all operations are idempotent):
#   - Enables the OIDC auth method (if not already enabled)
#   - Writes the OIDC config pointing at Keycloak realm "lab"
#   - Writes the default OIDC role with groups_claim and redirect URIs
#   - Creates the "vault-admins" external identity group with the built-in "admin" policy
#   - Creates the group alias that maps the Keycloak group "vault-admins"
#     to the Vault external group via the OIDC mount accessor
---
apiVersion: batch/v1
kind: Job
metadata:
  name: vault-configure-permissions
  namespace: infra
  annotations:
    argocd.argoproj.io/hook: PostSync
    argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
spec:
  ttlSecondsAfterFinished: 600
  backoffLimit: 5
  template:
    spec:
      restartPolicy: OnFailure
      containers:
        - name: vault-configure
          image: hashicorp/vault:1.17.0
          env:
            - name: VAULT_ADDR
              value: "http://vault.infra.svc.cluster.local:8200"
            - name: VAULT_TOKEN
              valueFrom:
                secretKeyRef:
                  name: vault-root-token
                  key: token
            - name: OIDC_CLIENT_SECRET
              valueFrom:
                secretKeyRef:
                  name: vault-oidc-credentials
                  key: clientSecret
          command:
            - /bin/sh
            - -c
            - |
              set -e

              # jq is not bundled in the Vault image – install it from Alpine repos
              apk add jq -q --no-progress

              # ── Wait for Vault to be unsealed ──────────────────────────────────
              echo ">>> Waiting for Vault to be unsealed..."
              until vault status 2>&1 | grep -q "Sealed.*false"; do
                echo "    not ready yet, retrying in 5s..."
                sleep 5
              done
              echo ">>> Vault is ready."

              # ── OIDC auth method ───────────────────────────────────────────────
              if vault auth list | grep -q "^oidc/"; then
                echo ">>> OIDC auth already enabled."
              else
                vault auth enable oidc
                echo ">>> OIDC auth enabled."
              fi

              vault write auth/oidc/config \
                oidc_discovery_url="https://keycloak.dvirlabs.com/realms/lab" \
                oidc_client_id="vault" \
                oidc_client_secret="${OIDC_CLIENT_SECRET}" \
                default_role="default"
              echo ">>> OIDC config written."

              vault write auth/oidc/role/default \
                user_claim="sub" \
                groups_claim="groups" \
                allowed_redirect_uris="https://vault.dvirlabs.com/ui/vault/auth/oidc/oidc/callback" \
                allowed_redirect_uris="https://vault.dvirlabs.com/oidc/callback" \
                bound_audiences="vault" \
                ttl="8h"
              echo ">>> OIDC role/default written."

              # ── Resolve OIDC mount accessor ────────────────────────────────────
              OIDC_ACCESSOR=$(vault auth list | awk '$1 == "oidc/" {print $3}')
              echo ">>> OIDC accessor: ${OIDC_ACCESSOR}"

              # ── vault-admins external group ────────────────────────────────────
              if vault read identity/group/name/vault-admins > /dev/null 2>&1; then
                echo ">>> vault-admins group exists – ensuring policy=admin..."
                vault write identity/group/name/vault-admins \
                  type="external" \
                  policies="admin"
              else
                echo ">>> Creating vault-admins external group..."
                vault write identity/group \
                  name="vault-admins" \
                  type="external" \
                  policies="admin"
              fi

              GROUP_ID=$(vault read -field=id identity/group/name/vault-admins)
              echo ">>> vault-admins group id: ${GROUP_ID}"

              # ── Group alias: Keycloak "vault-admins" → Vault external group ────
              # Walk existing aliases and look for one bound to this group + accessor
              EXISTING_ALIAS=$(vault list -format=json identity/group-alias/id 2>/dev/null \
                | jq -r '.[]' \
                | while read ALIAS_ID; do
                    DATA=$(vault read -format=json "identity/group-alias/id/${ALIAS_ID}" 2>/dev/null)
                    CID=$(echo "${DATA}" | jq -r '.data.canonical_id')
                    ACC=$(echo "${DATA}" | jq -r '.data.mount_accessor')
                    if [ "${CID}" = "${GROUP_ID}" ] && [ "${ACC}" = "${OIDC_ACCESSOR}" ]; then
                      echo "${ALIAS_ID}"
                    fi
                  done | head -1)

              if [ -n "${EXISTING_ALIAS}" ]; then
                echo ">>> Group alias already exists (id=${EXISTING_ALIAS}), skipping."
              else
                vault write identity/group-alias \
                  name="vault-admins" \
                  canonical_id="${GROUP_ID}" \
                  mount_accessor="${OIDC_ACCESSOR}"
                echo ">>> Group alias created."
              fi

              echo ""
              echo ">>> Vault OIDC and permissions configuration complete."
