|
| 1 | +apiVersion: v1 |
| 2 | +kind: ConfigMap |
| 3 | +metadata: |
| 4 | + name: openbao-bootstrap-script |
| 5 | + namespace: openbao |
| 6 | +data: |
| 7 | + bootstrap.sh: | |
| 8 | + #!/bin/sh |
| 9 | + # Idempotent OpenBao internal-config bootstrap. Safe to re-run any time. |
| 10 | + # Recreates the structural config that lives in raft (and is otherwise only |
| 11 | + # imperative): KV v2 mount, kubernetes auth method+config, policies, roles. |
| 12 | + # Secret VALUES are NOT handled here — those come from the mirror (P2) or the |
| 13 | + # age cold-export (P3b). This only rebuilds the scaffolding. |
| 14 | + set -eu |
| 15 | + export BAO_ADDR="${BAO_ADDR:-http://openbao.openbao.svc:8200}" |
| 16 | +
|
| 17 | + # --- obtain a privileged token ------------------------------------------- |
| 18 | + # DR mode: fresh `bao operator init` root token mounted out-of-band. |
| 19 | + # Steady mode: k8s-auth as the admin role (SA openbao-admin). |
| 20 | + if [ -f /bootstrap/root-token ]; then |
| 21 | + echo "[bootstrap] using root token from mounted Secret (DR mode)" |
| 22 | + BAO_TOKEN=$(cat /bootstrap/root-token) |
| 23 | + else |
| 24 | + echo "[bootstrap] no root-token Secret -> k8s-auth login role=admin" |
| 25 | + JWT=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) |
| 26 | + RESP=$(bao write -format=json auth/kubernetes/login role=admin jwt="$JWT") |
| 27 | + BAO_TOKEN=$(printf '%s' "$RESP" | grep '"client_token"' | head -1 \ |
| 28 | + | sed -E 's/.*"client_token": ?"([^"]+)".*/\1/') |
| 29 | + fi |
| 30 | + [ -n "${BAO_TOKEN:-}" ] || { echo "[bootstrap] FATAL: no token obtained"; exit 1; } |
| 31 | + export BAO_TOKEN |
| 32 | +
|
| 33 | + # --- 1. KV v2 secrets engine at mdapi/ ----------------------------------- |
| 34 | + if bao secrets list -format=json 2>/dev/null | grep -q '"mdapi/"'; then |
| 35 | + echo "[bootstrap] kv mdapi/ already enabled" |
| 36 | + else |
| 37 | + echo "[bootstrap] enabling kv-v2 at mdapi/" |
| 38 | + bao secrets enable -path=mdapi -version=2 kv |
| 39 | + fi |
| 40 | + # Cap version churn from the hourly mirror (was max_versions=0 = unlimited). |
| 41 | + bao write mdapi/config max_versions=10 |
| 42 | +
|
| 43 | + # --- 2. kubernetes auth method ------------------------------------------- |
| 44 | + if bao auth list -format=json 2>/dev/null | grep -q '"kubernetes/"'; then |
| 45 | + echo "[bootstrap] kubernetes auth already enabled" |
| 46 | + else |
| 47 | + echo "[bootstrap] enabling kubernetes auth" |
| 48 | + bao auth enable kubernetes |
| 49 | + fi |
| 50 | + bao write auth/kubernetes/config \ |
| 51 | + kubernetes_host="https://kubernetes.default.svc" \ |
| 52 | + disable_iss_validation=true |
| 53 | +
|
| 54 | + # --- 3. policies (idempotent overwrite) ---------------------------------- |
| 55 | + bao policy write admin - <<'POL' |
| 56 | + path "*" { capabilities = ["create","read","update","delete","list","sudo"] } |
| 57 | + POL |
| 58 | + bao policy write eso-read - <<'POL' |
| 59 | + path "mdapi/data/*" { capabilities = ["read"] } |
| 60 | + path "mdapi/metadata/*" { capabilities = ["read","list"] } |
| 61 | + POL |
| 62 | + bao policy write mirror - <<'POL' |
| 63 | + path "mdapi/data/*" { capabilities = ["create","update","read"] } |
| 64 | + path "mdapi/metadata/*" { capabilities = ["list","read"] } |
| 65 | + POL |
| 66 | + bao policy write archive-read - <<'POL' |
| 67 | + path "mdapi/data/*" { capabilities = ["read"] } |
| 68 | + path "mdapi/metadata/*" { capabilities = ["list","read"] } |
| 69 | + POL |
| 70 | + bao policy write snapshot-read - <<'POL' |
| 71 | + path "sys/storage/raft/snapshot" { capabilities = ["read"] } |
| 72 | + POL |
| 73 | +
|
| 74 | + # --- 4. kubernetes-auth roles (idempotent overwrite) --------------------- |
| 75 | + bao write auth/kubernetes/role/admin \ |
| 76 | + bound_service_account_names=openbao-admin \ |
| 77 | + bound_service_account_namespaces=openbao \ |
| 78 | + policies=admin ttl=1h |
| 79 | + bao write auth/kubernetes/role/eso \ |
| 80 | + bound_service_account_names=openbao-eso \ |
| 81 | + bound_service_account_namespaces=external-secrets \ |
| 82 | + policies=eso-read ttl=20m |
| 83 | + bao write auth/kubernetes/role/mirror \ |
| 84 | + bound_service_account_names=openbao-mirror \ |
| 85 | + bound_service_account_namespaces=openbao \ |
| 86 | + policies=mirror ttl=30m |
| 87 | + bao write auth/kubernetes/role/windmill-archive \ |
| 88 | + bound_service_account_names=windmill \ |
| 89 | + bound_service_account_namespaces=windmill \ |
| 90 | + policies=archive-read ttl=20m |
| 91 | + bao write auth/kubernetes/role/windmill-snapshot \ |
| 92 | + bound_service_account_names=windmill \ |
| 93 | + bound_service_account_namespaces=windmill \ |
| 94 | + policies=snapshot-read ttl=10m |
| 95 | +
|
| 96 | + echo "[bootstrap] OpenBao internal config asserted OK" |
| 97 | + echo "[bootstrap] policies:"; bao policy list |
| 98 | + echo "[bootstrap] k8s-auth roles:"; bao list auth/kubernetes/role |
0 commit comments