вторник, 30 августа 2016 г.

Splunk. Использование REST API

Приветствую, уважаемый читатель!


До сих пор мы рассматривали Splunk исключительно как средство сбора и анализа событий. Иногда возможны ситуации, когда нам необходимо получить события, которые уже собрал и проиндексировал Splunk, т.е. сам Splunk выступит источником событий. Сегодня я расскажу, как использовать Splunk в этом качестве :)




Итак, для решения поставленной задачи будем использовать Splunk rest API. Алгоритм действий следующий:
  1. Получить сессионный ключ для запросов к rest API.
  2. Создать задание на выполнение запроса и получить его ID.
  3. Получить статус выполнения запроса.
  4. Получить результаты запроса в удобном формате.

Начнем по порядку. 

1. Получить сессионный ключ для запросов к rest API.

Сессионный ключ будет использоваться во время запросов к Splunk rest API, в качестве HTTP-заголовка Authorization. Для его получения необходимо отправить запрос на https://<Splunk IP>:8089/services/auth/login и в теле запроса указать учётные данные для авторизации. По умолчанию – admin:changeme.

Сессионный ключ меняется после каждой перезагрузки Splunk, будьте внимательны.

Важно: Если запрос на получение сессионного ключа будет не с localhost, а с другого IP-адреса, то необходимо это разрешить в настройках Splunk.  

Открываем server.conf и дописываем строки ниже (обычно живет тут - /opt/splunk/etc/system/local/server.conf)

[general]
allowRemoteLogin = always

После этого перезагружаем Splunk. Код получения сессионного ключа ниже:

Python

import urllib
import urllib2
import json

auth_url = 'https://localhost:8089/services/auth/login?output_mode=json'
username = 'admin'
password = ' changeme '

#1: Session key 
data = urllib.urlencode({'username':username, 'password':password})
req = urllib2.Request(auth_url, data)
response = urllib2.urlopen(req)
auth_json = json.loads(response.read())
sessionkey = auth_json["sessionKey"]


curl

curl -k https://localhost:8089/services/auth/login -d username=admin -d password=changeme




2. Создать задание на выполнение запроса и получить его ID

У всех запросов в Splunk есть свой ID, по которому можно вернуть отобранные события. Посмотреть ID запросов можно с помощью оператора history.

| history | table _time,search,event_count,sid



Колонка sid как раз и содержит ID запросов. Для получения событий ранее выполненного запроса, вы можете использовать оператор loadjob.

| loadjob 1472542476.1726

Но вернёмся к нашей задаче. Для создания запроса, нам, естественно, необходим его текст и сессионный ключ (sessionkey), полученный на прошлом этапе. Запрос на создание поиска необходимо отправить на https://<Splunk IP>:8089/services/search/jobs/. Код представлен ниже.

Python

#2: Run search 

search_url = "https://localhost:8089/services/search/jobs/?output_mode=json"
search_query = "search sourcetype = fail2ban earliest=-4h latest=now() | top 5 srcip"
textS = urllib.urlencode({'search': search_query})

headers = {'Authorization' : 'Splunk %s' % sessionkey}
req = urllib2.Request(search_url, textS, headers)
response = urllib2.urlopen(req)
sid_json = json.loads(response.read())
sid_search = sid_json["sid"]

print "2. sid search: %s " % sid_search


Немного поясню скрипт.

Как вы уже, наверное,  поняли необходимо в явном виде указать временные границы для поиска событий, иначе ваш запрос будет выполняться с условием “All Time”. 
Для задания ограничений можно использовать 2 оператора earliest(начальная временная отсечка событий) и latest(конечная временная отсечка событий). Объяснять лучше на примерах:

earliest=-1d  latest=now()  -  отобрать события проиндексированные за прошедший день
earliest=-1h  latest=now()  -  отобрать события проиндексированные за прошедший час
earliest=-4h  latest=-2h  -  отобрать события проиндексированные начиная с 4-х часов по 2 часа назад

Доступные модификаторы времени:
  • second: s, sec, secs, second, seconds
  • minute: m, min, minute, minutes
  • hour: h, hr, hrs, hour, hours
  • day: d, day, days
  • week: w, week, weeks
  • month: mon, month, months
  • quarter: q, qtr, qtrs, quarter, quarters
  • year: y, yr, yrs, year, years


Подробнее можно почитать тут - http://docs.splunk.com/Documentation/Splunk/6.4.2/SearchReference/SearchTimeModifiers


3. Получить статус выполнения запроса.

Запрос на поиск событий, в зависимости от его сложности и количества собираемых событий, может выполняться длительное время. Сложные запросы могут выполняться секунд по 30. Splunk позволяет получить статус запроса по его ID. Код представлен ниже.

headers = {'Authorization' : 'Splunk %s' % sessionkey}
search_status = 'https://localhost:8089/services/search/jobs/%s/?output_mode=json' % sid_search
notdone = 1
while notdone == 1:
            req = urllib2.Request(search_status, None,headers)
            response = urllib2.urlopen(req)
            resp_json = json.loads(response.read())
            status_search = resp_json["entry"][0]["content"]["isDone"]
            if (status_search == True):
                        notdone = 2

print "3. search status: %s " % status_search

Как только в ответном json-документе параметр «isDone» будет установлен в «True», запрос считается отработанным и по его ID можно получить результаты.


4. Получить результаты запроса в удобном формате.

Итак, заключительная часть, а именно получение результатов запроса. Тут всё просто, как только статус выполнения запроса стал «True», результаты можно получить по адресу https://<Splunk IP>:8089/services/search/jobs/%s/results.

С помощью параметра output_mode, можно указать желаемый формат результата (json, xml, csv). Код получения результатов ниже.    


#4: Search result
headers = {'Authorization' : 'Splunk %s' % sessionkey}
search_result = 'https://localhost:8089/services/search/jobs/%s/results?output_mode=json' % sid_search
req = urllib2.Request(search_result,None)
response = urllib2.urlopen(req)

resp_json = json.loads(response.read())
content = resp_json["results"]
print "4.","srcip","count","percent"
for res in content:
            print res["srcip"],res["count"],res["percent"]


Если все 4 части отработали успешно, то вы увидите события (скрин ниже).



Собственно, полный текст скрипта:

#!/usr/bin/env python

import urllib
import urllib2
import json

auth_url = 'https://localhost:8089/services/auth/login?output_mode=json'
search_url = "https://localhost:8089/services/search/jobs/?output_mode=json"
username = 'admin'
password = 'changeme'

#1: Session key 
data = urllib.urlencode({'username':username, 'password':password})
req = urllib2.Request(auth_url, data)
response = urllib2.urlopen(req)
auth_json = json.loads(response.read())
sessionkey = auth_json["sessionKey"]

print "1. sessionkey: %s" % sessionkey

#2: Run search 

search_query = "search sourcetype = fail2ban earliest=-4h latest=now() | top 5 srcip"
textS = urllib.urlencode({'search': search_query})

headers = {'Authorization' : 'Splunk %s' % sessionkey}
req = urllib2.Request(search_url, textS, headers)
response = urllib2.urlopen(req)
sid_json = json.loads(response.read())
sid_search = sid_json["sid"]

print "2. sid search: %s " % sid_search

#3: Status search

headers = {'Authorization' : 'Splunk %s' % sessionkey}
search_status = 'https://localhost:8089/services/search/jobs/%s/?output_mode=json' % sid_search
notdone = 1
while notdone == 1:
            req = urllib2.Request(search_status, None,headers)
            response = urllib2.urlopen(req)
            resp_json = json.loads(response.read())
            status_search = resp_json["entry"][0]["content"]["isDone"]
            if (status_search == True):
                        notdone = 2

print "3. search status: %s " % status_search

#4: Search result
headers = {'Authorization' : 'Splunk %s' % sessionkey}
search_result = 'https://localhost:8089/services/search/jobs/%s/results?output_mode=json' % sid_search
req = urllib2.Request(search_result,None)
response = urllib2.urlopen(req)

resp_json = json.loads(response.read())
content = resp_json["results"]
print "4.","srcip","count","percent"
for res in content:
            print res["srcip"],res["count"],res["percent"]



Всем удачного использования)


Комментариев нет:

Отправить комментарий