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:
69
scripts/openbao-ui-overlay-apply.sh
Executable file
69
scripts/openbao-ui-overlay-apply.sh
Executable 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"
|
||||
143
scripts/openbao-verify-login-overlay.sh
Executable file
143
scripts/openbao-verify-login-overlay.sh
Executable 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"
|
||||
Reference in New Issue
Block a user