#!/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"