mirror of
https://github.com/dredx/prole.git
synced 2026-09-27 17:04:30 +00:00
- Secret Management: Integrated AESGCM for temporary secret handling in install.py and enhanced OpenBao (Vault) support with namespace injection and additional secret paths (Grafana, Kerberos, TDE).
- Infrastructure & K8s:
- Added Barman Object Store backup configuration (S3) to prole-db.yaml.
- Updated Prometheus deployment with PVC and persistent configuration.
- Updated k3s cluster/registry creation scripts.
- Added etc/build-a-bao.sh for OpenBao setup.
- MSSQL Integration: Updated docker scripts and k8s deployments for Prole MSSQL database.
- Documentation: Added docs/PROLE-CFG-SECRETS.md explaining the new secret handling.
- General: Refined initialization scripts (init_authority.sh, init_openbao.sh, etc.) and updated the ncurses installer.
333 lines
9.8 KiB
Bash
Executable File
333 lines
9.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
# init_kerberos_test.sh
|
|
# Purpose:
|
|
# - Run Kerberos authentication checks inside a Kubernetes pod
|
|
# - Uses the prole-krb5-conf ConfigMap for krb5.conf
|
|
|
|
# Initialize SCRIPT_DIR
|
|
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
|
|
ACTION=${1:-test}
|
|
|
|
# Load env
|
|
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
|
|
|
|
# Load config values from prole.cfg before applying defaults/CLI overrides.
|
|
# shellcheck disable=SC1090
|
|
source "$SCRIPT_DIR/prole_cfg.sh"
|
|
|
|
NAMESPACE=${NAMESPACE:-default}
|
|
KRB5_REALM=${KRB5_REALM:-${REALM:-}}
|
|
KRB5_KDC=${KRB5_KDC:-}
|
|
KRB5_USER=${KRB5_USER:-${KRB5_USERNAME:-}}
|
|
KRB5_PASSWORD=${KRB5_PASSWORD:-}
|
|
KRB5_TEST_IMAGE=${KRB5_TEST_IMAGE:-${PROLE_KRB_TEST_IMAGE:-ubuntu:24.04}}
|
|
KRB5_TEST_PACKAGES=${KRB5_TEST_PACKAGES:-"krb5-user krb5-config libpam-krb5 libnss-krb5 adcli samba-common-bin dnsutils ca-certificates"}
|
|
REALM_JOIN=${REALM_JOIN:-1}
|
|
KEEP_POD=${KEEP_POD:-0}
|
|
KRB5_TEST_HOST_NETWORK=${KRB5_TEST_HOST_NETWORK:-0}
|
|
KRB5_TEST_DNS_POLICY=${KRB5_TEST_DNS_POLICY:-}
|
|
|
|
ensure_tools() {
|
|
for t in kubectl curl jq; do
|
|
command -v "$t" >/dev/null || { echo "Missing required tool: $t" >&2; exit 1; }
|
|
done
|
|
}
|
|
|
|
ensure_namespace() {
|
|
if ! kubectl get namespace "$NAMESPACE" >/dev/null 2>&1; then
|
|
echo "Creating namespace '$NAMESPACE' ..."
|
|
kubectl create namespace "$NAMESPACE" >/dev/null 2>&1 || true
|
|
fi
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
openbao_token() {
|
|
if [[ -f "$PROLE_SERVICE/secrets/openbao-root-token" ]]; then
|
|
cat "$PROLE_SERVICE/secrets/openbao-root-token"
|
|
else
|
|
echo "${OPENBAO_ROOT_TOKEN:-}"
|
|
fi
|
|
}
|
|
|
|
fetch_openbao_secret() {
|
|
local path="$1"
|
|
local key="$2"
|
|
local token url
|
|
token=$(openbao_token)
|
|
url=$(openbao_url)
|
|
if [[ -z "$token" ]]; then
|
|
echo ""
|
|
return 0
|
|
fi
|
|
curl -sS -H "X-Vault-Token: $token" "$url/v1/kv/data/$path" | jq -r ".data.data.\"$key\"" || echo ""
|
|
}
|
|
|
|
resolve_krb5_password() {
|
|
if [[ -z "${KRB5_PASSWORD}" || "${KRB5_PASSWORD}" == '${OPENBAO:'* || "${KRB5_PASSWORD}" == '${PROLE_SECRET:'* ]]; then
|
|
local path="prole/${NAMESPACE:-default}/kerberos"
|
|
local fetched
|
|
fetched=$(fetch_openbao_secret "$path" "password")
|
|
if [[ -n "$fetched" && "$fetched" != "null" ]]; then
|
|
KRB5_PASSWORD="$fetched"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
detect_image() {
|
|
if [[ -n "$KRB5_TEST_IMAGE" ]]; then
|
|
echo "$KRB5_TEST_IMAGE"
|
|
return
|
|
fi
|
|
echo "ubuntu:24.04"
|
|
}
|
|
|
|
ensure_configmap() {
|
|
if kubectl -n "$NAMESPACE" get configmap prole-krb5-conf >/dev/null 2>&1; then
|
|
return
|
|
fi
|
|
echo "ConfigMap prole-krb5-conf not found. Running init_kerberos.sh update..."
|
|
if [[ -x "$SCRIPT_DIR/init_kerberos.sh" ]]; then
|
|
KRB5_REALM="$KRB5_REALM" KRB5_KDC="$KRB5_KDC" "$SCRIPT_DIR/init_kerberos.sh" update || true
|
|
fi
|
|
}
|
|
|
|
create_test_pod() {
|
|
local pod_name="$1"
|
|
local image="$2"
|
|
local host_net_block=""
|
|
if [[ "$KRB5_TEST_HOST_NETWORK" == "1" ]]; then
|
|
local dns_policy
|
|
dns_policy=${KRB5_TEST_DNS_POLICY:-Default}
|
|
host_net_block=$' hostNetwork: true\n dnsPolicy: '"$dns_policy"$'\n'
|
|
fi
|
|
cat <<EOF | kubectl apply -f -
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: ${pod_name}
|
|
namespace: ${NAMESPACE}
|
|
labels:
|
|
app: prole-kerberos-test
|
|
spec:
|
|
${host_net_block} restartPolicy: Never
|
|
containers:
|
|
- name: kerberos-test
|
|
image: ${image}
|
|
command: ["sleep","3600"]
|
|
EOF
|
|
}
|
|
|
|
install_kerberos_packages() {
|
|
local pod_name="$1"
|
|
echo "Installing Kerberos client packages in pod..."
|
|
|
|
kubectl -n "$NAMESPACE" exec "$pod_name" -- env KRB5_TEST_PACKAGES="$KRB5_TEST_PACKAGES" sh -c '
|
|
set -e
|
|
if [ -f /etc/apt/sources.list.d/ubuntu.sources ]; then
|
|
if ! grep -q "universe" /etc/apt/sources.list.d/ubuntu.sources; then
|
|
awk "
|
|
/^Components:/ {
|
|
if (\$0 !~ /universe/) {
|
|
\$0 = \$0 \" universe\"
|
|
}
|
|
}
|
|
{ print }
|
|
" /etc/apt/sources.list.d/ubuntu.sources > /tmp/ubuntu.sources
|
|
mv /tmp/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources
|
|
fi
|
|
elif [ -f /etc/apt/sources.list ]; then
|
|
if ! grep -q "universe" /etc/apt/sources.list; then
|
|
sed -i "s/ main$/ main universe/; s/ main restricted$/ main restricted universe/; s/ main restricted multiverse$/ main restricted universe multiverse/" /etc/apt/sources.list
|
|
fi
|
|
fi
|
|
|
|
apt-get update
|
|
|
|
available=""
|
|
missing=""
|
|
for pkg in $KRB5_TEST_PACKAGES; do
|
|
if apt-cache show "$pkg" >/dev/null 2>&1; then
|
|
available="$available $pkg"
|
|
else
|
|
missing="$missing $pkg"
|
|
fi
|
|
done
|
|
|
|
if [ -n "$missing" ]; then
|
|
echo "WARN: skipping missing packages:$missing" >&2
|
|
fi
|
|
if [ -z "$available" ]; then
|
|
echo "ERROR: none of the requested packages are available." >&2
|
|
exit 1
|
|
fi
|
|
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $available
|
|
'
|
|
}
|
|
|
|
resolve_domain() {
|
|
local domain="${DOMAIN:-}"
|
|
if [[ -z "$domain" ]]; then
|
|
domain=$(printf '%s' "$KRB5_REALM" | tr '[:upper:]' '[:lower:]')
|
|
fi
|
|
printf '%s' "$domain"
|
|
}
|
|
|
|
resolve_host_fqdn() {
|
|
local domain="$1"
|
|
local host_name="${KRB5_TEST_HOSTNAME:-$2}"
|
|
if [[ "$host_name" == *.* ]]; then
|
|
printf '%s' "$host_name"
|
|
else
|
|
printf '%s.%s' "$host_name" "$domain"
|
|
fi
|
|
}
|
|
|
|
join_realm() {
|
|
local pod_name="$1"
|
|
local domain
|
|
domain=$(resolve_domain)
|
|
local kdc_host
|
|
kdc_host=$(printf '%s' "$KRB5_KDC" | awk -F',' '{print $1}' | xargs)
|
|
local host_fqdn
|
|
host_fqdn=$(resolve_host_fqdn "$domain" "$pod_name")
|
|
|
|
echo "Registering new Kerberos client as ${host_fqdn} in ${domain} ..."
|
|
|
|
if kubectl -n "$NAMESPACE" exec "$pod_name" -- sh -c 'command -v adcli >/dev/null 2>&1'; then
|
|
printf '%s\n' "$KRB5_PASSWORD" | kubectl -n "$NAMESPACE" exec -i "$pod_name" -- \
|
|
adcli join --domain="$domain" --domain-controller "$kdc_host" --login-user "$KRB5_USER" --stdin-password --host-fqdn "$host_fqdn" --show-details
|
|
return $?
|
|
fi
|
|
|
|
if kubectl -n "$NAMESPACE" exec "$pod_name" -- sh -c 'command -v realm >/dev/null 2>&1'; then
|
|
printf '%s\n' "$KRB5_PASSWORD" | kubectl -n "$NAMESPACE" exec -i "$pod_name" -- \
|
|
realm join --user "$KRB5_USER" "$domain"
|
|
return $?
|
|
fi
|
|
|
|
echo "ERROR: Neither adcli nor realm found in image; cannot register client." >&2
|
|
return 1
|
|
}
|
|
|
|
run_test() {
|
|
ensure_tools
|
|
ensure_namespace
|
|
resolve_krb5_password
|
|
|
|
# Support both names for the toggle from prole.cfg
|
|
local enabled="${KERBEROS_ENABLED:-${ENABLED:-false}}"
|
|
if [[ "$enabled" == "false" || "$enabled" == "0" || "$enabled" == "False" ]]; then
|
|
echo "Kerberos is disabled (KERBEROS_ENABLED=$enabled). Skipping test."
|
|
return 0
|
|
fi
|
|
|
|
if [[ -z "$KRB5_REALM" || -z "$KRB5_USER" || -z "$KRB5_PASSWORD" || -z "$KRB5_KDC" ]]; then
|
|
echo "ERROR: Missing Kerberos configuration. Ensure KRB5_REALM, KRB5_KDC, KRB5_USER, KRB5_PASSWORD are set." >&2
|
|
exit 1
|
|
fi
|
|
|
|
ensure_configmap
|
|
|
|
local image pod_name
|
|
image=$(detect_image)
|
|
pod_name="prole-krb-test-$(date +%s)"
|
|
|
|
echo "Creating Kerberos test pod '$pod_name' in namespace '$NAMESPACE' using image '$image'..."
|
|
create_test_pod "$pod_name" "$image"
|
|
|
|
echo "Waiting for pod to become ready..."
|
|
if ! kubectl -n "$NAMESPACE" wait --for=condition=Ready pod/"$pod_name" --timeout=90s; then
|
|
echo "Pod did not become ready. Describing pod:"
|
|
kubectl -n "$NAMESPACE" describe pod "$pod_name" || true
|
|
if [[ "$KEEP_POD" != "1" ]]; then
|
|
kubectl -n "$NAMESPACE" delete pod "$pod_name" --ignore-not-found
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
install_kerberos_packages "$pod_name"
|
|
|
|
echo "Updating /etc/krb5.conf in pod $pod_name from ConfigMap..."
|
|
local conf
|
|
conf=$(kubectl -n "$NAMESPACE" get configmap prole-krb5-conf -o jsonpath='{.data.krb5\.conf}' 2>/dev/null || true)
|
|
if [[ -n "$conf" ]]; then
|
|
printf '%s' "$conf" | kubectl -n "$NAMESPACE" exec -i "$pod_name" -- sh -c 'cat > /etc/krb5.conf'
|
|
else
|
|
echo "WARN: ConfigMap prole-krb5-conf not found; /etc/krb5.conf may be missing or default."
|
|
fi
|
|
|
|
echo "Checking for kinit in pod..."
|
|
if ! kubectl -n "$NAMESPACE" exec "$pod_name" -- sh -c 'command -v kinit >/dev/null 2>&1'; then
|
|
echo "ERROR: kinit not found after package install in test pod image '$image'." >&2
|
|
if [[ "$KEEP_POD" != "1" ]]; then
|
|
kubectl -n "$NAMESPACE" delete pod "$pod_name" --ignore-not-found
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
echo "Running kinit for ${KRB5_USER}@${KRB5_REALM} ..."
|
|
if ! printf '%s\n' "$KRB5_PASSWORD" | kubectl -n "$NAMESPACE" exec -i "$pod_name" -- kinit "${KRB5_USER}@${KRB5_REALM}"; then
|
|
echo "ERROR: kinit failed for ${KRB5_USER}@${KRB5_REALM}." >&2
|
|
if [[ "$KEEP_POD" != "1" ]]; then
|
|
kubectl -n "$NAMESPACE" delete pod "$pod_name" --ignore-not-found
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
echo "Kerberos ticket cache:"
|
|
kubectl -n "$NAMESPACE" exec "$pod_name" -- klist || true
|
|
|
|
if [[ "${REALM_JOIN:-0}" == "1" ]]; then
|
|
if ! join_realm "$pod_name"; then
|
|
echo "ERROR: realm join failed." >&2
|
|
if [[ "$KEEP_POD" != "1" ]]; then
|
|
kubectl -n "$NAMESPACE" delete pod "$pod_name" --ignore-not-found
|
|
fi
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [[ "$KEEP_POD" != "1" ]]; then
|
|
kubectl -n "$NAMESPACE" delete pod "$pod_name" --ignore-not-found
|
|
else
|
|
echo "KEEP_POD=1 set; leaving test pod running: $pod_name"
|
|
fi
|
|
}
|
|
|
|
case "$ACTION" in
|
|
test)
|
|
run_test
|
|
;;
|
|
cleanup)
|
|
ensure_tools
|
|
echo "Deleting kerberos test pods in namespace '$NAMESPACE'..."
|
|
kubectl -n "$NAMESPACE" delete pod -l app=prole-kerberos-test --ignore-not-found
|
|
;;
|
|
*)
|
|
echo "Usage: $0 {test|cleanup}" >&2
|
|
exit 2
|
|
;;
|
|
esac
|