#!/bin/bash
# Read-only diagnostic for "kerberos_ticket_renew renews/prompts too
# often" on the gac-bernina account. Checks the things that would make
# `kinit -R` fail more than it should (forcing the interactive password
# fallback instead of silent renewal), and looks for anything else that
# might already be renewing/touching this account's ticket independently.
# Makes no changes -- run it, read the output, nothing to clean up after.
#
# Usage: check_kerberos_renewal [principal]   (default: gac-bernina)

set -uo pipefail

PRINCIPAL="${1:-gac-bernina}"

section() { echo; echo "=== $* ==="; }

section "Current ticket(s) + renewable flag (this krb5 build only supports klist -f, not -v)"
klist -f 2>&1
echo
echo "Looking for an 'R' (renewable) flag on the krbtgt ticket in the output above"
echo "(e.g. 'Flags: FRIA' -- R present). If it's missing, kinit -R can NEVER"
echo "succeed for this ticket no matter how recently it was issued -- every"
echo "renewal attempt would fall straight through to the interactive password"
echo "prompt, which is exactly what over-frequent PROMPTING would look like."
echo
echo "Also compare 'Valid starting' -> 'Expires' (actual ticket lifetime) against"
echo "kerberos_ticket_renew's RENEW_THRESHOLD (default 86400s = 24h): if the"
echo "real lifetime is shorter than the threshold -- e.g. PSI issuing ~10h"
echo "tickets renewable for 7 days is normal here -- every single hourly check"
echo "will always conclude renewal is needed and fire kinit -R, succeeding"
echo "silently but notifying every time. That's over-frequent NOTIFYING (not"
echo "prompting), and doesn't need anything external renewing to explain it."

section "Any process already touching Kerberos for this account"
ps -eo pid,ppid,user,lstart,cmd 2>/dev/null | grep -iE "kinit|krb5|kerberos.?ticket.?renew|k5start|krenew" | grep -v grep

section "Our own renewer: how many instances, and is the singleton lock actually working"
echo "-- process(es):"
pgrep -fa kerberos_ticket_renew || echo "(none running right now)"
echo
echo "-- lock file (should be exactly one holder; if XDG_RUNTIME_DIR is unset or"
echo "   inconsistent between invocations -- seen elsewhere this session -- the"
echo "   lock could silently end up in different places, defeating the"
echo "   single-instance guard and letting multiple copies run concurrently):"
echo "XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-<unset>}"
for f in "${XDG_RUNTIME_DIR:-}/kerberos_ticket_renew.lock" "/tmp/kerberos_ticket_renew.lock"; do
    [ -n "$f" ] && [ -e "$f" ] && echo "found: $f" && lsof "$f" 2>/dev/null
done

section "Cron / systemd --user timers or services that might also renew this ticket"
echo "-- crontab:"
crontab -l 2>&1
echo
echo "-- systemd --user timers:"
systemctl --user list-timers --all 2>&1
echo
echo "-- systemd --user services with kerberos/krb in the name:"
systemctl --user list-units --type=service --all 2>&1 | grep -iE "krb|kerberos"

section "KDC-side policy for this principal, if we're allowed to see it"
echo "(requires admin rights on the realm -- expected to fail for a normal"
echo " principal querying itself; worth trying anyway, costs nothing)"
kadmin -q "getprinc ${PRINCIPAL}" 2>&1 | grep -iE "maximum ticket life|maximum renewable life|attributes" || \
    echo "(no admin rights to query this, or kadmin unavailable -- expected)"

section "Done"
echo "Send back everything above. The 'Renewable flag check' and 'lifetime vs"
echo "renewable window' sections are the most likely to show the actual cause;"
echo "the process/cron/timer sections rule in or out something else already"
echo "renewing independently, per your suspicion."
