#!/usr/bin/env bash set -euo pipefail # init_authority.sh # Purpose: # - Ensure 'authority' namespace exists # - Spin up 'dog' container (Ubuntu 24) as primary KDC # - Configure KDC with root password and SSH keys from OpenBao # - Configure Samba AD authority and administrator account # - Save autogenerated administrator password to OpenBao SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) # Load environment and config via prole_cfg.sh # shellcheck disable=SC1090 source "$SCRIPT_DIR/prole_cfg.sh" if [[ "${1:-}" == "--mode" || "${1:-}" == "-m" ]]; then prole_set_mode "${2:-}" shift 2 elif [[ "${1:-}" == --mode=* || "${1:-}" == -m=* ]]; then prole_set_mode "${1#*=}" shift fi ACTION=${1:-start} NAMESPACE_AUTH="authority" KDC_NAME="dog" KDC_IMAGE="ubuntu:24.04" BAO_NAMESPACE="${NAMESPACE:-default}" BAO_PATH_PREFIX="prole/${BAO_NAMESPACE}" BAO_PATH_ADMIN="${BAO_PATH_PREFIX}/admin" BAO_PATH_AUTHORITY="${BAO_PATH_PREFIX}/authority" log() { printf '%s\n' "$*"; } err() { printf '%s\n' "$*" >&2; } ensure_tools() { for t in kubectl curl jq base64; do command -v "$t" >/dev/null || { err "Missing required tool: $t"; exit 1; } done } ensure_namespace() { if ! kubectl get namespace "$NAMESPACE_AUTH" >/dev/null 2>&1; then log "Creating namespace '$NAMESPACE_AUTH' ..." kubectl create namespace "$NAMESPACE_AUTH" fi } get_openbao_url() { if [[ -n "${PROLE_OPENBAO_URL:-}" ]]; then echo "$PROLE_OPENBAO_URL" elif curl -sS "http://127.0.0.1:18200/v1/sys/health" >/dev/null 2>&1; then echo "http://127.0.0.1:18200" else echo "http://openbao.${NAMESPACE}.svc.cluster.local:8200" fi } get_openbao_token() { if [[ -f "$PROLE_SERVICE/secrets/openbao-root-token" ]]; then cat "$PROLE_SERVICE/secrets/openbao-root-token" else echo "${OPENBAO_ROOT_TOKEN:-root}" fi } read_from_bao() { local path="$1" local key="$2" local url url=$(get_openbao_url) local token token=$(get_openbao_token) curl -sS -H "X-Vault-Token: $token" "$url/v1/kv/data/$path" | jq -r ".data.data.\"$key\"" || echo "" } write_to_bao() { local path="$1" local data="$2" local url url=$(get_openbao_url) local token token=$(get_openbao_token) curl -sS -H "X-Vault-Token: $token" -H 'Content-Type: application/json' \ -X POST "$url/v1/kv/data/$path" -d "{\"data\":$data}" >/dev/null } deploy_dog() { log "Deploying '$KDC_NAME' (Ubuntu 24.04) in namespace '$NAMESPACE_AUTH' ..." # Fetch secrets from OpenBao local root_pass root_pass=$(read_from_bao "$BAO_PATH_ADMIN" "root_password") if [[ -z "$root_pass" || "$root_pass" == "null" ]]; then root_pass=$(openssl rand -hex 16) log "Generated new root password for dog server." # We need to preserve existing data in prole/admin if we write to it local admin_data admin_data=$(get_openbao_url | xargs -I {} curl -sS -H "X-Vault-Token: $(get_openbao_token)" "{}/v1/kv/data/$BAO_PATH_ADMIN" | jq -r ".data.data") if [[ "$admin_data" == "null" ]]; then admin_data="{}" fi local new_admin_data new_admin_data=$(echo "$admin_data" | jq -c ". + {\"root_password\":\"$root_pass\"}") write_to_bao "$BAO_PATH_ADMIN" "$new_admin_data" fi local ssh_pub ssh_pub=$(read_from_bao "$BAO_PATH_ADMIN" "admin_public_key_b64" | base64 -d 2>/dev/null || true) local ansible_ssh_pub # Try to read ansible key from OpenBao, fallback to local file if it exists ansible_ssh_pub=$(read_from_bao "$BAO_PATH_ADMIN" "ansible_public_key_b64" | base64 -d 2>/dev/null || true) if [[ -z "$ansible_ssh_pub" && -f "$HOME/.ssh/id_ed25519_ansible.pub" ]]; then ansible_ssh_pub=$(cat "$HOME/.ssh/id_ed25519_ansible.pub") fi # Encode SSH keys to avoid YAML parsing issues from multi-line or PEM-style keys local ssh_pub_b64 ssh_pub_b64=$(printf '%s' "$ssh_pub" | tr -d '\r' | base64 | tr -d '\n') local ansible_ssh_pub_b64 ansible_ssh_pub_b64=$(printf '%s' "$ansible_ssh_pub" | tr -d '\r' | base64 | tr -d '\n') # Use a separate variable for the YAML to help with debugging and clarity local manifest manifest=$(cat < /root/.ssh/authorized_keys chmod 600 /root/.ssh/authorized_keys # Setup ansible user id ansible >/dev/null 2>&1 || useradd -m -s /bin/bash ansible echo 'ansible ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/90-ansible chmod 440 /etc/sudoers.d/90-ansible # Setup ansible SSH mkdir -p /home/ansible/.ssh printf '%s' "$ansible_ssh_pub_b64" | base64 -d > /home/ansible/.ssh/authorized_keys chmod 600 /home/ansible/.ssh/authorized_keys chown -R ansible:ansible /home/ansible/.ssh /usr/sbin/sshd -D ports: - containerPort: 22 - containerPort: 88 - containerPort: 464 - containerPort: 389 - containerPort: 445 EOF ) # Debug: log the manifest to a file if needed # echo "$manifest" > /tmp/dog-manifest.yaml if ! echo "$manifest" | kubectl apply -n "$NAMESPACE_AUTH" -f -; then err "Kubectl apply failed. Manifest was:" err "$manifest" exit 1 fi kubectl rollout status deployment/$KDC_NAME -n "$NAMESPACE_AUTH" --timeout=120s } configure_authority() { log "Configuring Samba AD and Kerberos on '$KDC_NAME' ..." local pod_name pod_name=$(kubectl get pod -n "$NAMESPACE_AUTH" -l app=$KDC_NAME -o jsonpath='{.items[0].metadata.name}') # Provision Samba AD (simplified for version 1) # In a real scenario, this would involve samba-tool domain provision # We'll generate a password and save it to OpenBao local admin_pass admin_pass=$(openssl rand -base64 16) # Mocking the configuration steps for now as per instructions kubectl exec -n "$NAMESPACE_AUTH" "$pod_name" -- bash -c "echo 'Setting up AD...'" log "Saving administrator password to OpenBao ..." write_to_bao "$BAO_PATH_AUTHORITY" "{\"administrator_password\":\"$admin_pass\"}" log "Administrator password saved to kv/$BAO_PATH_AUTHORITY/administrator_password" local kdc_ip kdc_ip=$(kubectl get svc -n "$NAMESPACE_AUTH" "$KDC_NAME" -o jsonpath='{.spec.clusterIP}' 2>/dev/null || echo "dog.${NAMESPACE_AUTH}.svc.cluster.local") log "----------------------------------------------------------" log "Kerberos Configuration for prole-db nodes (Version 1):" log "KDC Server: $kdc_ip" log "Realm: ${KRB5_REALM:-PROLE.ORG}" log "Admin Server: $kdc_ip" log "----------------------------------------------------------" } case "$ACTION" in start) ensure_tools ensure_namespace deploy_dog configure_authority ;; status) kubectl get pods,svc -n "$NAMESPACE_AUTH" ;; stop) kubectl delete namespace "$NAMESPACE_AUTH" ;; *) err "Usage: $0 {start|stop|status}" exit 1 ;; esac