feat(openbao-session): tie session token to the user entity

Mint the session token with -entity-alias from OPENBAO_SESSION_ENTITY so
{{identity.entity.id}} resolves and the session can read humans/self (read-only)
in addition to shared/*. Document the claude-session policy with humans/self.
Bump 0.1.1.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-09-01 11:19:00 +07:00
parent 6ad7202fdf
commit 6877bc7202
4 changed files with 15 additions and 5 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "openbao-session", "name": "openbao-session",
"version": "0.1.0", "version": "0.1.1",
"description": "Provisions a short-lived OpenBao session token for interactive agent sessions.", "description": "Provisions a short-lived OpenBao session token for interactive agent sessions.",
"author": { "name": "Senkensha" }, "author": { "name": "Senkensha" },
"hooks": "./hooks/claude-codex-hooks.json" "hooks": "./hooks/claude-codex-hooks.json"

View File

@@ -1,6 +1,6 @@
{ {
"name": "openbao-session", "name": "openbao-session",
"version": "0.1.0+codex.20260901021149", "version": "0.1.1+codex.20260901111859",
"description": "Provisions a short-lived OpenBao session token for interactive agent sessions.", "description": "Provisions a short-lived OpenBao session token for interactive agent sessions.",
"author": { "author": {
"name": "Local developer" "name": "Local developer"

View File

@@ -8,7 +8,7 @@ Saat sesi mulai, `hooks/bao-session.sh`:
1. Memastikan **SSH tunnel loopback** ke listener VPC privat OpenBao hidup (`127.0.0.1:8200 → 10.104.0.12:8200` lewat jumphost `mbu-backup-jumphost`). 1. Memastikan **SSH tunnel loopback** ke listener VPC privat OpenBao hidup (`127.0.0.1:8200 → 10.104.0.12:8200` lewat jumphost `mbu-backup-jumphost`).
2. Mengambil CA cert OpenBao (`/opt/openbao/tls/tls.crt`) dan menyimpannya lokal. 2. Mengambil CA cert OpenBao (`/opt/openbao/tls/tls.crt`) dan menyimpannya lokal.
3. Membaca **bootstrap credential** dari secrets store lokal (`manage.py get openbao bootstrap_token`). 3. Membaca **bootstrap credential** dari secrets store lokal (`manage.py get openbao bootstrap_token`).
4. **Mint token sesi** `claude-session` (TTL `4h`, renewable) memakai bootstrap credential sebagai caller. 4. **Mint token sesi** `claude-session` (TTL `4h`, renewable) memakai bootstrap credential sebagai caller; bila `OPENBAO_SESSION_ENTITY` diset, token dikaitkan ke entity pemakai (`-entity-alias`) sehingga `{{identity.entity.id}}` resolve dan sesi dapat membaca `humans/self`.
5. Menyuntikkan `OPENBAO_TOKEN`, `BAO_ADDR`, `BAO_CACERT`, `BAO_TLS_SERVER_NAME` ke sesi: 5. Menyuntikkan `OPENBAO_TOKEN`, `BAO_ADDR`, `BAO_CACERT`, `BAO_TLS_SERVER_NAME` ke sesi:
| Host | Mekanisme injeksi | | Host | Mekanisme injeksi |
@@ -38,12 +38,14 @@ path "auth/token/lookup-self" { capabilities = ["read"] }
EOF EOF
bao policy write openbao-session-creator /tmp/openbao-session-creator.hcl bao policy write openbao-session-creator /tmp/openbao-session-creator.hcl
# 2. Policy sesi: baca-only untuk secret yang memang di-assign ke agent # 2. Policy sesi: baca-only untuk secret yang memang di-assign ke agent.
# (sempitkan/sesuaikan daftar path mengikuti penugasan Phase 2 migrasi) # humans/self otomatis ter-scope ke entity pemakai via {{identity.entity.id}}
cat > /tmp/claude-session.hcl <<'EOF' cat > /tmp/claude-session.hcl <<'EOF'
# Refine daftar path di sini sesuai owner/consumer assignment. # Refine daftar path di sini sesuai owner/consumer assignment.
path "shared/data/*" { capabilities = ["read", "list"] } path "shared/data/*" { capabilities = ["read", "list"] }
path "shared/metadata/*" { capabilities = ["read", "list"] } path "shared/metadata/*" { capabilities = ["read", "list"] }
path "humans/data/{{identity.entity.id}}/*" { capabilities = ["read", "list"] }
path "humans/metadata/{{identity.entity.id}}/*" { capabilities = ["read", "list"] }
EOF EOF
bao policy write claude-session /tmp/claude-session.hcl bao policy write claude-session /tmp/claude-session.hcl
@@ -80,6 +82,7 @@ python3 ~/.config/devops-secrets/manage.py set openbao bootstrap_token --descrip
| `OPENBAO_SESSION_SSH_KEY` | `~/.ssh/id_ed25519` | key SSH ke jumphost | | `OPENBAO_SESSION_SSH_KEY` | `~/.ssh/id_ed25519` | key SSH ke jumphost |
| `OPENBAO_SESSION_POLICY` | `claude-session` | policy token sesi | | `OPENBAO_SESSION_POLICY` | `claude-session` | policy token sesi |
| `OPENBAO_SESSION_TTL` | `4h` | umur token sesi | | `OPENBAO_SESSION_TTL` | `4h` | umur token sesi |
| `OPENBAO_SESSION_ENTITY` | *(kosong)* | nama entity OpenBao pemakai (mis. `adnan`, `rizal`) → token sesi diikat ke entity (aktifkan `humans/self`) |
| `OPENBAO_SESSION_BAO_VER` | `2.6.2` | versi binary bao (auto-download jika belum ada) | | `OPENBAO_SESSION_BAO_VER` | `2.6.2` | versi binary bao (auto-download jika belum ada) |
| `OPENBAO_SESSION_SECRETS_HELPER` | `~/.config/devops-secrets/manage.py` | helper baca bootstrap | | `OPENBAO_SESSION_SECRETS_HELPER` | `~/.config/devops-secrets/manage.py` | helper baca bootstrap |
| `OPENBAO_SESSION_BOOTSTRAP_TOOL` / `_KEY` | `openbao` / `bootstrap_token` | lokasi bootstrap di secrets store | | `OPENBAO_SESSION_BOOTSTRAP_TOOL` / `_KEY` | `openbao` / `bootstrap_token` | lokasi bootstrap di secrets store |
@@ -88,6 +91,7 @@ python3 ~/.config/devops-secrets/manage.py set openbao bootstrap_token --descrip
- Nilai secret tidak pernah ditulis ke repo, chat, atau log; token sesi mengalir lewat `$CLAUDE_ENV_FILE` (Claude) atau session env file mode 600 (Codex), bukan argv dan bukan ke konteks model. - Nilai secret tidak pernah ditulis ke repo, chat, atau log; token sesi mengalir lewat `$CLAUDE_ENV_FILE` (Claude) atau session env file mode 600 (Codex), bukan argv dan bukan ke konteks model.
- Token sesi **short-lived** (`4h`, renewable) dan **scoped** ke policy `claude-session` saja. - Token sesi **short-lived** (`4h`, renewable) dan **scoped** ke policy `claude-session` saja.
- `humans/self` hanya terbaca lewat token yang **terikat entity pemakai** (`{{identity.entity.id}}`) — sesi orang lain tidak bisa membaca ruang pribadi Anda.
- Bootstrap credential tidak bisa membaca secret, tapi bisa mint token → rotasi bila dicurigai bocor: buat bootstrap baru, `manage.py set`, revoke yang lama (`bao token revoke <accessor>`). - Bootstrap credential tidak bisa membaca secret, tapi bisa mint token → rotasi bila dicurigai bocor: buat bootstrap baru, `manage.py set`, revoke yang lama (`bao token revoke <accessor>`).
- Tunnel hanya bind `127.0.0.1`; jangan pernah expose port publik atau pakai TLS skip-verify. - Tunnel hanya bind `127.0.0.1`; jangan pernah expose port publik atau pakai TLS skip-verify.

View File

@@ -36,6 +36,7 @@ TLS_NAME="${OPENBAO_SESSION_TLS_NAME:-mbu-backup-jumphost}"
BAO_VER="${OPENBAO_SESSION_BAO_VER:-2.6.2}" BAO_VER="${OPENBAO_SESSION_BAO_VER:-2.6.2}"
SESSION_POLICY="${OPENBAO_SESSION_POLICY:-claude-session}" SESSION_POLICY="${OPENBAO_SESSION_POLICY:-claude-session}"
SESSION_TTL="${OPENBAO_SESSION_TTL:-4h}" SESSION_TTL="${OPENBAO_SESSION_TTL:-4h}"
SESSION_ENTITY="${OPENBAO_SESSION_ENTITY:-}" # OpenBao entity name; ties the session token to the user (enables humans/self via {{identity.entity.id}})
SECRETS_HELPER="${OPENBAO_SESSION_SECRETS_HELPER:-$HOME/.config/devops-secrets/manage.py}" SECRETS_HELPER="${OPENBAO_SESSION_SECRETS_HELPER:-$HOME/.config/devops-secrets/manage.py}"
BOOTSTRAP_TOOL="${OPENBAO_SESSION_BOOTSTRAP_TOOL:-openbao}" BOOTSTRAP_TOOL="${OPENBAO_SESSION_BOOTSTRAP_TOOL:-openbao}"
BOOTSTRAP_KEY="${OPENBAO_SESSION_BOOTSTRAP_KEY:-bootstrap_token}" BOOTSTRAP_KEY="${OPENBAO_SESSION_BOOTSTRAP_KEY:-bootstrap_token}"
@@ -101,9 +102,14 @@ read_bootstrap() {
mint_session_token() { mint_session_token() {
local bootstrap json local bootstrap json
local -a entity_args=()
bootstrap="$(read_bootstrap)" || return 1 bootstrap="$(read_bootstrap)" || return 1
if [ -n "$SESSION_ENTITY" ]; then
entity_args+=("-entity-alias=$SESSION_ENTITY")
fi
json="$(BAO_ADDR="$BAO_ADDR_URL" BAO_CACERT="$CACERT" BAO_TLS_SERVER_NAME="$TLS_NAME" BAO_TOKEN="$bootstrap" \ json="$(BAO_ADDR="$BAO_ADDR_URL" BAO_CACERT="$CACERT" BAO_TLS_SERVER_NAME="$TLS_NAME" BAO_TOKEN="$bootstrap" \
"$BAO_BIN" token create -policy="$SESSION_POLICY" -ttl="$SESSION_TTL" -renewable \ "$BAO_BIN" token create -policy="$SESSION_POLICY" -ttl="$SESSION_TTL" -renewable \
"${entity_args[@]}" \
-display-name="openbao-session-$(hostname)" -format=json)" || { log "token create failed"; return 1; } -display-name="openbao-session-$(hostname)" -format=json)" || { log "token create failed"; return 1; }
SESSION_TOKEN="$(printf '%s' "$json" | jq -r '.auth.client_token // empty')" SESSION_TOKEN="$(printf '%s' "$json" | jq -r '.auth.client_token // empty')"
[ -n "$SESSION_TOKEN" ] || { log "no client_token in token create response"; return 1; } [ -n "$SESSION_TOKEN" ] || { log "no client_token in token create response"; return 1; }