Create ssh-login-alerting.md via n8n
This commit is contained in:
parent
ea5bc50260
commit
dda6eac571
153
Tech/Sessions/ssh-login-alerting.md
Normal file
153
Tech/Sessions/ssh-login-alerting.md
Normal file
@ -0,0 +1,153 @@
|
||||
---
|
||||
project: ssh-login-alerting
|
||||
type: session-notes
|
||||
status: active
|
||||
path: Tech/Sessions
|
||||
tags:
|
||||
- pbs
|
||||
- security
|
||||
- ssh
|
||||
- auditd
|
||||
- n8n
|
||||
- monitoring
|
||||
created: 2026-04-21
|
||||
updated: 2026-04-21
|
||||
---
|
||||
# SSH Login Alerting — Session Notes (April 21, 2026)
|
||||
|
||||
## What Got Done
|
||||
|
||||
- Installed Ansible on dev server (Ubuntu) via Ansible PPA
|
||||
- Ran Lovebug's `ssh_login_alert` Ansible role against staging — first run
|
||||
was clean, no errors
|
||||
- Confirmed auditd is running, audit rules are loaded, and the dispatcher
|
||||
plugin is wired to `ssh-login-alert.sh`
|
||||
- Confirmed the n8n webhook URL works (manual curl triggers successfully)
|
||||
- Confirmed `USER_LOGIN` events from sshd ARE being captured by auditd
|
||||
(`ausearch -m USER_LOGIN` returns them)
|
||||
- Identified and fixed the exe= quote escaping mismatch (changed from
|
||||
escaped `\"` to single-quoted literal match)
|
||||
- Confirmed the script receives events via stdin (debug logger proved it)
|
||||
|
||||
## Current Blocker
|
||||
|
||||
The script matches `USER_LOGIN` events but fails silently at username
|
||||
extraction. The root cause:
|
||||
|
||||
`USER_LOGIN` events do NOT contain an `acct=` field. They use a different
|
||||
format:
|
||||
|
||||
|
||||
type=USER_LOGIN msg=audit(...): pid=... uid=0 auid=1000 ses=387
|
||||
subj=unconfined msg='op=login id=1000 exe="/usr/sbin/sshd" hostname=X
|
||||
addr=X terminal=/dev/pts/0 res=success'UID="root" AUID="tj57testadmin"
|
||||
ID="tj57testadmin"
|
||||
|
||||
|
||||
Key differences from what the script expects:
|
||||
- Username is in `AUID="username"` (enriched suffix), not `acct="username"`
|
||||
- Also available as `ID="username"` in the enriched suffix
|
||||
- Numeric `auid=1000` is in the main body but needs `getent passwd` to
|
||||
resolve
|
||||
- `id=1000` inside the `msg='...'` block is also numeric
|
||||
|
||||
The script hits `[[ -n "$username" ]] || continue` with an empty username
|
||||
and silently skips the event.
|
||||
|
||||
An `AUID` regex fallback was added but still failed — needs further
|
||||
debugging.
|
||||
|
||||
## Next Steps — Debugging Checklist
|
||||
|
||||
- [ ] SSH into staging and capture raw event: `sudo ausearch -m USER_LOGIN
|
||||
--start recent --raw | tail -1`
|
||||
- [ ] Test regex patterns manually against the raw event line in bash to
|
||||
confirm which pattern actually matches
|
||||
- [ ] Key test patterns to try in bash:
|
||||
bash
|
||||
line=''
|
||||
# Test 1: AUID with quotes
|
||||
[[ "$line" =~ AUID=\"([^\"]+)\" ]] && echo "AUID match:
|
||||
${BASH_REMATCH[1]}" || echo "no AUID match"
|
||||
# Test 2: acct with quotes
|
||||
[[ "$line" =~ acct=\"([^\"]+)\" ]] && echo "acct match:
|
||||
${BASH_REMATCH[1]}" || echo "no acct match"
|
||||
# Test 3: ID with quotes
|
||||
[[ "$line" =~ ID=\"([^\"]+)\" ]] && echo "ID match: ${BASH_REMATCH[1]}"
|
||||
|| echo "no ID match"
|
||||
# Test 4: auid numeric then resolve
|
||||
[[ "$line" =~ auid=([0-9]+) ]] && echo "auid match: ${BASH_REMATCH[1]}"
|
||||
|| echo "no auid match"
|
||||
|
||||
- [ ] Once the working regex is identified, update the username extraction
|
||||
block in `/usr/local/bin/ssh-login-alert.sh`
|
||||
- [ ] Restart auditd: `sudo service auditd restart`
|
||||
- [ ] SSH in from another terminal and check: `sudo journalctl -t
|
||||
ssh-login-alert --since "1 minute ago" --no-pager -o cat`
|
||||
- [ ] Confirm Google Chat notification arrives
|
||||
- [ ] Once working on staging, backport the fix into the Ansible role
|
||||
template
|
||||
- [ ] Remove the old commented-out exe= line from the script
|
||||
|
||||
## Architecture Reminder
|
||||
|
||||
|
||||
SSH login → auditd captures USER_LOGIN event → audispd plugin pipes to
|
||||
ssh-login-alert.sh →
|
||||
script extracts fields + POSTs JSON to n8n webhook → n8n formats + sends to
|
||||
Google Chat
|
||||
|
||||
|
||||
## Useful Debug Commands
|
||||
|
||||
bash
|
||||
# Check auditd status
|
||||
sudo systemctl status auditd
|
||||
|
||||
# Check loaded audit rules
|
||||
sudo auditctl -l
|
||||
|
||||
# Search for SSH login events
|
||||
sudo ausearch -m USER_LOGIN --start recent
|
||||
|
||||
# Raw event format (what the script actually sees)
|
||||
sudo ausearch -m USER_LOGIN --start recent --raw | tail -1
|
||||
|
||||
# Tail audit log for live events
|
||||
sudo tail -f /var/log/audit/audit.log
|
||||
|
||||
# Check script logs
|
||||
sudo journalctl -t ssh-login-alert --since "5 minutes ago" --no-pager -o cat
|
||||
|
||||
# Restart auditd (picks up script changes)
|
||||
sudo service auditd restart
|
||||
|
||||
# Verify config file
|
||||
sudo cat /etc/pbs-alerts/config
|
||||
|
||||
|
||||
## Learnings
|
||||
|
||||
- `USER_LOGIN` is a PAM userspace event, not a syscall — audit rule `key=`
|
||||
tags don't apply to it
|
||||
- The exe= field in USER_LOGIN events uses literal double quotes, not
|
||||
escaped quotes — use single-quoted bash patterns for matching
|
||||
- auditd dispatcher plugins (`type = always`) receive ALL events —
|
||||
filtering must happen in the script
|
||||
- Debug logger lines spawning per-event can overwhelm auditd's plugin queue
|
||||
— use sparingly and remove after testing
|
||||
- `sudo ausearch -m USER_LOGIN --start recent --raw` is the best way to see
|
||||
exactly what the script receives
|
||||
|
||||
## Open Items from Session
|
||||
|
||||
- Ansible user strategy: `pbsdeploy` (no password, no sudo, key-only) is
|
||||
for CI/CD only. Ansible playbooks should run as admin account with `-K` for
|
||||
sudo. These are separate concerns — revisit when CI/CD pipeline discussion
|
||||
comes back up.
|
||||
---
|
||||
*Session Date: April 21, 2026*
|
||||
*Next Session: Continue debugging username regex, get end-to-end alert
|
||||
working*
|
||||
|
||||
...sent from Jenny & Travis
|
||||
Loading…
Reference in New Issue
Block a user