prole/etc/init_authority.sh
chrisfu da2f6600ba feat: infrastructure and installer updates for k3s, OpenTofu, and prole-db
- Add k3s start/stop Ansible playbooks and roles.

- Implement OpenTofu initialization scripts and k8s manifests.

- Update ncurses installer with OpenTofu support and improved k3s integration.

- Add mode support (--mode) to etc/ initialization scripts.

- Update prole-db with recovery, barman objectstore, and SSH OpenBao support.

- Refine k8s manifests for OpenBao and prole-db.
2026-02-05 21:27:18 -08:00

245 lines
7.4 KiB
Bash
Executable File

#!/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 <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: $KDC_NAME
labels:
app: $KDC_NAME
spec:
replicas: 1
selector:
matchLabels:
app: $KDC_NAME
template:
metadata:
labels:
app: $KDC_NAME
spec:
containers:
- name: dog
image: $KDC_IMAGE
command: ["/bin/bash", "-c"]
args:
- |
apt-get update && apt-get install -y openssh-server krb5-kdc krb5-admin-server samba winbind libpam-winbind libnss-winbind sudo
mkdir -p /run/sshd
echo "root:\$root_pass" | chpasswd
# Setup root SSH
mkdir -p /root/.ssh
printf '%s' "$ssh_pub_b64" | base64 -d > /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