Files
2026-04-22 21:53:08 +12:00

97 lines
3.5 KiB
Bash

#!/usr/bin/env bash
# =============================================================================
# 05a-kerberos.sh — Install Kerberos client, stage keytab, and install a
# systemd timer that renews the TGT on a schedule.
#
# The app service reads KRB5CCNAME from its .env file and uses the shared
# ticket cache when opening SQL Server connections via pyodbc/SQLAlchemy.
# =============================================================================
require_vars APP_USER APP_GROUP \
KRB_PRINCIPAL KRB_KEYTAB_SRC KRB_KEYTAB_PATH KRB_CCACHE_PATH \
|| return 1
KRB_RENEW_INTERVAL="${KRB_RENEW_INTERVAL:-30min}"
KRB_RENEWAL_SERVICE="${APP_SERVICE_NAME:-recon-ranger}-kerberos-renewal"
# ---- Install the Kerberos client ------------------------------------------
if ! command -v kinit &>/dev/null; then
log_info "Installing krb5-workstation"
dnf install -y krb5-workstation \
|| { log_error "Failed to install krb5-workstation"; return 1; }
else
log_info "krb5-workstation already installed"
fi
# ---- Sanity check /etc/krb5.conf ------------------------------------------
if [[ ! -s /etc/krb5.conf ]] || ! grep -q "default_realm" /etc/krb5.conf; then
log_error "/etc/krb5.conf missing or has no default_realm — configure the realm first"
return 1
fi
# ---- Stage the keytab at the target path ----------------------------------
if [[ ! -f "$KRB_KEYTAB_SRC" ]]; then
log_error "Keytab source not found: $KRB_KEYTAB_SRC"
return 1
fi
install -d -o "$APP_USER" -g "$APP_GROUP" -m 0750 "$(dirname "$KRB_KEYTAB_PATH")"
install -o "$APP_USER" -g "$APP_GROUP" -m 0600 "$KRB_KEYTAB_SRC" "$KRB_KEYTAB_PATH"
# Show what is inside the keytab so deploy logs record the principals/enctypes.
log_info "Keytab contents:"
klist -ekt "$KRB_KEYTAB_PATH" || log_warn "Could not list keytab contents"
# ---- Prepare the ticket cache directory -----------------------------------
install -d -o "$APP_USER" -g "$APP_GROUP" -m 0700 "$(dirname "$KRB_CCACHE_PATH")"
# ---- Prime the cache immediately ------------------------------------------
log_info "Running initial kinit as $APP_USER"
sudo -u "$APP_USER" \
kinit -k -t "$KRB_KEYTAB_PATH" -c "FILE:$KRB_CCACHE_PATH" "$KRB_PRINCIPAL" \
|| { log_error "Initial kinit failed for $KRB_PRINCIPAL"; return 1; }
sudo -u "$APP_USER" klist -c "FILE:$KRB_CCACHE_PATH" \
|| log_warn "klist failed after kinit"
# ---- Renewal service (oneshot, fires kinit) -------------------------------
RENEWAL_UNIT="/etc/systemd/system/${KRB_RENEWAL_SERVICE}.service"
RENEWAL_TIMER="/etc/systemd/system/${KRB_RENEWAL_SERVICE}.timer"
log_info "Writing $RENEWAL_UNIT"
cat > "$RENEWAL_UNIT" <<UNITEOF
[Unit]
Description=Kerberos TGT renewal for ${APP_SERVICE_NAME:-recon-ranger}
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
User=${APP_USER}
Group=${APP_GROUP}
ExecStart=/usr/bin/kinit -k -t ${KRB_KEYTAB_PATH} -c FILE:${KRB_CCACHE_PATH} ${KRB_PRINCIPAL}
UNITEOF
log_info "Writing $RENEWAL_TIMER"
cat > "$RENEWAL_TIMER" <<TIMEREOF
[Unit]
Description=Periodic Kerberos TGT renewal for ${APP_SERVICE_NAME:-recon-ranger}
[Timer]
OnBootSec=1min
OnUnitActiveSec=${KRB_RENEW_INTERVAL}
Unit=${KRB_RENEWAL_SERVICE}.service
Persistent=true
[Install]
WantedBy=timers.target
TIMEREOF
systemctl daemon-reload \
|| { log_error "systemctl daemon-reload failed"; return 1; }
systemctl enable --now "${KRB_RENEWAL_SERVICE}.timer" \
|| { log_error "Failed to enable ${KRB_RENEWAL_SERVICE}.timer"; return 1; }
systemctl --no-pager status "${KRB_RENEWAL_SERVICE}.timer" || true