Files
railiance-platform/scripts/openbao-verify-login-overlay.sh
tegwick 520c7ea2c0 fix(openbao-ui): serve standalone KeyCape login at /ui/vault/auth
Ember's auth route bounces between ?with=netkingdom/ and ?with=token when
OIDC mounts are hidden from the unauthenticated listing. Bypass Ember on the
bare auth path with a static login page that calls auth_url directly; OIDC
callbacks still proxy to the OpenBao UI.
2026-06-19 21:13:08 +02:00

161 lines
4.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
BASE_URL="${OPENBAO_UI_BASE_URL:-https://bao.coulomb.social}"
OVERLAY_DIR="${OPENBAO_UI_OVERLAY_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/helm/openbao-ui-overlay}"
CHECK_DRIFT="${CHECK_UPSTREAM_DRIFT:-0}"
ok() { printf '[OK] %s\n' "$*"; }
err() { printf '[ERR] %s\n' "$*" >&2; }
step() { printf '\n==> %s\n' "$*"; }
usage() {
cat <<'USAGE'
Usage: scripts/openbao-verify-login-overlay.sh [--check-upstream-drift]
Verifies the public OpenBao UI serves the KeyCape login overlay assets and
that index.html injection is present.
Environment:
OPENBAO_UI_BASE_URL Public UI base URL. Default: https://bao.coulomb.social
OPENBAO_UI_OVERLAY_DIR Local overlay directory for drift fingerprints
CHECK_UPSTREAM_DRIFT Set to 1 to compare live UI hashes with patches/
USAGE
}
while [ "$#" -gt 0 ]; do
case "$1" in
--check-upstream-drift)
CHECK_DRIFT=1
shift
;;
-h|--help)
usage
exit 0
;;
*)
err "unknown argument: $1"
usage >&2
exit 2
;;
esac
done
require_pattern() {
local label="$1"
local haystack="$2"
local pattern="$3"
if ! grep -Eq "$pattern" <<<"$haystack"; then
err "$label"
return 1
fi
ok "$label"
}
step "Standalone login page"
auth_html="$(curl -fsS "$BASE_URL/ui/vault/auth")"
require_pattern \
"auth page serves standalone KeyCape login" \
"$auth_html" \
'id="login-submit"|Sign in with KeyCape'
if grep -Eq 'vault-|engines-dist' <<<"$auth_html"; then
err "auth page still serves Ember shell (expected standalone login.html)"
exit 1
fi
ok "auth page is standalone login.html (no Ember shell)"
step "Overlay asset endpoints"
index_html="$(curl -fsS "$BASE_URL/ui/")"
overlay_js="$(curl -fsS "$BASE_URL/ui/platform-overlay/overlay.js")"
overlay_css="$(curl -fsS "$BASE_URL/ui/platform-overlay/overlay.css")"
presets_json="$(curl -fsS "$BASE_URL/ui/platform-overlay/presets.json")"
require_pattern \
"index.html injects overlay.js" \
"$index_html" \
'/ui/platform-overlay/overlay\.js'
require_pattern \
"index.html injects overlay.css" \
"$index_html" \
'/ui/platform-overlay/overlay\.css'
require_pattern \
"overlay.js activates KeyCape overlay" \
"$overlay_js" \
'keycape-overlay-active'
require_pattern \
"overlay.js starts direct KeyCape OIDC redirect" \
"$overlay_js" \
'oidc/auth_url'
require_pattern \
"presets.json targets netkingdom mount" \
"$presets_json" \
'"mount"[[:space:]]*:[[:space:]]*"netkingdom"'
require_pattern \
"presets.json targets platform-admin role" \
"$presets_json" \
'"role"[[:space:]]*:[[:space:]]*"platform-admin"'
require_pattern \
"overlay.css hides namespace picker" \
"$overlay_css" \
'toolbar-namespace-picker'
require_pattern \
"overlay branding title present in presets" \
"$presets_json" \
'Sign in with KeyCape'
step "Hidden-field selectors still present in overlay.js"
require_pattern \
"overlay.js hides namespace input" \
"$overlay_js" \
'#namespace|input\[name="namespace"\]'
require_pattern \
"overlay.js hides role input" \
"$overlay_js" \
'#role|input\[name="role"\]'
require_pattern \
"overlay.js hides mount path input" \
"$overlay_js" \
'#custom-path|input\[name="custom-path"\]'
if [ "$CHECK_DRIFT" = "1" ]; then
step "Upstream UI drift check"
version_file="$OVERLAY_DIR/VERSION"
if [ ! -f "$version_file" ]; then
err "missing overlay VERSION file: $version_file"
exit 1
fi
version="$(tr -d '[:space:]' < "$version_file")"
manifest="$OVERLAY_DIR/patches/$version/manifest.sha256"
if [ ! -f "$manifest" ]; then
err "missing fingerprint manifest: $manifest"
exit 1
fi
vault_asset="$(grep -Eo '/ui/assets/vault-[a-f0-9]+\.js' <<<"$index_html" | head -1 || true)"
if [ -z "$vault_asset" ]; then
err "could not locate vault.js asset path in index.html"
exit 1
fi
live_vault_hash="$(curl -fsS "$BASE_URL$vault_asset" | sha256sum | awk '{print $1}')"
expected_vault_hash="$(awk '!/^#/ && /ui\/assets\/vault-/ {print $1; exit}' "$manifest")"
expected_vault_path="$(awk '!/^#/ && /ui\/assets\/vault-/ {print $2; exit}' "$manifest")"
if [ -n "$expected_vault_hash" ] && [ "$live_vault_hash" != "$expected_vault_hash" ]; then
err "vault bundle hash drift for ${vault_asset:-unknown}: expected $expected_vault_hash got $live_vault_hash"
exit 1
fi
ok "vault bundle hash matches patches/$version/manifest.sha256 (${expected_vault_path:-$vault_asset})"
fi
printf '\nOpenBao login overlay verification passed for %s\n' "$BASE_URL"