Skip to content

Commit 3ed16b3

Browse files
committed
Implement ElastAlert and enhance frontend navigation
1 parent de7947e commit 3ed16b3

File tree

24 files changed

+537
-61
lines changed

24 files changed

+537
-61
lines changed

.env

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ SENTINELKIT_KIBANA_HOSTNAME=kibana.sentinel-kit.local
77
SENTINELKIT_GRAFANA_HOSTNAME=grafana.sentinel-kit.local
88
SENTINELKIT_DATAMONITOR_SERVER_TOKEN=9561ffd1b6de615286b9e52a9d5bc3226970449700c9461bdbe4225730b47b20
99
BACKEND_JWT_PASSPHRASE=f164cfc913d2faf65a1b7bc8ccd4aa8b11b5958bce7c20c8cf159a576f8a75f7
10-
MYSQL_ROOT_PASSWORD=sentinel-kit_r00tp4ssw0rd
11-
MYSQL_EXPORTER_PASSWORD=sentinel-kit_3xp0rt3rp4ssw0rd
12-
MYSQL_USER=sentinel-kit_user
13-
MYSQL_PASSWORD=sentinel-kit_passwd
10+
MYSQL_ROOT_PASSWORD=sentinel-kit_mysql_r00tp4ssw0rd
11+
MYSQL_EXPORTER_PASSWORD=sentinel-kit_mysql_3xp0rt3rp4ssw0rd
12+
MYSQL_USER=sentinel-kit_mysql_user
13+
MYSQL_PASSWORD=sentinel-kit_mysql_passwd
1414
MYSQL_DATABASE=sentinel-kit_db
1515
GF_SECURITY_ADMIN_USER=sentinel-kit_grafana_admin
1616
GF_SECURITY_ADMIN_PASSWORD=sentinel-kit_grafana_password

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
/config/caddy_server/certificates/*
55
/config/yara_ruleset/*
66
/config/sigma_ruleset/*
7+
/config/elastalert_ruleset/*
78
/config/backend/*
89
/data/caddy_logs/*
910
/data/ftp_data/*
@@ -19,6 +20,7 @@
1920
/sentinel-kit_server_frontend/node_modules/*
2021
/sentinel-kit_server_frontend/package-lock.json
2122
/sentinel-kit_server_backend/composer.lock
23+
/sentinel-kit_server_backend/.initial_setup_done
2224
/sentinel-kit_server_backend/migrations/*
2325
/sentinel-kit_server_backend/var/*
2426
/sentinel-kit_server_backend/vendor/*

clean-user-data.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Remove-Item ./config/backend/.initial_setup_done -Force
22
Remove-Item ./config/caddy_server/certificates/* -Recurse -Force
33
Remove-Item ./sentinel-kit_server_backend/config/jwt/*.pem -Force
4+
Remove-Item ./sentinel-kit_server_backend/.initial_setup_done -Force
45
Remove-Item ./data/caddy_logs/* -Recurse -Force
56
Remove-Item ./data/ftp_data/* -Recurse -Force
67
Remove-Item ./data/grafana/* -Recurse -Force

clean-user-data.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
rm -f ./config/backend/.initial_setup_done
22
rm -rf ./config/caddy_server/certificates/*
33
rm -f ./sentinel-kit_server_backend/config/jwt/*.pem
4+
rm -f ./sentinel-kit_server_backend/.initial_setup_done
45
rm -rf ./data/caddy_logs/*
56
rm -rf ./data/ftp_data/*
67
rm -rf ./data/grafana/*

config/docker-config/Dockerfile.backend

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,26 @@ RUN apk update && \
44
apk add --no-cache icu-dev zip libzip-dev bash && \
55
docker-php-ext-install intl pdo pdo_mysql zip
66

7-
RUN apk add --no-cache libpng-dev libjpeg-turbo-dev libwebp-dev libxpm-dev freetype-dev && \
7+
RUN apk add --no-cache libpng-dev libjpeg-turbo-dev libwebp-dev libxpm-dev freetype-dev python3 pipx && \
88
docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp --with-xpm && \
99
docker-php-ext-install gd
1010

11+
RUN export PIPX_GLOBAL_HOME=/opt/pipx && export PIPX_GLOBAL_BIN_DIR=/usr/local/bin
12+
13+
RUN pipx ensurepath && pipx install sigma-cli --global && \
14+
/usr/local/bin/sigma plugin install elasticsearch
15+
16+
RUN mkdir /detection-rules
17+
1118
COPY config/docker-config/uploads.ini /usr/local/etc/php/conf.d/uploads.ini
1219

1320
RUN curl -1sLf 'https://dl.cloudsmith.io/public/symfony/stable/setup.alpine.sh' | bash && \
1421
apk add symfony-cli
1522

16-
RUN cd /var/www/html && \
17-
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
23+
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
1824

25+
RUN chown -R www-data:www-data /var/www/html && chown -R www-data:www-data /detection-rules
26+
# Note: We start as root to fix permissions of mounted volumes, then switch to www-data in entrypoint
1927
WORKDIR /var/www/html
20-
CMD ["php-fpm"]
28+
29+
ENTRYPOINT ["/bin/sh", "-c", "/opt/server-backend/backend-entrypoint.sh"]
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
FROM python:3.12-alpine
2+
3+
RUN apk update \
4+
&& apk add --no-cache \
5+
bash \
6+
git \
7+
pipx \
8+
build-base \
9+
mysql-client \
10+
mysql-dev \
11+
&& rm -rf /var/cache/apk/*
12+
13+
WORKDIR /app
14+
RUN adduser -D appuser
15+
16+
RUN export PIPX_GLOBAL_HOME=/opt/pipx && export PIPX_GLOBAL_BIN_DIR=/usr/local/bin
17+
18+
RUN pipx ensurepath && pipx install sigma-cli --global && \
19+
/usr/local/bin/sigma plugin install elasticsearch && \
20+
pip install --upgrade pip && \
21+
pip install setuptools wheel PyYAML requests urllib3 && \
22+
git clone https://github.com/jertel/elastalert2.git && \
23+
cd elastalert2 && \
24+
pip install -r requirements.txt && \
25+
python setup.py install
26+
27+
COPY ./config/docker-config/scanner-entrypoint.sh /usr/local/bin/scanner-entrypoint.sh
28+
29+
RUN chmod +x /usr/local/bin/scanner-entrypoint.sh
30+
31+
RUN chown -R appuser:appuser /app
32+
33+
USER appuser
34+
35+
ENTRYPOINT ["/bin/bash", "/usr/local/bin/scanner-entrypoint.sh"]

config/docker-config/backend-entrypoint.sh

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
#!/bin/sh
2-
MARKER_FILE="/opt/server-backend/.initial_setup_done"
2+
chown -R www-data:www-data /var/www/html
3+
chown -R www-data:www-data /detection-rules
4+
5+
su -s /bin/sh www-data << 'EOF'
6+
MARKER_FILE="/var/www/html/.initial_setup_done"
37
rm -rf /var/www/html/var/cache
48
rm -rf /var/www/html/public/bundles
9+
rm -rf /detection-rules/elastalert/*
510
composer install
611
if [ ! -f "$MARKER_FILE" ]; then
712
echo "Running initial setup..."
@@ -15,4 +20,5 @@ php /var/www/html/bin/console lexik:jwt:check-config
1520
touch "$MARKER_FILE"
1621
fi
1722
echo "Starting Symfony server..."
18-
symfony server:start --allow-http --port=8000 --listen-ip='0.0.0.0'
23+
symfony server:start --allow-http --port=8000 --listen-ip='0.0.0.0'
24+
EOF
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/bin/bash
2+
3+
echo "Starting ElastAlert with Prometheus monitoring..."
4+
5+
export ELASTALERT_CONFIG_FILE="/app/elastalert_config.yml"
6+
export ELASTALERT_CONFIG_PROCESSED="/app/elastalert_config_processed.yml"
7+
export PROMETHEUS_PORT="9091"
8+
9+
echo "Setting up SSL certificates..."
10+
mkdir -p /app/certs/ca
11+
12+
if [ -f "/app/certs/ca/ca.crt" ]; then
13+
echo "SSL certificate found, using verify_certs=true"
14+
else
15+
echo "WARNING: SSL certificate not found, falling back to verify_certs=false"
16+
sed 's/verify_certs: true/verify_certs: false/' "$ELASTALERT_CONFIG_FILE" > "$ELASTALERT_CONFIG_PROCESSED"
17+
sed -i '/ca_certs:/d' "$ELASTALERT_CONFIG_PROCESSED"
18+
export ELASTALERT_CONFIG_FILE="$ELASTALERT_CONFIG_PROCESSED"
19+
fi
20+
21+
echo "Starting in daemon mode..."
22+
23+
if [ ! -f "$ELASTALERT_CONFIG_FILE" ]; then
24+
echo "ERROR: Configuration file not found: $ELASTALERT_CONFIG_FILE"
25+
exit 1
26+
fi
27+
28+
echo "Configuration file found: $ELASTALERT_CONFIG_FILE"
29+
echo "Testing Elasticsearch connectivity..."
30+
31+
python3 -c "
32+
import yaml
33+
import requests
34+
import os
35+
from requests.auth import HTTPBasicAuth
36+
from urllib3 import disable_warnings
37+
from urllib3.exceptions import InsecureRequestWarning
38+
39+
disable_warnings(InsecureRequestWarning)
40+
41+
es_password_env = os.environ.get('ES_PASSWORD')
42+
43+
# Get config file path from shell argument
44+
config_file = '$ELASTALERT_CONFIG_FILE'
45+
46+
try:
47+
with open(config_file, 'r') as f:
48+
config = yaml.safe_load(f)
49+
except FileNotFoundError:
50+
print(f'ERROR: Config file not found in Python: {config_file}')
51+
exit(1)
52+
except Exception as e:
53+
print(f'ERROR: Failed to load YAML: {e}')
54+
exit(1)
55+
56+
es_host = config.get('es_host')
57+
es_port = config.get('es_port')
58+
es_username = config.get('es_username')
59+
60+
if not all([es_host, es_port, es_username, es_password_env]):
61+
print('ERROR: Missing required configuration (host, port, username, or ES_PASSWORD environment variable).')
62+
exit(1)
63+
64+
url = f'https://{es_host}:{es_port}/_cluster/health'
65+
try:
66+
# Use the password from the environment variable
67+
response = requests.get(url, auth=HTTPBasicAuth(es_username, es_password_env), verify=False, timeout=10)
68+
if response.status_code == 200:
69+
print('SUCCESS: Elasticsearch connection successful')
70+
else:
71+
# Use a print statement that is compatible with older Python versions if needed
72+
print('ERROR: Elasticsearch connection failed. Status code: ' + str(response.status_code))
73+
exit(1)
74+
except Exception as e:
75+
print('ERROR: Elasticsearch connection error: ' + str(e))
76+
exit(1)
77+
"
78+
79+
if [ $? -ne 0 ]; then
80+
echo "ERROR: Elasticsearch connectivity test failed"
81+
exit 1
82+
fi
83+
84+
echo "Creating ElastAlert writeback index if needed..."
85+
elastalert-create-index --config "$ELASTALERT_CONFIG_FILE" --index elastalert_status || true
86+
87+
echo "Starting ElastAlert daemon..."
88+
echo "Prometheus metrics will be available on port $PROMETHEUS_PORT"
89+
echo "ElastAlert UI accessible for monitoring"
90+
91+
exec elastalert --config "$ELASTALERT_CONFIG_FILE" --verbose

config/elastalert/defaults.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Default shared configuration for all Elastalert rules
2+
# This file can be imported in other rules with "import:"
3+
4+
# Elasticsearch connection parameters
5+
es_conn_timeout: 30
6+
max_query_size: 1000
7+
8+
# Timing parameters
9+
buffer_time:
10+
minutes: 1
11+
realert:
12+
minutes: 1
13+
14+
# Index parameters
15+
use_strftime_index: false
16+
timestamp_field: '@timestamp'
17+
18+
# Alert parameters
19+
priority: 1
20+
type: any
21+
22+
# Fields to include in alerts
23+
include:
24+
- _index
25+
- _id
26+
- '@timestamp'
27+
- source
28+
- message
29+
30+
# Default alert template
31+
alert_text: |
32+
🚨 Sentinel-Kit Alert
33+
=====================
34+
Rule: {rule_name}
35+
Index: {0}
36+
Document ID: {1}
37+
Timestamp: {2}
38+
Source: {3}
39+
Message: {4}
40+
41+
alert_text_args:
42+
- _index
43+
- _id
44+
- '@timestamp'
45+
- source
46+
- message
47+
48+
# Configuration for debug alerts
49+
alert:
50+
- debug
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
rules_folder: /app/elastalert_ruleset
2+
run_every:
3+
seconds: 30
4+
buffer_time:
5+
minutes: 15
6+
es_host: sentinel-kit-db-elasticsearch-es01
7+
es_port: 9200
8+
es_username: elastic
9+
use_ssl: true
10+
verify_certs: true
11+
ca_certs: /app/certs/ca/ca.crt
12+
writeback_index: elastalert_status
13+
alert_time_limit:
14+
days: 2
15+
prometheus_port: 9091
16+
prometheus_host: 0.0.0.0
17+
18+
es_conn_timeout: 60
19+
max_query_size: 10000
20+
max_aggregation: 10000
21+
scroll_keepalive: 1m
22+
23+
# Default configuration for all rules
24+
global_defaults:
25+
# Elasticsearch connection
26+
es_conn_timeout: 30
27+
max_query_size: 1000
28+
29+
# Timing
30+
buffer_time:
31+
minutes: 1
32+
realert:
33+
minutes: 1
34+
35+
# Index settings
36+
use_strftime_index: false
37+
timestamp_field: '@timestamp'
38+
39+
# Alert settings
40+
priority: 1
41+
type: any
42+
43+
# Fields to include in alerts
44+
include:
45+
- _index
46+
- _id
47+
- '@timestamp'
48+
49+
# Default alert template
50+
alert_text: |
51+
Sentinel-Kit Alert
52+
Rule: {rule_name}
53+
Index: {0}
54+
Document ID: {1}
55+
Timestamp: {2}
56+
57+
alert_text_args:
58+
- _index
59+
- _id
60+
- '@timestamp'

0 commit comments

Comments
 (0)