OS Windows WMI / Получения статистики с zbxwmi

Шаблоны под операционную систему Windows
Аватара пользователя
Артём Мамзиков
Admin
Сообщения: 804
Стаж: 5 лет 1 месяц
Откуда: Вологодская область
Поблагодарили: 33 раза
Контактная информация:

OS Windows WMI / Получения статистики с zbxwmi

Сообщение Артём Мамзиков »

Шаблон OS Windows WMI / Получения статистики с zbxwmi

СКАЧАТЬ
Получения статистики с zbxwmi.zip
Получения статистики с zbxwmi.zip
(9.45 КБ) 14 скачиваний
Шаблон для получения статистики с zbxwmi сценария.
Этот метод позволяет получить статистику удален WMI без установки агента в ОС.
Источник github zbxwmi


Коннектор Zabbix WMI - обнаружение и получение информации с хостов MS Windows без установки агента.
Зависит от impacket библиотеки Python .

Работает в 4 режимах:
Откройте для себя объекты
Получить одно значение
Получить несколько значений в JSON
Получите несколько значений и отправьте их с помощьюzabbix_sender

Файл учетных данных состоит из трех строк: логин, пароль, домен.
Параметры командной строки
Показать
usage: zbxwmi [-h] [-v] [-action {get,bulk,json,discover,both}]
[-namespace NAMESPACE] [-key KEY] [-fields FIELDS]
[-filter FILTER] [-type TYPE] [-item ITEM]
[-server address] [-sender path] [-cred CRED]
[-dc-ip ip address] [-rpc-auth-level [{integrity,privacy,default}]]
class target

usage: zbxwmi [-h] [-v] [-action {get,bulk,json,discover,both}] [-namespace NAMESPACE] [-key KEY] [-fields FIELDS] [-type TYPE] [-filter FILTER]
[-item ITEM] [-server address] [-sender path] [-cred CRED] [-dc-ip ip address] [-rpc-auth-level [{integrity,privacy,default}]]
class target

Zabbix WMI connector

positional arguments:
class WMI class
target target address

optional arguments:
-h, --help show this help message and exit
-v, --version show program's version number and exit
-action {get,bulk,json,discover,both}
Action to take (default: get)
-namespace NAMESPACE namespace name (default: //./root/cimv2)
-key KEY Key
-fields FIELDS Field list delimited by comma
-type TYPE Field type hint delimited by comma: n - number, s - string (default)
-filter FILTER Filter
-item ITEM Selected item

Zabbix:
-server address Zabbix server (default: 127.0.0.1)
-sender path Zabbix sender (default: /usr/bin/zabbix_sender)

Authentication:
-cred CRED Credential file (default: /etc/zabbix/wmi.pw)
-dc-ip ip address IP Address of the domain controller. If ommited it use
the domain part (FQDN) specified in the target
parameter
-rpc-auth-level [{integrity,privacy,default}]
integrity (RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) or privacy
(RPC_C_AUTHN_LEVEL_PKT_PRIVACY). (default: default)

Установка

Предположим, вы установили Zabbix Appliance с Ubuntu на борту.
Получите доступ к корневой оболочке и установите соответствующие зависимости.

Скрипт zbxwmi

Код: Выделить всё

#!/usr/bin/env python3
#
# zbxwmi : discovery and bulk checks of WMI items with Zabbix
# Requires impacket (python pkg) and optionally zabbix_sender
#
# Author:
#  Vitaly Chekryzhev (13hakta@gmail.com)

import argparse, sys, os

def main():
	parser = argparse.ArgumentParser(add_help = True, description = "Zabbix WMI connector")
	parser.add_argument('-v', '--version', action='version', version='0.1.3')
	parser.add_argument('cls', metavar='class', help='WMI class')
	parser.add_argument('target', help='target address')

	parser.add_argument('-action', default='get', choices=['get', 'bulk', 'json', 'discover', 'both'], help='Action to take (default: %(default)s)')
	parser.add_argument('-namespace', default='//./root/cimv2', help='namespace name (default: %(default)s)')

	parser.add_argument('-key', help='Key')
	parser.add_argument('-fields', help='Field list delimited by comma')
	parser.add_argument('-type', help='Field type hint delimited by comma: n - number, s - string (default)')
	parser.add_argument('-filter', default='', help='Filter')
	parser.add_argument('-item', default='', help='Selected item')

	group = parser.add_argument_group('Zabbix')

	group.add_argument('-server', metavar='address', default='127.0.0.1', help='Zabbix server (default: %(default)s)')
	group.add_argument('-sender', metavar='path', default='/usr/bin/zabbix_sender', help='Zabbix sender (default: %(default)s)')

	group = parser.add_argument_group('Authentication')

	group.add_argument('-cred', type=argparse.FileType('r'), default='/etc/zabbix/wmi.pw', help='Credential file (default: %(default)s)')

	group.add_argument('-dc-ip', metavar = "ip address", help='IP Address of the domain controller. If '
										'ommited it use the domain part (FQDN) specified in the target parameter')
	group.add_argument('-rpc-auth-level', choices=['integrity', 'privacy', 'default'], nargs='?', default='default',
										help='integrity (RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) or privacy '
													'(RPC_C_AUTHN_LEVEL_PKT_PRIVACY). (default: %(default)s)')

	if len(sys.argv) == 1:
			parser.print_help()
			sys.exit(1)

	options = parser.parse_args()

	# Extract the arguments
	emulatekey = False

	if options.key:
		key = options.key
	else:
		key = 'Name'
		emulatekey = True

	fieldlist = options.fields.split(',')

	if (options.action == 'get' and options.fields and len(fieldlist) != 1):
		print("action 'get' requires only one item")
		exit(1)

	idx = 0
	hintlist = options.type.split(',')
	for f in fieldlist:
		if idx < len(hintlist):
			hints[f] = hintlist[idx]
		else:
			hints[f] = 's'

		idx += 1

	username = options.cred.readline().strip()
	password = options.cred.readline().strip()
	domain = options.cred.readline().strip()

	from impacket.dcerpc.v5.dtypes import NULL
	from impacket.dcerpc.v5.dcom import wmi
	from impacket.dcerpc.v5.dcomrt import DCOMConnection
	from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_LEVEL_NONE

	try:
		dcom = DCOMConnection(options.target, username, password, domain, '', '', '', oxidResolver=True,
													doKerberos=False, kdcHost=options.dc_ip)
		iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login)
		iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
		iWbemServices = iWbemLevel1Login.NTLMLogin(options.namespace, NULL, NULL)

		if options.rpc_auth_level == 'privacy':
			iWbemServices.get_dce_rpc().set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
		elif options.rpc_auth_level == 'integrity':
			iWbemServices.get_dce_rpc().set_auth_level(RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)

		iWbemLevel1Login.RemRelease()

		# Construct the query
		query = "SELECT "

		if options.fields is None:
			options.fields = key
			query += key
		else:
			query += key + ',' + options.fields

		query += " FROM " + options.cls

		# Conditional request
		if options.filter or options.item:
			query += " WHERE "
			wheres = []

			if options.filter:
				wheres.append(options.filter)

			if options.item:
				wheres.append(key + '="' + options.item + '"')

			query += ' AND '.join(wheres)

		response = []

		try:
			iEnum = iWbemServices.ExecQuery(query)

			while True:
				try:
					pEnum = iEnum.Next(0xffffffff, 1)[0]
					record = pEnum.getProperties()

					j = {}

					for k in record:
						if type(record[k]['value']) is list:
							j[k] = []
							for item in record[k]['value']:
								j[k].append(item)
						else:
							j[k] = record[k]['value']

					response.append(j) # the response output
				except Exception as e:
					if str(e).find('S_FALSE') < 0:
						raise
					else:
						break

			iEnum.RemRelease()
		except Exception as e:
			print("An error occured: " + str(e))

		iWbemServices.RemRelease()
		dcom.disconnect()

		# Что делать с результатами?
		if options.action == 'get':
			print(str(response[0][options.fields]))
		elif options.action == 'bulk':
			send2zabbix(response, key, options.target, options.sender, options.server)
		elif options.action == 'json':
			send2zabbix_json(response)
		elif options.action == 'discover':
			discovery_json(response)
		elif options.action == 'both': # Discover + bulk
			send2zabbix(response, key, options.target, options.sender, options.server)
			discovery_json(response)
		else:
			print("Invalid action.")
			exit(1)
	except Exception as e:
		print("An error occured: " + str(e))
		try:
			dcom.disconnect()
		except:
			pass

def tval(k, v):
	if hints[k] == 's':
		return ['"' + v + '"', '""'][v is None]

	if hints[k] == 'n':
		return [str(v), '0'][v is None]

def discovery_json(data):

	"""
	Display a JSON-formatted index for Zabbix LLD discovery
	"""

	output = []

	for eachItem in data:
		res = []
		for k in eachItem:
			key = '{#WMI.' + k.upper() + '}'
			res.append('"' + key + '": ' + tval(k, eachItem[k]))
		output.append('{' + ', '.join(res) + '}')

	print('{ "data": [', ', '.join(output), '] }')

def send2zabbix_json(data):

	"""
	Display a JSON-formatted index for Zabbix bulk
	"""

	output = []

	for eachItem in data:
		res = ['"' + k + '": ' + tval(k, eachItem[k]) for k in eachItem]

		output.append('{' + ', '.join(res) + '}')

	print("[" + ','.join(output) + "]")


def send2zabbix(data, key, host, sender, server):

	"""
	Bulk inserts data into Zabbix using zabbix_sender
	"""

	# Contruct the input for zabbix_sender
	output = ""
	for eachItem in data:
		val = "[" + str(eachItem.pop(key)) + "] "
		for k in eachItem:
			output += host + " " + k + val + ' ' + tval(k, eachItem[k]) + "\n"

	# Отправьте значения на сервер
	import subprocess

	f = open(os.devnull, "w")

	try:
		p = subprocess.Popen([sender, '-r', '-z', server, '-i', '-'], stdin=subprocess.PIPE, stdout=f, stderr=f)
		p.communicate(output.encode())
	except Exception as e:
		print("An error occured with zabbix_sender. " + str(e))
		exit(1)

if __name__ == '__main__':
	hints = {'Name': 's'}
	main()
Скопируйте zbxwmi скрипт /usr/lib/zabbix/externalscripts
и установите разрешения:

Код: Выделить всё

cd /usr/lib/zabbix/externalscripts
chmod 755 zbxwmi
chown root.root zbxwmi

Установите необходимые модули Python:

Код: Выделить всё

apt install python3-six python3-pycryptodome python3-pyasn1
Установите библиотеку

Код: Выделить всё

импактов
.

Загрузите с github или урезанную версию, достаточную для выполнения вызовов WMI. Распакуйте содержимое в директорию /usr/lib/python3.6(проверьте соответствующую версию).

Создайте файл /etc/zabbix/wmi.pw с логином, паролем и доменом по одному параметру в строке.
Установить доступ к файлу:

Код: Выделить всё

chmod 640 /etc/zabbix/wmi.pw
chown zabbix.zabbix /etc/zabbix/wmi.pw
Пустые значения
Для строкового типа возвращается '' (пустая строка).
Для числового типа возвращается «0».
Если предполагается, что поле является числовым, то для этого поля следует установить подсказку типа.
Допустим, у вас есть 4 поля:
1 — строка,
2 — число,
3 — число,
4 — строка,
тогда вы должны добавить опцию:-type s,n,n,s

Примеры
Получить одно значение:
Получить доступное место на диске
$ zbxwmi \
-a get \
-k DeviceID \
-fields "FreeSpace" \
-item "C:" \
"Win32_LogicalDisk" \
"remote.domain"
Выходы типа: 5121286144

Получить несколько значений:
Получите доступное и общее место на диске с помощью zabbix_sender
$ zbxwmi \
-a bulk \
-k DeviceID \
-fields "Size,FreeSpace" \
-item "C:" \
"Win32_LogicalDisk" \
"remote.domain"

Получить доступное и общее место на диске
$ zbxwmi \
-a json \
-k DeviceID \
-fields "Size,FreeSpace" \
-item "C:" \
"Win32_LogicalDisk" \
"remote.domain"
Выходы типа: [{"Size": "2197918158848", "DeviceID": "C:", "FreeSpace": "5121286144"}]

Откройте для себя объекты:
Обнаружение разделов локального диска
$ zbxwmi \
-action discover \
-k DeviceID \
-filter MediaType=12 \
"Win32_LogicalDisk" \
"remote.domain"
Выходы типа: { "data": [ {"{#WMI.DEVICEID}":"C:"}, {"{#WMI.DEVICEID}":"D:"}, {"{#WMI.DEVICEID}":"E:"} ] }

Обнаружить
Получить загрузку процессора:

Код: Выделить всё

zbxwmi["-action","discover","-type","n","-fields","PercentProcessorTime","-filter","Name<>'_Total'","Win32_PerfFormattedData_PerfOS_Processor",{HOST.HOST}]
Получить загрузку дискового ввода-вывода:

Код: Выделить всё

zbxwmi["-action","-json","-k","Name","-type","n,n,n,n,n","-fields","DiskWritesPersec,DiskWriteBytesPersec,DiskReadsPersec,DiskReadBytesPersec,CurrentDiskQueueLength","-filter","Name='_Total'","Win32_PerfRawData_PerfDisk_LogicalDisk",{HOST.HOST}]
Получить загрузку памяти:

Код: Выделить всё

zbxwmi["-action","-json","-type","n,n,n","-fields","AvailableBytes,CommitLimit,CommittedBytes","Win32_PerfRawData_PerfOS_Memory",{HOST.HOST}]
Использование в Zabbix
Создать шаблон
Если ваш файл учетных данных находится не в /etc/zabbix/wmi.pw,
то установите macro {$WMI_AUTHFILE}=/path/to/wmi.pw
Создайте правило обнаружения с внешним скриптом проверки
zbxwmi["-action","discover","-k","DeviceID","-filter","MediaType=12","-cred","{$WMI_AUTHFILE}","Win32_LogicalDisk",{HOST.HOST}]
Создание прототипов элементов обнаружения
Создайте основной элемент для получения нескольких значений типаField[{#WMI.NAME}]
Создавайте зависимые элементы с предварительной обработкой JSON, например, Field2[{#WMI.NAME}]и адресом JSON.$[0].Field2
Создать прототип графика
При желании создать триггер
Назначить шаблон хостам MS Windows
Получения статистики с zbxwmi
Получения статистики с zbxwmi
Макросы
{$WMI_AUTHFILE} /etc/zabbix/wmi.pw


Группы элементов данных

Место хранения
WMI


Элементы данных
Получения статистики с zbxwmi - Элементы данных
Получения статистики с zbxwmi - Элементы данных
Дисковый ввод-вывод zbxwmi["-action","json","-fields","DiskWritesPersec,DiskWriteBytesPersec,DiskReadsPersec,DiskReadBytesPersec","-filter","Name='_Total'","Win32_PerfRawData_PerfDisk_LogicalDisk","{$WMI_AUTHFILE}",{HOST.HOST}] 5m 3600 Внешняя проверка Место хранения Активировано

Процессоры zbxwmi["-action","json","-fields","PercentProcessorTime","-filter","Name<>'_Total'","Win32_PerfFormattedData_PerfOS_Processor","{$WMI_AUTHFILE}",{HOST.HOST}] 5m 3600 Внешняя проверка WMI Активировано

Процессоры: CPU #1 cpu1 90d 365d Зависимый элемент данных WMI Активировано

Процессоры: CPU #2 cpu2 90d 365d Зависимый элемент данных WMI Активировано

Процессоры: CPU #3 cpu3 90d 365d Зависимый элемент данных WMI Активировано

Процессоры: CPU #4 cpu4 90d 365d Зависимый элемент данных WMI Активировано

Процессоры: CPU #5 cpu5 90d 365d Зависимый элемент данных WMI Активировано

Процессоры: CPU #6 cpu6 90d 365d Зависимый элемент данных WMI Активировано

Процессоры: CPU #7 cpu7 90d 365d Зависимый элемент данных WMI Активировано

Процессоры: CPU #8 cpu8 90d 365d Зависимый элемент данных WMI Активировано

Дисковый ввод-вывод: Чтение / сек DiskReadsPersec 90d 365d Зависимый элемент данных Место хранения Активировано

Дисковый ввод-вывод: Записи / сек DiskWritesPersec 90d 365d Зависимый элемент данных Место хранения Активировано


Графики
Получения статистики с zbxwmi - Графики
Получения статистики с zbxwmi - Графики
Дисковый ввод-вывод 900 200 Нормальный
Процессоры 500 200 Нормальный


Правила обнаружения
Получения статистики с zbxwmi - Правила обнаружения
Получения статистики с zbxwmi - Правила обнаружения
Найти диск Прототипы элементов данных 4 Прототипы триггеров 1 Прототипы графиков 1 Прототипы узлов сети zbxwmi["-action","discover","-k","DeviceID","-fields","VolumeName","-filter","MediaType=12","Win32_LogicalDisk","{$WMI_AUTHFILE}",{HOST.HOST}] 1h Внешняя проверка Активировано


Мои Преобразования
количество слов: 1517
32pac
Гость
Сообщения: 1
Стаж: 8 месяцев

OS Windows WMI / Получения статистики с zbxwmi

Сообщение 32pac »

Добрый день. Шаблон импортировал, Zabbix 6.4, при запросе:

Код: Выделить всё

zbxwmi["-action","json","-fields","PercentProcessorTime","-filter","Name<>'_Total'","Win32_PerfFormattedData_PerfOS_Processor","{$WMI_AUTHFILE}",{HOST.HOST}]
Возвращает:

Код: Выделить всё

zbxwmi: error: unrecognized arguments: win19.test.local
В hosts добавил все вариации win19 win19.test.local

Если из консоли:

Код: Выделить всё

# ./zbxwmi ["-action","json","-fields","PercentProcessorTime","-filter","Name<>'_Total'","Win32_PerfFormattedData_PerfOS_Processor","/etc/zabbix/wmi.pw",win19.test.local]
то:

Код: Выделить всё

zbxwmi: error: the following arguments are required: target
Подскажите пожалуйста, в какую сторону "копать"? Спасибо!

Вопрос снят. Zabbix server должен быть на Win.
количество слов: 61
Ответить Вложения 5 Пред. темаСлед. тема

Вернуться в «Windows, Server»