Add KeyCape login overlay gateway for OpenBao browser UI

Streamline bao.coulomb.social login as "Sign in with KeyCape" via a versioned
nginx gateway that injects overlay assets and proxies to OpenBao. Disable chart
ingress in favor of the overlay ingress, wire make openbao-deploy, and add
openbao-verify-login-overlay with upstream drift detection.
This commit is contained in:
2026-06-19 20:28:16 +02:00
parent 665d43386f
commit 6ddf4e56b4
14 changed files with 728 additions and 22 deletions

View File

@@ -0,0 +1,69 @@
#!/usr/bin/env bash
set -euo pipefail
OPENBAO_NAMESPACE="${OPENBAO_NAMESPACE:-openbao}"
KUBECTL="${KUBECTL:-kubectl}"
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
OVERLAY_DIR="${OPENBAO_UI_OVERLAY_DIR:-$ROOT_DIR/helm/openbao-ui-overlay}"
K8S_MANIFEST="${OPENBAO_UI_OVERLAY_K8S:-$ROOT_DIR/helm/openbao-ui-overlay-k8s.yaml}"
usage() {
cat <<'USAGE'
Usage: scripts/openbao-ui-overlay-apply.sh
Builds and applies the OpenBao KeyCape login overlay ConfigMaps and gateway
Deployment/Service/Ingress. Idempotent — safe to run on every openbao-deploy.
Environment:
OPENBAO_NAMESPACE Kubernetes namespace. Default: openbao
KUBECTL kubectl command, including --kubeconfig if needed
OPENBAO_UI_OVERLAY_DIR Overlay asset directory
OPENBAO_UI_OVERLAY_K8S Gateway manifest path
USAGE
}
if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
usage
exit 0
fi
for required in overlay.css overlay.js presets.json nginx.conf VERSION; do
if [ ! -f "$OVERLAY_DIR/$required" ]; then
echo "missing overlay asset: $OVERLAY_DIR/$required" >&2
exit 1
fi
done
if [ ! -f "$K8S_MANIFEST" ]; then
echo "missing gateway manifest: $K8S_MANIFEST" >&2
exit 1
fi
# shellcheck disable=SC2086
$KUBECTL create namespace "$OPENBAO_NAMESPACE" --dry-run=client -o yaml | $KUBECTL apply -f -
# shellcheck disable=SC2086
$KUBECTL create configmap openbao-ui-overlay \
--namespace "$OPENBAO_NAMESPACE" \
--from-file="$OVERLAY_DIR/overlay.css" \
--from-file="$OVERLAY_DIR/overlay.js" \
--from-file="$OVERLAY_DIR/presets.json" \
--from-file="$OVERLAY_DIR/VERSION" \
--dry-run=client -o yaml | $KUBECTL apply -f -
# shellcheck disable=SC2086
$KUBECTL create configmap openbao-ui-gateway-nginx \
--namespace "$OPENBAO_NAMESPACE" \
--from-file=nginx.conf="$OVERLAY_DIR/nginx.conf" \
--dry-run=client -o yaml | $KUBECTL apply -f -
# shellcheck disable=SC2086
$KUBECTL apply -f "$K8S_MANIFEST"
# shellcheck disable=SC2086
$KUBECTL rollout restart deployment/openbao-ui-gateway -n "$OPENBAO_NAMESPACE"
# shellcheck disable=SC2086
$KUBECTL rollout status deployment/openbao-ui-gateway -n "$OPENBAO_NAMESPACE" --timeout=120s
printf '[OK] OpenBao UI overlay applied from %s\n' "$OVERLAY_DIR"

View File

@@ -0,0 +1,143 @@
#!/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 "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 \
"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"