본문 바로가기
Bigdata/Splunk

Splunk - CustomCommand 개발 이해

by 올엠 2024. 8. 12.
반응형

Splunk에는 Custom Command라는 사용자가 직접 명령어를 개발하는 것이 가능하다.

Splunk는 다른 데이터 분석 플랫폼보다 다양한 통계나 데이터 가공이 SPL를 통해서 진행할 수 있는데,  Custom Command 를 이를 더욱 풍푸하게 해주는 기능이라고 할 수 있다.

예를 들어, 외부의 플랫폼의 데이터를 가져와서 Splunk에서 추가 통계 자료로 만들거나, Splunk 내 데이터와 함께 이용하는 것을 Custom Command를 통해서 가능하다고 할 수 있다.

1. Splunk에서 데이터 조회 | Custom Command

2. Custom Command로 외부 데이터 조회 | Splunk SPL

그럼 Custom Command를 어떻게 만들수 있는지 간단히 이해해보도록 하자.

1. 앱 생성

Splunk Custom Comnand를 만들고자 한다면, 앱의 뼈대를 이루는 파일을 만들기 위해 가장 먼저 Splunk에서 App을 생성해야 한다. 기본 화면에서 앱 우측에 톱니바퀴를 누르거나, 앱 화면이라면, 앱 을 확장해 앱 관리를 통해서 앱 관리 화면으로 들어가도록 하자.



이후 앱 만들기를 통해서 기본이 되는 boreborn 템플릿의 앱을 만들 수 있다.

여기에서, 명령어로만 보통 사용되기 때문에 앱 표시를 하지 않도록 하는 것을 추천하면, 템플릿은 barebones를 선택하자.

이렇게 선택하면, 기본 설치 경로 기준으로 /opt/splunk/etc/apps에 우리가 지정한 vtsearch라는 앱 폴더인 vtsearch가 생성된다.

이렇게 생성된 vtsearch의 폴더에 들어가 가장 기본이 되는 Custom Command의 환경 구성을 진행하도록 하자.
 

2. 커멘드 환경 구성

이제 실제 명령어와 명령어를 실행할 Python 파일을 지정할 차례이다.
 
vtsearch의 디렉토리 구조는 다음과 같다.
bin 디렉토리: 실행을 위한 Python 파일이 위치
default 디렉토리: 커멘드 환경 구성 위치, Splunk에서 입력할 명령어 지정과 Python 실행 파일의 위치를 지정하는 commands.conf가 위치하는 곳이다. searchbnf.conf를 구성하면 Custom Command에 설명을 추가할 수 있다.
그외 경로는 크게 중요한 부분이 없으므로 위 2가지 경로를 중심적으로 설명하도록 하겠다.
 
bin은 실제 Python 실행 파일이 위치하면 된다.
 
따라서 default 경로에 들어가서, 환경 설정 파일인 commands.conf를 구성하도록 하자. 필자는 vtsearch라는 명령어를 bin/vtsearch.py 에 위치하도록 하기위해 아래와 같이 작성하였다.
[vtsearch]
filename = vtsearch.py
python.version = python3
chunked = true

[vtsearch]: 중괄호는 Splunk에서 호출할 명령어라고 이해하면 된다. 만약에 test라고 입력하면, Splunk SPL에서 test로 호출할 수 있다.

filenname: 는 bin 디렉토리에 호출할 Python 파일 이름을 지정한다.
python.version: Splunk는 Python2와 Python3을 사용할 수 있는데, Python3를 사용하도록 지정할 수 있다.
chunked: chunked를 이해하기 위해서는, 현재 Custom Command는 Splunk Command 생성하는 버전기준으로 v2이라는 점을 알아야 한다.
v1은 Splunk 6.x 이전 버전에서 사용하던 방식으로 현재는 개선된 v2로 개발이 가능하나 호환성을 위해 v1으로 작성한 Custom Command도 실행이 가능하다.
Custom Command의 환경을 구성할 때  v1인지 v2인지를 알려주는 값을 설정할 수 있는데, 바로 chunked 이다. chunked를 true로 주면 v2로 인식된다.
 
commands.conf 파일 까지 생성하였다면, 이제 실제 실행을 위한 bin 디렉토리에 Python 파일를 생성할 차례이다.
 

3. 커맨드 타입 선택

Splunk는 일반적인 Python 파일을 실행하는 것이 아니 Splunk에서 이용할 수 있도록 만들고자 하는 명령마다 커맨트 타입을 지원해 주고 있다.
 
따라서 Python 파일을 만들기 전에 자신이 Custom Command를 만들기 위해 필요한 Splunk에서 제공하는 Command 타입중에 선택을 해야 한다.
  • GeneratingCommand
        이벤트 생성에 사용, SPL 파이프 라인에서 가장 먼저 사용되어야 함
        inputlookup, inputcsv....
  • StreamingCommand
        이벤트들을 1대1로 변환하는 용도로 사용
        eval, fields, where....
  • ReportingCommand
        데이터 테이블 용도로 사용
        chart, timechart, stats....
  • EventingCommand
        데이터 정렬이나 중복 제거등의 용도로 사용
        sort, dedup....
필자는 VirusTotal을 조회하고 이벤트 생성하는 명령어이므로 Generationg으로 개발할 예정이 이렇게 사용하고자 하는 Command 타입을 정했다면, bin 디렉토리에 vtsearch.py를 생성하고, 관련 라이브러리를 해당 bin 디렉토리에 함께 생성하도록 하자.
cd \opt\splunk\etc\app\vtsearch\bin
pip3 install -t . splunk-sdk virustotal3

#윈도우의 경우
pip3 install -t . splunk-sdk virustotal3 --no-user
되도록이면 각 라이브러리는 Custom Command 별로 가지고 있는 것이 유용하다.
그리고 아래와 같이 vtsearch.py를 생성하였다.
""" A custom search command that returns the results of a VirusTotal search """

import sys
import time
import json

from splunklib.searchcommands import dispatch, GeneratingCommand, Option, Configuration

import virustotal3.core


@Configuration()
class VirusTotalSearchCommand(GeneratingCommand):
    """A custom search command that returns the results of a VirusTotal search"""

    q = Option(require=True)

    def generate(self):
        api_key = "api-key-here"

        virus_total = virustotal3.core.IP(api_key=api_key)

        try:
            result = virus_total.info_ip(self.q)

            yield self.get_event(result["data"])

        except Exception as error:  # pylint: disable=broad-except
            self.get_event(
                {
                    "error": "No result from virustotal with error: "
                    + str(error)
                    + " for query: "
                    + self.q
                    + ""
                }
            )

    def get_event(self, result):
        """Return an event"""
        event = result
        event["_time"] = time.time()
        event["_raw"] = json.dumps(result)
        return event


dispatch(
    VirusTotalSearchCommand, sys.argv, sys.stdin, sys.stdout, __name__
)  # pylint: disable=abstract-class-instantiated
위에 보면, getEvent와 generate 함수가 사용된 것을 알 수 있는데, 이는 GenerationCommand에서 제공하는 내부 함수을 재정의한 것이라고 할 수 있다. getEvent를 호출하면, 이 함수는 Splunk 화면에 결과를 출력해주게 된다. 그리고 generate는 이벤트 생성을 시작하는 함수이다.
그리고 Option은 Custom Command에서 추가적인 파라미터를 받을 수 있는데, 필수 인지 아닌지등을 선택할 수 있다.
필자는 q라는 파라미터를 Virustotal에 검색하고자 하는 IP 값을 추가하기 위해서 필수 파라미터로 지정하였다.
Option 관련해서는 아래 글을 참고하면 좋을 것 같다.
처리 흐름을 이해해 보면,
 
1. Splunk에서 vtsearch를 입력하면,  dispacth를 통해 VesearchCommand 함수를 실행하고
 
2. 가장 처럼 generate를 실행하게 된다. 이후 결과가 있다면, yield를 통해서 getEvent를 생성하는 구조라고 생각하면, 된다. 
 
Splunk Custom Command에서는 기본 generate에 yield를 사용할 것을 추천하는데, 이유는 여러번의 결과가 생성되는 경우 해당 이벤트들을 yield를 통해서 처리할 수 있기 때문이다.
 
마지막으로, 앱 권한을 전역 으로 설정하면, 끝이다.

이렇게 작성을 하였다면, Custom Command 적용을 위해 Splunk를 재시작하면 아래와 같이 우리가 만든 Custom Command를 사용할 수 있게 된다.


 
 
반응형