Compare commits

...
19 Commits
Author SHA1 Message Date
Jason Ertel 9a0e88f8d2 Merge branch '3/dev' into jertel/wip 2026-11-11 15:42:51 -05:00
reyesj2 d37241376a Surface ILM policy validation errors in highstate
Fail 4xx ILM PUTs immediately (retry 429/5xx/connect), print the
Elasticsearch reason in the salt summary, and retry the load on the
next highstate via /opt/so/state/esilm.txt when the last run failed.

Fixes https://github.com/Security-Onion-Solutions/sos/issues/277
2026-11-11 15:40:50 -05:00
reyesj2 3d8e6d0c6e Wait for Elasticsearch and retry ILM policy loads
Require wait_for_so-elasticsearch, check ES is responsive before
dispatch, and retry each policy PUT so soup no longer fails with
empty output when ES is not ready yet.

Fixes https://github.com/Security-Onion-Solutions/securityonion/issues/16369
2026-11-11 15:40:50 -05:00
reyesj2 ddf168f062 Skip leftover ISO registry.tar when tags do not match SOVERSION
Fixes #16372
2026-11-11 15:40:50 -05:00
Doug Burks 693f7917ae Install securityonion-so-crates on Security Onion Desktop 2026-11-11 15:40:50 -05:00
Mike Reeves 3682e0fde6 Remove x86-64-v3 CPU check from soup 2026-11-11 15:40:50 -05:00
Mike Reeves 161d0d145f Add version 3.5.0 to discussion template 2026-11-11 15:40:50 -05:00
Mike Reeves c04f06af1e Bump version from 3.4.0 to 3.5.0 2026-11-11 15:40:49 -05:00
Mike Reeves 7b2c44e965 3.4.0 2026-11-11 15:40:49 -05:00
Mike Reeves 9895dfbe7f 3.4.0 2026-11-11 15:40:49 -05:00
Corey Ogburn a21d4b5f1b New Configurable Timeouts for Detection Engine Syncs
Each engine now has timeouts for how long to allow a sync to go on after detections are modified.
2026-11-11 15:40:49 -05:00
Mike Reeves f5edb1f6a4 Use the host CA trust store for sensor, strelka and idh containers
Mount the host trust store into zeek, suricata, tcpreplay, the strelka
containers and idh, and restart them when it changes. Point the Python
requests clients in strelka-backend and idh at it instead of certifi.

Remove the frozen /opt/so/conf/ca bundles from every node in ca.trust
rather than only on the manager in soup.
2026-11-11 15:40:49 -05:00
Mike Reeves 708b872583 Use the host CA trust store for all grid containers
Anchor the grid CA and blocklist the eMudhra roots in the host trust
store (new ca.trust state, also used by the desktop role), then mount the
extracted store into each container instead of the frozen copies made by
so-catrust. Containers restart when the host trust changes.
2026-11-11 15:40:49 -05:00
Mike Reeves 844ca33aed Remove unused elasticsearch.p12/sokeys keystore 2026-11-11 15:40:49 -05:00
Josh Patterson 45046b946e Add custom_bind_mounts to so-kafka and so-soc
Every container in docker/defaults.yaml exposes custom_bind_mounts via
soc_docker.yaml, but kafka and soc enabled.sls never appended them to
binds, so the setting was silently ignored for those two containers.
2026-11-11 15:40:49 -05:00
Jorge Reyes 40a30f6908 Merge pull request #16389 from Security-Onion-Solutions/reyesj2-patch-1
update elastic-agent artifact repo directory
2026-11-11 14:32:59 -06:00
Mike Reeves 1fd37251c9 Merge pull request #16390 from Security-Onion-Solutions/foundry/mwaq014injcipm
Telegraf: fix EPS double counting and duplicate metric rows
2026-11-10 14:53:30 -05:00
Mike Reeves 4a5253f688 Telegraf: fix EPS double counting and duplicate metric rows 2026-11-10 08:26:19 -05:00
reyesj2 ec220572f0 dedup artifact registry config & split ea artifacts out of /opt/socore/html/ into dedicated /opt/socore/elastic-artifacts/artifacts/ 2026-11-09 12:32:06 -06:00
8 changed files with 79 additions and 67 deletions

No files matched your search

+2 -2
View File
@@ -54,9 +54,9 @@ so-nginx:
- /opt/so/log/nginx/:/var/log/nginx:rw - /opt/so/log/nginx/:/var/log/nginx:rw
- /opt/so/tmp/nginx/:/var/lib/nginx:rw - /opt/so/tmp/nginx/:/var/lib/nginx:rw
- /opt/so/tmp/nginx/:/run:rw - /opt/so/tmp/nginx/:/run:rw
- /nsm/elastic-fleet/so_agent-installers/:/opt/socore/html/packages - /nsm/elastic-fleet/artifacts/:/opt/socore/elastic-artifacts/artifacts:ro
- /nsm/elastic-fleet/artifacts/:/opt/socore/html/artifacts
{% if GLOBALS.is_manager %} {% if GLOBALS.is_manager %}
- /nsm/elastic-fleet/so_agent-installers/:/opt/socore/html/packages
- /etc/pki/managerssl.crt:/etc/pki/nginx/server.crt:ro - /etc/pki/managerssl.crt:/etc/pki/nginx/server.crt:ro
- /etc/pki/managerssl.key:/etc/pki/nginx/server.key:ro - /etc/pki/managerssl.key:/etc/pki/nginx/server.key:ro
# ATT&CK Navigator binds # ATT&CK Navigator binds
+15 -34
View File
@@ -4,6 +4,8 @@
{%- set role = grains.id.split('_') | last %} {%- set role = grains.id.split('_') | last %}
{%- set influxpass = salt['pillar.get']('secrets:influx_pass') %} {%- set influxpass = salt['pillar.get']('secrets:influx_pass') %}
{%- set influxauth = ('so:' + influxpass) | base64_encode %} {%- set influxauth = ('so:' + influxpass) | base64_encode %}
{%- set all_names = [GLOBALS.hostname, GLOBALS.url_base] + NGINXMERGED.ssl.alt_names %}
{%- set full_server_name = all_names | unique | join(' ') %}
worker_processes auto; worker_processes auto;
error_log /var/log/nginx/error.log; error_log /var/log/nginx/error.log;
@@ -39,52 +41,31 @@ http {
include /etc/nginx/conf.d/*.conf; include /etc/nginx/conf.d/*.conf;
{%- if role in ['fleet'] %}
server {
listen 8443;
server_name {{ GLOBALS.hostname }};
root /opt/socore/html;
location /artifacts/ {
try_files $uri =206;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Proxy "";
proxy_set_header X-Forwarded-Proto $scheme;
}
}
{%- endif %}
{%- if GLOBALS.is_manager %} {%- if GLOBALS.is_manager %}
{%- set all_names = [GLOBALS.hostname, GLOBALS.url_base] + NGINXMERGED.ssl.alt_names %}
{%- set full_server_name = all_names | unique | join(' ') %}
server { server {
listen 80 default_server; listen 80 default_server;
server_name _; server_name _;
return 307 https://{{ GLOBALS.url_base }}$request_uri; return 307 https://{{ GLOBALS.url_base }}$request_uri;
} }
{%- endif %}
{%- if GLOBALS.is_manager or role == 'fleet' %}
server { server {
listen 8443; listen 8443;
{%- if GLOBALS.is_manager %}
server_name {{ full_server_name }}; server_name {{ full_server_name }};
root /opt/socore/html; {%- else %}
server_name {{ GLOBALS.hostname }};
{%- endif %}
root /opt/socore/elastic-artifacts;
location /artifacts/ { location /artifacts/ {
try_files $uri =206; try_files $uri =404;
proxy_read_timeout 90; }
proxy_connect_timeout 90; location / {
proxy_set_header Host $host; return 404;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Proxy "";
proxy_set_header X-Forwarded-Proto $scheme;
} }
} }
{%- endif %}
{%- if GLOBALS.is_manager %}
server { server {
listen 443 ssl default_server; listen 443 ssl default_server;
http2 on; http2 on;
+25 -7
View File
@@ -138,6 +138,10 @@
# AGGREGATOR PLUGINS # # AGGREGATOR PLUGINS #
############################################################################### ###############################################################################
[[aggregators.merge]]
drop_original = true
namepass = ["system", "swap", "kafka_partition"]
############################################################################### ###############################################################################
# INPUT PLUGINS # # INPUT PLUGINS #
############################################################################### ###############################################################################
@@ -289,7 +293,7 @@
password = "{{ salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass') }}" password = "{{ salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass') }}"
{%- endif %} {%- endif %}
{% if grains.role in ['so-manager','so-managersearch','so-standalone','so-receiver'] and GLOBALS.pipeline == "KAFKA" -%} {% if grains.role in ['so-manager','so-managerhype','so-managersearch','so-standalone','so-receiver'] and GLOBALS.pipeline == "KAFKA" -%}
[[inputs.jolokia2_agent]] [[inputs.jolokia2_agent]]
name_prefix= "kafka_" name_prefix= "kafka_"
urls = ["http://{{ NODEIP }}:8778/jolokia"] urls = ["http://{{ NODEIP }}:8778/jolokia"]
@@ -346,6 +350,26 @@
interval = "60s" interval = "60s"
{%- endif %} {%- endif %}
{#- These report state that changes slowly; collecting them every interval only stores duplicate rows #}
{%- set SLOWSCRIPTS = [] %}
{%- for script in ['agentstatus.sh', 'os.sh', 'features.sh', 'raid.sh', 'zeekloss.sh'] %}
{%- if script in TELEGRAFMERGED.scripts[GLOBALS.role.split('-')[1]] %}
{%- do TELEGRAFMERGED.scripts[GLOBALS.role.split('-')[1]].remove(script) %}
{%- do SLOWSCRIPTS.append(script) %}
{%- endif %}
{%- endfor %}
{%- if SLOWSCRIPTS | length > 0 %}
[[inputs.exec]]
commands = [
{%- for script in SLOWSCRIPTS %}
["/scripts/{{script}}"]{% if not loop.last %},{% endif %}
{%- endfor %}
]
data_format = "influx"
timeout = "15s"
interval = "5m"
{%- endif %}
{%- if TELEGRAFMERGED.scripts[GLOBALS.role.split('-')[1]] | length > 0 %} {%- if TELEGRAFMERGED.scripts[GLOBALS.role.split('-')[1]] | length > 0 %}
[[inputs.exec]] [[inputs.exec]]
commands = [ commands = [
@@ -358,12 +382,6 @@
timeout = "15s" timeout = "15s"
{%- endif %} {%- endif %}
{%- if salt['pillar.get']('healthcheck:enabled', False) %}
[[inputs.file]]
files = ["/host/nsm/zeek/logs/zeek_restart.log"]
data_format = "influx"
{%- endif %}
[[inputs.file]] [[inputs.file]]
files = ["/etc/telegraf/node_config.json"] files = ["/etc/telegraf/node_config.json"]
name_override = "node_config" name_override = "node_config"
+1 -1
View File
@@ -18,7 +18,7 @@
{% if GLOBALS.pipeline != 'REDIS' %} {% if GLOBALS.pipeline != 'REDIS' %}
{# When global pipeline is not REDIS remove redis.sh script. KAFKA metrics are collected via jolokia agent. Config in telegraf.conf #} {# When global pipeline is not REDIS remove redis.sh script. KAFKA metrics are collected via jolokia agent. Config in telegraf.conf #}
{% if GLOBALS.role in ['so-standalone', 'so-manager', 'so-managersearch', 'so-receiver', 'so-heavynode'] %} {% if GLOBALS.role in ['so-standalone', 'so-manager', 'so-managerhype', 'so-managersearch', 'so-receiver', 'so-heavynode'] %}
{% do TELEGRAFMERGED.scripts[GLOBALS.role.split('-')[1]].remove('redis.sh') %} {% do TELEGRAFMERGED.scripts[GLOBALS.role.split('-')[1]].remove('redis.sh') %}
{% endif %} {% endif %}
{% endif %} {% endif %}
+1 -1
View File
@@ -10,7 +10,7 @@
# if this script isn't already running # if this script isn't already running
if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then
FILES=$(ls -1x /host/nsm/strelka/unprocessed | wc -l) FILES=$(find /host/nsm/strelka/unprocessed -maxdepth 1 -type f | wc -l)
echo "faffiles files=$FILES" echo "faffiles files=$FILES"
fi fi
+3 -2
View File
@@ -12,8 +12,9 @@ if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then
CONTAINERSLOG=/var/log/somon/containers.log CONTAINERSLOG=/var/log/somon/containers.log
# the collector rewrites this every minute; report nothing rather than repeating a stale # the collector rewrites this every minute; report nothing rather than repeating a stale
# file as if it were current, in case a run was skipped or the collector is wedged # file as if it were current, in case a run was skipped or the collector is wedged.
MAXAGE=150 # Kept under two collector cycles so a 60s telegraf interval can't emit the same snapshot twice.
MAXAGE=90
if [ -r "$CONTAINERSLOG" ]; then if [ -r "$CONTAINERSLOG" ]; then
AGE=$(( $(date +%s) - $(stat -c %Y "$CONTAINERSLOG") )) AGE=$(( $(date +%s) - $(stat -c %Y "$CONTAINERSLOG") ))
+31 -18
View File
@@ -11,27 +11,40 @@
if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then
PREVCOUNTFILE='/tmp/eps.txt' PREVCOUNTFILE='/tmp/eps.txt'
EVENTCOUNTCURRENT="$(curl -s localhost:9600/_node/stats | jq '.events.in')" STATS="$(curl -s localhost:9600/_node/stats)"
if [ ! -z "$EVENTCOUNTCURRENT" ]; then if echo "$STATS" | jq -e '.pipelines.search' > /dev/null 2>&1; then
STAGE=search
if [ -f "$PREVCOUNTFILE" ]; then COUNT="$(echo "$STATS" | jq '.pipelines.search.events.out')"
EVENTCOUNTPREVIOUS=`cat $PREVCOUNTFILE` elif echo "$STATS" | jq -e '.pipelines.receiver' > /dev/null 2>&1; then
else STAGE=receiver
echo "${EVENTCOUNTCURRENT}" > $PREVCOUNTFILE COUNT="$(echo "$STATS" | jq '.pipelines.receiver.events.in')"
exit 0 else
fi exit 0
echo "${EVENTCOUNTCURRENT}" > $PREVCOUNTFILE
# the division by 30 is because the agent interval is 30 seconds
EVENTS=$(((EVENTCOUNTCURRENT - EVENTCOUNTPREVIOUS)/30))
if [ "$EVENTS" -lt 0 ]; then
EVENTS=0
fi
echo "consumptioneps eps=${EVENTS%%.*}"
fi fi
if ! [[ "$COUNT" =~ ^[0-9]+$ ]]; then
exit 0
fi
NOW=$(date +%s)
read -r PREVEPOCH PREVCOUNT 2>/dev/null < "$PREVCOUNTFILE"
echo "${NOW} ${COUNT}" > "$PREVCOUNTFILE"
if ! [[ "$PREVEPOCH" =~ ^[0-9]+$ && "$PREVCOUNT" =~ ^[0-9]+$ ]]; then
exit 0
fi
ELAPSED=$((NOW - PREVEPOCH))
DELTA=$((COUNT - PREVCOUNT))
if [ "$ELAPSED" -le 0 ] || [ "$DELTA" -lt 0 ]; then
EPS=0
else
EPS=$((DELTA / ELAPSED))
fi
echo "consumptioneps,stage=${STAGE} eps=${EPS}"
fi fi
exit 0 exit 0
+1 -2
View File
@@ -10,8 +10,7 @@ if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then
FPS_ENABLED=$(cat /var/log/sostatus/fps_enabled) FPS_ENABLED=$(cat /var/log/sostatus/fps_enabled)
LKS_ENABLED=$(cat /var/log/sostatus/lks_enabled) LKS_ENABLED=$(cat /var/log/sostatus/lks_enabled)
echo "features fps=$FPS_ENABLED" echo "features fps=$FPS_ENABLED,lks=$LKS_ENABLED"
echo "features lks=$LKS_ENABLED"
fi fi
exit 0 exit 0