#!/usr/bin/env python
# Author: <NAME> <<EMAIL>, <EMAIL>>

# 1.) Check that all OSSEC services are running
# $ ./check_ossec.py -T status

# 2.) Check status of all OSSEC agents except one
# $ ./check_ossec.py -T connected --skip www2.company.com

# 3.) Check status of specific OSSEC agents
# $ ./check_ossec.py -T connected --agents www1.company.com,www2.company.com

# 4.) Report critical if more than 3 agents are offline and warning if at least 1 is offline.
# $ ./check_ossec.py -T connected -c 3 -w 1

# 5.) Check that a syscheck scan as completed for all agents in the last 12 hours, warning if 6
# $ ./check_ossec.py -T syscheck -c 12 -w 6

# 6.) Check that a rootcheck scan as completed for agent in the last 4 hours, warning if 2
# $ ./check_ossec.py -T rootcheck --agents www2.company.com -c 4 -w 2

import sys
import argparse
import os
import subprocess
import datetime
import time

# Nagios exit codes
NAGIOS_OK       = 0
NAGIOS_WARNING  = 1
NAGIOS_CRITICAL = 2
NAGIOS_UNKNOWN  = 3

STATUS_MSG = {
  0:  'OK',
  1:  'WARNING',
  2:  'CRITICAL',
  3:  'UNKNOWN',
}

status_checks=['connected', 'syscheck', 'rootcheck', 'status']

def arguments():
  global path
  # Defaults
  crit = 1
  warn = 1
  path = '/var/ossec'

  parser = argparse.ArgumentParser(description='Check OSSEC Configuration')
  parser.add_argument("-s", "--skip",     type=str, help="Items to skip from check")
  parser.add_argument("-a", "--agents",   type=str, help="Check status of agents (def: all) (sep:,) e.g. www1,www2")
  parser.add_argument("-T", "--type",     type=str, help="Type of check", choices=status_checks)
  parser.add_argument("-p", "--path",     type=str, help="Path of OSSEC directory (def: /var/ossec)")
  parser.add_argument("-c", "--critical", type=int, help="Critical value in count for checks")
  parser.add_argument("-w", "--warning",  type=int, help="Warning value in count for checks")
  args = parser.parse_args()

  option = args.type
  if args.critical:
    crit = args.critical
  if args.warning:
    warn = args.warning

  if args.skip:
    skip = args.skip.split(",")
  else:
    skip = "None"
  if args.agents:
    agents = args.agents.split(",")
  else:
    agents = False
  if args.path: 
    path = args.path

  return option, agents, skip, crit, warn

def threshold(inactive_agents, crit, warn):
  if inactive_agents >= crit:
    return NAGIOS_CRITICAL
  if inactive_agents >= warn:
    return NAGIOS_WARNING
  return NAGIOS_OK

def is_ossec(path):
 if os.path.isdir(path):
   files = [ 
     'etc/ossec.conf', 
     'etc/shared/agent.conf', 
     'bin/syscheck_control',
     'bin/rootcheck_control',
     'bin/agent_control'
    ]
   for f in files:
     fp = path + '/' + f
     if not os.path.isfile(fp):
       print "Error: Installation missing file %s" % fp
       return False
 return True

def get_output_dict(cmd, arg):
  c=0
  data={}
  command = path + '/' + cmd
  result = subprocess.Popen([command,arg],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
  set_result = set(result.stdout)
  for i in set_result:
    data[c]= [i.split(',')]
    c += 1
  return data

def get_output_set(cmd, arg):
  command = path + '/' + cmd
  result = subprocess.Popen([command,arg],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
  data = set(result.stdout)
  return data

def is_server():
  filename = '/etc/ossec-init.conf'
  try:
    with open(filename, 'r') as f:
      contents = f.readlines()
      install_type = contents[3].strip().split('=')[1]
    if install_type == '"server"':
      return True
    else:
      print "ERROR: Unable to detect OSSEC server: %s" % install_type
      return False
    
  except IOError:
    print "ERROR: Cannot open file %s. Is OSSEC installed?" % filename
    exit(NAGIOS_UNKNOWN)

def open_queue(filename, service):
  try:
    with open(filename, 'r') as f:
      for i in f.readlines():
        if service == 'syscheck':
          if 'Starting syscheck scan.' in i:
            syscheck_start_ts = i[1:11]
            return syscheck_start_ts
        if service == 'rootcheck':
          if 'Starting rootcheck scan.' in i:
            rootcheck_start_ts = i[1:11]
            return rootcheck_start_ts
      else:
            return False
  except IOError:
    print "ERROR: Cannot read queue file %s" % filename
    exit(NAGIOS_UNKNOWN)

def older_than(ts, name, crit_ts, warn_ts):
  if not ts:
      print "%s: %s: LastCheckTime: Unknown" % (STATUS_MSG[NAGIOS_UNKNOWN], name)
      return NAGIOS_UNKNOWN
  service_timestamp = datetime.datetime.fromtimestamp(float(ts))
  if service_timestamp < crit_ts:
      print "%s: %s: LastCheckTime: %s" % (STATUS_MSG[NAGIOS_CRITICAL], name, service_timestamp)
      return NAGIOS_CRITICAL
  elif service_timestamp < warn_ts:
          print "%s: %s: LastCheckTime: %s" % (STATUS_MSG[NAGIOS_WARNING], name, service_timestamp)
          return NAGIOS_WARNING
  else:
          return NAGIOS_OK

def check_connected(agents, skip, crit, warn):
  data = get_output_dict('bin/agent_control', '-l')
  c=0
  inactive_agents = 0
  active = [ 'Active', 'Active/Local' ]
  notactive = {}

  for i in data:
    line =  data[c][0]
    c += 1
    # Check for lines with fields we need
    # Extract agent name and status message
    if len(line) == 4:
      name=line[1][6:].lstrip()
      status=line[3].lstrip().rstrip()

      # If --agents is specified only check for specified agents
      if agents:
        if name not in agents:
          continue
      else:
        # If --agents is not specified check all except in skip
        if name in skip:
          continue

      if status not in active:
        notactive[name] = status
        inactive_agents += 1

  # Check if inactive agents were fonud 
  if notactive:
    exit_code = threshold(inactive_agents, crit, warn)
    print "%s: %d agents not connected" % (STATUS_MSG[exit_code], len(notactive))
    for k,v in notactive.items():
      print "Name: %s, Status: %s" % (k,v)
    return exit_code
  else:
    print "%s: All agents connected" % STATUS_MSG[NAGIOS_OK]
    return NAGIOS_OK
      
def check_service(service, agents, skip, crit, warn):
  dir = os.path.join(path,'queue/rootcheck')
  crit_ts = datetime.datetime.now() - datetime.timedelta(hours=crit)
  warn_ts = datetime.datetime.now() - datetime.timedelta(hours=warn)
  status_list = []
  for queue in os.listdir(dir):
     name = queue.strip('()').split()[0].rstrip(')')
     if agents:
       if name not in agents:
         continue
     else:
       if name == 'rootcheck':
         continue
       if name in skip:
         continue
     f = os.path.join(dir, queue)
     if os.path.isfile(f):
       ts = open_queue(f, service)
       status = older_than(ts, name, crit_ts, warn_ts)
     status_list.append(status)
     exit_code = max(status_list)
  if exit_code == NAGIOS_OK:
    print "%s: Agent %s runtimes are up to date" % (STATUS_MSG[NAGIOS_OK],service)
  return exit_code

def check_status(agents, skip):
  data = get_output_set('bin/ossec-control', 'status')
  not_running=[]
  for i in data:
    # If --skip is used skip these
    if i in skip:
      continue
    # Add names of services not running to list
    if 'not running' in i:
      not_running.append(i)
      continue
  # Test for entries in list. Entries mean something wasn't running
  if not_running:
    print "%s: Some services running" % STATUS_MSG[NAGIOS_CRITICAL]
    for i in not_running:
      print i.rstrip()
    return NAGIOS_CRITICAL
  else:
    print "%s: All services running" % STATUS_MSG[NAGIOS_OK]
    return NAGIOS_OK

def main():
  option, agents, skip, crit, warn = arguments()

  if not is_ossec(path):
    exit(NAGIOS_UNKNOWN)
  if not is_server():
    exit(NAGIOS_UNKNOWN)

  if option == "connected":
    exit(check_connected(agents, skip, crit, warn))
  elif option == "syscheck":
    exit(check_service(option, agents, skip, crit, warn))
  elif option == "rootcheck":
    exit(check_service(option, agents, skip, crit, warn))
  elif option == "status":
    exit(check_status(agents, skip))
  else:
    print "Invalid type option"
    exit(NAGIOS_UNKNOWN)

if __name__ == "__main__":
  main()

#!/usr/bin/env python
# Author: <NAME> <<EMAIL>, <EMAIL>>

# 1.) Check that all OSSEC services are running
# $ ./check_ossec.py -T status

# 2.) Check status of all OSSEC agents except one
# $ ./check_ossec.py -T connected --skip www2.company.com

# 3.) Check status of specific OSSEC agents
# $ ./check_ossec.py -T connected --agents www1.company.com,www2.company.com

# 4.) Report critical if more than 3 agents are offline and warning if at least 1 is offline.
# $ ./check_ossec.py -T connected -c 3 -w 1

# 5.) Check that a syscheck scan as completed for all agents in the last 12 hours, warning if 6
# $ ./check_ossec.py -T syscheck -c 12 -w 6

# 6.) Check that a rootcheck scan as completed for agent in the last 4 hours, warning if 2
# $ ./check_ossec.py -T rootcheck --agents www2.company.com -c 4 -w 2

import sys
import argparse
import os
import subprocess
import datetime
import time

# Nagios exit codes
NAGIOS_OK       = 0
NAGIOS_WARNING  = 1
NAGIOS_CRITICAL = 2
NAGIOS_UNKNOWN  = 3

STATUS_MSG = {
  0:  'OK',
  1:  'WARNING',
  2:  'CRITICAL',
  3:  'UNKNOWN',
}

status_checks=['connected', 'syscheck', 'rootcheck', 'status']

def arguments():
  global path
  # Defaults
  crit = 1
  warn = 1
  path = '/var/ossec'

  parser = argparse.ArgumentParser(description='Check OSSEC Configuration')
  parser.add_argument("-s", "--skip",     type=str, help="Items to skip from check")
  parser.add_argument("-a", "--agents",   type=str, help="Check status of agents (def: all) (sep:,) e.g. www1,www2")
  parser.add_argument("-T", "--type",     type=str, help="Type of check", choices=status_checks)
  parser.add_argument("-p", "--path",     type=str, help="Path of OSSEC directory (def: /var/ossec)")
  parser.add_argument("-c", "--critical", type=int, help="Critical value in count for checks")
  parser.add_argument("-w", "--warning",  type=int, help="Warning value in count for checks")
  args = parser.parse_args()

  option = args.type
  if args.critical:
    crit = args.critical
  if args.warning:
    warn = args.warning

  if args.skip:
    skip = args.skip.split(",")
  else:
    skip = "None"
  if args.agents:
    agents = args.agents.split(",")
  else:
    agents = False
  if args.path: 
    path = args.path

  return option, agents, skip, crit, warn

def threshold(inactive_agents, crit, warn):
  if inactive_agents >= crit:
    return NAGIOS_CRITICAL
  if inactive_agents >= warn:
    return NAGIOS_WARNING
  return NAGIOS_OK

def is_ossec(path):
 if os.path.isdir(path):
   files = [ 
     'etc/ossec.conf', 
     'etc/shared/agent.conf', 
     'bin/syscheck_control',
     'bin/rootcheck_control',
     'bin/agent_control'
    ]
   for f in files:
     fp = path + '/' + f
     if not os.path.isfile(fp):
       print "Error: Installation missing file %s" % fp
       return False
 return True

def get_output_dict(cmd, arg):
  c=0
  data={}
  command = path + '/' + cmd
  result = subprocess.Popen([command,arg],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
  set_result = set(result.stdout)
  for i in set_result:
    data[c]= [i.split(',')]
    c += 1
  return data

def get_output_set(cmd, arg):
  command = path + '/' + cmd
  result = subprocess.Popen([command,arg],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
  data = set(result.stdout)
  return data

def is_server():
  filename = '/etc/ossec-init.conf'
  try:
    with open(filename, 'r') as f:
      contents = f.readlines()
      install_type = contents[3].strip().split('=')[1]
    if install_type == '"server"':
      return True
    else:
      print "ERROR: Unable to detect OSSEC server: %s" % install_type
      return False
    
  except IOError:
    print "ERROR: Cannot open file %s. Is OSSEC installed?" % filename
    exit(NAGIOS_UNKNOWN)

def open_queue(filename, service):
  try:
    with open(filename, 'r') as f:
      for i in f.readlines():
        if service == 'syscheck':
          if 'Starting syscheck scan.' in i:
            syscheck_start_ts = i[1:11]
            return syscheck_start_ts
        if service == 'rootcheck':
          if 'Starting rootcheck scan.' in i:
            rootcheck_start_ts = i[1:11]
            return rootcheck_start_ts
      else:
            return False
  except IOError:
    print "ERROR: Cannot read queue file %s" % filename
    exit(NAGIOS_UNKNOWN)

def older_than(ts, name, crit_ts, warn_ts):
  if not ts:
      print "%s: %s: LastCheckTime: Unknown" % (STATUS_MSG[NAGIOS_UNKNOWN], name)
      return NAGIOS_UNKNOWN
  service_timestamp = datetime.datetime.fromtimestamp(float(ts))
  if service_timestamp < crit_ts:
      print "%s: %s: LastCheckTime: %s" % (STATUS_MSG[NAGIOS_CRITICAL], name, service_timestamp)
      return NAGIOS_CRITICAL
  elif service_timestamp < warn_ts:
          print "%s: %s: LastCheckTime: %s" % (STATUS_MSG[NAGIOS_WARNING], name, service_timestamp)
          return NAGIOS_WARNING
  else:
          return NAGIOS_OK

def check_connected(agents, skip, crit, warn):
  data = get_output_dict('bin/agent_control', '-l')
  c=0
  inactive_agents = 0
  active = [ 'Active', 'Active/Local' ]
  notactive = {}

  for i in data:
    line =  data[c][0]
    c += 1
    # Check for lines with fields we need
    # Extract agent name and status message
    if len(line) == 4:
      name=line[1][6:].lstrip()
      status=line[3].lstrip().rstrip()

      # If --agents is specified only check for specified agents
      if agents:
        if name not in agents:
          continue
      else:
        # If --agents is not specified check all except in skip
        if name in skip:
          continue

      if status not in active:
        notactive[name] = status
        inactive_agents += 1

  # Check if inactive agents were fonud 
  if notactive:
    exit_code = threshold(inactive_agents, crit, warn)
    print "%s: %d agents not connected" % (STATUS_MSG[exit_code], len(notactive))
    for k,v in notactive.items():
      print "Name: %s, Status: %s" % (k,v)
    return exit_code
  else:
    print "%s: All agents connected" % STATUS_MSG[NAGIOS_OK]
    return NAGIOS_OK
      
def check_service(service, agents, skip, crit, warn):
  dir = os.path.join(path,'queue/rootcheck')
  crit_ts = datetime.datetime.now() - datetime.timedelta(hours=crit)
  warn_ts = datetime.datetime.now() - datetime.timedelta(hours=warn)
  status_list = []
  for queue in os.listdir(dir):
     name = queue.strip('()').split()[0].rstrip(')')
     if agents:
       if name not in agents:
         continue
     else:
       if name == 'rootcheck':
         continue
       if name in skip:
         continue
     f = os.path.join(dir, queue)
     if os.path.isfile(f):
       ts = open_queue(f, service)
       status = older_than(ts, name, crit_ts, warn_ts)
     status_list.append(status)
     exit_code = max(status_list)
  if exit_code == NAGIOS_OK:
    print "%s: Agent %s runtimes are up to date" % (STATUS_MSG[NAGIOS_OK],service)
  return exit_code

def check_status(agents, skip):
  data = get_output_set('bin/ossec-control', 'status')
  not_running=[]
  for i in data:
    # If --skip is used skip these
    if i in skip:
      continue
    # Add names of services not running to list
    if 'not running' in i:
      not_running.append(i)
      continue
  # Test for entries in list. Entries mean something wasn't running
  if not_running:
    print "%s: Some services running" % STATUS_MSG[NAGIOS_CRITICAL]
    for i in not_running:
      print i.rstrip()
    return NAGIOS_CRITICAL
  else:
    print "%s: All services running" % STATUS_MSG[NAGIOS_OK]
    return NAGIOS_OK

def main():
  option, agents, skip, crit, warn = arguments()

  if not is_ossec(path):
    exit(NAGIOS_UNKNOWN)
  if not is_server():
    exit(NAGIOS_UNKNOWN)

  if option == "connected":
    exit(check_connected(agents, skip, crit, warn))
  elif option == "syscheck":
    exit(check_service(option, agents, skip, crit, warn))
  elif option == "rootcheck":
    exit(check_service(option, agents, skip, crit, warn))
  elif option == "status":
    exit(check_status(agents, skip))
  else:
    print "Invalid type option"
    exit(NAGIOS_UNKNOWN)

if __name__ == "__main__":
  main()

#!/usr/bin/env python # Author: <NAME> <<EMAIL>, <EMAIL>> # 1.) Check that all OSSEC services are running # $ ./check_ossec.py -T status # 2.) Check status of all OSSEC agents except one # $ ./check_ossec.py -T connected --skip www2.company.com # 3.) Check status of specific OSSEC agents # $ ./check_ossec.py -T connected --agents www1.company.com,www2.company.com # 4.) Report critical if more than 3 agents are offline and warning if at least 1 is offline. # $ ./check_ossec.py -T connected -c 3 -w 1 # 5.) Check that a syscheck scan as completed for all agents in the last 12 hours, warning if 6 # $ ./check_ossec.py -T syscheck -c 12 -w 6 # 6.) Check that a rootcheck scan as completed for agent in the last 4 hours, warning if 2 # $ ./check_ossec.py -T rootcheck --agents www2.company.com -c 4 -w 2 # Nagios exit codes # Defaults # Check for lines with fields we need # Extract agent name and status message # If --agents is specified only check for specified agents # If --agents is not specified check all except in skip # Check if inactive agents were fonud # If --skip is used skip these # Add names of services not running to list # Test for entries in list. Entries mean something wasn't running