Compare commits

..

61 Commits

Author SHA1 Message Date
Mike Reeves
350588f080 Change ulimits to structured dict format and add daemon.json ulimit support
Convert ulimits from flat strings to structured dicts with name, soft,
and hard fields for better UI experience. Add default_ulimits as a
configurable setting that dynamically renders into daemon.json, giving
two layers of control: global defaults via the daemon and per-container
overrides.
2026-03-17 16:51:04 -04:00
Mike Reeves
9a07a32a48 Add customizable ulimit settings for all Docker containers
Add ulimits as a configurable advanced setting for every container,
allowing customization through the web UI. Move hardcoded ulimits
from elasticsearch and zeek into defaults.yaml and fix elasticsearch
ulimits that were incorrectly nested under the environment key.
2026-03-17 15:14:34 -04:00
Mike Reeves
4bb61d999d Merge pull request #15628 from Security-Onion-Solutions/zeekload
Add salt states for custom Zeek package loading
2026-03-17 13:40:14 -04:00
Mike Reeves
e0e0e3e97b Exclude README from zkg sync 2026-03-17 13:36:56 -04:00
Mike Reeves
6b039b3f94 Consolidate zkg directory creation into file.recurse with makedirs 2026-03-17 13:36:03 -04:00
Josh Patterson
d2d2f0cb5f Merge pull request #15627 from Security-Onion-Solutions/delta
old code cleanup. add ja4 toggle in soc.
2026-03-17 13:24:59 -04:00
Mike Reeves
e6ee7dac7c Add salt states for custom Zeek package loading
Create /opt/so/conf/zeek/zkg directory and sync custom packages
from the manager via file.recurse. Bind mount the directory into
the so-zeek container so the entrypoint can install packages on
startup.
2026-03-17 13:22:59 -04:00
Josh Patterson
7bf63b822d replace placeholder files with .gitkeep to keep empty directories 2026-03-17 11:40:49 -04:00
Josh Patterson
1a7d72c630 ensure empty directory tracked by git 2026-03-17 11:11:02 -04:00
Josh Patterson
4224713cc6 Merge pull request #15624 from Security-Onion-Solutions/moreja
Add SOC UI toggle for JA4+ fingerprinting
2026-03-17 09:44:04 -04:00
Mike Reeves
b452e70419 Keep JA4S_raw and JA4H_raw hardcoded to disabled 2026-03-17 09:37:37 -04:00
Mike Reeves
6809497730 Add SOC UI toggle for JA4+ fingerprinting in Zeek
JA4 (BSD licensed) remains always enabled, but JA4+ variants (JA4S,
JA4D, JA4H, JA4L, JA4SSH, JA4T, JA4TS, JA4X) require a FoxIO license
and are now toggleable via the SOC UI. The toggle includes a license
agreement warning and defaults to disabled.
2026-03-17 09:35:31 -04:00
Jason Ertel
70597a77ab Merge pull request #15623 from Security-Onion-Solutions/jertel/wip
fix hydra health check
2026-03-17 07:53:00 -04:00
Jason Ertel
f5faf86cb3 fix hydra health check 2026-03-17 07:50:40 -04:00
Mike Reeves
be4e253620 Merge pull request #15621 from Security-Onion-Solutions/analyzer-cp314-wheels
Rebuild analyzer source-packages wheels for Python 3.14
2026-03-16 19:07:27 -04:00
Mike Reeves
ebc1152376 Rebuild all analyzer source-packages for Python 3.14
Full rebuild of all analyzer source-packages via pip download targeting
cp314/manylinux_2_17_x86_64 to match the so-soc Dockerfile base image
(python:3.14.3-slim).

Replaces cp313 wheels with cp314 for pyyaml and charset_normalizer,
and picks up certifi 2026.2.25 (from 2026.1.4).
2026-03-16 18:58:24 -04:00
Mike Reeves
625bfb3ba7 Rebuild analyzer source-packages wheels for Python 3.14
The so-soc Dockerfile base image moved to python:3.14.3-slim but
analyzer source-packages still contained cp313 wheels for pyyaml and
charset_normalizer, causing pip install failures at container startup.

Replace all cp313 wheels with cp314 builds (pyyaml 6.0.3,
charset_normalizer 3.4.6) across all 14 analyzers and update the
CI python-test workflow to match.
2026-03-16 18:58:23 -04:00
Jason Ertel
c11b83c712 Merge pull request #15622 from Security-Onion-Solutions/jertel/wip
fix health check for new hydra version
2026-03-16 18:45:34 -04:00
Jason Ertel
a3b471c1d1 fix health check for new hydra version 2026-03-16 18:43:36 -04:00
Mike Reeves
64bb0dfb5b Merge pull request #15610 from Security-Onion-Solutions/moresoup
Add -r flag to so-yaml get and migrate pcap pillar to suricata
2026-03-16 17:36:32 -04:00
Mike Reeves
ddb26a9f42 Add test for raw dict output in so-yaml get to reach 100% coverage
Covers the dict/list branch in raw mode (line 358) that was missing
test coverage.
2026-03-16 17:19:14 -04:00
Josh Patterson
744d8fdd5e Merge pull request #15620 from Security-Onion-Solutions/mreeves/remove-non-oracle9-salt
Remove non-Oracle Linux 9 support from salt states
2026-03-16 17:10:24 -04:00
Josh Patterson
6feb06e623 cleanup preflight 2026-03-16 17:02:36 -04:00
Mike Reeves
afc14ec29d Remove non-Oracle Linux 9 support from salt states
Simplifies salt states, map files, and modules to only support
Oracle Linux 9, removing all Debian/Ubuntu/CentOS/Rocky/AlmaLinux/RHEL
conditional branches.
2026-03-16 16:58:39 -04:00
Josh Patterson
59134c65d0 Merge pull request #15619 from Security-Onion-Solutions/mreeves/remove-non-oracle9-support
Remove support for non-Oracle Linux 9 operating systems
2026-03-16 16:55:59 -04:00
Josh Patterson
614537998a remove curator.disabled from top 2026-03-16 16:44:11 -04:00
Mike Reeves
d2cee468a0 Remove support for non-Oracle Linux 9 operating systems
Security Onion now exclusively supports Oracle Linux 9. This removes
detection, setup, and update logic for Ubuntu, Debian, CentOS, Rocky,
AlmaLinux, and RHEL.
2026-03-16 16:44:07 -04:00
Josh Patterson
94f454c311 cleanup file.absent 2026-03-16 15:57:15 -04:00
Josh Patterson
17881c9a36 cleanup highlander 2026-03-16 15:56:16 -04:00
Josh Patterson
5b2def6fdd Merge pull request #15618 from Security-Onion-Solutions/delta
forcedType bool
2026-03-16 12:50:06 -04:00
Josh Patterson
9b6d29212d forcedType bool 2026-03-16 12:46:25 -04:00
Josh Patterson
c1bff03b1c Merge pull request #15615 from Security-Onion-Solutions/delta
initialize pcap-log
2026-03-14 20:33:28 -04:00
Josh Patterson
b00f113658 initialize pcap-log 2026-03-14 19:45:50 -04:00
Jason Ertel
7dcd923ebf Merge pull request #15612 from Security-Onion-Solutions/jertel/wip
API errors will no longer redirect
2026-03-13 17:04:51 -04:00
Jason Ertel
1fcd8a7c1a API errors will no longer redirect 2026-03-13 16:53:38 -04:00
Mike Reeves
4a89f7f26b Add -r flag to so-yaml get for raw output without YAML formatting
Preserve default get behavior with yaml.safe_dump output for backwards
compatibility. Add -r flag for clean scalar output used by soup pcap
migration.
2026-03-13 16:24:41 -04:00
Mike Reeves
a9196348ab Merge pull request #15609 from Security-Onion-Solutions/moresoup
Moresoup
2026-03-13 16:16:35 -04:00
Mike Reeves
12dec366e0 Fix so-yaml get to output booleans in YAML format and add bool test 2026-03-13 15:58:47 -04:00
Mike Reeves
1713f6af76 Fix so-yaml tests to match scalar output without document end marker 2026-03-13 15:53:53 -04:00
Mike Reeves
7f4adb70bd Fix so-yaml get to print scalar values without YAML document end marker 2026-03-13 15:34:04 -04:00
Mike Reeves
e2483e4be0 Fix so-yaml addKey crash when intermediate key has None value 2026-03-13 15:22:29 -04:00
Mike Reeves
322c0b8d56 Move pcap.enabled under suricata.pcap.enabled in so-minion 2026-03-13 15:14:19 -04:00
Mike Reeves
81c1d8362d Fix pcap migration to strip yaml document end marker from so-yaml output 2026-03-13 15:09:37 -04:00
Mike Reeves
d1156ee3fd Merge pull request #15608 from Security-Onion-Solutions/moresoup
Improve soup version checks and migrate pcap to suricata
2026-03-13 14:59:57 -04:00
Mike Reeves
18f971954b Improve soup version checks and migrate pcap pillar to suricata
Consolidate version checks to use regex patterns for 2.4.21X and 3.x
versions. Add migrate_pcap_to_suricata to move pcap.enabled to
suricata.pcap.enabled in minion and pcap pillar files during upgrade.
2026-03-13 14:54:23 -04:00
Josh Patterson
e55ac7062c Merge pull request #15574 from Security-Onion-Solutions/delta
pcap cleanup state. enable/disable pcap for suricata in soc
2026-03-13 14:54:06 -04:00
Josh Patterson
c178eada22 Merge pull request #15595 from Security-Onion-Solutions/TOoSmOotH-patch-5
Update version check to include 2.4.211
2026-03-13 14:32:59 -04:00
Doug Burks
92213e302f Merge pull request #15603 from Security-Onion-Solutions/dougburks-patch-1
Remove version 3.0.0 from 2.4 discussion template
2026-03-13 10:53:24 -04:00
Doug Burks
72193b0249 Remove version 3.0.0 from 2.4 discussion template 2026-03-13 10:51:25 -04:00
Mike Reeves
066d7106b0 Merge pull request #15599 from Security-Onion-Solutions/TOoSmOotH-patch-6
Add version 2.4.211 to discussion template
2026-03-13 10:49:12 -04:00
Mike Reeves
89f144df75 Remove upgrade instructions for 2.4 branch
Removed outdated instructions for upgrading to the latest 2.4 branch.
2026-03-11 16:05:06 -04:00
Mike Reeves
cfccbe2bed Update version check to include 2.4.211 2026-03-11 15:59:23 -04:00
Josh Patterson
0360d4145c sensors run pcap.cleanup state 2026-03-10 15:58:26 -04:00
Josh Patterson
398bd0c1da Update VERSION 2026-03-10 15:00:19 -04:00
Josh Patterson
32241faf55 cleanup steno 2026-03-10 14:02:28 -04:00
Josh Patterson
88de779ff7 revert to salt 3006.19 2026-03-10 11:31:56 -04:00
Josh Patterson
d452694c55 enable/disable suricata pcap 2026-03-10 11:30:24 -04:00
Josh Patterson
7fba8ac2b4 Merge remote-tracking branch 'origin/3/dev' into delta 2026-03-10 11:24:44 -04:00
Josh Patterson
6809a40257 Merge remote-tracking branch 'origin/delta' into delta 2026-03-05 16:40:02 -05:00
Josh Patterson
cea55a72c3 upgrade salt 3006.23 2026-03-05 16:35:15 -05:00
Jason Ertel
e38a4a21ee version for delta 2026-03-05 11:52:51 -05:00
166 changed files with 594 additions and 1403 deletions

View File

@@ -13,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.13"]
python-version: ["3.14"]
python-code-path: ["salt/sensoroni/files/analyzers", "salt/manager/tools/sbin"]
steps:

View File

@@ -1,24 +1,14 @@
from os import path
import subprocess
def check():
osfam = __grains__['os_family']
retval = 'False'
if osfam == 'Debian':
if path.exists('/var/run/reboot-required'):
retval = 'True'
cmd = 'needs-restarting -r > /dev/null 2>&1'
elif osfam == 'RedHat':
cmd = 'needs-restarting -r > /dev/null 2>&1'
try:
needs_restarting = subprocess.check_call(cmd, shell=True)
except subprocess.CalledProcessError:
retval = 'True'
else:
retval = 'Unsupported OS: %s' % os
try:
needs_restarting = subprocess.check_call(cmd, shell=True)
except subprocess.CalledProcessError:
retval = 'True'
return retval

View File

@@ -3,8 +3,6 @@
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
{% from 'vars/globals.map.jinja' import GLOBALS %}
include:
- docker
@@ -18,9 +16,3 @@ trusttheca:
- show_changes: False
- makedirs: True
{% if GLOBALS.os_family == 'Debian' %}
symlinkca:
file.symlink:
- target: /etc/pki/tls/certs/intca.crt
- name: /etc/ssl/certs/intca.crt
{% endif %}

View File

@@ -1,3 +1,4 @@
{% from 'docker/docker.map.jinja' import DOCKER -%}
{
"registry-mirrors": [
"https://:5000"
@@ -8,12 +9,16 @@
"base": "172.17.0.0/24",
"size": 24
}
],
]
{%- if DOCKER.default_ulimits %},
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Soft": 1048576,
"Hard": 1048576
}
{%- for ULIMIT in DOCKER.default_ulimits %}
"{{ ULIMIT.name }}": {
"Name": "{{ ULIMIT.name }}",
"Soft": {{ ULIMIT.soft }},
"Hard": {{ ULIMIT.hard }}
}{{ "," if not loop.last else "" }}
{%- endfor %}
}
{%- endif %}
}

View File

@@ -20,11 +20,6 @@ kernel.printk:
sysctl.present:
- value: "3 4 1 3"
# Remove variables.txt from /tmp - This is temp
rmvariablesfile:
file.absent:
- name: /tmp/variables.txt
# Add socore Group
socoregroup:
group.present:
@@ -149,28 +144,6 @@ common_sbin_jinja:
- so-import-pcap
{% endif %}
{% if GLOBALS.role == 'so-heavynode' %}
remove_so-pcap-import_heavynode:
file.absent:
- name: /usr/sbin/so-pcap-import
remove_so-import-pcap_heavynode:
file.absent:
- name: /usr/sbin/so-import-pcap
{% endif %}
{% if not GLOBALS.is_manager%}
# prior to 2.4.50 these scripts were in common/tools/sbin on the manager because of soup and distributed to non managers
# these two states remove the scripts from non manager nodes
remove_soup:
file.absent:
- name: /usr/sbin/soup
remove_so-firewall:
file.absent:
- name: /usr/sbin/so-firewall
{% endif %}
so-status_script:
file.managed:
- name: /usr/sbin/so-status

View File

@@ -1,52 +1,5 @@
# we cannot import GLOBALS from vars/globals.map.jinja in this state since it is called in setup.virt.init
# since it is early in setup of a new VM, the pillars imported in GLOBALS are not yet defined
{% if grains.os_family == 'Debian' %}
commonpkgs:
pkg.installed:
- skip_suggestions: True
- pkgs:
- apache2-utils
- wget
- ntpdate
- jq
- curl
- ca-certificates
- software-properties-common
- apt-transport-https
- openssl
- netcat-openbsd
- sqlite3
- libssl-dev
- procps
- python3-dateutil
- python3-docker
- python3-packaging
- python3-lxml
- git
- rsync
- vim
- tar
- unzip
- bc
{% if grains.oscodename != 'focal' %}
- python3-rich
{% endif %}
{% if grains.oscodename == 'focal' %}
# since Ubuntu requires and internet connection we can use pip to install modules
python3-pip:
pkg.installed
python-rich:
pip.installed:
- name: rich
- target: /usr/local/lib/python3.8/dist-packages/
- require:
- pkg: python3-pip
{% endif %}
{% endif %}
{% if grains.os_family == 'RedHat' %}
remove_mariadb:
pkg.removed:
@@ -84,5 +37,3 @@ commonpkgs:
- unzip
- wget
- yum-utils
{% endif %}

View File

@@ -11,14 +11,6 @@
{% endif %}
{% set SOVERSION = salt['file.read']('/etc/soversion').strip() %}
remove_common_soup:
file.absent:
- name: /opt/so/saltstack/default/salt/common/tools/sbin/soup
remove_common_so-firewall:
file.absent:
- name: /opt/so/saltstack/default/salt/common/tools/sbin/so-firewall
# This section is used to put the scripts in place in the Salt file system
# in case a state run tries to overwrite what we do in the next section.
copy_so-common_common_tools_sbin:

View File

@@ -349,21 +349,16 @@ get_random_value() {
}
gpg_rpm_import() {
if [[ $is_oracle ]]; then
if [[ "$WHATWOULDYOUSAYYAHDOHERE" == "setup" ]]; then
local RPMKEYSLOC="../salt/repo/client/files/$OS/keys"
else
local RPMKEYSLOC="$UPDATE_DIR/salt/repo/client/files/$OS/keys"
fi
RPMKEYS=('RPM-GPG-KEY-oracle' 'RPM-GPG-KEY-EPEL-9' 'SALT-PROJECT-GPG-PUBKEY-2023.pub' 'docker.pub' 'securityonion.pub')
for RPMKEY in "${RPMKEYS[@]}"; do
rpm --import $RPMKEYSLOC/$RPMKEY
echo "Imported $RPMKEY"
done
elif [[ $is_rpm ]]; then
echo "Importing the security onion GPG key"
rpm --import ../salt/repo/client/files/oracle/keys/securityonion.pub
if [[ "$WHATWOULDYOUSAYYAHDOHERE" == "setup" ]]; then
local RPMKEYSLOC="../salt/repo/client/files/$OS/keys"
else
local RPMKEYSLOC="$UPDATE_DIR/salt/repo/client/files/$OS/keys"
fi
RPMKEYS=('RPM-GPG-KEY-oracle' 'RPM-GPG-KEY-EPEL-9' 'SALT-PROJECT-GPG-PUBKEY-2023.pub' 'docker.pub' 'securityonion.pub')
for RPMKEY in "${RPMKEYS[@]}"; do
rpm --import $RPMKEYSLOC/$RPMKEY
echo "Imported $RPMKEY"
done
}
header() {
@@ -615,69 +610,19 @@ salt_minion_count() {
}
set_os() {
if [ -f /etc/redhat-release ]; then
if grep -q "Rocky Linux release 9" /etc/redhat-release; then
OS=rocky
OSVER=9
is_rocky=true
is_rpm=true
elif grep -q "CentOS Stream release 9" /etc/redhat-release; then
OS=centos
OSVER=9
is_centos=true
is_rpm=true
elif grep -q "AlmaLinux release 9" /etc/redhat-release; then
OS=alma
OSVER=9
is_alma=true
is_rpm=true
elif grep -q "Red Hat Enterprise Linux release 9" /etc/redhat-release; then
if [ -f /etc/oracle-release ]; then
OS=oracle
OSVER=9
is_oracle=true
is_rpm=true
else
OS=rhel
OSVER=9
is_rhel=true
is_rpm=true
fi
fi
cron_service_name="crond"
elif [ -f /etc/os-release ]; then
if grep -q "UBUNTU_CODENAME=focal" /etc/os-release; then
OSVER=focal
UBVER=20.04
OS=ubuntu
is_ubuntu=true
is_deb=true
elif grep -q "UBUNTU_CODENAME=jammy" /etc/os-release; then
OSVER=jammy
UBVER=22.04
OS=ubuntu
is_ubuntu=true
is_deb=true
elif grep -q "VERSION_CODENAME=bookworm" /etc/os-release; then
OSVER=bookworm
DEBVER=12
is_debian=true
OS=debian
is_deb=true
fi
cron_service_name="cron"
if [ -f /etc/redhat-release ] && grep -q "Red Hat Enterprise Linux release 9" /etc/redhat-release && [ -f /etc/oracle-release ]; then
OS=oracle
OSVER=9
is_oracle=true
is_rpm=true
fi
cron_service_name="crond"
}
set_minionid() {
MINIONID=$(lookup_grain id)
}
set_palette() {
if [[ $is_deb ]]; then
update-alternatives --set newt-palette /etc/newt/palette.original
fi
}
set_version() {
CURRENTVERSION=0.0.0

View File

@@ -1,34 +0,0 @@
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
so-curator:
docker_container.absent:
- force: True
so-curator_so-status.disabled:
file.line:
- name: /opt/so/conf/so-status/so-status.conf
- match: ^so-curator$
- mode: delete
so-curator-cluster-close:
cron.absent:
- identifier: so-curator-cluster-close
so-curator-cluster-delete:
cron.absent:
- identifier: so-curator-cluster-delete
delete_curator_configuration:
file.absent:
- name: /opt/so/conf/curator
- recurse: True
{% set files = salt.file.find(path='/usr/sbin', name='so-curator*') %}
{% if files|length > 0 %}
delete_curator_scripts:
file.absent:
- names: {{files|yaml}}
{% endif %}

View File

@@ -1,6 +1,10 @@
docker:
range: '172.17.1.0/24'
gateway: '172.17.1.1'
default_ulimits:
- name: nofile
soft: 1048576
hard: 1048576
containers:
'so-dockerregistry':
final_octet: 20
@@ -9,6 +13,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-elastic-fleet':
final_octet: 21
port_bindings:
@@ -16,6 +21,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-elasticsearch':
final_octet: 22
port_bindings:
@@ -24,6 +30,16 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits:
- name: memlock
soft: -1
hard: -1
- name: nofile
soft: 65536
hard: 65536
- name: nproc
soft: 4096
hard: 4096
'so-influxdb':
final_octet: 26
port_bindings:
@@ -31,6 +47,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-kibana':
final_octet: 27
port_bindings:
@@ -38,6 +55,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-kratos':
final_octet: 28
port_bindings:
@@ -46,6 +64,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-hydra':
final_octet: 30
port_bindings:
@@ -54,6 +73,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-logstash':
final_octet: 29
port_bindings:
@@ -70,6 +90,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-nginx':
final_octet: 31
port_bindings:
@@ -81,6 +102,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-nginx-fleet-node':
final_octet: 31
port_bindings:
@@ -88,6 +110,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-redis':
final_octet: 33
port_bindings:
@@ -96,11 +119,13 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-sensoroni':
final_octet: 99
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-soc':
final_octet: 34
port_bindings:
@@ -108,16 +133,19 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-strelka-backend':
final_octet: 36
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-strelka-filestream':
final_octet: 37
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-strelka-frontend':
final_octet: 38
port_bindings:
@@ -125,11 +153,13 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-strelka-manager':
final_octet: 39
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-strelka-gatekeeper':
final_octet: 40
port_bindings:
@@ -137,6 +167,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-strelka-coordinator':
final_octet: 41
port_bindings:
@@ -144,11 +175,13 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-elastalert':
final_octet: 42
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-elastic-fleet-package-registry':
final_octet: 44
port_bindings:
@@ -156,11 +189,13 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-idh':
final_octet: 45
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-elastic-agent':
final_octet: 46
port_bindings:
@@ -169,23 +204,34 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-telegraf':
final_octet: 99
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-suricata':
final_octet: 99
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits:
- memlock=524288000
- name: memlock
soft: 524288000
hard: 524288000
'so-zeek':
final_octet: 99
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits:
- name: core
soft: 0
hard: 0
- name: nofile
soft: 1048576
hard: 1048576
'so-kafka':
final_octet: 88
port_bindings:
@@ -196,3 +242,4 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []

View File

@@ -15,39 +15,6 @@ dockergroup:
- name: docker
- gid: 920
{% if GLOBALS.os_family == 'Debian' %}
{% if grains.oscodename == 'bookworm' %}
dockerheldpackages:
pkg.installed:
- pkgs:
- containerd.io: 2.2.1-1~debian.12~bookworm
- docker-ce: 5:29.2.1-1~debian.12~bookworm
- docker-ce-cli: 5:29.2.1-1~debian.12~bookworm
- docker-ce-rootless-extras: 5:29.2.1-1~debian.12~bookworm
- hold: True
- update_holds: True
{% elif grains.oscodename == 'jammy' %}
dockerheldpackages:
pkg.installed:
- pkgs:
- containerd.io: 2.2.1-1~ubuntu.22.04~jammy
- docker-ce: 5:29.2.1-1~ubuntu.22.04~jammy
- docker-ce-cli: 5:29.2.1-1~ubuntu.22.04~jammy
- docker-ce-rootless-extras: 5:29.2.1-1~ubuntu.22.04~jammy
- hold: True
- update_holds: True
{% else %}
dockerheldpackages:
pkg.installed:
- pkgs:
- containerd.io: 1.7.21-1
- docker-ce: 5:27.2.0-1~ubuntu.20.04~focal
- docker-ce-cli: 5:27.2.0-1~ubuntu.20.04~focal
- docker-ce-rootless-extras: 5:27.2.0-1~ubuntu.20.04~focal
- hold: True
- update_holds: True
{% endif %}
{% else %}
dockerheldpackages:
pkg.installed:
- pkgs:
@@ -57,7 +24,6 @@ dockerheldpackages:
- docker-ce-rootless-extras: 29.2.1-1.el9
- hold: True
- update_holds: True
{% endif %}
#disable docker from managing iptables
iptables_disabled:

View File

@@ -7,6 +7,22 @@ docker:
description: Default docker IP range for containers.
helpLink: docker.html
advanced: True
default_ulimits:
description: Default ulimit settings applied to all containers via the Docker daemon. Each entry specifies a resource name (e.g. nofile, memlock, core, nproc) with soft and hard limits. Individual container ulimits override these defaults.
advanced: True
helpLink: docker.html
forcedType: "[]{}"
syntax: json
uiElements:
- field: name
label: Resource Name
required: True
- field: soft
label: Soft Limit
forcedType: int
- field: hard
label: Hard Limit
forcedType: int
containers:
so-dockerregistry: &dockerOptions
final_octet:
@@ -39,6 +55,22 @@ docker:
helpLink: docker.html
multiline: True
forcedType: "[]string"
ulimits:
description: Ulimit settings for the container. Each entry specifies a resource name (e.g. nofile, memlock, core, nproc) with optional soft and hard limits.
advanced: True
helpLink: docker.html
forcedType: "[]{}"
syntax: json
uiElements:
- field: name
label: Resource Name
required: True
- field: soft
label: Soft Limit
forcedType: int
- field: hard
label: Hard Limit
forcedType: int
so-elastic-fleet: *dockerOptions
so-elasticsearch: *dockerOptions
so-influxdb: *dockerOptions
@@ -62,42 +94,6 @@ docker:
so-idh: *dockerOptions
so-elastic-agent: *dockerOptions
so-telegraf: *dockerOptions
so-suricata:
final_octet:
description: Last octet of the container IP address.
helpLink: docker.html
readonly: True
advanced: True
global: True
port_bindings:
description: List of port bindings for the container.
helpLink: docker.html
advanced: True
multiline: True
forcedType: "[]string"
custom_bind_mounts:
description: List of custom local volume bindings.
advanced: True
helpLink: docker.html
multiline: True
forcedType: "[]string"
extra_hosts:
description: List of additional host entries for the container.
advanced: True
helpLink: docker.html
multiline: True
forcedType: "[]string"
extra_env:
description: List of additional ENV entries for the container.
advanced: True
helpLink: docker.html
multiline: True
forcedType: "[]string"
ulimits:
description: Ulimits for the container, in bytes.
advanced: True
helpLink: docker.html
multiline: True
forcedType: "[]string"
so-suricata: *dockerOptions
so-zeek: *dockerOptions
so-kafka: *dockerOptions

View File

@@ -51,6 +51,12 @@ so-elastalert:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-elastalert'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-elastalert'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- require:
- cmd: wait_for_elasticsearch
- file: elastarules

View File

@@ -1 +0,0 @@
THIS IS A PLACEHOLDER FILE

View File

@@ -45,6 +45,12 @@ so-elastic-fleet-package-registry:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-elastic-fleet-package-registry'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-elastic-fleet-package-registry'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
delete_so-elastic-fleet-package-registry_so-status.disabled:
file.uncomment:
- name: /opt/so/conf/so-status/so-status.conf

View File

@@ -54,6 +54,12 @@ so-elastic-agent:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-elastic-agent'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-elastic-agent'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- require:
- file: create-elastic-agent-config
- file: trusttheca

View File

@@ -133,6 +133,12 @@ so-elastic-fleet:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-elastic-fleet'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-elastic-fleet'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: trusttheca
- x509: etc_elasticfleet_key

View File

@@ -6,8 +6,6 @@
{% from 'vars/globals.map.jinja' import GLOBALS %}
{% import_yaml 'elasticsearch/defaults.yaml' as ELASTICSEARCHDEFAULTS with context %}
{% set HIGHLANDER = salt['pillar.get']('global:highlander', False) %}
{# this is a list of dicts containing hostname:ip for elasticsearch nodes that need to know about each other for cluster #}
{% set ELASTICSEARCH_SEED_HOSTS = [] %}
{% set node_data = salt['pillar.get']('elasticsearch:nodes', {GLOBALS.role.split('-')[1]: {GLOBALS.hostname: {'ip': GLOBALS.node_ip}}}) %}
@@ -36,14 +34,8 @@
{% endfor %}
{% endif %}
{% elif grains.id.split('_') | last == 'searchnode' %}
{% if HIGHLANDER %}
{% do ELASTICSEARCHDEFAULTS.elasticsearch.config.node.roles.extend(['ml', 'master', 'transform']) %}
{% endif %}
{% do ELASTICSEARCHDEFAULTS.elasticsearch.config.update({'discovery': {'seed_hosts': [GLOBALS.manager]}}) %}
{% endif %}
{% if HIGHLANDER %}
{% do ELASTICSEARCHDEFAULTS.elasticsearch.config.xpack.ml.update({'enabled': true}) %}
{% endif %}
{% do ELASTICSEARCHDEFAULTS.elasticsearch.config.node.update({'name': GLOBALS.hostname}) %}
{% do ELASTICSEARCHDEFAULTS.elasticsearch.config.cluster.update({'name': GLOBALS.hostname}) %}

View File

@@ -98,10 +98,6 @@ esrolesdir:
- group: 939
- makedirs: True
eslibdir:
file.absent:
- name: /opt/so/conf/elasticsearch/lib
esingestdynamicconf:
file.recurse:
- name: /opt/so/conf/elasticsearch/ingest
@@ -119,11 +115,6 @@ esingestconf:
- group: 939
- show_changes: False
# Remove .fleet_final_pipeline-1 because we are using global@custom now
so-fleet-final-pipeline-remove:
file.absent:
- name: /opt/so/conf/elasticsearch/ingest/.fleet_final_pipeline-1
# Auto-generate Elasticsearch ingest node pipelines from pillar
{% for pipeline, config in ELASTICSEARCHMERGED.pipelines.items() %}
es_ingest_conf_{{pipeline}}:

View File

@@ -45,15 +45,17 @@ so-elasticsearch:
- discovery.type=single-node
{% endif %}
- ES_JAVA_OPTS=-Xms{{ GLOBALS.elasticsearch.es_heap }} -Xmx{{ GLOBALS.elasticsearch.es_heap }} -Des.transport.cname_in_publish_address=true -Dlog4j2.formatMsgNoLookups=true
ulimits:
- memlock=-1:-1
- nofile=65536:65536
- nproc=4096
{% if DOCKER.containers['so-elasticsearch'].extra_env %}
{% for XTRAENV in DOCKER.containers['so-elasticsearch'].extra_env %}
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-elasticsearch'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-elasticsearch'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- port_bindings:
{% for BINDING in DOCKER.containers['so-elasticsearch'].port_bindings %}
- {{ BINDING }}

View File

@@ -1,5 +1,3 @@
{%- set HIGHLANDER = salt['pillar.get']('global:highlander', False) -%}
{%- raw -%}
{
"description" : "common",
"processors" : [
@@ -67,19 +65,7 @@
{ "append": { "if": "ctx.dataset_tag_temp != null", "field": "tags", "value": "{{dataset_tag_temp.1}}" } },
{ "grok": { "if": "ctx.http?.response?.status_code != null", "field": "http.response.status_code", "patterns": ["%{NUMBER:http.response.status_code:long} %{GREEDYDATA}"]} },
{ "set": { "if": "ctx?.metadata?.kafka != null" , "field": "kafka.id", "value": "{{metadata.kafka.partition}}{{metadata.kafka.offset}}{{metadata.kafka.timestamp}}", "ignore_failure": true } },
{ "remove": { "field": [ "message2", "type", "fields", "category", "module", "dataset", "dataset_tag_temp", "event.dataset_temp" ], "ignore_missing": true, "ignore_failure": true } }
{%- endraw %}
{%- if HIGHLANDER %}
,
{
"pipeline": {
"name": "ecs"
}
}
{%- endif %}
{%- raw %}
,
{ "remove": { "field": [ "message2", "type", "fields", "category", "module", "dataset", "dataset_tag_temp", "event.dataset_temp" ], "ignore_missing": true, "ignore_failure": true } },
{ "pipeline": { "name": "global@custom", "ignore_missing_pipeline": true, "description": "[Fleet] Global pipeline for all data streams" } }
]
}
{% endraw %}

View File

@@ -27,14 +27,12 @@ iptables_config:
- source: salt://firewall/iptables.jinja
- template: jinja
{% if grains.os_family == 'RedHat' %}
disable_firewalld:
service.dead:
- name: firewalld
- enable: False
- require:
- file: iptables_config
{% endif %}
iptables_restore:
cmd.run:
@@ -44,7 +42,6 @@ iptables_restore:
- onlyif:
- iptables-restore --test {{ iptmap.configfile }}
{% if grains.os_family == 'RedHat' %}
enable_firewalld:
service.running:
- name: firewalld
@@ -52,7 +49,6 @@ enable_firewalld:
- onfail:
- file: iptables_config
- cmd: iptables_restore
{% endif %}
{% else %}

View File

@@ -1,14 +1,6 @@
{% set iptmap = salt['grains.filter_by']({
'Debian': {
'service': 'netfilter-persistent',
'iptpkg': 'iptables',
'persistpkg': 'iptables-persistent',
'configfile': '/etc/iptables/rules.v4'
},
'RedHat': {
'service': 'iptables',
'iptpkg': 'iptables-nft',
'persistpkg': 'iptables-nft-services',
'configfile': '/etc/sysconfig/iptables'
},
}) %}
{% set iptmap = {
'service': 'iptables',
'iptpkg': 'iptables-nft',
'persistpkg': 'iptables-nft-services',
'configfile': '/etc/sysconfig/iptables'
} %}

View File

@@ -52,6 +52,12 @@ so-hydra:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-hydra'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-hydra'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- restart_policy: unless-stopped
- watch:
- file: hydraconfig
@@ -67,7 +73,7 @@ delete_so-hydra_so-status.disabled:
wait_for_hydra:
http.wait_for_successful_query:
- name: 'http://{{ GLOBALS.manager }}:4444/'
- name: 'http://{{ GLOBALS.manager }}:4444/health/alive'
- ssl: True
- verify_ssl: False
- status:

View File

@@ -39,6 +39,12 @@ so-idh:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-idh'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-idh'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: opencanary_config
- require:

View File

@@ -3,7 +3,6 @@
include:
- idh.openssh
{% if grains.os_family == 'RedHat' %}
idh_sshd_selinux:
selinux.port_policy_present:
- port: {{ openssh_map.config.port }}
@@ -13,7 +12,6 @@ idh_sshd_selinux:
- file: openssh_config
- require:
- pkg: python_selinux_mgmt_tools
{% endif %}
openssh_config:
file.replace:

View File

@@ -16,8 +16,6 @@ openssh:
- name: {{ openssh_map.service }}
{% endif %}
{% if grains.os_family == 'RedHat' %}
python_selinux_mgmt_tools:
pkg.installed:
- name: policycoreutils-python-utils
{% endif %}

View File

@@ -58,6 +58,12 @@ so-influxdb:
- {{ XTRAHOST }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-influxdb'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-influxdb'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: influxdbconf
- x509: influxdb_key

View File

@@ -60,6 +60,12 @@ so-kafka:
{% if KAFKA_EXTERNAL_ACCESS %}
- /opt/so/conf/kafka/kafka_server_jaas.conf:/opt/kafka/config/kafka_server_jaas.conf:ro
{% endif %}
{% if DOCKER.containers['so-kafka'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-kafka'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
{% for sc in ['server', 'client'] %}
- file: kafka_kraft_{{sc}}_properties

View File

@@ -51,6 +51,12 @@ so-kibana:
{% for BINDING in DOCKER.containers['so-kibana'].port_bindings %}
- {{ BINDING }}
{% endfor %}
{% if DOCKER.containers['so-kibana'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-kibana'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: kibanaconfig

View File

@@ -5,7 +5,6 @@
{% from 'vars/globals.map.jinja' import GLOBALS %}
{% import_yaml 'kibana/defaults.yaml' as KIBANADEFAULTS with context %}
{% set HIGHLANDER = salt['pillar.get']('global:highlander', False) %}
{% do KIBANADEFAULTS.kibana.config.server.update({'publicBaseUrl': 'https://' ~ GLOBALS.url_base ~ '/kibana'}) %}
{% do KIBANADEFAULTS.kibana.config.elasticsearch.update({'hosts': ['https://' ~ GLOBALS.manager ~ ':9200']}) %}

View File

@@ -3,7 +3,6 @@
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
{% set HIGHLANDER = salt['pillar.get']('global:highlander', False) %}
include:
- kibana.enabled
@@ -29,27 +28,3 @@ so-kibana-dashboard-load:
- require:
- sls: kibana.enabled
- file: dashboard_saved_objects_template
{%- if HIGHLANDER %}
dashboard_saved_objects_template_hl:
file.managed:
- name: /opt/so/conf/kibana/hl.ndjson.template
- source: salt://kibana/files/hl.ndjson
- user: 932
- group: 939
- show_changes: False
dashboard_saved_objects_hl_changes:
file.absent:
- names:
- /opt/so/state/kibana_hl.txt
- onchanges:
- file: dashboard_saved_objects_template_hl
so-kibana-dashboard-load_hl:
cmd.run:
- name: /usr/sbin/so-kibana-config-load -i /opt/so/conf/kibana/hl.ndjson.template
- cwd: /opt/so
- require:
- sls: kibana.enabled
- file: dashboard_saved_objects_template_hl
{%- endif %}

View File

@@ -1,6 +1,5 @@
#!/bin/bash
. /usr/sbin/so-common
{% set HIGHLANDER = salt['pillar.get']('global:highlander', False) %}
wait_for_web_response "http://localhost:5601/api/spaces/space/default" "default" 300 "curl -K /opt/so/conf/elasticsearch/curl.config"
## This hackery will be removed if using Elastic Auth ##
@@ -9,10 +8,6 @@ SESSIONCOOKIE=$(curl -K /opt/so/conf/elasticsearch/curl.config -c - -X GET http:
# Disable certain Features from showing up in the Kibana UI
echo
echo "Setting up default Space:"
{% if HIGHLANDER %}
curl -K /opt/so/conf/elasticsearch/curl.config -b "sid=$SESSIONCOOKIE" -L -X PUT "localhost:5601/api/spaces/space/default" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d' {"id":"default","name":"Default","disabledFeatures":["enterpriseSearch"]} ' >> /opt/so/log/kibana/misc.log
{% else %}
echo "Setting up default Kibana Space:"
curl -K /opt/so/conf/elasticsearch/curl.config -b "sid=$SESSIONCOOKIE" -L -X PUT "localhost:5601/api/spaces/space/default" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d' {"id":"default","name":"Default","disabledFeatures":["ml","enterpriseSearch","logs","infrastructure","apm","uptime","monitoring","stackAlerts","actions","securitySolutionCasesV3","inventory","dataQuality","searchSynonyms","enterpriseSearchApplications","enterpriseSearchAnalytics","securitySolutionTimeline","securitySolutionNotes","entityManager"]} ' >> /opt/so/log/kibana/misc.log
{% endif %}
echo

View File

@@ -45,6 +45,12 @@ so-kratos:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-kratos'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-kratos'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- restart_policy: unless-stopped
- watch:
- file: kratosschema

View File

@@ -36,10 +36,6 @@ logstash:
- gid: 931
- home: /opt/so/conf/logstash
lslibdir:
file.absent:
- name: /opt/so/conf/logstash/lib
logstash_sbin:
file.recurse:
- name: /usr/sbin

View File

@@ -96,6 +96,12 @@ so-logstash:
- {{ BIND }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-logstash'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-logstash'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: lsetcsync
- file: trusttheca

View File

@@ -63,11 +63,9 @@ yara_log_dir:
- user
- group
{% if GLOBALS.os_family == 'RedHat' %}
install_createrepo:
pkg.installed:
- name: createrepo_c
{% endif %}
repo_conf_dir:
file.directory:

View File

@@ -134,8 +134,8 @@ function require() {
function verifyEnvironment() {
require "jq"
require "curl"
response=$(curl -Ss -L ${hydraUrl}/)
[[ "$response" != *"Error 404"* ]] && fail "Unable to communicate with Hydra; specify URL via HYDRA_URL environment variable"
response=$(curl -Ss -L ${hydraUrl}/health/alive)
[[ "$response" != '{"status":"ok"}' ]] && fail "Unable to communicate with Hydra; specify URL via HYDRA_URL environment variable"
}
function createFile() {

View File

@@ -462,19 +462,14 @@ function add_sensor_to_minion() {
echo " lb_procs: '$CORECOUNT'"
echo "suricata:"
echo " enabled: True "
echo " pcap:"
echo " enabled: True"
if [[ $is_pcaplimit ]]; then
echo " pcap:"
echo " maxsize: $MAX_PCAP_SPACE"
fi
echo " config:"
echo " af-packet:"
echo " threads: '$CORECOUNT'"
echo "pcap:"
echo " enabled: True"
if [[ $is_pcaplimit ]]; then
echo " config:"
echo " diskfreepercentage: $DFREEPERCENT"
fi
echo " "
} >> $PILLARFILE
if [ $? -ne 0 ]; then

View File

@@ -22,7 +22,7 @@ def showUsage(args):
print(' removelistitem - Remove a list item from a yaml key, if it exists and is a list. Requires KEY and LISTITEM args.', file=sys.stderr)
print(' replacelistobject - Replace a list object based on a condition. Requires KEY, CONDITION_FIELD, CONDITION_VALUE, and JSON_OBJECT args.', file=sys.stderr)
print(' add - Add a new key and set its value. Fails if key already exists. Requires KEY and VALUE args.', file=sys.stderr)
print(' get - Displays (to stdout) the value stored in the given key. Requires KEY arg.', file=sys.stderr)
print(' get [-r] - Displays (to stdout) the value stored in the given key. Requires KEY arg. Use -r for raw output without YAML formatting.', file=sys.stderr)
print(' remove - Removes a yaml key, if it exists. Requires KEY arg.', file=sys.stderr)
print(' replace - Replaces (or adds) a new key and set its value. Requires KEY and VALUE args.', file=sys.stderr)
print(' help - Prints this usage information.', file=sys.stderr)
@@ -256,7 +256,7 @@ def replacelistobject(args):
def addKey(content, key, value):
pieces = key.split(".", 1)
if len(pieces) > 1:
if not pieces[0] in content:
if pieces[0] not in content or content[pieces[0]] is None:
content[pieces[0]] = {}
addKey(content[pieces[0]], pieces[1], value)
elif key in content:
@@ -332,6 +332,11 @@ def getKeyValue(content, key):
def get(args):
raw = False
if len(args) > 0 and args[0] == '-r':
raw = True
args = args[1:]
if len(args) != 2:
print('Missing filename or key arg', file=sys.stderr)
showUsage(None)
@@ -346,7 +351,15 @@ def get(args):
print(f"Key '{key}' not found by so-yaml.py", file=sys.stderr)
return 2
print(yaml.safe_dump(output))
if raw:
if isinstance(output, bool):
print(str(output).lower())
elif isinstance(output, (dict, list)):
print(yaml.safe_dump(output).strip())
else:
print(output)
else:
print(yaml.safe_dump(output))
return 0

View File

@@ -395,6 +395,17 @@ class TestRemove(unittest.TestCase):
self.assertEqual(result, 0)
self.assertIn("45\n...", mock_stdout.getvalue())
def test_get_int_raw(self):
with patch('sys.stdout', new=StringIO()) as mock_stdout:
filename = "/tmp/so-yaml_test-get.yaml"
file = open(filename, "w")
file.write("{key1: { child1: 123, child2: { deep1: 45 } }, key2: false, key3: [e,f,g]}")
file.close()
result = soyaml.get(["-r", filename, "key1.child2.deep1"])
self.assertEqual(result, 0)
self.assertEqual("45\n", mock_stdout.getvalue())
def test_get_str(self):
with patch('sys.stdout', new=StringIO()) as mock_stdout:
filename = "/tmp/so-yaml_test-get.yaml"
@@ -406,6 +417,51 @@ class TestRemove(unittest.TestCase):
self.assertEqual(result, 0)
self.assertIn("hello\n...", mock_stdout.getvalue())
def test_get_str_raw(self):
with patch('sys.stdout', new=StringIO()) as mock_stdout:
filename = "/tmp/so-yaml_test-get.yaml"
file = open(filename, "w")
file.write("{key1: { child1: 123, child2: { deep1: \"hello\" } }, key2: false, key3: [e,f,g]}")
file.close()
result = soyaml.get(["-r", filename, "key1.child2.deep1"])
self.assertEqual(result, 0)
self.assertEqual("hello\n", mock_stdout.getvalue())
def test_get_bool(self):
with patch('sys.stdout', new=StringIO()) as mock_stdout:
filename = "/tmp/so-yaml_test-get.yaml"
file = open(filename, "w")
file.write("{key1: { child1: 123, child2: { deep1: 45 } }, key2: false, key3: [e,f,g]}")
file.close()
result = soyaml.get([filename, "key2"])
self.assertEqual(result, 0)
self.assertIn("false\n...", mock_stdout.getvalue())
def test_get_bool_raw(self):
with patch('sys.stdout', new=StringIO()) as mock_stdout:
filename = "/tmp/so-yaml_test-get.yaml"
file = open(filename, "w")
file.write("{key1: { child1: 123, child2: { deep1: 45 } }, key2: false, key3: [e,f,g]}")
file.close()
result = soyaml.get(["-r", filename, "key2"])
self.assertEqual(result, 0)
self.assertEqual("false\n", mock_stdout.getvalue())
def test_get_dict_raw(self):
with patch('sys.stdout', new=StringIO()) as mock_stdout:
filename = "/tmp/so-yaml_test-get.yaml"
file = open(filename, "w")
file.write("{key1: { child1: 123, child2: { deep1: 45 } }, key2: false, key3: [e,f,g]}")
file.close()
result = soyaml.get(["-r", filename, "key1"])
self.assertEqual(result, 0)
self.assertIn("child1: 123", mock_stdout.getvalue())
self.assertNotIn("...", mock_stdout.getvalue())
def test_get_list(self):
with patch('sys.stdout', new=StringIO()) as mock_stdout:
filename = "/tmp/so-yaml_test-get.yaml"

View File

@@ -88,7 +88,7 @@ check_err() {
echo 'No route to host'
;;
160)
echo 'Incompatiable Elasticsearch upgrade'
echo 'Incompatible Elasticsearch upgrade'
;;
161)
echo 'Required intermediate Elasticsearch upgrade not complete'
@@ -362,7 +362,7 @@ preupgrade_changes() {
# This function is to add any new pillar items if needed.
echo "Checking to see if changes are needed."
[[ "$INSTALLEDVERSION" == 2.4.210 ]] && up_to_3.0.0
[[ "$INSTALLEDVERSION" =~ ^2\.4\.21[0-9]+$ ]] && up_to_3.0.0
true
}
@@ -370,12 +370,12 @@ postupgrade_changes() {
# This function is to add any new pillar items if needed.
echo "Running post upgrade processes."
[[ "$POSTVERSION" == 2.4.210 ]] && post_to_3.0.0
[[ "$POSTVERSION" =~ ^2\.4\.21[0-9]+$ ]] && post_to_3.0.0
true
}
check_minimum_version() {
if [[ "$INSTALLEDVERSION" != "2.4.210" ]] && [[ ! "$INSTALLEDVERSION" =~ ^3\. ]]; then
if [[ ! "$INSTALLEDVERSION" =~ ^(2\.4\.21[0-9]+|3\.) ]]; then
echo "You must be on at least Security Onion 2.4.210 to upgrade. Currently installed version: $INSTALLEDVERSION"
exit 1
fi
@@ -385,10 +385,23 @@ check_minimum_version() {
up_to_3.0.0() {
determine_elastic_agent_upgrade
migrate_pcap_to_suricata
INSTALLEDVERSION=3.0.0
}
migrate_pcap_to_suricata() {
local MINIONDIR=/opt/so/saltstack/local/pillar/minions
local PCAPFILE=/opt/so/saltstack/local/pillar/pcap/soc_pcap.sls
for pillar_file in "$PCAPFILE" "$MINIONDIR"/*.sls; do
[[ -f "$pillar_file" ]] || continue
pcap_enabled=$(so-yaml.py get -r "$pillar_file" pcap.enabled 2>/dev/null) || continue
so-yaml.py add "$pillar_file" suricata.pcap.enabled "$pcap_enabled"
so-yaml.py remove "$pillar_file" pcap
done
}
post_to_3.0.0() {
echo "Nothing to apply"
POSTVERSION=3.0.0
@@ -563,78 +576,46 @@ upgrade_check_salt() {
upgrade_salt() {
echo "Performing upgrade of Salt from $INSTALLEDSALTVERSION to $NEWSALTVERSION."
echo ""
# If rhel family
if [[ $is_rpm ]]; then
# Check if salt-cloud is installed
if rpm -q salt-cloud &>/dev/null; then
SALT_CLOUD_INSTALLED=true
fi
# Check if salt-cloud is configured
if [[ -f /etc/salt/cloud.profiles.d/socloud.conf ]]; then
SALT_CLOUD_CONFIGURED=true
fi
echo "Removing yum versionlock for Salt."
echo ""
yum versionlock delete "salt"
yum versionlock delete "salt-minion"
yum versionlock delete "salt-master"
# Remove salt-cloud versionlock if installed
if [[ $SALT_CLOUD_INSTALLED == true ]]; then
yum versionlock delete "salt-cloud"
fi
echo "Updating Salt packages."
echo ""
set +e
# if oracle run with -r to ignore repos set by bootstrap
if [[ $OS == 'oracle' ]]; then
# Add -L flag only if salt-cloud is already installed
if [[ $SALT_CLOUD_INSTALLED == true ]]; then
run_check_net_err \
"sh $UPDATE_DIR/salt/salt/scripts/bootstrap-salt.sh -X -r -L -F -M stable \"$NEWSALTVERSION\"" \
"Could not update salt, please check $SOUP_LOG for details."
else
run_check_net_err \
"sh $UPDATE_DIR/salt/salt/scripts/bootstrap-salt.sh -X -r -F -M stable \"$NEWSALTVERSION\"" \
"Could not update salt, please check $SOUP_LOG for details."
fi
# if another rhel family variant we want to run without -r to allow the bootstrap script to manage repos
else
run_check_net_err \
"sh $UPDATE_DIR/salt/salt/scripts/bootstrap-salt.sh -X -F -M stable \"$NEWSALTVERSION\"" \
"Could not update salt, please check $SOUP_LOG for details."
fi
set -e
echo "Applying yum versionlock for Salt."
echo ""
yum versionlock add "salt-0:$NEWSALTVERSION-0.*"
yum versionlock add "salt-minion-0:$NEWSALTVERSION-0.*"
yum versionlock add "salt-master-0:$NEWSALTVERSION-0.*"
# Add salt-cloud versionlock if installed
if [[ $SALT_CLOUD_INSTALLED == true ]]; then
yum versionlock add "salt-cloud-0:$NEWSALTVERSION-0.*"
fi
# Else do Ubuntu things
elif [[ $is_deb ]]; then
# ensure these files don't exist when upgrading from 3006.9 to 3006.16
rm -f /etc/apt/keyrings/salt-archive-keyring-2023.pgp /etc/apt/sources.list.d/salt.list
echo "Removing apt hold for Salt."
echo ""
apt-mark unhold "salt-common"
apt-mark unhold "salt-master"
apt-mark unhold "salt-minion"
echo "Updating Salt packages."
echo ""
set +e
# Check if salt-cloud is installed
if rpm -q salt-cloud &>/dev/null; then
SALT_CLOUD_INSTALLED=true
fi
# Check if salt-cloud is configured
if [[ -f /etc/salt/cloud.profiles.d/socloud.conf ]]; then
SALT_CLOUD_CONFIGURED=true
fi
echo "Removing yum versionlock for Salt."
echo ""
yum versionlock delete "salt"
yum versionlock delete "salt-minion"
yum versionlock delete "salt-master"
# Remove salt-cloud versionlock if installed
if [[ $SALT_CLOUD_INSTALLED == true ]]; then
yum versionlock delete "salt-cloud"
fi
echo "Updating Salt packages."
echo ""
set +e
# Run with -r to ignore repos set by bootstrap
if [[ $SALT_CLOUD_INSTALLED == true ]]; then
run_check_net_err \
"sh $UPDATE_DIR/salt/salt/scripts/bootstrap-salt.sh -X -F -M stable \"$NEWSALTVERSION\"" \
"sh $UPDATE_DIR/salt/salt/scripts/bootstrap-salt.sh -X -r -L -F -M stable \"$NEWSALTVERSION\"" \
"Could not update salt, please check $SOUP_LOG for details."
set -e
echo "Applying apt hold for Salt."
echo ""
apt-mark hold "salt-common"
apt-mark hold "salt-master"
apt-mark hold "salt-minion"
else
run_check_net_err \
"sh $UPDATE_DIR/salt/salt/scripts/bootstrap-salt.sh -X -r -F -M stable \"$NEWSALTVERSION\"" \
"Could not update salt, please check $SOUP_LOG for details."
fi
set -e
echo "Applying yum versionlock for Salt."
echo ""
yum versionlock add "salt-0:$NEWSALTVERSION-0.*"
yum versionlock add "salt-minion-0:$NEWSALTVERSION-0.*"
yum versionlock add "salt-master-0:$NEWSALTVERSION-0.*"
# Add salt-cloud versionlock if installed
if [[ $SALT_CLOUD_INSTALLED == true ]]; then
yum versionlock add "salt-cloud-0:$NEWSALTVERSION-0.*"
fi
echo "Checking if Salt was upgraded."
@@ -1071,6 +1052,10 @@ main() {
echo ""
set_os
if [[ ! $is_oracle ]]; then
fail "This OS is not supported. Security Onion requires Oracle Linux 9."
fi
check_salt_master_status 1 || fail "Could not talk to salt master: Please run 'systemctl status salt-master' to ensure the salt-master service is running and check the log at /opt/so/log/salt/master."
echo "Checking to see if this is a manager."
@@ -1180,14 +1165,6 @@ main() {
echo "Upgrading Salt"
# Update the repo files so it can actually upgrade
upgrade_salt
# for Debian based distro, we need to stop salt again after upgrade output below is from bootstrap-salt
# * WARN: Not starting daemons on Debian based distributions
# is not working mostly because starting them is the default behaviour.
if [[ $is_deb ]]; then
stop_salt_minion
stop_salt_master
fi
fi
preupgrade_changes

View File

@@ -75,6 +75,12 @@ so-nginx:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers[container_config].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers[container_config].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- cap_add: NET_BIND_SERVICE
- port_bindings:
{% for BINDING in DOCKER.containers[container_config].port_bindings %}

View File

@@ -387,15 +387,13 @@ http {
error_page 429 = @error429;
location @error401 {
if ($request_uri ~* (^/connect/.*|^/oauth2/.*)) {
if ($request_uri ~* (^/api/.*|^/connect/.*|^/oauth2/.*)) {
return 401;
}
if ($request_uri ~* ^/(?!(^/api/.*))) {
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
}
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
if ($request_uri ~* ^/(?!(api/|login|auth|oauth2|$))) {
if ($request_uri ~* ^/(?!(login|auth|oauth2|$))) {
add_header Set-Cookie "AUTH_REDIRECT=$request_uri;Path=/;Max-Age=14400";
}
return 302 /auth/self-service/login/browser;

View File

@@ -2,7 +2,6 @@
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
{% from 'vars/globals.map.jinja' import GLOBALS %}
{% from 'ntp/config.map.jinja' import NTPCONFIG %}
chrony_pkg:
@@ -17,11 +16,7 @@ chronyconf:
- defaults:
NTPCONFIG: {{ NTPCONFIG }}
{% if GLOBALS.os_family == 'RedHat' %}
chronyd:
{% else %}
chrony:
{% endif %}
service.running:
- enable: True
- watch:

View File

@@ -1,17 +0,0 @@
[Unit]
Description=Podman API Service
Requires=podman.socket
After=podman.socket
Documentation=man:podman-api(1)
StartLimitIntervalSec=0
[Service]
Type=oneshot
Environment=REGISTRIES_CONFIG_PATH=/etc/containers/registries.conf
ExecStart=/usr/bin/podman system service
TimeoutStopSec=30
KillMode=process
[Install]
WantedBy=multi-user.target
Also=podman.socket

View File

@@ -1,10 +0,0 @@
[Unit]
Description=Podman API Socket
Documentation=man:podman-api(1)
[Socket]
ListenStream=%t/podman/podman.sock
SocketMode=0660
[Install]
WantedBy=sockets.target

View File

@@ -1,48 +0,0 @@
{
"args": {
"podman_options": {
"isolate": "true",
"mtu": "1500"
}
},
"cniVersion": "0.4.0",
"name": "sobridge",
"plugins": [
{
"type": "bridge",
"bridge": "sobridge",
"isGateway": true,
"ipMasq": false,
"mtu": 1500,
"hairpinMode": false,
"ipam": {
"type": "host-local",
"routes": [
{
"dst": "0.0.0.0/0"
}
],
"ranges": [
[
{
"subnet": "172.17.1.0/24",
"gateway": "172.17.1.1"
}
]
]
},
"capabilities": {
"ips": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": false
}
},
{
"type": "tuning"
}
]
}

View File

@@ -1,56 +0,0 @@
{% from 'docker/docker.map.jinja' import DOCKER %}
Podman pkg:
pkg.installed:
- name: podman
cnipkg:
pkg.installed:
- name: containernetworking-plugins
{#
Podman service:
file.managed:
- name: /usr/lib/systemd/system/podman.service
- source: salt://podman/podman.service
#}
sobridgeconf:
file.managed:
- name: /etc/cni/net.d/sobridge.conflist
- source: salt://podman/files/sobridge.conflist
Podman_socket_service:
service.running:
- name: podman.socket
- enable: true
Podman_service:
service.running:
- name: podman.service
- enable: true
Docker socket:
file.symlink:
- name: /var/run/docker.sock
- target: /var/run/podman/podman.sock
podman_docker_symlink:
file.symlink:
- name: /usr/bin/docker
- target: /usr/bin/podman
{#
sos_docker_net:
docker_network.present:
- name: sobridge
- subnet: {{ DOCKER.range }}
- gateway: {{ DOCKER.bip }}
- options:
com.docker.network.bridge.name: 'sobridge'
com.docker.network.driver.mtu: '1500'
com.docker.network.bridge.enable_ip_masquerade: 'true'
com.docker.network.bridge.enable_icc: 'true'
com.docker.network.bridge.host_binding_ipv4: '0.0.0.0'
- unless: 'docker network ls | grep sobridge'
#}

View File

@@ -51,6 +51,12 @@ so-redis:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-redis'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-redis'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- entrypoint: "redis-server /usr/local/etc/redis/redis.conf"
- watch:
- file: trusttheca

View File

@@ -51,6 +51,12 @@ so-dockerregistry:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-dockerregistry'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-dockerregistry'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- retry:
attempts: 5
interval: 30

View File

@@ -1,43 +1,29 @@
{% from 'vars/globals.map.jinja' import GLOBALS %}
{% if GLOBALS.os_family == 'RedHat' %}
{% set REPOPATH = '/etc/yum.repos.d/' %}
{% if GLOBALS.os == 'OEL' %}
{% set ABSENTFILES = [
'centos-addons.repo',
'centos-devel.repo',
'centos-extras.repo',
'centos.repo',
'docker-ce.repo',
'epel.repo',
'epel-testing.repo',
'saltstack.repo',
'salt-latest.repo',
'wazuh.repo'
'Rocky-Base.repo',
'Rocky-CR.repo',
'Rocky-Debuginfo.repo',
'Rocky-fasttrack.repo',
'Rocky-Media.repo',
'Rocky-Sources.repo',
'Rocky-Vault.repo',
'Rocky-x86_64-kernel.repo',
'rocky-addons.repo',
'rocky-devel.repo',
'rocky-extras.repo',
'rocky.repo',
'oracle-linux-ol9.repo',
'uek-ol9.repo',
'virt-ol9.repo'
]
%}
{% else %}
{% set ABSENTFILES = [] %}
{% endif %}
{% else %}
{% set REPOPATH = '/etc/apt/sources.list.d/' %}
{% set ABSENTFILES = [] %}
{% endif %}
{% set REPOPATH = '/etc/yum.repos.d/' %}
{% set ABSENTFILES = [
'centos-addons.repo',
'centos-devel.repo',
'centos-extras.repo',
'centos.repo',
'docker-ce.repo',
'epel.repo',
'epel-testing.repo',
'saltstack.repo',
'salt-latest.repo',
'wazuh.repo'
'Rocky-Base.repo',
'Rocky-CR.repo',
'Rocky-Debuginfo.repo',
'Rocky-fasttrack.repo',
'Rocky-Media.repo',
'Rocky-Sources.repo',
'Rocky-Vault.repo',
'Rocky-x86_64-kernel.repo',
'rocky-addons.repo',
'rocky-devel.repo',
'rocky-extras.repo',
'rocky.repo',
'oracle-linux-ol9.repo',
'uek-ol9.repo',
'virt-ol9.repo'
]
%}

View File

@@ -1,10 +1,3 @@
{% if grains.oscodename == 'focal' %}
saltpymodules:
pkg.installed:
- pkgs:
- python3-docker
{% endif %}
# distribute to minions for salt upgrades
salt_bootstrap:
file.managed:

View File

@@ -17,22 +17,12 @@
{% set SALTVERSION = saltminion.salt.minion.version | string %}
{% set INSTALLEDSALTVERSION = grains.saltversion | string %}
{% if grains.os_family == 'Debian' %}
{% set SPLITCHAR = '+' %}
{% set SALTPACKAGES = ['salt-common', 'salt-master', 'salt-minion', 'salt-cloud'] %}
{% set SYSTEMD_UNIT_FILE = '/lib/systemd/system/salt-minion.service' %}
{% else %}
{% set SPLITCHAR = '-' %}
{% set SALTPACKAGES = ['salt', 'salt-master', 'salt-minion', 'salt-cloud'] %}
{% set SYSTEMD_UNIT_FILE = '/usr/lib/systemd/system/salt-minion.service' %}
{% endif %}
{% set SPLITCHAR = '-' %}
{% set SALTPACKAGES = ['salt', 'salt-master', 'salt-minion', 'salt-cloud'] %}
{% set SYSTEMD_UNIT_FILE = '/usr/lib/systemd/system/salt-minion.service' %}
{% if INSTALLEDSALTVERSION != SALTVERSION %}
{% if grains.os_family|lower == 'redhat' %}
{% set UPGRADECOMMAND = 'yum clean all ; /usr/sbin/bootstrap-salt.sh -X -r -F stable ' ~ SALTVERSION %}
{% elif grains.os_family|lower == 'debian' %}
{% set UPGRADECOMMAND = '/usr/sbin/bootstrap-salt.sh -X -F stable ' ~ SALTVERSION %}
{% endif %}
{% set UPGRADECOMMAND = 'yum clean all ; /usr/sbin/bootstrap-salt.sh -X -r -F stable ' ~ SALTVERSION %}
{% else %}
{% set UPGRADECOMMAND = 'echo Already running Salt Minion version ' ~ SALTVERSION %}
{% endif %}

View File

@@ -23,15 +23,6 @@ sync_runners:
- name: saltutil.sync_runners
{% endif %}
# prior to 2.4.30 this engine ran on the manager with salt-minion
# this has changed to running with the salt-master in 2.4.30
remove_engines_config:
file.absent:
- name: /etc/salt/minion.d/engines.conf
- source: salt://salt/files/engines.conf
- watch_in:
- service: salt_minion_service
checkmine_engine:
file.managed:
- name: /etc/salt/engines/checkmine.py

View File

@@ -40,6 +40,12 @@ so-sensoroni:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-sensoroni'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-sensoroni'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: /opt/so/conf/sensoroni/sensoroni.json
- require:

Some files were not shown because too many files have changed in this diff Show More