#!/bin/sh set -e # OpenBao Auto-Init Script # Auto-initializes, unseals, and configures OpenBao on first run # Idempotent - safe to run multiple times INIT_DIR="/openbao/init" UNSEAL_KEY_FILE="${INIT_DIR}/unseal-key" ROOT_TOKEN_FILE="${INIT_DIR}/root-token" APPROLE_CREDS_FILE="${INIT_DIR}/approle-credentials" VAULT_ADDR="http://openbao:8200" export VAULT_ADDR # Ensure init directory exists mkdir -p "${INIT_DIR}" echo "=== OpenBao Auto-Init Script ===" echo "Vault Address: ${VAULT_ADDR}" # Wait for OpenBao to be ready echo "Waiting for OpenBao API to be available..." MAX_RETRIES=30 RETRY_COUNT=0 while ! wget -q -O- "${VAULT_ADDR}/v1/sys/init" >/dev/null 2>&1; do RETRY_COUNT=$((RETRY_COUNT + 1)) if [ ${RETRY_COUNT} -ge ${MAX_RETRIES} ]; then echo "ERROR: OpenBao API not available after ${MAX_RETRIES} attempts" exit 1 fi echo "Waiting for OpenBao... (${RETRY_COUNT}/${MAX_RETRIES})" sleep 2 done echo "OpenBao API is available" # Check initialization status INIT_STATUS=$(wget -qO- "${VAULT_ADDR}/v1/sys/init" 2>/dev/null || echo '{"initialized":false}') IS_INITIALIZED=$(echo "${INIT_STATUS}" | grep -o '"initialized":[^,}]*' | cut -d':' -f2) if [ "${IS_INITIALIZED}" = "true" ]; then echo "OpenBao is already initialized" # Check if sealed SEAL_STATUS=$(wget -qO- "${VAULT_ADDR}/v1/sys/seal-status" 2>/dev/null) IS_SEALED=$(echo "${SEAL_STATUS}" | grep -o '"sealed":[^,}]*' | cut -d':' -f2) if [ "${IS_SEALED}" = "true" ]; then echo "OpenBao is sealed - unsealing..." if [ ! -f "${UNSEAL_KEY_FILE}" ]; then echo "ERROR: Unseal key not found at ${UNSEAL_KEY_FILE}" exit 1 fi UNSEAL_KEY=$(cat "${UNSEAL_KEY_FILE}") # Unseal with retry logic MAX_UNSEAL_RETRIES=3 UNSEAL_RETRY=0 UNSEAL_SUCCESS=false while [ ${UNSEAL_RETRY} -lt ${MAX_UNSEAL_RETRIES} ]; do UNSEAL_RESPONSE=$(wget -qO- --header="Content-Type: application/json" --post-data="{\"key\":\"${UNSEAL_KEY}\"}" "${VAULT_ADDR}/v1/sys/unseal" 2>&1) # Verify unseal was successful by checking sealed status sleep 1 VERIFY_STATUS=$(wget -qO- "${VAULT_ADDR}/v1/sys/seal-status" 2>/dev/null || echo '{"sealed":true}') VERIFY_SEALED=$(echo "${VERIFY_STATUS}" | grep -o '"sealed":[^,}]*' | cut -d':' -f2) if [ "${VERIFY_SEALED}" = "false" ]; then UNSEAL_SUCCESS=true echo "OpenBao unsealed successfully" break fi UNSEAL_RETRY=$((UNSEAL_RETRY + 1)) echo "Unseal attempt ${UNSEAL_RETRY} failed, retrying..." sleep 2 done if [ "${UNSEAL_SUCCESS}" = "false" ]; then echo "ERROR: Failed to unseal OpenBao after ${MAX_UNSEAL_RETRIES} attempts" exit 1 fi else echo "OpenBao is already unsealed" fi # Verify Transit engine and AppRole are configured if [ -f "${ROOT_TOKEN_FILE}" ]; then export VAULT_TOKEN=$(cat "${ROOT_TOKEN_FILE}") # Check Transit engine if ! bao secrets list | grep -q "transit/"; then echo "Transit engine not found - configuring..." bao secrets enable transit echo "Transit secrets engine enabled" else echo "Transit secrets engine already enabled" fi # Check AppRole if ! bao auth list | grep -q "approle/"; then echo "AppRole not found - configuring..." bao auth enable approle echo "AppRole auth method enabled" else echo "AppRole auth method already enabled" fi fi echo "Initialization check complete - OpenBao is ready" exit 0 fi echo "OpenBao is not initialized - initializing with 1-of-1 key shares..." # Initialize with 1 key share, threshold 1 (turnkey mode) INIT_OUTPUT=$(bao operator init -key-shares=1 -key-threshold=1 -format=json) # Extract unseal key and root token from JSON output # First collapse multi-line JSON to single line, then parse INIT_JSON=$(echo "${INIT_OUTPUT}" | tr -d '\n' | tr -d ' ') UNSEAL_KEY=$(echo "${INIT_JSON}" | grep -o '"unseal_keys_b64":\["[^"]*"' | cut -d'"' -f4) ROOT_TOKEN=$(echo "${INIT_JSON}" | grep -o '"root_token":"[^"]*"' | cut -d'"' -f4) # Save to files echo "${UNSEAL_KEY}" > "${UNSEAL_KEY_FILE}" echo "${ROOT_TOKEN}" > "${ROOT_TOKEN_FILE}" chmod 600 "${UNSEAL_KEY_FILE}" "${ROOT_TOKEN_FILE}" echo "Initialization complete" echo "Unseal key saved to ${UNSEAL_KEY_FILE}" echo "Root token saved to ${ROOT_TOKEN_FILE}" # Unseal with retry logic echo "Unsealing OpenBao..." MAX_UNSEAL_RETRIES=3 UNSEAL_RETRY=0 UNSEAL_SUCCESS=false while [ ${UNSEAL_RETRY} -lt ${MAX_UNSEAL_RETRIES} ]; do UNSEAL_RESPONSE=$(wget -qO- --header="Content-Type: application/json" --post-data="{\"key\":\"${UNSEAL_KEY}\"}" "${VAULT_ADDR}/v1/sys/unseal" 2>&1) # Verify unseal was successful by checking sealed status sleep 1 VERIFY_STATUS=$(wget -qO- "${VAULT_ADDR}/v1/sys/seal-status" 2>/dev/null || echo '{"sealed":true}') VERIFY_SEALED=$(echo "${VERIFY_STATUS}" | grep -o '"sealed":[^,}]*' | cut -d':' -f2) if [ "${VERIFY_SEALED}" = "false" ]; then UNSEAL_SUCCESS=true echo "OpenBao unsealed successfully" break fi UNSEAL_RETRY=$((UNSEAL_RETRY + 1)) echo "Unseal attempt ${UNSEAL_RETRY} failed, retrying..." sleep 2 done if [ "${UNSEAL_SUCCESS}" = "false" ]; then echo "ERROR: Failed to unseal OpenBao after ${MAX_UNSEAL_RETRIES} attempts" exit 1 fi # Configure with root token export VAULT_TOKEN="${ROOT_TOKEN}" # Enable Transit secrets engine echo "Enabling Transit secrets engine..." bao secrets enable transit echo "Transit secrets engine enabled" # Create Transit encryption keys echo "Creating Transit encryption keys..." bao write -f transit/keys/mosaic-credentials type=aes256-gcm96 echo "Created key: mosaic-credentials" bao write -f transit/keys/mosaic-account-tokens type=aes256-gcm96 echo "Created key: mosaic-account-tokens" bao write -f transit/keys/mosaic-federation type=aes256-gcm96 echo "Created key: mosaic-federation" bao write -f transit/keys/mosaic-llm-config type=aes256-gcm96 echo "Created key: mosaic-llm-config" echo "All Transit keys created" # Enable AppRole auth method echo "Enabling AppRole auth method..." bao auth enable approle echo "AppRole auth method enabled" # Create Transit-only policy echo "Creating Transit-only policy..." cat > /tmp/transit-policy.hcl < "${APPROLE_CREDS_FILE}" </dev/null || echo '{"sealed":false}') IS_SEALED=$(echo "${SEAL_STATUS}" | grep -o '"sealed":[^,}]*' | cut -d':' -f2) if [ "${IS_SEALED}" = "true" ]; then echo "OpenBao is sealed - unsealing..." if [ -f "${UNSEAL_KEY_FILE}" ]; then UNSEAL_KEY=$(cat "${UNSEAL_KEY_FILE}") # Try to unseal with verification UNSEAL_RESPONSE=$(wget -qO- --header="Content-Type: application/json" --post-data="{\"key\":\"${UNSEAL_KEY}\"}" "${VAULT_ADDR}/v1/sys/unseal" 2>&1) # Verify unseal was successful sleep 1 VERIFY_STATUS=$(wget -qO- "${VAULT_ADDR}/v1/sys/seal-status" 2>/dev/null || echo '{"sealed":true}') VERIFY_SEALED=$(echo "${VERIFY_STATUS}" | grep -o '"sealed":[^,}]*' | cut -d':' -f2) if [ "${VERIFY_SEALED}" = "false" ]; then echo "OpenBao unsealed successfully" else echo "WARNING: Unseal operation completed but OpenBao is still sealed" fi else echo "WARNING: Unseal key not found, cannot auto-unseal" fi fi done