#!/usr/bin/env bash set -euo pipefail # init_primary_domain.sh # Purpose: # - Deploy OpenBao to Kubernetes (dev mode) and store admin ed25519 key pair # Generate and apply a Kerberos krb5.conf ConfigMap for an external realm # - Local Docker helpers for OpenBao (optional) # Initialize SCRIPT_DIR SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) # Preserve positional args while sourcing env __PROLE_SAVED_ARGS=("$@") if [[ -n "${PROLE_HOME:-}" && -f "$PROLE_HOME/env.sh" ]]; then set -- # shellcheck disable=SC1090 source "$PROLE_HOME/env.sh" elif [[ -f "$HOME/.prole/env.sh" ]]; then set -- # shellcheck disable=SC1090 source "$HOME/.prole/env.sh" fi set -- "${__PROLE_SAVED_ARGS[@]}" unset __PROLE_SAVED_ARGS if [[ -z "${PROLE_SERVICE:-}" ]]; then echo "ERROR: PROLE_SERVICE is not defined in env. Provide PROLE_HOME/env.sh or ~/.prole/env.sh" >&2 exit 1 fi ACTION=${1:-} # Defaults NAMESPACE=${NAMESPACE:-default} OPENBAO_NAME=${OPENBAO_NAME:-openbao} OPENBAO_IMAGE=${OPENBAO_IMAGE:-ghcr.io/openbao/openbao:latest} OPENBAO_MANIFEST_DIR="$SCRIPT_DIR/../k8s/openbao" # Kerberos realm defaults KRB5_REALM=${KRB5_REALM:-PROLE.ORG} DOMAIN=${DOMAIN:-$(echo "$KRB5_REALM" | tr 'A-Z' 'a-z')} KRB5_KDC=${KRB5_KDC:-kdc.$DOMAIN} KRB5_ADMIN=${KRB5_ADMIN:-} # Secrets and token locations SECRETS_DIR="$PROLE_SERVICE/secrets" mkdir -p "$SECRETS_DIR" admin_key_priv="$SECRETS_DIR/admin_ed25519.key" admin_key_pub="$SECRETS_DIR/admin_ed25519.pub" root_token_file="$SECRETS_DIR/openbao-root-token" ensure_tools() { for t in kubectl curl openssl base64; do command -v "$t" >/dev/null || { echo "Missing required tool: $t" >&2; exit 1; } done } ensure_docker() { command -v docker >/dev/null || { echo "Missing required tool: docker" >&2; exit 1; } } ensure_admin_keypair() { # Ensure admin ed25519 keypair exists and a root token is available mkdir -p "$SECRETS_DIR" if [[ ! -f "$admin_key_priv" || ! -f "$admin_key_pub" ]]; then echo "Generating admin ed25519 keypair in $SECRETS_DIR ..." openssl genpkey -algorithm ED25519 -out "$admin_key_priv" openssl pkey -in "$admin_key_priv" -pubout -out "$admin_key_pub" chmod 0600 "$admin_key_priv" fi # Ensure a root token exists for OpenBao dev server interactions if [[ ! -f "$root_token_file" || ! -s "$root_token_file" ]]; then openssl rand -hex 24 >"$root_token_file" chmod 0600 "$root_token_file" fi } generate_openbao_manifests() { mkdir -p "$OPENBAO_MANIFEST_DIR" # Only create a simple deployment if none exists; otherwise respect current file local deploy="$OPENBAO_MANIFEST_DIR/deployment.yaml" if [[ ! -f "$deploy" ]]; then cat >"$deploy" <"$OPENBAO_MANIFEST_DIR/kerberos-configmap.yaml" </dev/null echo "Stored admin key pair in OpenBao kv/prole/admin." } # Removed: prompt_admin_password_and_apply_secret (no AD admin secret required) docker_start() { echo "Starting local Docker container for OpenBao ..." ensure_docker docker rm -f "$OPENBAO_NAME" >/dev/null 2>&1 || true # OpenBao dev local token token=$(cat "$root_token_file" 2>/dev/null || true) if [[ -z "$token" ]]; then token=$(openssl rand -hex 24) printf "%s" "$token" >"$root_token_file" chmod 0600 "$root_token_file" fi docker run -d --name "$OPENBAO_NAME" -p 18200:8200 \ "$OPENBAO_IMAGE" server -dev -dev-listen-address=0.0.0.0:8200 -dev-root-token-id="$token" echo "Docker container started: $OPENBAO_NAME" } docker_stop() { docker rm -f "$OPENBAO_NAME" >/dev/null 2>&1 || true echo "Stopped OpenBao container if it was running." } docker_restart() { docker_stop docker_start } # status command implementation wrapped in a function to avoid top-level 'local' cmd_status() { echo "--- init_primary_domain status ---" echo "Namespace: $NAMESPACE" echo "OpenBao name: $OPENBAO_NAME" echo "Manifest dir: $OPENBAO_MANIFEST_DIR" # Files/manifests present local ok=0 if [[ -f "$OPENBAO_MANIFEST_DIR/deployment.yaml" ]]; then echo "[OK] OpenBao deployment manifest exists" else echo "[MISSING] $OPENBAO_MANIFEST_DIR/deployment.yaml" ok=1 fi if [[ -f "$OPENBAO_MANIFEST_DIR/kerberos-configmap.yaml" ]]; then echo "[OK] Kerberos ConfigMap manifest exists" else echo "[MISSING] $OPENBAO_MANIFEST_DIR/kerberos-configmap.yaml" ok=1 fi # K8s resources if kubectl -n "$NAMESPACE" get deploy "$OPENBAO_NAME" >/dev/null 2>&1; then # Get readiness local ready desired ready=$(kubectl -n "$NAMESPACE" get deploy "$OPENBAO_NAME" -o jsonpath='{.status.readyReplicas}' 2>/dev/null || echo "0") desired=$(kubectl -n "$NAMESPACE" get deploy "$OPENBAO_NAME" -o jsonpath='{.status.replicas}' 2>/dev/null || echo "0") ready=${ready:-0} desired=${desired:-0} if [[ "$ready" == "$desired" && "$ready" != "0" ]]; then echo "[OK] OpenBao Deployment running ($ready/$desired ready)" else echo "[WARN] OpenBao Deployment not fully ready ($ready/$desired)" ok=1 fi else echo "[MISSING] OpenBao Deployment '$OPENBAO_NAME' in namespace '$NAMESPACE'" ok=1 fi if kubectl -n "$NAMESPACE" get configmap prole-krb5-conf >/dev/null 2>&1; then echo "[OK] Kerberos ConfigMap 'prole-krb5-conf' present" else echo "[MISSING] Kerberos ConfigMap 'prole-krb5-conf' in namespace '$NAMESPACE'" ok=1 fi # Docker (optional local mode) if command -v docker >/dev/null 2>&1; then if docker ps --format '{{.Names}}' | grep -Fxq "$OPENBAO_NAME"; then echo "[OK] Docker container '$OPENBAO_NAME' is running" else # Not necessarily an error; we primarily use k8s echo "[INFO] Docker container '$OPENBAO_NAME' not running (k8s mode may be in use)" fi fi # Secrets and tokens if [[ -f "$admin_key_priv" && -f "$admin_key_pub" ]]; then echo "[OK] Admin ed25519 keypair present in $SECRETS_DIR" else echo "[MISSING] Admin keypair files in $SECRETS_DIR" ok=1 fi if [[ -s "$root_token_file" ]]; then echo "[OK] OpenBao root token file present" else echo "[MISSING] OpenBao root token file ($root_token_file)" ok=1 fi # OpenBao reachability and token validity (best-effort) # Prefer explicit override, then localhost port-forward, then cluster DNS local svc_url if [[ -n "${PROLE_OPENBAO_URL:-}" ]]; then svc_url="$PROLE_OPENBAO_URL" elif curl -sS "http://127.0.0.1:18200/v1/sys/health" >/dev/null 2>&1; then svc_url="http://127.0.0.1:18200" else svc_url="http://$OPENBAO_NAME.$NAMESPACE.svc.cluster.local:8200" fi if curl -sS "$svc_url/v1/sys/health" >/dev/null 2>&1; then echo "[OK] OpenBao service reachable" if [[ -s "$root_token_file" ]]; then local code code=$(curl -s -o /dev/null -w "%{http_code}" -H "X-Vault-Token: $(cat "$root_token_file")" "$svc_url/v1/sys/mounts" || echo "000") if [[ "$code" == "200" ]]; then echo "[OK] OpenBao root token authenticates" else echo "[WARN] OpenBao root token did not authenticate (HTTP $code)" ok=1 fi fi else echo "[WARN] OpenBao service not reachable at $svc_url" ok=1 fi # Service certificate existence (CNPG TLS) local CNPG_CLUSTER_NAME CNPG_CLUSTER_NAME=${CNPG_CLUSTER_NAME:-prole-db} if kubectl -n "$NAMESPACE" get secret "${CNPG_CLUSTER_NAME}-tls" >/dev/null 2>&1; then echo "[OK] Service certificate secret '${CNPG_CLUSTER_NAME}-tls' exists" else echo "[INFO] Service certificate secret '${CNPG_CLUSTER_NAME}-tls' not found" fi echo "-------------------------------------" if [[ $ok -eq 0 ]]; then echo "Status: OK" return 0 else echo "Status: Issues detected" return 1 fi } case "$ACTION" in start) ensure_tools ensure_docker ensure_admin_keypair docker_start ;; status) ensure_tools cmd_status ;; stop) ensure_docker docker_stop ;; restart) ensure_tools ensure_docker ensure_admin_keypair docker_restart ;; initialize) ensure_tools # Read password from stdin if provided local db_pass="" if [[ ! -t 0 ]]; then read -r db_pass fi ensure_admin_keypair generate_openbao_manifests generate_kerberos_configmap apply_k8s if [[ -n "$db_pass" ]]; then echo "Creating database user secret 'prole-db-user' ..." kubectl create secret generic prole-db-user -n "$NAMESPACE" \ --from-literal=username=prole \ --from-literal=password="$db_pass" \ --dry-run=client -o yaml | kubectl apply -f - fi wait_for_openbao # Expect a persistent port-forward to be managed by etc/init_port_forwards.sh if ! curl -sS http://127.0.0.1:18200/v1/sys/health >/dev/null 2>&1; then echo "ERROR: OpenBao not reachable at http://127.0.0.1:18200." >&2 echo "Please start port-forwards: $PROLE_HOME/etc/init_port_forwards.sh start" >&2 exit 1 fi init_openbao_kv_and_store_admin_key echo "Initialization complete. Manifests in: $OPENBAO_MANIFEST_DIR" ;; update|reload) generate_openbao_manifests generate_kerberos_configmap kubectl apply -f "$OPENBAO_MANIFEST_DIR/deployment.yaml" kubectl apply -f "$OPENBAO_MANIFEST_DIR/kerberos-configmap.yaml" echo "Re-applied manifests." ;; *) echo "Usage: $0 {start|stop|status|restart|initialize|update|reload}" >&2 exit 2 ;; esac