Zabbix. Список служб Windows.

Будем использовать Zabbix для слежения за списком установленных служб/сервисов Windows.

Это важно по нескольким причинам:

  1. Вирусы часто устанавливают в системе новые службы, а это значит, что нужно следить за появлением новых служб.
  2. Бывает, что некоторые службы Windows , имеющие тип запуска auto или delayed-auto не работают, а это повод проверить их настройки.

Замечание 1.
Способ установки Python 2.7 описан тут: https://www.mihanik.net/tihaja-ustanovka-python-2-7/

Замечание 2.

Способ становки Zabbix-агента (клиента) описан тут: https://www.mihanik.net/ustanovka-zabbix-klienta/

1. Собираем данные по установленным программам при помощи скрипта.

Скрипт  написан на Python 2.7, он собирает данные по установленным службам и формирует 3 файла:

    • Полный список служб —  ‘C:\Zabbix\scripts\soft_list\service_list.lst’
    • Список недавно установленных/удалённых служб —  ‘C:\Zabbix\scripts\soft_list\service_diff.lst’
    • Список служб, с установленным способом запуска Auto или Delayed-auto, но не работающих  — ‘C:\Zabbix\scripts\soft_list\service_stoped.lst’.

Нужно отметить, что некоторые автоматически запускаемые службы Windows могут прекращать работу. Для каких-то служб это нормально, поэтому, чтобы не поднимать панику раньше времени,  скрипт использует файл со списком служб за которыми не нужно наблюдать — ‘C:\Zabbix\scripts\soft_list\NotMonitoredServices.txt’.

Сам скрипт сохранён под именем C:\Zabbix\scripts\soft_list\serviceslist.py.

Текст скрипта:
# -*- coding: utf-8 -*-
import os
import sys
import ctypes
import errno
import _winreg
import codecs
import wmi

#
# Функция проверки наличия прав администратора
# Вход: нет
# Выход: true - есть права администратора,
#        false - нет прав администратора
#
def is_admin():
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False
# 
# Функция удаления дубликатов из списка
# Вход: список
# Выход: список без дубликатов
#
def DuplicateRemoval ( InboundList ):
    OutboundList = []
    for i in InboundList:
        if i not in OutboundList:
            OutboundList.append(i)
    return OutboundList

# 
# Функция загрузки списка из файла
# Вход: путь к файлу со списком
# Выход: список
#
def ListLoad ( InboundFileName ):
    OutboundList = []
    
    # Если указанного файла не существует возвращаем пустой список
    if not os.path.exists( InboundFileName ):
        return OutboundList
    
    if not os.path.isfile( InboundFileName ):
        return OutboundList
    
    # Читаем файл построчно
    f = open( InboundFileName,'r')
    try:
        OutboundList = f.read().splitlines()
    except Exception:
        pass
    finally:
        f.close()

    return OutboundList

# 
# Функция сохранения списка в файл
# Вход: список, путь к файлу
# Выход: true - успешная запись, false - ошибка при записи
#
def ListSave ( OutboundList, OutboundFileName ):
    
    # Записываем файл построчно
   f = open( OutboundFileName,'w')
   try:
     for line in OutboundList:
           f.write(line + '\n')
   except Exception:
       MyResult = False
   else:
       MyResult = True
   finally:
      f.close()
    
   return MyResult

# 
# Функция получения списка установленных служб Windows имеющих способ запуска auto или Delayed-auto, но не работающих
# Вход: нет
# Выход: список установленных служб Windows имеющих способ запуска auto или Delayed-auto, но не работающих
#
def StopedServicesList():
    
   List = []
   
   c = wmi.WMI ()

   stopped_services = c.Win32_Service (StartMode="Auto", State="Stopped")
   
   for Service in stopped_services:
         List.append (Service.Name + ' - ' + Service.Caption + ' - ' + Service.State)

   stopped_services = c.Win32_Service (StartMode="Delayed-auto", State="Stopped")

   for Service in stopped_services:
         List.append (Service.Name + ' - ' + Service.Caption + ' - ' + Service.State)
   
   List.sort()
   
   return List

# 
# Функция получения списка всех установленных служб Windows
# Вход: нет
# Выход: список всех установленных служб Windows
#
def ServicesList():
    
   List = []
   
   c = wmi.WMI ()
   Services = c.Win32_Service ()

   for Service in Services:
         List.append (Service.Name + ' - ' + Service.Caption)
   
   List.sort()
   
   return List

################################################################################
#   Начало программы
################################################################################
def main(argv=None):
   # Проверяем наличие прав админа.
   if not is_admin ():
      sys.exit ('Not enough permissions to run the script !!!')
   
   # Устанавливаем кодировку по умолчанию.
   reload(sys)
   sys.setdefaultencoding('utf8')
   
   # Зададим имена файлам, которые будем использовать
   # Полный список служб
   MyServicesListFile=r'C:\Zabbix\scripts\soft_list\service_list.lst'
   # Список установленных/удалённых служб
   MyServicesDiffFile=r'C:\Zabbix\scripts\soft_list\service_diff.lst'
   # Список не работающих служб
   MyServicesStopedFile=r'C:\Zabbix\scripts\soft_list\service_stoped.lst'
   # Список не наблюдаемых служб
   MyServicesNotMonitored=r'C:\Zabbix\scripts\soft_list\NotMonitoredServices.txt'
   
   # Получаем список установленных служб Windows
   List = ServicesList()
   
   # Получаем прежний список из файла
   OldList = ListLoad ( MyServicesListFile )
    
   # Ищем установленные/удалённые службы Windows
   DeletedList = []
   InstalledList = []
   
   # Получаем список свежеустановленных служб Windows
   for i in List:
       if i not in OldList:
            InstalledList.append(i)
   
   # Получаем список удалённых служб Windows
   for i in OldList:
       if i not in List:
            DeletedList.append(i)
   
   # Сохраняем список изменений в diff-файл построчно
   f = open( MyServicesDiffFile,'w')
   try:
      f.write('Deleted:'+ '\n')
      for line in DeletedList:
         f.write(line + '\n')
      f.write('\n')
      f.write('Installed:'+ '\n')
      for line in InstalledList:
         f.write(line + '\n')
   except Exception:
      pass
   finally:
      f.close()
   
   # Сохраняем текущий список установленных служб Windows в файл
   if not ListSave (List, MyServicesListFile):
      sys.exit ('Unable to save installed services list!!!')
   
   # Сохраняем текущий список установленных служб Windows  имеющих способ запуска auto, но не работающих в файл.
   # Предварительно из этого списка уберём упоминание тех служб, за которыми не нужно следить.
   List = StopedServicesList()
   NotMonitored = ListLoad ( MyServicesNotMonitored )
   
   for i in NotMonitored:
      for ListItem in List:
         if i in ListItem:
            List.remove(ListItem)
   
   if not ListSave (List, MyServicesStopedFile):
      sys.exit ('Unable to save stoped services list!!!')

if __name__ == "__main__":
    sys.exit(main())

2. Устанавливаем скрипт в системе.

Скрипт лучше запускать каждый час, — не слишком часто, но и не слишком редко.

Запланировать выполнение скрипта можно при помощи планировщика Windows. Задание планировщика можно создать вручную, а можно и при помощи bat-файла.

Я обычно это делаю при помощи «батника», имя своему батнику я дал INSTALL_get_services_list.bat .

Текст скрипта:
@echo off

Rem Предполагаем, что на Windows XP скрипт запускается администратором.
Rem Для более старших систем это неверно.

rem Получаем версию ОС
ver | find "5.1."

rem Windows XP ?
If %errorlevel%==0  (
	rem Пропускаем проверку админских прав
	GOTO SKIPADMIN
 )
 
SET HasAdminRights=0

FOR /F %%i IN ('WHOAMI /PRIV /NH') DO (
	IF "%%i"=="SeTakeOwnershipPrivilege" SET HasAdminRights=1
)

IF NOT %HasAdminRights%==1 (
	ECHO .
	ECHO Not enough permissions to run the script !!!
	ECHO .
	GOTO END
)

:SKIPADMIN

rem Получаем версию ОС
rem Windows XP ?

ver | find "5.1."

If %errorlevel%==0  (
	rem Windows XP
	SCHTASKS /Create /RU "NT AUTHORITY\SYSTEM" /SC HOURLY /ST 00:05:00 /TN "InstalledServices" /TR "python \"C:\zabbix\scripts\soft_list\serviceslist.py\""
 ) else (
	rem НЕ Windows XP
	SCHTASKS /Create /RU "NT AUTHORITY\SYSTEM" /SC DAILY /ST 00:05 /RI 60 /DU 24:00 /TN "InstalledServices" /TR "python \"C:\zabbix\scripts\soft_list\serviceslist.py\"" /RL HIGHEST /F
 )

cd "C:\Zabbix\scripts\soft_list"

python "C:\zabbix\scripts\soft_list\serviceslist.py"

:END

EXIT /B

3. Формируем шаблон в Zabbix.

В Zabbix при этом добавляем несложный шаблон.

Сначала приведу описание шаблона в картинках.

Создаём шаблон с именем : Active Computer — Python — ServicesList


Добавляем группу элементов данных…


Теперь добавляем 3 элемента данных…






И, наконец, пару несложныйх триггеров, которые будут срабатывать при изменении списка служб или при остановке какой-то службы…




А вот и готовый для импорта заархивированный файл с описанным выше шаблоном: zbx_export_templates_serviceslist.xml

Описанные ранее скрипты можно найти в этом архиве: soft_list

4. Сбор данных.

Осталось назначить созданный шаблон соответствующему узлу сети и ждать начала поступления данных. 🙂

Всё.

🙂