841d195384a27e1f11424742d024d2fe64c8de47
   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.formatting import *
  11from logparse.util import resolve
  12from logparse import config
  13from logparse.load_parsers import Parser
  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_boot()
  29        j.log_level(journal.LOG_DEBUG)
  30        j.add_match(_COMM="sshd")
  31        
  32        messages = [entry["MESSAGE"] for entry in j if "MESSAGE" in entry]
  33
  34        login_data = Data("successful", [])
  35        invalid_data = Data("invalid", [])
  36        failed_data = Data("failed", [])
  37
  38        for msg in messages:
  39
  40            if "Accepted publickey" in msg:
  41                entry = re.search('^.*publickey\sfor\s(\w*)\sfrom\s(\S*)', msg)  # [('user', 'ip')]
  42                user = entry.group(1)
  43                ip = entry.group(2)
  44
  45                userhost = user + '@' + resolve(ip, fqdn=config.prefs.get("sshd", "sshd-resolve-domains"))
  46                login_data.items.append(userhost)
  47
  48            elif "Connection closed by authenticating user root" in msg:
  49                entry = re.search('^.*Connection closed by authenticating user (\S+) (\S+)', msg)  # [('user', 'ip')]
  50                user = entry.group(1)
  51                ip = entry.group(2)
  52
  53                userhost = user + '@' + resolve(ip, fqdn=config.prefs.get("sshd", "sshd-resolve-domains"))
  54                failed_data.items.append(userhost)
  55
  56            elif "Invalid user" in msg:
  57                entry = re.search('^.*Invalid user (\S+) from (\S+).*', msg)  # [('user', 'ip')]
  58                user = entry.group(1)
  59                ip = entry.group(2)
  60
  61                userhost = user + '@' + resolve(ip, fqdn=config.prefs.get("sshd", "sshd-resolve-domains"))
  62                invalid_data.items.append(userhost)
  63
  64        login_data.subtitle = plural("successful login", len(login_data.items)) + " from"
  65        login_data.orderbyfreq()
  66        login_data.truncl(config.prefs.getint("logparse", "maxlist"))
  67        
  68        invalid_data.subtitle = plural("attempted login", len(invalid_data.items))
  69        invalid_data.orderbyfreq()
  70        invalid_data.subtitle +=  plural(" from invalid user", len(invalid_data.items), False)
  71        invalid_data.truncl(config.prefs.getint("logparse", "maxlist"))
  72
  73        failed_data.subtitle = plural("failed login", len(failed_data.items)) + " from"
  74        failed_data.orderbyfreq()
  75        failed_data.truncl(config.prefs.getint("logparse", "maxlist"))
  76
  77        section.append_data(login_data)
  78        section.append_data(invalid_data)
  79        section.append_data(failed_data)
  80
  81        logger.info("Finished sshd section")
  82        return section