Skip to content

Usage

What the wrappers do

/usr/sbin/connection handles local login and sshd sessions. /usr/sbin/escalation handles su and sudo. Both source /usr/lib/user-notifier/pam-common.sh, classify the PAM environment, and call user-notify with four arguments: type, hostname, details, and state (open or close).

Same-user sudo to root is skipped (no notify). An empty PAM_RUSER is treated as actor unknown.

What user-notify does

user-notify reads /etc/user-notifier/notifier.conf (or USER_NOTIFIER_CONFIG), exports the hook contract, and runs every executable in hooks_dir in name order. It continues after a hook fails. Classified events always exit 0 so PAM is not failed by a config or hook error.

Do not write to the login TTY from a hook. Use logger -t user-notifier if you need logs.

Dry-run without PAM

Point the wrappers at the tree in this repo and a fake notifier:

export USER_NOTIFIER_LIB="$PWD/src/pam-common.sh"
export USER_NOTIFY="$PWD/src/user-notify"
export USER_NOTIFIER_CONFIG="$PWD/config/notifier.conf.example"
export NOTIFY_TEST_HOSTNAME=testhost

PAM_TYPE=open_session PAM_SERVICE=sshd PAM_USER=user1 PAM_RHOST=10.0.0.8 \
  bash src/connection

NOTIFY_TEST_HOSTNAME overrides the live hostname so tests and dry-runs stay deterministic.

To exercise only the dispatcher:

USER_NOTIFIER_CONFIG="$PWD/config/notifier.conf.example" \
  python3 src/user-notify ssh testhost "user1 has logged on from 10.0.0.8" open

With an empty webhook URL, 50-slack is a no-op.

Environment overrides

Variable Role
USER_NOTIFY Path to user-notify (wrappers look here first)
USER_NOTIFIER_LIB Path to pam-common.sh
USER_NOTIFIER_CONFIG Path to notifier.conf
NOTIFY_TEST_HOSTNAME Hostname used in the classified message

On a live install, leave these unset so /usr/sbin and /etc/user-notifier win.