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

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

Разрешается использовать любые скриптовые языки, например, 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()

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

Тестреакции

При срабатывании директивы в папке /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()