logparse / parsers / sshd_journald.pyon commit add systemctl and ufw parsers, support for varying degrees of severity (890d820)
   1#
   2#   sshd_journald.py
   3#   
   4#   Find number of ssh logins and authorised users (uses journald)
   5#
   6
   7import re
   8from systemd import journal
   9
  10from logparse import config
  11from logparse.formatting import *
  12from logparse.load_parsers import Parser
  13from logparse.util import resole
  14
  15class SshdJournald(Parser):
  16
  17    def __init__(self):
  18        super().__init__()
  19        self.name = "sshd_journald"
  20        self.info = "Find number of ssh logins and authorised users (uses journald)"
  21
  22    def parse_log(self):
  23
  24        logger.debug("Starting sshd section")
  25        section = Section("ssh")
  26
  27        j = journal.Reader()
  28        j.this_machine()
  29        j.log_level(journal.LOG_INFO)
  30        j.add_match(_COMM="sshd")
  31        j.seek_realtime(section.period.startdate)
  32        
  33        messages = [entry["MESSAGE"] for entry in j if "MESSAGE" in entry]
  34
  35        login_data = Data("successful", [])
  36        invalid_data = Data("invalid", [])
  37        failed_data = Data("failed", [])
  38
  39        for msg in messages:
  40
  41            if "Accepted publickey" in msg:
  42                entry = re.search('^.*publickey\sfor\s(\w*)\sfrom\s(\S*)', msg)  # [('user', 'ip')]
  43                user = entry.group(1)
  44                ip = entry.group(2)
  45
  46                userhost = user + '@' + resolve(ip, fqdn=config.prefs.get("sshd", "sshd-resolve-domains"))
  47                login_data.items.append(userhost)
  48
  49            elif "Connection closed by authenticating user root" in msg:
  50                entry = re.search('^.*Connection closed by authenticating user (\S+) (\S+)', msg)  # [('user', 'ip')]
  51                user = entry.group(1)
  52                ip = entry.group(2)
  53
  54                userhost = user + '@' + resolve(ip, fqdn=config.prefs.get("sshd", "sshd-resolve-domains"))
  55                failed_data.items.append(userhost)
  56
  57            elif "Invalid user" in msg:
  58                entry = re.search('^.*Invalid user (\S+) from (\S+).*', msg)  # [('user', 'ip')]
  59                user = entry.group(1)
  60                ip = entry.group(2)
  61
  62                userhost = user + '@' + resolve(ip, fqdn=config.prefs.get("sshd", "sshd-resolve-domains"))
  63                invalid_data.items.append(userhost)
  64
  65        login_data.subtitle = plural("successful login", len(login_data.items)) + " from"
  66        login_data.orderbyfreq()
  67        login_data.truncl(config.prefs.getint("logparse", "maxlist"))
  68        
  69        invalid_data.subtitle = plural("attempted login", len(invalid_data.items))
  70        invalid_data.orderbyfreq()
  71        invalid_data.subtitle +=  plural(" from invalid user", len(invalid_data.items), False)
  72        invalid_data.truncl(config.prefs.getint("logparse", "maxlist"))
  73
  74        failed_data.subtitle = plural("failed login", len(failed_data.items)) + " from"
  75        failed_data.orderbyfreq()
  76        failed_data.truncl(config.prefs.getint("logparse", "maxlist"))
  77
  78        section.append_data(login_data)
  79        section.append_data(invalid_data)
  80        section.append_data(failed_data)
  81
  82        logger.info("Finished sshd section")
  83        return section