Перейти к основному содержимому
Версия: 4.5.X

Работа с реакциями

Модуль реакции позволяет писать обработчики срабатываний директивы корреляции для автоматической реакции на инцидент.

Разрешается использовать любые скриптовые языки, например, Bash, Python, Perl, Lua, но потребуется установка интерпретатора языка в ОС на узле с komrad-reactor.

По умолчанию скрипты располагаются в папке /opt/echelon/komrad/komrad-reactor/scripts. Изменить данную папку возможно в файле конфигурации komrad-reactor. Также в конфигурационном файле можно управлять доступными интерпретаторами скриптов.

подсказка

Проверяйте права на папку со скриптами, пользователь komrad-reactor должен иметь права не только на папку, но и на запускаемый скрипт

Логирование исполнения скриптов осуществляется в файлы в папке /var/log/echelon/komrad/komrad-reactor/, путь можно изменять в файле конфигурации. Имена файлов с логами запуска соответствуют имени файла скрипта с суффиксами .stderr для ошибок и .stdout для вывода консоли скрипта.

Пример скрипта реакции на инцидент

Создайте скрипт реакции:

nano /opt/echelon/komrad/komrad-reactor/scripts/react-incident.py
chown -R komrad-reactor:komrad /opt/echelon/komrad/komrad-reactor
chmod u+x /opt/echelon/komrad/komrad-reactor/scripts/react-incident.py

Текст скрипта:

import json
import sys


def load_komrad_reactor_vars():
all_vars = {}

for arg in sys.argv[1:]:
data = json.loads(arg)
for k, v in data.items():
all_vars[k] = v
return all_vars


def react_incident(all_vars):
if all_vars.get('vars.Debug', '') != '':
# вывести все переменные для отладки скрипта
# если в инциденте есть не пустая переменная Debug.
# Вывод производится в файл
# /var/log/echelon/komrad/komrad-reactor/react.py.stdout
print(all_vars)
foo = all_vars.get('vars.Foo', '')
bar = all_vars.get('vars.Bar', '')
tenant_id = all_vars.get('vars.TID', '')
if len(tenant_id) == 0:
return # нет реакции при пустой переменной
with open("reaction-py.txt", "a") as f:
f.write('tenant_id: [%s]: new incident on host=%s port=%s\n' % (tenant_id, foo, bar))


def react():
data = load_komrad_reactor_vars()
react_incident(data)


if __name__ == '__main__':
react()

Выберите скрипт реакции в дополнительных настройках директивы.

1

При срабатывании директивы в папке /opt/echelon/komrad/komrad-reactor/scripts/ появится новый файл reaction-py.txt примерно с таким текстом:

tenant_id: [75]: new incident on host=10.0.4.112 port=49000
tenant_id: [75]: new incident on host=10.0.4.112 port=49000

Реакция на инциденты и интеграция с внешними системами

Приведённый выше скрипт можно модифицировать для интеграции с внешними системами. Для этого достаточно изменять текст функции react_incident.

Реакция на инцидент в виде HTTP POST-запроса

Реакцией может быть отправка HTTP-запроса. Например, можно отправлять запрос на HTTP-коллектор KOMRAD с использованием TLS на самоподписных сертификатах:

import os
import requests

def react_incident2(all_vars):
foo = all_vars.get('vars.Foo', '')
bar = all_vars.get('vars.Bar', '')
tenant_id = all_vars.get('vars.TID', '')

url = 'https://http.komrad.lan:49000'
ca_bundle = '/var/lib/echelon/certs/ca.pem'
os.environ["REQUESTS_CA_BUNDLE"] = ca_bundle
os.environ["SSL_CERT_FILE"] = ca_bundle
data = json.dumps({"tenant_id": tenant_id, "bar": bar, foo: "foo"})

try:
response = requests.post(url, data=data, verify=ca_bundle)
except requests.ConnectionError as e:
print(str(e))
except requests.Timeout as e:
print(str(e))
except requests.RequestException as e:
print(str(e))

if response.status_code == 200:
print('Success!')
elif response.status_code == 404:
print('Not Found.')

Реакция на инцидент в виде SNMP Trap

Из скрипта можно запускать программу snmptrap для отправки оповещений SNMP Trap:

import subprocess

def react_incident(all_vars):
foo = all_vars.get('vars.Foo', '')
bar = all_vars.get('vars.Bar', '')
tenant_id = all_vars.get('vars.TID', '')

cmd_str = 'snmptrap -c public -v 2c "" %s 1.3.6.1.2.1.43.18.2.0.1' % foo
subprocess.run(cmd_str, shell=True)

Скрипт reaction-py.txt можно дорабатывать, добавлять логику отправки HTTP-запросов, SNMP trap, отправки сообщений по другим протоколам.

Реакция на инцидент в виде Syslog CEF

import pysyslogclient
from cefevent import CEFEvent


def build_cef_message(host, port, tenant_id):
c = CEFEvent()
c.set_field('name', 'Some Event')
c.set_field('deviceVendor', 'Some Corp')
c.set_field('deviceProduct', 'cefevent')
c.set_field('dvchost', 'some.lan')
message = "tenant_id is" + str(tenant_id)
c.set_field('message', message)
c.set_field('sourceAddress', host)
c.set_field('sourcePort', port)
return c.build_cef()


def react_incident(all_vars):
remote_syslog_host = 'localhost'
remote_syslog_port = '49000'

client = pysyslogclient.SyslogClientRFC5424(remote_syslog_host, remote_syslog_port, proto='tcp')
msg = build_cef_message(all_vars.get('vars.Foo', ''), all_vars.get('vars.Bar', ''), all_vars.get('vars.TID', ''))

client.log(message=msg, program="")

client.close()