Run:
journalctl -q _AUDIT_TYPE=1112 _TRANSPORT=audit
Explanation:
Assuming you have the audit subsystem running (and unless you disabled it, you do), that's the best way to get this kind of information, because among other things if you use _TRANSPORT=audit
, messages can't be spoofed like those over the traditional syslog socket. To see all of the messages sent through this transport, use journalctl -q _TRANSPORT=audit
. (The -q keeps out annoying -- Reboot --
lines.)
To see these in verbose form, do journalctl -q _TRANSPORT=audit -o verbose
. Actually, I suggest stopping and doing that right now as you're following along, because the next thing we want to do is to filter on one some of the fields we see there. Here's a record from my system:
_BOOT_ID=[redacted]
_MACHINE_ID=[redacted]
_HOSTNAME=[redacted]
_UID=0
_TRANSPORT=audit
SYSLOG_FACILITY=4
SYSLOG_IDENTIFIER=audit
AUDIT_FIELD_HOSTNAME=?
AUDIT_FIELD_ADDR=?
AUDIT_FIELD_RES=success
_AUDIT_LOGINUID=18281
_AUDIT_TYPE=1112
AUDIT_FIELD_OP=login
AUDIT_FIELD_ID=18281
_PID=5398
_SELINUX_CONTEXT=system_u:system_r:local_login_t:s0-s0:c0.c1023
AUDIT_FIELD_EXE=/usr/bin/login
AUDIT_FIELD_TERMINAL=tty6
_AUDIT_SESSION=541
_SOURCE_REALTIME_TIMESTAMP=1480529473269000
_AUDIT_ID=7444
MESSAGE=USER_LOGIN pid=5398 uid=0 auid=18281 ses=541 subj=system_u:system_r:local_login_t:s0-s0:c0.c1023 msg='op=login id=18281 exe="/usr/bin/login" hostname=? addr=? terminal=tty6 res=success'
The MESSAGE
at the bottom is the unstructured log record, which is basically what you see in the non-verbose syslog-style output. We could grep for MESSAGE=USER_LOGIN
(and be done right now) but the journal lets us do more cool stuff, so let's keep at it.
Each audit message type has an associated _AUDIT_TYPE
(imagine that!). For some reason, this doesn't get helpfully converted to text in the structured output, but 1112
corresponds to USER_LOGIN
. I confirmed this by checking in libaudit.h
, which has (with some context lines):
#define AUDIT_USER_CHAUTHTOK 1108 /* User acct password or pin changed */
#define AUDIT_USER_ERR 1109 /* User acct state error */
#define AUDIT_CRED_REFR 1110 /* User credential refreshed */
#define AUDIT_USYS_CONFIG 1111 /* User space system config change */
#define AUDIT_USER_LOGIN 1112 /* User has logged in */
#define AUDIT_USER_LOGOUT 1113 /* User has logged out */
#define AUDIT_ADD_USER 1114 /* User account added */
#define AUDIT_DEL_USER 1115 /* User account deleted */
so, journalctl -q _AUDIT_TYPE=1112 _TRANSPORT=audit
is what you need. It gets ssh, terminal, and GUI logins, and records success and failure. Note that it doesn't catch things like sudo
or su
— there are different audit records for those.
Even the "short" version of the output is kind of verbose, so you might want to use -o json
and create a short script to parse the output into a pretty format.
last
andsudo lastb
are clean and mostly robust ways to get this data and still work on Fedora, though lastb omits failed logins viagdm
: unix.stackexchange.com/questions/10046/…