root@syslogserver:~# pip install elastalert2
root@syslogserver:~# cd /opt
root@syslogserver:~# git clone https://github.com/jertel/elastalert2.git
root@syslogserver:~# cd elastalert2
root@syslogserver:~/elastalert2# pip install "setuptools>=11.3"
root@syslogserver:~/elastalert2# python3 setup.py install
root@syslogserver:~/elastalert2# cd /opt
# elastalert 설치하신 후 "elastalert " 이라고 명령어를 치면 에러 메시지가 보입니다.
# 이때 경로 확인이 가능해요.
root@syslogserver:/opt# ln -s /usr/local/lib/python3.10/dist-packages/elastalert/ ./elastalert
root@syslogserver:/opt# ls -al
root@syslogserver:/opt# ls -al
total 8476
drwxr-xr-x 5 root root 4096 1월 15 12:26 .
drwxr-xr-x 20 root root 4096 12월 22 15:41 ..
lrwxrwxrwx 1 root root 51 1월 15 12:26 elastalert -> /usr/local/lib/python3.10/dist-packages/elastalert/
drwxr-xr-x 3 grafana grafana 4096 12월 26 17:27 grafana-plugin
drwxr-xr-x 2 root root 4096 12월 22 15:45 node_modules
drwxr-xr-x 2 1001 1002 4096 12월 21 12:55 snmp_exporter
root@syslogserver:/opt# cd elastalert
root@syslogserver:/opt/elastalert# cat ./config.yaml
# 폴더 명
# 폴더 경로를 설정할 경우, elastalert을 실행할 때 rule 옵션을 별도로 주지 않아도 됨
# 예: elastalert --config /opt/elastalert/config.yaml
rules_folder: /opt/elastalert/rules
# elasticsearch를 쿼리하는 빈도
run_every:
minutes: 1
# 쿼리가 실행되는 시간부터 뒤로 늘어나는 쿼리 창의 크기
buffer_time:
minutes: 15
# elasticsearch host
es_host: 192.168.000.000
# elasticsearch 사용 port
es_port: 9200
# elastalert2가 데이터를 저장할 index
# 굉장히 중요 합니다!!!!
writeback_index: elastalert_status
# 실패한 경고에 대한 재시도 기간
alert_time_limit:
days: 2
root@syslogserver:/opt/elastalert#
# elasticsearch index를 생성하지 않으면 아래처럼 오류 발생
root@syslogserver:/opt/elastalert# elastalert
WARNING:elasticsearch:POST http://192.168.000.000:9200/elastalert_status/_search?size=1000 [status:404 request:0.027s]
ERROR:elastalert:Error finding recent pending alerts: NotFoundError(404, 'index_not_found_exception', 'no such index [elastalert_status]', elastalert_status, index_or_alias) {'query': {'bool': {'must': {'query_string': {'query': '!_exists_:aggregate_id AND alert_sent:false'}}, 'filter': {'range': {'alert_time': {'from': '2024-01-13T03:27:38.609562Z', 'to': '2024-01-15T03:27:38.609590Z'}}}}}, 'sort': {'alert_time': {'order': 'asc'}}}
Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/elastalert/elastalert.py", line 1503, in find_recent_pending_alerts
res = self.writeback_es.search(index=self.writeback_index, body=query, size=1000)
File "/usr/local/lib/python3.10/dist-packages/elasticsearch/client/utils.py", line 152, in _wrapped
return func(*args, params=params, headers=headers, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/elastalert/__init__.py", line 147, in search
results = self.transport.perform_request(
File "/usr/local/lib/python3.10/dist-packages/elasticsearch/transport.py", line 392, in perform_request
raise e
File "/usr/local/lib/python3.10/dist-packages/elasticsearch/transport.py", line 358, in perform_request
status, headers_response, data = connection.perform_request(
File "/usr/local/lib/python3.10/dist-packages/elasticsearch/connection/http_requests.py", line 199, in perform_request
self._raise_error(response.status_code, raw_data)
File "/usr/local/lib/python3.10/dist-packages/elasticsearch/connection/base.py", line 315, in _raise_error
raise HTTP_EXCEPTIONS.get(status_code, TransportError)(
elasticsearch.exceptions.NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index [elastalert_status]', elastalert_status, index_or_alias)
^C
root@syslogserver:/opt/elastalert#
# elasticsearch index 생성
root@syslogserver:/opt/elastalert# elastalert-create-index
Enter Elasticsearch host: 192.168.000.000
Enter Elasticsearch port: 9200
Use SSL? t/f: f
Enter optional basic-auth username (or leave blank):
Enter optional basic-auth password (or leave blank):
Enter optional Elasticsearch URL prefix (prepends a string to the URL of every request):
New index name? (Default elastalert_status)
Name of existing index to copy? (Default None)
Reading Elastic 8 index mappings:
Reading index mapping 'es_mappings/8/silence.json'
Reading index mapping 'es_mappings/8/elastalert_status.json'
Reading index mapping 'es_mappings/8/elastalert.json'
Reading index mapping 'es_mappings/8/past_elastalert.json'
Reading index mapping 'es_mappings/8/elastalert_error.json'
Deleting index elastalert_status_status.
Deleting index elastalert_status_error.
New index elastalert_status created
Done!
root@syslogserver:~#
# elastalert 명령어를 실행할 경우 기본적으로 현재의 경로에서 config.yaml을 찾게 됩니다.
# 그래서 아래와 같은 오류 메시지를 볼 수 있습니다.
root@syslogserver:~# elastalert
Traceback (most recent call last):
File "/usr/local/bin/elastalert", line 33, in <module>
sys.exit(load_entry_point('elastalert2==2.15.0', 'console_scripts', 'elastalert')())
File "/usr/local/lib/python3.10/dist-packages/elastalert/elastalert.py", line 1900, in main
client = ElastAlerter(args)
File "/usr/local/lib/python3.10/dist-packages/elastalert/elastalert.py", line 127, in __init__
self.conf = load_conf(self.args)
File "/usr/local/lib/python3.10/dist-packages/elastalert/config.py", line 49, in load_conf
conf = read_yaml(filename)
File "/usr/local/lib/python3.10/dist-packages/elastalert/yaml.py", line 6, in read_yaml
with open(path) as f:
FileNotFoundError: [Errno 2] No such file or directory: 'config.yaml'
root@syslogserver:~#
# 단발성으로 실행할 경우 아래의 명령어를 통해서 실행
root@syslogserver:~# python3 -m elastalert.elastalert --verbose --config /opt/elastalert/configy.yaml
# systemctl에 등록하여 실행할 경우
root@syslogserver:~# cd /etc/systemd/system
root@syslogserver:/etc/systemd/system# cat elastalert.service
[Unit]
Description=Severe_logalerts
After=elasticsearch.service
[Service]
Type=simple
WorkingDirectory=/opt/elastalert
ExecStart=/usr/local/bin/elastalert --verbose --config /opt/elastalert/config.yaml
[Install]
WantedBy=multi-user.target
root@syslogserver:/etc/systemd/system# systemctl daemon-reload
root@syslogserver:/etc/systemd/system# systemctl restart elastalert.service
#name
name: ap_login_success
# 로그는 탐지하는 타입
type: any
# logstash에서 설정한 log의 index 값
index: "logstash-ap*"
# 필터 grok 패턴 지정한 필드의 값에 같은 값이 들어올 경우
filter:
- query_string:
query: access_result:"successfully"
# document type
doc_type: _doc
# 알람 전송 매체 지정
alert:
- "slack"
# 알람 전송 옵션
slack:
# 슬랙 웹훅 주소
slack_webhook_url: "https://hooks.slack.com/services/---------------------------------------"
# 슬랙 채널에 메시지 전달할 이름
slack_username_override: "ElastAlert-Bot"
# 슬랙 메시지를 보낼 채널
slack_channel_override: "#security_alert"
# 슬랙 메시지에 타이틀 지정
# 지정하지 않을 경우 rule의 절대 경로 명이 찍힘: /opt/elastalert/ruls/ap_login_fail.yaml
slack_title: AP_LOGIN_SUCCESS
# 슬랙 메시지 색
slack_msg_color: "good"
# 슬랙에 전송할 메시지
# 슬랙에 전송할 메시지 중 배열 입력시 맨 아랫줄의 순서에 따라 숫자 입력
# 숫자 위치는 바뀌어도 됨
alert_text: "AP_LOGIN_SUCESS: {0} / 접속자:{1} / 접속자IP: {2}"
# 슬랙에 전송할 메시지 타입
alert_text_type: "alert_text_only"
# 슬랙에 전송할 메시지 중 탐지된 메시지에 대한 배열 입력
alert_text_args: ["ip_or_host", "user", "source_ip"]
룰 입력 후 저장을 누르면 아래와 같은 화면을 볼 수 있습니다.
웹페이지 상에서 룰을 생성할 경우, 서버에서도 마찬가지로 자동으로 생성됩니다.
[root@tmplogsvr rules]# pwd
/opt/elastalert/rules
[root@tmplogsvr rules]# ls -al
합계 16
drwxr-xr-x. 2 root root 4096 3월 16 18:08 .
drwxr-xr-x. 13 root root 4096 3월 16 18:09 ..
-rw-r--r--. 1 root root 574 3월 16 18:17 ap_login_fail.yaml
-rw-r--r--. 1 root root 1383 3월 16 18:17 ap_login_success.yaml
[root@tmplogsvr rules]#
[root@tmplogsvr rules]# cat ./ap_login_success.yaml
#name
name: ap_login_success
# 로그는 탐지하는 타입
type: any
# logstash에서 설정한 log의 index 값
index: "logstash-ap*"
# 필터 grok 패턴 지정한 필드의 값에 같은 값이 들어올 경우
filter:
- query_string:
query: access_result:"successfully"
doc_type: _doc
# 알람 전송 매체 지정
alert:
- "slack"
# 알람 전송 옵션
slack:
# 슬랙 웹훅 주소
slack_webhook_url: "https://hooks.slack.com/services/---------------------------------"
# 슬랙 채널에 메시지 전달할 이름
slack_username_override: "ElastAlert-Bot"
# 슬랙 메시지를 보낼 채널
slack_channel_override: "#security_alert"
# 슬랙 메시지에 타이틀 지정
# 지정하지 않을 경우 rule의 절대 경로 명이 찍힘: /opt/elastalert/ruls/ap_login_fail.yaml
slack_title: AP_LOGIN_SUCCESS
# 슬랙 메시지 색
slack_msg_color: "good"
# 슬랙에 전송할 메시지
# 슬랙에 전송할 메시지 중 배열 입력시 맨 아랫줄의 순서에 따라 숫자 입력
# 숫자 위치는 바뀌어도 됨
alert_text: "AP_LOGIN_SUCESS: {0} / 접속자:{1} / 접속자IP: {2}"
# 슬랙에 전송할 메시지 타입
alert_text_type: "alert_text_only"
# 슬랙에 전송할 메시지 중 탐지된 메시지에 대한 배열 입력
alert_text_args: ["ip_or_host", "user", "source_ip"]
[root@tmplogsvr rules]#
kibana 웹페이지에서 elastalert을 사용하기 위해서는 실행방법이 기존과는 다릅니다.
bitsensor 버전의 elastalert은 기본 경로가 /opt/elastalert 입니다.
해당 위치에서 npm의 설정들을 진행하였기에 아래 화면을 따르면 됩니다.
[root@tmplogsvr elastalert]# pwd
/opt/elastalert
방법 1. 프로세스가 끊기지 않고 지속적으로 로그를 확인하고 싶을 때
[root@tmplogsvr elastalert]# npm start <- 이렇게 실행할 경우 프로세스가 끊기지 않고 계속적으로 로그가 보일 것입니다.
> @bitsensor/elastalert@3.0.0-beta.0 start /opt/elastalert
> sh ./scripts/start.sh
02:12:53.493Z INFO elastalert-server: Config: No config.dev.json file was found in /opt/elastalert/config/config.dev.json.
02:12:53.494Z INFO elastalert-server: Config: Proceeding to look for normal config file.
02:12:53.494Z INFO elastalert-server: Config: A config file was found in /opt/elastalert/config/config.json. Using that config.
02:12:53.500Z INFO elastalert-server: Router: Listening for GET request on /.
02:12:53.500Z INFO elastalert-server: Router: Listening for GET request on /status.
02:12:53.500Z INFO elastalert-server: Router: Listening for GET request on /status/control/:action.
02:12:53.500Z INFO elastalert-server: Router: Listening for GET request on /status/errors.
02:12:53.500Z INFO elastalert-server: Router: Listening for GET request on /rules.
02:12:53.501Z INFO elastalert-server: Router: Listening for GET request on /rules/:id.
02:12:53.501Z INFO elastalert-server: Router: Listening for POST request on /rules/:id.
02:12:53.501Z INFO elastalert-server: Router: Listening for DELETE request on /rules/:id.
02:12:53.501Z INFO elastalert-server: Router: Listening for GET request on /templates.
02:12:53.501Z INFO elastalert-server: Router: Listening for GET request on /templates/:id.
02:12:53.501Z INFO elastalert-server: Router: Listening for POST request on /templates/:id.
02:12:53.501Z INFO elastalert-server: Router: Listening for DELETE request on /templates/:id.
02:12:53.501Z INFO elastalert-server: Router: Listening for POST request on /test.
02:12:53.501Z INFO elastalert-server: Router: Listening for GET request on /config.
02:12:53.501Z INFO elastalert-server: Router: Listening for POST request on /config.
02:12:53.501Z INFO elastalert-server: Router: Listening for POST request on /download.
02:12:53.502Z INFO elastalert-server: Router: Listening for GET request on /metadata/:type.
02:12:53.502Z INFO elastalert-server: Router: Listening for GET request on /mapping/:index.
02:12:53.502Z INFO elastalert-server: Router: Listening for POST request on /search/:index.
02:12:53.504Z INFO elastalert-server: ProcessController: Starting ElastAlert
02:12:53.504Z INFO elastalert-server: ProcessController: Creating index
02:12:53.697Z INFO elastalert-server:
ProcessController: Elastic Version: 8.6.2
Reading Elastic 6 index mappings:
Reading index mapping 'es_mappings/6/silence.json'
Reading index mapping 'es_mappings/6/elastalert_status.json'
Reading index mapping 'es_mappings/6/elastalert.json'
Reading index mapping 'es_mappings/6/past_elastalert.json'
Reading index mapping 'es_mappings/6/elastalert_error.json'
Index elastalert_status already exists. Skipping index creation.
02:12:53.697Z INFO elastalert-server: ProcessController: Index create exited with code 0
02:12:53.698Z INFO elastalert-server: ProcessController: Starting elastalert with arguments [none]
02:12:53.701Z INFO elastalert-server: ProcessController: Started Elastalert (PID: 107223)
02:12:53.702Z INFO elastalert-server: Server: Server listening on port 3030
02:12:53.702Z INFO elastalert-server: Server: Websocket listening on port 3333
02:12:53.703Z INFO elastalert-server: Server: Server started
방법2: 실행 후 백그라운드로 실행하기 (터미널을 끊어도 프로세스가 살아 있습니다.)
[root@tmplogsvr elastalert]# npm start &
[1] 107293
[root@tmplogsvr elastalert]#
> @bitsensor/elastalert@3.0.0-beta.0 start /opt/elastalert
> sh ./scripts/start.sh
02:17:42.163Z INFO elastalert-server: Config: No config.dev.json file was found in /opt/elastalert/config/config.dev.json.
02:17:42.164Z INFO elastalert-server: Config: Proceeding to look for normal config file.
02:17:42.164Z INFO elastalert-server: Config: A config file was found in /opt/elastalert/config/config.json. Using that config.
02:17:42.170Z INFO elastalert-server: Router: Listening for GET request on /.
02:17:42.170Z INFO elastalert-server: Router: Listening for GET request on /status.
02:17:42.170Z INFO elastalert-server: Router: Listening for GET request on /status/control/:action.
02:17:42.170Z INFO elastalert-server: Router: Listening for GET request on /status/errors.
02:17:42.170Z INFO elastalert-server: Router: Listening for GET request on /rules.
02:17:42.171Z INFO elastalert-server: Router: Listening for GET request on /rules/:id.
02:17:42.171Z INFO elastalert-server: Router: Listening for POST request on /rules/:id.
02:17:42.172Z INFO elastalert-server: Router: Listening for DELETE request on /rules/:id.
02:17:42.172Z INFO elastalert-server: Router: Listening for GET request on /templates.
02:17:42.172Z INFO elastalert-server: Router: Listening for GET request on /templates/:id.
02:17:42.172Z INFO elastalert-server: Router: Listening for POST request on /templates/:id.
02:17:42.172Z INFO elastalert-server: Router: Listening for DELETE request on /templates/:id.
02:17:42.172Z INFO elastalert-server: Router: Listening for POST request on /test.
02:17:42.172Z INFO elastalert-server: Router: Listening for GET request on /config.
02:17:42.172Z INFO elastalert-server: Router: Listening for POST request on /config.
02:17:42.172Z INFO elastalert-server: Router: Listening for POST request on /download.
02:17:42.172Z INFO elastalert-server: Router: Listening for GET request on /metadata/:type.
02:17:42.172Z INFO elastalert-server: Router: Listening for GET request on /mapping/:index.
02:17:42.172Z INFO elastalert-server: Router: Listening for POST request on /search/:index.
02:17:42.174Z INFO elastalert-server: ProcessController: Starting ElastAlert
02:17:42.174Z INFO elastalert-server: ProcessController: Creating index
02:17:42.366Z INFO elastalert-server:
ProcessController: Elastic Version: 8.6.2
Reading Elastic 6 index mappings:
Reading index mapping 'es_mappings/6/silence.json'
Reading index mapping 'es_mappings/6/elastalert_status.json'
Reading index mapping 'es_mappings/6/elastalert.json'
Reading index mapping 'es_mappings/6/past_elastalert.json'
Reading index mapping 'es_mappings/6/elastalert_error.json'
Index elastalert_status already exists. Skipping index creation.
02:17:42.366Z INFO elastalert-server: ProcessController: Index create exited with code 0
02:17:42.367Z INFO elastalert-server: ProcessController: Starting elastalert with arguments [none]
02:17:42.370Z INFO elastalert-server: ProcessController: Started Elastalert (PID: 107325)
02:17:42.371Z INFO elastalert-server: Server: Server listening on port 3030
02:17:42.371Z INFO elastalert-server: Server: Websocket listening on port 3333
02:17:42.371Z INFO elastalert-server: Server: Server started
[root@tmplogsvr elastalert]#
실행 시킨 터미널 창을 닫은 후 아래와 같이 프로세스를 검색하시면 작동 여부를 알 수 있습니다.
#name
name: ap_login_success
# 로그는 탐지하는 타입
type: any
# logstash에서 설정한 log의 index 값
index: "logstash-ap*"
# 필터 grok 패턴 지정한 필드의 값에 같은 값이 들어올 경우
filter:
- query_string:
query: access_result:"successfully"
# 메시지 타입
doc_type: _doc
# 알람 전송 매체 지정
alert:
- "slack"
# 알람 전송 옵션
slack:
# 슬랙 웹훅 주소
slack_webhook_url: "https://hooks.slack.com/services/--------------------------------------"
# 슬랙 채널에 메시지 전달할 이름
slack_username_override: "ElastAlert-Bot"
# 슬랙 메시지를 보낼 채널
slack_channel_override: "#security_alert"
# 슬랙 메시지에 타이틀 지정
# 지정하지 않을 경우 rule의 절대 경로 명이 찍힘: /opt/elastalert/ruls/ap_login_fail.yaml
slack_title: AP_LOGIN_SUCCESS
# 슬랙 메시지 색
slack_msg_color: "good"
# 슬랙에 전송할 메시지
# 슬랙에 전송할 메시지 중 배열 입력시 맨 아랫줄의 순서에 따라 숫자 입력
# 숫자 위치는 바뀌어도 됨
alert_text: "AP_LOGIN_SUCESS: {0} / 접속자:{1} / 접속자IP: {2}"
# 슬랙에 전송할 메시지 타입
alert_text_type: "alert_text_only"
# 슬랙에 전송할 메시지 중 탐지된 메시지에 대한 배열 입력
alert_text_args: ["ip_or_host", "user", "source_ip"]
# 폴더 명
# 폴더 경로를 설정할 경우, elastalert을 실행할 때 rule 옵션을 별도로 주지 않아도 됨
# 예: elastalert --config /opt/elastalert/config.yaml
rules_folder: /opt/elastalert/rules
# elasticsearch를 쿼리하는 빈도
run_every:
minutes: 1
# 쿼리가 실행되는 시간부터 뒤로 늘어나는 쿼리 창의 크기
buffer_time:
minutes: 15
# elasticsearch host
es_host: 192.168.0.17
# elasticsearch 사용 port
es_port: 9200
# elastalert2가 데이터를 저장할 index
writeback_index: elastalert_status
# 실패한 경고에 대한 재시도 기간
alert_time_limit:
days: 2