diff --git a/docs/changelog-20260721-tenant-review-pin.md b/docs/changelog-20260721-tenant-review-pin.md index 35ad9c2..a669d8a 100644 --- a/docs/changelog-20260721-tenant-review-pin.md +++ b/docs/changelog-20260721-tenant-review-pin.md @@ -141,3 +141,18 @@ remainder only); CURRENT-STATE item 4 + ledger machine block coupled. - **Revert:** git revert the four commits (records only; no live surface touched). + +## 11. D-068 item 3 delivery: A9 vault-kv auth section in cloud-assert.sh + +- Per the item-3 ruling ("Adopt + probe on VR1 now"): new section A9 + delegates to the EXISTING scripts/vault-kv-health.sh (the D-068 outer + driver, dynamic consumer discovery, one real 60s-TTL AppRole login per + consumer) and maps its exit 0/1/2 to ok/fail/warn. SKIPS with ok when + the model carries no vault application -- the pre-Stage-5 VR1 shape -- + so current sweeps are unaffected. CLOUD_ASSERT_VKH env = documented + test seam (offline harness stubs the driver; unset in real runs). +- Harness: tests/cloud-assert +3 cases (T13 skip-when-no-vault, T14 + pass mapping, T15 fail mapping) -- 15/15; gauntlet 76 ALL GREEN; + repo-lint 0-fail. No live execution (nothing to probe until Stage 5). +- **Revert:** git revert this commit (restores cloud-assert.sh + harness + to pre-A9; no live surface touched). diff --git a/scripts/cloud-assert.sh b/scripts/cloud-assert.sh index 5d3a0d0..c17377b 100644 --- a/scripts/cloud-assert.sh +++ b/scripts/cloud-assert.sh @@ -22,6 +22,9 @@ # 'openstack coe service list' returns the conductor row (no 403) [OS_*] # A8 conductor graft: magnum-conductor LIVE process args carry --config-dir # (D-037: verify the launched cmdline, never the config text) +# A9 vault-kv consumer AppRole auth (D-068 item 3, ruled 2026-07-21): +# delegates to vault-kv-health.sh (one real 60s-TTL login per consumer); +# SKIPS (ok) when the model has no vault application -- pre-Stage-5 VR1 # # --capture: additionally writes a deploy BOM (bill of materials) to # asbuilt// : exported bundle, juju status yaml, driver pip @@ -174,6 +177,27 @@ elif grep -qi 'no such\|not found\|cannot' <<<"$P"; then warn "magnum/0 unreachable for A8: $(head -1 <<<"$P")" else fail "conductor LIVE args lack --config-dir (graft not in effect; config-file presence proves nothing): $(head -1 <<<"$P")"; fi +echo "================ A9: vault-kv consumer AppRole auth (D-068 item 3) ================" +# Ruled 2026-07-21 ("Adopt + probe on VR1 now"): the proactive login check is +# part of every sweep -- expiry surfaces here, never via a tenant's failed +# cluster-create. Delegates to vault-kv-health.sh (dynamic consumer discovery; +# exit 0 pass / 1 fail / 2 coverage-gap). CLOUD_ASSERT_VKH overrides the +# script path -- test seam for the offline harness, unset in real runs. +SD="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +VKH="${CLOUD_ASSERT_VKH:-$SD/vault-kv-health.sh}" +if ! jq -e '.applications.vault' >/dev/null 2>&1 <<<"$ST"; then + ok "no vault application in model '$MODEL' -- A9 skipped (vault arrives Stage 5)" +elif [ ! -s "$VKH" ]; then + fail "vault present but probe driver missing: $VKH" +else + VKO=$(MODEL="$MODEL" bash "$VKH" 2>&1) ; VKRC=$? + case "$VKRC" in + 0) ok "vault-kv health: every consumer AppRole login 200" ;; + 2) warn "vault-kv health coverage gap/warnings: $(grep -m2 '^WARN' <<<"$VKO" | tr '\n' ' ')" ;; + *) fail "vault-kv health FAILED: $(grep -m3 '^FAIL' <<<"$VKO" | tr '\n' ' ')" ;; + esac +fi + if [ "$CAPTURE" -eq 1 ]; then echo "================ CAPTURE: as-built BOM ================" DIR="asbuilt/$(date -u +%Y%m%d-%H%M%S)"; mkdir -p "$DIR" diff --git a/tests/cloud-assert/run-tests.sh b/tests/cloud-assert/run-tests.sh index 024a396..4fa4ecc 100644 --- a/tests/cloud-assert/run-tests.sh +++ b/tests/cloud-assert/run-tests.sh @@ -136,6 +136,26 @@ F="$TMP/svcerr"; mkgood "$F"; : > "$F/svc-err" run 1 'compute service list unreadable' "T12 erroring service-list FAILS (was fail-open)" "$F" +# T13-T15 (D-068 item 3): A9 vault-kv consumer auth section +addvault() { # add a vault app to a fixture's status.json + python3 - "$1/status.json" <<'PY' +import json,sys; p=sys.argv[1]; d=json.load(open(p)) +d["applications"]["vault"]={"units":{"vault/0":{"workload-status":{"current":"active"}}}} +json.dump(d,open(p,"w")) +PY +} +# T13: no vault app in model -> A9 skips with ok (the pre-Stage-5 VR1 shape) +F="$TMP/novault"; mkgood "$F" + run 0 'A9 skipped \(vault arrives Stage 5\)' "T13 no vault app -> A9 skip, still PASS" "$F" +# T14: vault present, probe driver passes -> PASS line +F="$TMP/vkpass"; mkgood "$F"; addvault "$F" +printf '#!/usr/bin/env bash\necho PASS: all consumers\nexit 0\n' > "$TMP/vkh-pass.sh" + run 0 'every consumer AppRole login 200' "T14 vault-kv health pass -> ok" "$F" CLOUD_ASSERT_VKH="$TMP/vkh-pass.sh" +# T15: vault present, probe driver fails -> section FAILs the sweep +F="$TMP/vkfail"; mkgood "$F"; addvault "$F" +printf '#!/usr/bin/env bash\necho "FAIL: barbican-vault login_http=403"\nexit 1\n' > "$TMP/vkh-fail.sh" + run 1 'vault-kv health FAILED' "T15 vault-kv health fail -> FAIL (D-068 item 3)" "$F" CLOUD_ASSERT_VKH="$TMP/vkh-fail.sh" + # T9: no admin scope -> A5-A7 HELD, exit 2 (never a silent pass) F="$TMP/held"; mkgood "$F" out="$(cd "$TMP" && env -u OS_AUTH_URL FIXDIR="$F" PATH="$BIN:$PATH" bash "$REPO/scripts/cloud-assert.sh" 2>&1)"; rc=$?