СКАЧАТЬ Шаблон для получения статистики с 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)
[-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()
и установите разрешения:
Код: Выделить всё
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}]
Создать шаблон
Если ваш файл учетных данных находится не в /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
Макросы
{$WMI_AUTHFILE} /etc/zabbix/wmi.pw
Группы элементов данных
Место хранения
WMI
Элементы данных Дисковый ввод-вывод 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 Зависимый элемент данных Место хранения Активировано
Графики Дисковый ввод-вывод 900 200 Нормальный
Процессоры 500 200 Нормальный
Правила обнаружения Найти диск Прототипы элементов данных 4 Прототипы триггеров 1 Прототипы графиков 1 Прототипы узлов сети zbxwmi["-action","discover","-k","DeviceID","-fields","VolumeName","-filter","MediaType=12","Win32_LogicalDisk","{$WMI_AUTHFILE}",{HOST.HOST}] 1h Внешняя проверка Активировано
Мои Преобразования