Compare commits

..
1 Commits
Author SHA1 Message Date
Mike Reeves 3e5a934ff8 Merge pull request #16238 from Security-Onion-Solutions/hotfix/3.3.0
Hotfix/3.3.0
2026-09-11 16:38:51 -04:00
80 changed files with 247 additions and 867 deletions

No files matched your search

-1
View File
@@ -13,7 +13,6 @@ body:
- 3.1.0 - 3.1.0
- 3.2.0 - 3.2.0
- 3.3.0 - 3.3.0
- 3.4.0
- Other (please provide detail below) - Other (please provide detail below)
validations: validations:
required: true required: true
+1 -1
View File
@@ -1 +1 @@
20260911
+1 -1
View File
@@ -1 +1 @@
3.4.0 3.3.0
+4 -17
View File
@@ -117,25 +117,14 @@ elastic_curl_config:
{% endif %} {% endif %}
# A non-root owner here can chmod the directory and replace any script in it, including
# the root-owned ones. 555 is the mode the filesystem RPM ships; root ignores it anyway.
usr_sbin_perms:
file.directory:
- name: /usr/sbin
- user: root
- group: root
- mode: 555
common_sbin: common_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://common/tools/sbin - source: salt://common/tools/sbin
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
- show_changes: False - show_changes: False
- require:
- file: usr_sbin_perms
{% if GLOBALS.role == 'so-heavynode' %} {% if GLOBALS.role == 'so-heavynode' %}
- exclude_pat: - exclude_pat:
- so-pcap-import - so-pcap-import
@@ -170,8 +159,8 @@ common_sbin_jinja:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://common/tools/sbin_jinja - source: salt://common/tools/sbin_jinja
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
- template: jinja - template: jinja
- show_changes: False - show_changes: False
@@ -184,8 +173,6 @@ so-status_script:
file.managed: file.managed:
- name: /usr/sbin/so-status - name: /usr/sbin/so-status
- source: salt://common/tools/sbin/so-status - source: salt://common/tools/sbin/so-status
- user: root
- group: root
- mode: 755 - mode: 755
{% if GLOBALS.is_sensor %} {% if GLOBALS.is_sensor %}
+14 -42
View File
@@ -18,61 +18,47 @@ copy_so-common_common_tools_sbin:
- name: /opt/so/saltstack/default/salt/common/tools/sbin/so-common - name: /opt/so/saltstack/default/salt/common/tools/sbin/so-common
- source: {{UPDATE_DIR}}/salt/common/tools/sbin/so-common - source: {{UPDATE_DIR}}/salt/common/tools/sbin/so-common
- force: True - force: True
- user: root - preserve: True
- group: root
- mode: 755
copy_so-image-common_common_tools_sbin: copy_so-image-common_common_tools_sbin:
file.copy: file.copy:
- name: /opt/so/saltstack/default/salt/common/tools/sbin/so-image-common - name: /opt/so/saltstack/default/salt/common/tools/sbin/so-image-common
- source: {{UPDATE_DIR}}/salt/common/tools/sbin/so-image-common - source: {{UPDATE_DIR}}/salt/common/tools/sbin/so-image-common
- force: True - force: True
- user: root - preserve: True
- group: root
- mode: 755
copy_soup_manager_tools_sbin: copy_soup_manager_tools_sbin:
file.copy: file.copy:
- name: /opt/so/saltstack/default/salt/manager/tools/sbin/soup - name: /opt/so/saltstack/default/salt/manager/tools/sbin/soup
- source: {{UPDATE_DIR}}/salt/manager/tools/sbin/soup - source: {{UPDATE_DIR}}/salt/manager/tools/sbin/soup
- force: True - force: True
- user: root - preserve: True
- group: root
- mode: 755
copy_so-firewall_manager_tools_sbin: copy_so-firewall_manager_tools_sbin:
file.copy: file.copy:
- name: /opt/so/saltstack/default/salt/manager/tools/sbin/so-firewall - name: /opt/so/saltstack/default/salt/manager/tools/sbin/so-firewall
- source: {{UPDATE_DIR}}/salt/manager/tools/sbin/so-firewall - source: {{UPDATE_DIR}}/salt/manager/tools/sbin/so-firewall
- force: True - force: True
- user: root - preserve: True
- group: root
- mode: 755
copy_so-yaml_manager_tools_sbin: copy_so-yaml_manager_tools_sbin:
file.copy: file.copy:
- name: /opt/so/saltstack/default/salt/manager/tools/sbin/so-yaml.py - name: /opt/so/saltstack/default/salt/manager/tools/sbin/so-yaml.py
- source: {{UPDATE_DIR}}/salt/manager/tools/sbin/so-yaml.py - source: {{UPDATE_DIR}}/salt/manager/tools/sbin/so-yaml.py
- force: True - force: True
- user: root - preserve: True
- group: root
- mode: 755
copy_so-repo-sync_manager_tools_sbin: copy_so-repo-sync_manager_tools_sbin:
file.copy: file.copy:
- name: /opt/so/saltstack/default/salt/manager/tools/sbin/so-repo-sync - name: /opt/so/saltstack/default/salt/manager/tools/sbin/so-repo-sync
- source: {{UPDATE_DIR}}/salt/manager/tools/sbin/so-repo-sync - source: {{UPDATE_DIR}}/salt/manager/tools/sbin/so-repo-sync
- user: root - preserve: True
- group: root
- mode: 755
copy_bootstrap-salt_manager_tools_sbin: copy_bootstrap-salt_manager_tools_sbin:
file.copy: file.copy:
- name: /opt/so/saltstack/default/salt/salt/scripts/bootstrap-salt.sh - name: /opt/so/saltstack/default/salt/salt/scripts/bootstrap-salt.sh
- source: {{UPDATE_DIR}}/salt/salt/scripts/bootstrap-salt.sh - source: {{UPDATE_DIR}}/salt/salt/scripts/bootstrap-salt.sh
- user: root - preserve: True
- group: root
- mode: 644
# This section is used to put the new script in place so that it can be called during soup. # This section is used to put the new script in place so that it can be called during soup.
# It is faster than calling the states that normally manage them to put them in place. # It is faster than calling the states that normally manage them to put them in place.
@@ -81,60 +67,46 @@ copy_so-common_sbin:
- name: /usr/sbin/so-common - name: /usr/sbin/so-common
- source: {{UPDATE_DIR}}/salt/common/tools/sbin/so-common - source: {{UPDATE_DIR}}/salt/common/tools/sbin/so-common
- force: True - force: True
- user: root - preserve: True
- group: root
- mode: 755
copy_so-image-common_sbin: copy_so-image-common_sbin:
file.copy: file.copy:
- name: /usr/sbin/so-image-common - name: /usr/sbin/so-image-common
- source: {{UPDATE_DIR}}/salt/common/tools/sbin/so-image-common - source: {{UPDATE_DIR}}/salt/common/tools/sbin/so-image-common
- force: True - force: True
- user: root - preserve: True
- group: root
- mode: 755
copy_soup_sbin: copy_soup_sbin:
file.copy: file.copy:
- name: /usr/sbin/soup - name: /usr/sbin/soup
- source: {{UPDATE_DIR}}/salt/manager/tools/sbin/soup - source: {{UPDATE_DIR}}/salt/manager/tools/sbin/soup
- force: True - force: True
- user: root - preserve: True
- group: root
- mode: 755
copy_so-firewall_sbin: copy_so-firewall_sbin:
file.copy: file.copy:
- name: /usr/sbin/so-firewall - name: /usr/sbin/so-firewall
- source: {{UPDATE_DIR}}/salt/manager/tools/sbin/so-firewall - source: {{UPDATE_DIR}}/salt/manager/tools/sbin/so-firewall
- force: True - force: True
- user: root - preserve: True
- group: root
- mode: 755
copy_so-yaml_sbin: copy_so-yaml_sbin:
file.copy: file.copy:
- name: /usr/sbin/so-yaml.py - name: /usr/sbin/so-yaml.py
- source: {{UPDATE_DIR}}/salt/manager/tools/sbin/so-yaml.py - source: {{UPDATE_DIR}}/salt/manager/tools/sbin/so-yaml.py
- force: True - force: True
- user: root - preserve: True
- group: root
- mode: 755
copy_so-repo-sync_sbin: copy_so-repo-sync_sbin:
file.copy: file.copy:
- name: /usr/sbin/so-repo-sync - name: /usr/sbin/so-repo-sync
- source: {{UPDATE_DIR}}/salt/manager/tools/sbin/so-repo-sync - source: {{UPDATE_DIR}}/salt/manager/tools/sbin/so-repo-sync
- force: True - force: True
- user: root - preserve: True
- group: root
- mode: 755
copy_bootstrap-salt_sbin: copy_bootstrap-salt_sbin:
file.copy: file.copy:
- name: /usr/sbin/bootstrap-salt.sh - name: /usr/sbin/bootstrap-salt.sh
- source: {{UPDATE_DIR}}/salt/salt/scripts/bootstrap-salt.sh - source: {{UPDATE_DIR}}/salt/salt/scripts/bootstrap-salt.sh
- force: True - force: True
- user: root - preserve: True
- group: root
- mode: 755
+1 -2
View File
@@ -240,8 +240,7 @@ copy_new_files() {
cd $UPDATE_DIR cd $UPDATE_DIR
rsync -a salt $DEFAULT_SALT_DIR/ --delete "${EXCLUDE_ARGS[@]}" rsync -a salt $DEFAULT_SALT_DIR/ --delete "${EXCLUDE_ARGS[@]}"
rsync -a pillar $DEFAULT_SALT_DIR/ --delete "${EXCLUDE_ARGS[@]}" rsync -a pillar $DEFAULT_SALT_DIR/ --delete "${EXCLUDE_ARGS[@]}"
# Root-executed code; SOC only needs to read it. Local dirs stay socore-owned. chown -R socore:socore $DEFAULT_SALT_DIR/
chown -R root:root $DEFAULT_SALT_DIR/
cd /tmp cd /tmp
} }
+47 -78
View File
@@ -8,37 +8,21 @@
# Elastic License 2.0. # Elastic License 2.0.
SENSOR_DIR="${SENSOR_DIR:-/nsm}" SENSOR_DIR='/nsm'
CRIT_DISK_USAGE=90 CRIT_DISK_USAGE=90
LOG="${LOG:-/opt/so/log/sensor_clean.log}" CUR_USAGE=$(df -P $SENSOR_DIR | tail -1 | awk '{print $5}' | tr -d %)
LOCK="${LOCK:-/var/tmp/so-sensor-clean.lock}" LOG="/opt/so/log/sensor_clean.log"
MAX_PASSES=100 TODAY=$(date -u "+%Y-%m-%d")
ZEEK_LOGS="$SENSOR_DIR/zeek/logs"
STRELKA_FILES="$SENSOR_DIR/strelka/processed"
SURICATA_LOGS="$SENSOR_DIR/suricata"
PCAPS="$SENSOR_DIR/pcapout"
log() {
echo "$(date) - $*" >>"$LOG"
}
disk_usage() {
df -P "$SENSOR_DIR" | tail -1 | awk '{print $5}' | tr -d %
}
disk_avail() {
df -P "$SENSOR_DIR" | tail -1 | awk '{print $4}'
}
# sets REMOVED=1 if anything was actually deleted
clean() { clean() {
## find the oldest Zeek logs directory ## find the oldest Zeek logs directory
OLDEST_DIR=$(ls "$ZEEK_LOGS" 2>/dev/null | grep -v "current" | grep -v "stats" | grep -v "packetloss" | grep -v "zeek_clean" | sort | head -n 1) OLDEST_DIR=$(ls /nsm/zeek/logs/ | grep -v "current" | grep -v "stats" | grep -v "packetloss" | grep -v "zeek_clean" | sort | head -n 1)
if [ -n "$OLDEST_DIR" ]; then if [ -z "$OLDEST_DIR" -o "$OLDEST_DIR" == ".." -o "$OLDEST_DIR" == "." ]; then
log "Removing directory: $ZEEK_LOGS/$OLDEST_DIR" echo "$(date) - No old Zeek logs available to clean up in /nsm/zeek/logs/" >>$LOG
rm -rf "$ZEEK_LOGS/$OLDEST_DIR" #exit 0
REMOVED=1 else
echo "$(date) - Removing directory: /nsm/zeek/logs/$OLDEST_DIR" >>$LOG
rm -rf /nsm/zeek/logs/"$OLDEST_DIR"
fi fi
## Remarking for now, as we are moving extracted files to /nsm/strelka/processed ## Remarking for now, as we are moving extracted files to /nsm/strelka/processed
@@ -59,73 +43,58 @@ clean() {
#fi #fi
## Clean up Zeek extracted files processed by Strelka ## Clean up Zeek extracted files processed by Strelka
OLDEST_STRELKA=$(find "$STRELKA_FILES" -type f -printf '%T+ %p\n' 2>/dev/null | sort -n | head -n 1) STRELKA_FILES='/nsm/strelka/processed'
if [ -n "$OLDEST_STRELKA" ]; then OLDEST_STRELKA=$(find $STRELKA_FILES -type f -printf '%T+ %p\n' | sort -n | head -n 1)
if [ -z "$OLDEST_STRELKA" -o "$OLDEST_STRELKA" == ".." -o "$OLDEST_STRELKA" == "." ]; then
echo "$(date) - No old files available to clean up in $STRELKA_FILES" >>$LOG
else
OLDEST_STRELKA_DATE=$(echo $OLDEST_STRELKA | awk '{print $1}' | cut -d+ -f1) OLDEST_STRELKA_DATE=$(echo $OLDEST_STRELKA | awk '{print $1}' | cut -d+ -f1)
log "Removing extracted files for $OLDEST_STRELKA_DATE" OLDEST_STRELKA_FILE=$(echo $OLDEST_STRELKA | awk '{print $2}')
REMOVED=1 echo "$(date) - Removing extracted files for $OLDEST_STRELKA_DATE" >>$LOG
find "$STRELKA_FILES" -type f -printf '%T+ %p\n' 2>/dev/null | grep $OLDEST_STRELKA_DATE | awk '{print $2}' | while read FILE; do find $STRELKA_FILES -type f -printf '%T+ %p\n' | grep $OLDEST_STRELKA_DATE | awk '{print $2}' | while read FILE; do
log "Removing file: $FILE" echo "$(date) - Removing file: $FILE" >>$LOG
rm -f "$FILE" rm -f "$FILE"
done done
fi fi
## Clean up Suricata log files ## Clean up Suricata log files
OLDEST_SURICATA=$(find "$SURICATA_LOGS" -type f -printf '%T+ %p\n' 2>/dev/null | sort -n | head -n 1) SURICATA_LOGS='/nsm/suricata'
if [ -n "$OLDEST_SURICATA" ]; then OLDEST_SURICATA=$(find $SURICATA_LOGS -type f -printf '%T+ %p\n' | sort -n | head -n 1)
if [[ -z "$OLDEST_SURICATA" ]] || [[ "$OLDEST_SURICATA" == ".." ]] || [[ "$OLDEST_SURICATA" == "." ]]; then
echo "$(date) - No old files available to clean up in $SURICATA_LOGS" >>$LOG
else
OLDEST_SURICATA_DATE=$(echo $OLDEST_SURICATA | awk '{print $1}' | cut -d+ -f1) OLDEST_SURICATA_DATE=$(echo $OLDEST_SURICATA | awk '{print $1}' | cut -d+ -f1)
log "Removing logs for $OLDEST_SURICATA_DATE" OLDEST_SURICATA_FILE=$(echo $OLDEST_SURICATA | awk '{print $2}')
REMOVED=1 echo "$(date) - Removing logs for $OLDEST_SURICATA_DATE" >>$LOG
find "$SURICATA_LOGS" -type f -printf '%T+ %p\n' 2>/dev/null | grep $OLDEST_SURICATA_DATE | awk '{print $2}' | while read FILE; do find $SURICATA_LOGS -type f -printf '%T+ %p\n' | grep $OLDEST_SURICATA_DATE | awk '{print $2}' | while read FILE; do
log "Removing file: $FILE" echo "$(date) - Removing file: $FILE" >>$LOG
rm -f "$FILE" rm -f "$FILE"
done done
fi fi
## Clean up extracted pcaps ## Clean up extracted pcaps
OLDEST_PCAP=$(find "$PCAPS" -type f -printf '%T+ %p\n' 2>/dev/null | sort -n | head -n 1) PCAPS='/nsm/pcapout'
if [ -n "$OLDEST_PCAP" ]; then OLDEST_PCAP=$(find $PCAPS -type f -printf '%T+ %p\n' | sort -n | head -n 1)
if [ -z "$OLDEST_PCAP" -o "$OLDEST_PCAP" == ".." -o "$OLDEST_PCAP" == "." ]; then
echo "$(date) - No old files available to clean up in $PCAPS" >>$LOG
else
OLDEST_PCAP_DATE=$(echo $OLDEST_PCAP | awk '{print $1}' | cut -d+ -f1) OLDEST_PCAP_DATE=$(echo $OLDEST_PCAP | awk '{print $1}' | cut -d+ -f1)
log "Removing extracted files for $OLDEST_PCAP_DATE" OLDEST_PCAP_FILE=$(echo $OLDEST_PCAP | awk '{print $2}')
REMOVED=1 echo "$(date) - Removing extracted files for $OLDEST_PCAP_DATE" >>$LOG
find "$PCAPS" -type f -printf '%T+ %p\n' 2>/dev/null | grep $OLDEST_PCAP_DATE | awk '{print $2}' | while read FILE; do find $PCAPS -type f -printf '%T+ %p\n' | grep $OLDEST_PCAP_DATE | awk '{print $2}' | while read FILE; do
log "Removing file: $FILE" echo "$(date) - Removing file: $FILE" >>$LOG
rm -f "$FILE" rm -f "$FILE"
done done
fi fi
} }
# Only one instance at a time; the lock is the fd, so it releases on any exit # Check to see if we are already running
exec 9>"$LOCK" || exit 1 NUM_RUNNING=$(pgrep -cf "/bin/bash /usr/sbin/so-sensor-clean")
if ! flock -n 9; then [ "$NUM_RUNNING" -gt 1 ] && echo "$(date) - $NUM_RUNNING sensor clean script processes running...exiting." >>$LOG && exit 0
log "another so-sensor-clean is already running (lock $LOCK held); exiting"
exit 0 if [ "$CUR_USAGE" -gt "$CRIT_DISK_USAGE" ]; then
while [ "$CUR_USAGE" -gt "$CRIT_DISK_USAGE" ]; do
clean
CUR_USAGE=$(df -P $SENSOR_DIR | tail -1 | awk '{print $5}' | tr -d %)
done
fi fi
CUR_USAGE=$(disk_usage)
[ "$CUR_USAGE" -gt "$CRIT_DISK_USAGE" ] || exit 0
log "$SENSOR_DIR at ${CUR_USAGE}% (threshold ${CRIT_DISK_USAGE}%); starting cleanup"
PASS=0
while [ "$CUR_USAGE" -gt "$CRIT_DISK_USAGE" ]; do
PASS=$((PASS + 1))
if [ "$PASS" -gt "$MAX_PASSES" ]; then
log "stopping after $MAX_PASSES passes; $SENSOR_DIR still at ${CUR_USAGE}%"
break
fi
REMOVED=0
BEFORE=$(disk_avail)
clean
CUR_USAGE=$(disk_usage)
if [ "$REMOVED" -eq 0 ]; then
log "nothing left to remove in $ZEEK_LOGS, $STRELKA_FILES, $SURICATA_LOGS, $PCAPS; $SENSOR_DIR still at ${CUR_USAGE}% - space is consumed outside of NSM cleanup scope"
break
fi
if [ "$(disk_avail)" -le "$BEFORE" ]; then
log "pass $PASS freed no space; $SENSOR_DIR still at ${CUR_USAGE}% - stopping until next run"
break
fi
done
+2 -9
View File
@@ -1,12 +1,6 @@
docker: docker:
range: '172.17.1.0/24' range: '172.17.1.0/24'
gateway: '172.17.1.1' gateway: '172.17.1.1'
networks:
sobridge: {}
soauth:
range: '172.17.2.0/24'
gateway: '172.17.2.1'
manager_only: True
ulimits: ulimits:
- name: nofile - name: nofile
soft: 1048576 soft: 1048576
@@ -64,18 +58,18 @@ docker:
ulimits: [] ulimits: []
'so-kratos': 'so-kratos':
final_octet: 28 final_octet: 28
networks: ['soauth']
port_bindings: port_bindings:
- 0.0.0.0:4433:4433 - 0.0.0.0:4433:4433
- 0.0.0.0:4434:4434
custom_bind_mounts: [] custom_bind_mounts: []
extra_hosts: [] extra_hosts: []
extra_env: [] extra_env: []
ulimits: [] ulimits: []
'so-hydra': 'so-hydra':
final_octet: 30 final_octet: 30
networks: ['soauth']
port_bindings: port_bindings:
- 0.0.0.0:4444:4444 - 0.0.0.0:4444:4444
- 0.0.0.0:4445:4445
custom_bind_mounts: [] custom_bind_mounts: []
extra_hosts: [] extra_hosts: []
extra_env: [] extra_env: []
@@ -134,7 +128,6 @@ docker:
ulimits: [] ulimits: []
'so-soc': 'so-soc':
final_octet: 34 final_octet: 34
networks: ['sobridge', 'soauth']
port_bindings: port_bindings:
- 0.0.0.0:9822:9822 - 0.0.0.0:9822:9822
custom_bind_mounts: [] custom_bind_mounts: []
+3 -21
View File
@@ -1,26 +1,8 @@
{% import_yaml 'docker/defaults.yaml' as DOCKERDEFAULTS %} {% import_yaml 'docker/defaults.yaml' as DOCKERDEFAULTS %}
{% set DOCKERMERGED = salt['pillar.get']('docker', DOCKERDEFAULTS.docker, merge=True) %} {% set DOCKERMERGED = salt['pillar.get']('docker', DOCKERDEFAULTS.docker, merge=True) %}
{% set RANGESPLIT = DOCKERMERGED.range.split('.') %}
{% if DOCKERMERGED.networks.sobridge is not mapping %} {% set FIRSTTHREE = RANGESPLIT[0] ~ '.' ~ RANGESPLIT[1] ~ '.' ~ RANGESPLIT[2] ~ '.' %}
{% do DOCKERMERGED.networks.update({'sobridge': {}}) %}
{% endif %}
{% do DOCKERMERGED.networks['sobridge'].update({'range': DOCKERMERGED.range, 'gateway': DOCKERMERGED.gateway}) %}
{% for netname, net in DOCKERMERGED.networks.items() %}
{% set RANGESPLIT = net.range.split('.') %}
{% do net.update({'prefix': RANGESPLIT[0] ~ '.' ~ RANGESPLIT[1] ~ '.' ~ RANGESPLIT[2] ~ '.'}) %}
{% endfor %}
{% for container, vals in DOCKERMERGED.containers.items() %} {% for container, vals in DOCKERMERGED.containers.items() %}
{% set CONTAINER_NETS = vals.get('networks', ['sobridge']) %} {% do DOCKERMERGED.containers[container].update({'ip': FIRSTTHREE ~ DOCKERMERGED.containers[container].final_octet}) %}
{% set IPS = {} %}
{% for netname in CONTAINER_NETS %}
{% do IPS.update({netname: DOCKERMERGED.networks[netname].prefix ~ vals.final_octet}) %}
{% endfor %}
{% do DOCKERMERGED.containers[container].update({
'networks': CONTAINER_NETS,
'ips': IPS,
'network': CONTAINER_NETS[0],
'ip': IPS[CONTAINER_NETS[0]]
}) %}
{% endfor %} {% endfor %}
+6 -10
View File
@@ -71,19 +71,15 @@ dockerreserveports:
- source: salt://common/files/99-reserved-ports.conf - source: salt://common/files/99-reserved-ports.conf
- name: /etc/sysctl.d/99-reserved-ports.conf - name: /etc/sysctl.d/99-reserved-ports.conf
{% for NETNAME, NETWORK in DOCKERMERGED.networks.items() %} sos_docker_net:
{% if not NETWORK.get('manager_only') or GLOBALS.get('is_manager', False) %}
sos_docker_net_{{ NETNAME }}:
docker_network.present: docker_network.present:
- name: {{ NETNAME }} - name: sobridge
- subnet: {{ NETWORK.range }} - subnet: {{ DOCKERMERGED.range }}
- gateway: {{ NETWORK.gateway }} - gateway: {{ DOCKERMERGED.gateway }}
- options: - options:
com.docker.network.bridge.name: '{{ NETNAME }}' com.docker.network.bridge.name: 'sobridge'
com.docker.network.driver.mtu: '1500' com.docker.network.driver.mtu: '1500'
com.docker.network.bridge.enable_ip_masquerade: 'true' com.docker.network.bridge.enable_ip_masquerade: 'true'
com.docker.network.bridge.enable_icc: 'true' com.docker.network.bridge.enable_icc: 'true'
com.docker.network.bridge.host_binding_ipv4: '0.0.0.0' com.docker.network.bridge.host_binding_ipv4: '0.0.0.0'
- unless: ip l | grep {{ NETNAME }} - unless: ip l | grep sobridge
{% endif %}
{% endfor %}
-44
View File
@@ -7,40 +7,6 @@ docker:
description: Default docker IP range for containers. description: Default docker IP range for containers.
helpLink: docker helpLink: docker
advanced: True advanced: True
networks:
sobridge:
description: |
The default docker network, carrying most containers. Its range and gateway are taken
from the docker.range and docker.gateway settings above rather than set here.
helpLink: docker
readonly: True
advanced: True
global: True
soauth:
range:
description: |
IP range for the soauth docker network, an isolated network for the authentication
services, so that the Kratos and Hydra admin APIs are only reachable from the
containers placed on it.
helpLink: docker
readonly: True
advanced: True
global: True
gateway:
description: Gateway for the soauth docker network.
helpLink: docker
readonly: True
advanced: True
global: True
manager_only:
description: |
Limits the soauth network to grid members running the authentication containers,
instead of creating it on every node.
helpLink: docker
readonly: True
advanced: True
global: True
forcedType: bool
ulimits: ulimits:
description: | 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. Valid resource names include: cpu, fsize, data, stack, core, rss, nproc, nofile, memlock, as, locks, sigpending, msgqueue, nice, rtprio, rttime. 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. Valid resource names include: cpu, fsize, data, stack, core, rss, nproc, nofile, memlock, as, locks, sigpending, msgqueue, nice, rtprio, rttime.
@@ -68,16 +34,6 @@ docker:
readonly: True readonly: True
advanced: True advanced: True
global: True global: True
networks:
description: |
Docker networks this container is attached to. The first entry is the container's
primary network and determines the address its published ports are forwarded to.
Defaults to sobridge when unset.
helpLink: docker
readonly: True
advanced: True
global: True
forcedType: "[]string"
port_bindings: port_bindings:
description: List of port bindings for the container. description: List of port bindings for the container.
helpLink: docker helpLink: docker
+2 -2
View File
@@ -33,8 +33,8 @@ elastalert_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://elastalert/tools/sbin - source: salt://elastalert/tools/sbin
- user: root - user: 933
- group: root - group: 939
- file_mode: 755 - file_mode: 755
#elastalert_sbin_jinja: #elastalert_sbin_jinja:
+2 -2
View File
@@ -39,8 +39,8 @@ elasticagent_sbin_jinja:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://elasticagent/tools/sbin_jinja - source: salt://elasticagent/tools/sbin_jinja
- user: root - user: 949
- group: root - group: 939
- file_mode: 755 - file_mode: 755
- template: jinja - template: jinja
+6 -6
View File
@@ -31,8 +31,8 @@ elasticfleet_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://elasticfleet/tools/sbin - source: salt://elasticfleet/tools/sbin
- user: root - user: 947
- group: root - group: 939
- file_mode: 755 - file_mode: 755
- show_changes: False - show_changes: False
@@ -40,8 +40,8 @@ elasticfleet_sbin_jinja:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://elasticfleet/tools/sbin_jinja - source: salt://elasticfleet/tools/sbin_jinja
- user: root - user: 947
- group: root - group: 939
- file_mode: 755 - file_mode: 755
- template: jinja - template: jinja
- exclude_pat: - exclude_pat:
@@ -81,8 +81,8 @@ eapackageupgrade:
file.managed: file.managed:
- name: /usr/sbin/so-elastic-fleet-package-upgrade - name: /usr/sbin/so-elastic-fleet-package-upgrade
- source: salt://elasticfleet/tools/sbin_jinja/so-elastic-fleet-package-upgrade - source: salt://elasticfleet/tools/sbin_jinja/so-elastic-fleet-package-upgrade
- user: root - user: 947
- group: root - group: 939
- mode: 755 - mode: 755
- template: jinja - template: jinja
+2 -2
View File
@@ -14,8 +14,8 @@ so-elastic-agent-install:
file.managed: file.managed:
- name: /usr/sbin/so-elastic-agent-install - name: /usr/sbin/so-elastic-agent-install
- source: salt://elasticfleet/tools/sbin/so-elastic-agent-install - source: salt://elasticfleet/tools/sbin/so-elastic-agent-install
- user: root - user: 947
- group: root - group: 939
- mode: 755 - mode: 755
- show_changes: False - show_changes: False
@@ -30,56 +30,6 @@ fleet_api() {
curl -sK /opt/so/conf/elasticsearch/curl.config -L "localhost:5601/api/fleet/${QUERYPATH}" "$@" --retry 3 --retry-delay 10 --fail 2>/dev/null curl -sK /opt/so/conf/elasticsearch/curl.config -L "localhost:5601/api/fleet/${QUERYPATH}" "$@" --retry 3 --retry-delay 10 --fail 2>/dev/null
} }
elastic_fleet_require_agent_policy() {
local AGENT_POLICY=$1
local POLICY_JSON
if ! POLICY_JSON=$(fleet_api "agent_policies/$AGENT_POLICY") || [ -z "$POLICY_JSON" ]; then
echo "Error: Agent policy '$AGENT_POLICY' was not found or is not visible in the current Kibana space." >&2
return 1
fi
if ! jq -e '.item.package_policies | type == "array"' <<<"$POLICY_JSON" >/dev/null 2>&1; then
echo "Error: Agent policy '$AGENT_POLICY' was not found or is not visible in the current Kibana space." >&2
return 1
fi
echo "$POLICY_JSON"
}
# Print the single active enrollment token for POLICY_ID.
# Exit 1: retryable (API failure, invalid response, no active token)
# Exit 2: multiple active tokens - Shouldn't get into this state without manual intervention
elastic_fleet_active_enrollment_token() {
local POLICY_ID=$1
local RESP TOKEN_COUNT API_KEY
if ! RESP=$(fleet_api "enrollment_api_keys?perPage=100" -H 'kbn-xsrf: true' -H 'Content-Type: application/json'); then
echo "Error: Failed to retrieve enrollment tokens for agent policy '$POLICY_ID'." >&2
return 1
fi
if ! jq -e '.list' <<<"$RESP" >/dev/null 2>&1; then
echo "Error: Invalid enrollment token response for agent policy '$POLICY_ID'." >&2
return 1
fi
TOKEN_COUNT=$(jq --arg pid "$POLICY_ID" '[.list[] | select(.policy_id == $pid and .active == true)] | length' <<<"$RESP")
if [ "${TOKEN_COUNT:-0}" -eq 0 ]; then
echo "Error: No active enrollment token found for agent policy '$POLICY_ID'." >&2
return 1
fi
if [ "$TOKEN_COUNT" -gt 1 ]; then
echo "Error: Found $TOKEN_COUNT active enrollment tokens for agent policy '$POLICY_ID'; expected exactly one." >&2
return 2
fi
API_KEY=$(jq -r --arg pid "$POLICY_ID" '.list[] | select(.policy_id == $pid and .active == true) | .api_key' <<<"$RESP")
echo "$API_KEY"
}
# Max number of concurrent Fleet write jobs (create/update). Override via env if needed. # Max number of concurrent Fleet write jobs (create/update). Override via env if needed.
MAX_FLEET_JOBS=${MAX_FLEET_JOBS:-10} MAX_FLEET_JOBS=${MAX_FLEET_JOBS:-10}
@@ -112,7 +62,15 @@ elastic_fleet_load_integrations_dir() {
i=0 i=0
# Fetch the agent policy a single time; we look up integration ids locally below. # Fetch the agent policy a single time; we look up integration ids locally below.
if ! POLICY_JSON=$(elastic_fleet_require_agent_policy "$AGENT_POLICY"); then if ! POLICY_JSON=$(fleet_api "agent_policies/$AGENT_POLICY"); then
echo "Error: Failed to retrieve agent policy '$AGENT_POLICY'."
rm -f "$FAIL_FILE"
rm -rf "$OUT_DIR"
return 1
fi
if ! jq -e '.item.package_policies' <<<"$POLICY_JSON" >/dev/null 2>&1; then
echo "Error: Invalid agent policy response for '$AGENT_POLICY'."
rm -f "$FAIL_FILE" rm -f "$FAIL_FILE"
rm -rf "$OUT_DIR" rm -rf "$OUT_DIR"
return 1 return 1
@@ -166,15 +124,9 @@ elastic_fleet_integration_check() {
JSON_STRING=$2 JSON_STRING=$2
NAME=$(jq -r .name "$JSON_STRING") NAME=$(jq -r .name $JSON_STRING)
INTEGRATION_ID=""
local POLICY_JSON INTEGRATION_ID=$(/usr/sbin/so-elastic-fleet-agent-policy-view "$AGENT_POLICY" | jq -r '.item.package_policies[] | select(.name=="'"$NAME"'") | .id')
if ! POLICY_JSON=$(elastic_fleet_require_agent_policy "$AGENT_POLICY"); then
return 1
fi
INTEGRATION_ID=$(jq -r --arg n "$NAME" '.item.package_policies[]? | select(.name==$n) | .id' <<<"$POLICY_JSON")
} }
@@ -196,16 +148,7 @@ elastic_fleet_integration_remove() {
NAME=$2 NAME=$2
local POLICY_JSON INTEGRATION_ID=$(/usr/sbin/so-elastic-fleet-agent-policy-view "$AGENT_POLICY" | jq -r '.item.package_policies[] | select(.name=="'"$NAME"'") | .id')
if ! POLICY_JSON=$(elastic_fleet_require_agent_policy "$AGENT_POLICY"); then
return 1
fi
INTEGRATION_ID=$(jq -r --arg n "$NAME" '.item.package_policies[]? | select(.name==$n) | .id' <<<"$POLICY_JSON")
if [ -z "$INTEGRATION_ID" ]; then
echo "Error: Integration '$NAME' was not found in agent policy '$AGENT_POLICY'." >&2
return 1
fi
JSON_STRING=$( jq -n \ JSON_STRING=$( jq -n \
--arg INTEGRATIONID "$INTEGRATION_ID" \ --arg INTEGRATIONID "$INTEGRATION_ID" \
@@ -13,10 +13,7 @@ ERROR=false
for INTEGRATION in /opt/so/conf/elastic-fleet/integrations/elastic-defend/*.json for INTEGRATION in /opt/so/conf/elastic-fleet/integrations/elastic-defend/*.json
do do
printf "\n\nInitial Endpoints Policy - Loading $INTEGRATION\n" printf "\n\nInitial Endpoints Policy - Loading $INTEGRATION\n"
if ! elastic_fleet_integration_check "endpoints-initial" "$INTEGRATION"; then elastic_fleet_integration_check "endpoints-initial" "$INTEGRATION"
ERROR=true
continue
fi
if [ -n "$INTEGRATION_ID" ]; then if [ -n "$INTEGRATION_ID" ]; then
printf "\n\nIntegration $NAME exists - Upgrading integration policy\n" printf "\n\nIntegration $NAME exists - Upgrading integration policy\n"
if ! elastic_fleet_integration_policy_upgrade "$INTEGRATION_ID"; then if ! elastic_fleet_integration_policy_upgrade "$INTEGRATION_ID"; then
@@ -7,35 +7,20 @@
. /usr/sbin/so-elastic-fleet-common . /usr/sbin/so-elastic-fleet-common
# Get all the fleet policies # Get all the fleet policies
if ! json_output=$(fleet_api "agent_policies" -H 'kbn-xsrf: true'); then json_output=$(curl -s -K /opt/so/conf/elasticsearch/curl.config -L -X GET "localhost:5601/api/fleet/agent_policies" -H 'kbn-xsrf: true')
echo "Error: Failed to retrieve Fleet agent policies." >&2
exit 1
fi
if ! jq -e '.items' <<<"$json_output" >/dev/null 2>&1; then
echo "Error: Invalid Fleet agent policies response." >&2
exit 1
fi
# Extract the IDs that start with "FleetServer_" # Extract the IDs that start with "FleetServer_"
POLICY=$(jq -r '.items[] | select(.id | startswith("FleetServer_")) | .id' <<<"$json_output") POLICY=$(echo "$json_output" | jq -r '.items[] | select(.id | startswith("FleetServer_")) | .id')
# Iterate over each ID in the POLICY variable # Iterate over each ID in the POLICY variable
for POLICYNAME in $POLICY; do for POLICYNAME in $POLICY; do
printf "\nUpdating Policy: $POLICYNAME\n" printf "\nUpdating Policy: $POLICYNAME\n"
if ! POLICY_JSON=$(elastic_fleet_require_agent_policy "$POLICYNAME"); then # First get the Integration ID
exit 1 INTEGRATION_ID=$(/usr/sbin/so-elastic-fleet-agent-policy-view "$POLICYNAME" | jq -r '.item.package_policies[] | select(.package.name == "fleet_server") | .id')
fi
INTEGRATION_ID=$(jq -r '.item.package_policies[]? | select(.package.name == "fleet_server") | .id' <<<"$POLICY_JSON")
if [ -z "$INTEGRATION_ID" ]; then
echo "Error: fleet_server integration was not found in agent policy '$POLICYNAME'." >&2
exit 1
fi
# Modify the default integration policy to update the policy_id and an with the correct naming # Modify the default integration policy to update the policy_id and an with the correct naming
UPDATED_INTEGRATION_POLICY=$(jq --arg policy_id "$POLICYNAME" --arg name "fleet_server-$POLICYNAME" ' UPDATED_INTEGRATION_POLICY=$(jq --arg policy_id "$POLICYNAME" --arg name "fleet_server-$POLICYNAME" '
.policy_id = $policy_id | .policy_id = $policy_id |
.name = $name' /opt/so/conf/elastic-fleet/integrations/fleet-server/fleet-server.json) .name = $name' /opt/so/conf/elastic-fleet/integrations/fleet-server/fleet-server.json)
@@ -22,19 +22,12 @@ NUM_RUNNING=$(pgrep -cf "/bin/bash /sbin/so-elastic-agent-gen-installers")
for i in {1..30} for i in {1..30}
do do
ENROLLMENTOKEN=$(elastic_fleet_active_enrollment_token "endpoints-initial") ENROLLMENTOKEN=$(curl -K /opt/so/conf/elasticsearch/curl.config -L "localhost:5601/api/fleet/enrollment_api_keys?perPage=100" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' | jq .list | jq -r -c '.[] | select(.policy_id | contains("endpoints-initial")) | .api_key')
TOKEN_RC=$?
if [ "$TOKEN_RC" -eq 2 ]; then
exit 1
fi
FLEETHOST=$(curl -K /opt/so/conf/elasticsearch/curl.config 'http://localhost:5601/api/fleet/fleet_server_hosts/grid-default' | jq -r '.item.host_urls[]' | paste -sd ',') FLEETHOST=$(curl -K /opt/so/conf/elasticsearch/curl.config 'http://localhost:5601/api/fleet/fleet_server_hosts/grid-default' | jq -r '.item.host_urls[]' | paste -sd ',')
if [[ -n "$FLEETHOST" ]] && [[ -n "$ENROLLMENTOKEN" ]]; then if [[ $FLEETHOST ]] && [[ $ENROLLMENTOKEN ]]; then break; else sleep 10; fi
break
fi
sleep 10
done done
if [[ -z "$FLEETHOST" ]] || [[ -z "$ENROLLMENTOKEN" ]]; then if [[ -z $FLEETHOST ]] || [[ -z $ENROLLMENTOKEN ]]; then
printf "\nFleet Host URL, Enrollment Token or Elastic Version empty - exiting..." printf "\nFleet Host URL, Enrollment Token or Elastic Version empty - exiting..."
printf "\nFleet Host: $FLEETHOST, Enrollment Token: $ENROLLMENTOKEN\n" printf "\nFleet Host: $FLEETHOST, Enrollment Token: $ENROLLMENTOKEN\n"
exit 1 exit 1
@@ -74,25 +67,19 @@ for GOOS in "${GOTARGETOS[@]}"; do
GOARCH="amd64" GOARCH="amd64"
if [[ $GOOS == 'darwin/arm64' ]]; then GOOS="darwin" && GOARCH="arm64"; fi if [[ $GOOS == 'darwin/arm64' ]]; then GOOS="darwin" && GOARCH="arm64"; fi
printf "\n\n### Generating $GOOS/$GOARCH Installer...\n" printf "\n\n### Generating $GOOS/$GOARCH Installer...\n"
if ! docker run -e CGO_ENABLED=0 -e GOOS=$GOOS -e GOARCH=$GOARCH \ docker run -e CGO_ENABLED=0 -e GOOS=$GOOS -e GOARCH=$GOARCH \
--mount type=bind,source=/etc/pki/tls/certs/,target=/workspace/files/cert/ \ --mount type=bind,source=/etc/pki/tls/certs/,target=/workspace/files/cert/ \
--mount type=bind,source=/nsm/elastic-agent-workspace/,target=/workspace/files/elastic-agent/ \ --mount type=bind,source=/nsm/elastic-agent-workspace/,target=/workspace/files/elastic-agent/ \
--mount type=bind,source=/opt/so/saltstack/local/salt/elasticfleet/files/,target=/output/ \ --mount type=bind,source=/opt/so/saltstack/local/salt/elasticfleet/files/,target=/output/ \
{{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-elastic-agent-builder:{{ GLOBALS.so_version }} go build -ldflags "-X main.fleetHostURLsList=$FLEETHOST -X main.enrollmentToken=$ENROLLMENTOKEN" -o /output/so-elastic-agent_${GOOS}_${GOARCH}; then {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-elastic-agent-builder:{{ GLOBALS.so_version }} go build -ldflags "-X main.fleetHostURLsList=$FLEETHOST -X main.enrollmentToken=$ENROLLMENTOKEN" -o /output/so-elastic-agent_${GOOS}_${GOARCH}
printf "\n### ERROR: Failed to generate $GOOS/$GOARCH installer. Exiting...\n"
exit 1
fi
printf "\n### $GOOS/$GOARCH Installer Generated...\n" printf "\n### $GOOS/$GOARCH Installer Generated...\n"
done done
printf "\n\n### Generating MSI...\n" printf "\n\n### Generating MSI...\n"
cp /opt/so/saltstack/local/salt/elasticfleet/files/so-elastic-agent_windows_amd64 /opt/so/saltstack/local/salt/elasticfleet/files/so-elastic-agent_windows_amd64.exe cp /opt/so/saltstack/local/salt/elasticfleet/files/so-elastic-agent_windows_amd64 /opt/so/saltstack/local/salt/elasticfleet/files/so-elastic-agent_windows_amd64.exe
if ! docker run \ docker run \
--mount type=bind,source=/opt/so/saltstack/local/salt/elasticfleet/files/,target=/output/ -w /output \ --mount type=bind,source=/opt/so/saltstack/local/salt/elasticfleet/files/,target=/output/ -w /output \
{{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-elastic-agent-builder:{{ GLOBALS.so_version }} wixl -o so-elastic-agent_windows_amd64_msi --arch x64 /workspace/so-elastic-agent.wxs; then {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-elastic-agent-builder:{{ GLOBALS.so_version }} wixl -o so-elastic-agent_windows_amd64_msi --arch x64 /workspace/so-elastic-agent.wxs
printf "\n### ERROR: Failed to generate MSI. Exiting...\n"
exit 1
fi
printf "\n### MSI Generated...\n" printf "\n### MSI Generated...\n"
# Verify installers were created # Verify installers were created
@@ -202,9 +202,26 @@ fi
### Finalization ### ### Finalization ###
# Query for Enrollment Tokens for default policies # Query for Enrollment Tokens for default policies
ENDPOINTSENROLLMENTOKEN=$(elastic_fleet_active_enrollment_token "endpoints-initial") || exit 1 if ENDPOINTSENROLLMENTOKEN_RAW=$(fleet_api "enrollment_api_keys" -H 'kbn-xsrf: true' -H 'Content-Type: application/json'); then
GRIDNODESENROLLMENTOKENGENERAL=$(elastic_fleet_active_enrollment_token "so-grid-nodes_general") || exit 1 ENDPOINTSENROLLMENTOKEN=$(echo "$ENDPOINTSENROLLMENTOKEN_RAW" | jq .list | jq -r -c '.[] | select(.policy_id | contains("endpoints-initial")) | .api_key')
GRIDNODESENROLLMENTOKENHEAVY=$(elastic_fleet_active_enrollment_token "so-grid-nodes_heavy") || exit 1 else
echo -e "\nFailed to query for Endpoints enrollment token"
exit 1
fi
if GRIDNODESENROLLMENTOKENGENERAL_RAW=$(fleet_api "enrollment_api_keys" -H 'kbn-xsrf: true' -H 'Content-Type: application/json'); then
GRIDNODESENROLLMENTOKENGENERAL=$(echo "$GRIDNODESENROLLMENTOKENGENERAL_RAW" | jq .list | jq -r -c '.[] | select(.policy_id | contains("so-grid-nodes_general")) | .api_key')
else
echo -e "\nFailed to query for Grid nodes - General enrollment token"
exit 1
fi
if GRIDNODESENROLLMENTOKENHEAVY_RAW=$(fleet_api "enrollment_api_keys" -H 'kbn-xsrf: true' -H 'Content-Type: application/json'); then
GRIDNODESENROLLMENTOKENHEAVY=$(echo "$GRIDNODESENROLLMENTOKENHEAVY_RAW" | jq .list | jq -r -c '.[] | select(.policy_id | contains("so-grid-nodes_heavy")) | .api_key')
else
echo -e "\nFailed to query for Grid nodes - Heavy enrollment token"
exit 1
fi
# Store needed data in minion pillar # Store needed data in minion pillar
pillar_file=/opt/so/saltstack/local/pillar/minions/{{ GLOBALS.minion_id }}.sls pillar_file=/opt/so/saltstack/local/pillar/minions/{{ GLOBALS.minion_id }}.sls
+10 -10
View File
@@ -37,8 +37,8 @@ elasticsearch_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://elasticsearch/tools/sbin - source: salt://elasticsearch/tools/sbin
- user: root - user: 930
- group: root - group: 939
- file_mode: 755 - file_mode: 755
- exclude_pat: - exclude_pat:
- so-elasticsearch-pipelines # exclude this because we need to watch it for changes, we sync it in another state - so-elasticsearch-pipelines # exclude this because we need to watch it for changes, we sync it in another state
@@ -49,8 +49,8 @@ so-elasticsearch-system-indices-patch-script:
file.managed: file.managed:
- name: /usr/sbin/so-elasticsearch-system-indices-patch - name: /usr/sbin/so-elasticsearch-system-indices-patch
- source: salt://elasticsearch/tools/sbin/so-elasticsearch-system-indices-patch - source: salt://elasticsearch/tools/sbin/so-elasticsearch-system-indices-patch
- user: root - user: 930
- group: root - group: 939
- mode: 755 - mode: 755
- show_changes: False - show_changes: False
@@ -58,8 +58,8 @@ elasticsearch_sbin_jinja:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://elasticsearch/tools/sbin_jinja - source: salt://elasticsearch/tools/sbin_jinja
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
- template: jinja - template: jinja
- exclude_pat: - exclude_pat:
@@ -72,8 +72,8 @@ so-elasticsearch-ilm-policy-load-script:
file.managed: file.managed:
- name: /usr/sbin/so-elasticsearch-ilm-policy-load - name: /usr/sbin/so-elasticsearch-ilm-policy-load
- source: salt://elasticsearch/tools/sbin_jinja/so-elasticsearch-ilm-policy-load - source: salt://elasticsearch/tools/sbin_jinja/so-elasticsearch-ilm-policy-load
- user: root - user: 930
- group: root - group: 939
- mode: 754 - mode: 754
- template: jinja - template: jinja
- defaults: - defaults:
@@ -84,8 +84,8 @@ so-elasticsearch-pipelines-script:
file.managed: file.managed:
- name: /usr/sbin/so-elasticsearch-pipelines - name: /usr/sbin/so-elasticsearch-pipelines
- source: salt://elasticsearch/tools/sbin/so-elasticsearch-pipelines - source: salt://elasticsearch/tools/sbin/so-elasticsearch-pipelines
- user: root - user: 930
- group: root - group: 939
- mode: 754 - mode: 754
- show_changes: False - show_changes: False
@@ -5,8 +5,7 @@
{ "rename": { "field": "message2.proto", "target_field": "network.transport", "ignore_missing": true } }, { "rename": { "field": "message2.proto", "target_field": "network.transport", "ignore_missing": true } },
{ "rename": { "field": "message2.app_proto", "target_field": "network.protocol", "ignore_missing": true } }, { "rename": { "field": "message2.app_proto", "target_field": "network.protocol", "ignore_missing": true } },
{ "rename": { "field": "message2.fileinfo.filename", "target_field": "file.name", "ignore_missing": true } }, { "rename": { "field": "message2.fileinfo.filename", "target_field": "file.name", "ignore_missing": true } },
{ "rename": { "field": "message2.fileinfo.gaps", "target_field": "suricata.fileinfo.gaps", "ignore_missing": true } }, { "rename": { "field": "message2.fileinfo.gaps", "target_field": "file.bytes.missing", "ignore_missing": true } },
{ "set": { "if": "ctx.suricata?.fileinfo?.gaps == false", "field": "file.bytes.missing", "value": 0 } },
{ "rename": { "field": "message2.fileinfo.magic", "target_field": "file.mime_type", "ignore_missing": true } }, { "rename": { "field": "message2.fileinfo.magic", "target_field": "file.mime_type", "ignore_missing": true } },
{ "rename": { "field": "message2.fileinfo.md5", "target_field": "hash.md5", "ignore_missing": true } }, { "rename": { "field": "message2.fileinfo.md5", "target_field": "hash.md5", "ignore_missing": true } },
{ "rename": { "field": "message2.fileinfo.sha1", "target_field": "hash.sha1", "ignore_missing": true } }, { "rename": { "field": "message2.fileinfo.sha1", "target_field": "hash.sha1", "ignore_missing": true } },
+14 -33
View File
@@ -4,19 +4,11 @@
{%- set role = GLOBALS.role.split('-')[1] %} {%- set role = GLOBALS.role.split('-')[1] %}
{%- from 'firewall/containers.map.jinja' import NODE_CONTAINERS %} {%- from 'firewall/containers.map.jinja' import NODE_CONTAINERS %}
{%- set NODE_NETWORKS = [] %}
{%- for NETNAME, NETWORK in DOCKERMERGED.networks.items() %}
{%- if not NETWORK.get('manager_only') or GLOBALS.get('is_manager', False) %}
{%- do NODE_NETWORKS.append(NETNAME) %}
{%- endif %}
{%- endfor %}
{%- set PR = [] %} {%- set PR = [] %}
{%- set D1 = [] %} {%- set D1 = [] %}
{%- set D2 = [] %} {%- set D2 = [] %}
{%- for container in NODE_CONTAINERS %} {%- for container in NODE_CONTAINERS %}
{%- set IP = DOCKERMERGED.containers[container].ip %} {%- set IP = DOCKERMERGED.containers[container].ip %}
{%- set BRIDGE = DOCKERMERGED.containers[container].network %}
{%- if DOCKERMERGED.containers[container].port_bindings is defined %} {%- if DOCKERMERGED.containers[container].port_bindings is defined %}
{%- for binding in DOCKERMERGED.containers[container].port_bindings %} {%- for binding in DOCKERMERGED.containers[container].port_bindings %}
{#- cant split int so we convert to string #} {#- cant split int so we convert to string #}
@@ -43,11 +35,11 @@
{%- endif %} {%- endif %}
{%- do PR.append("-A POSTROUTING -s " ~ DOCKERMERGED.containers[container].ip ~ "/32 -d " ~ DOCKERMERGED.containers[container].ip ~ "/32 -p " ~ proto ~ " -m " ~ proto ~ " --dport " ~ containerPort ~ " -j MASQUERADE") %} {%- do PR.append("-A POSTROUTING -s " ~ DOCKERMERGED.containers[container].ip ~ "/32 -d " ~ DOCKERMERGED.containers[container].ip ~ "/32 -p " ~ proto ~ " -m " ~ proto ~ " --dport " ~ containerPort ~ " -j MASQUERADE") %}
{%- if bindip | length and bindip != '0.0.0.0' %} {%- if bindip | length and bindip != '0.0.0.0' %}
{%- do D1.append("-A DOCKER -d " ~ bindip ~ "/32 ! -i " ~ BRIDGE ~ " -p " ~ proto ~ " -m " ~ proto ~ " --dport " ~ hostPort ~ " -j DNAT --to-destination " ~ DOCKERMERGED.containers[container].ip ~ ":" ~ containerPort) %} {%- do D1.append("-A DOCKER -d " ~ bindip ~ "/32 ! -i sobridge -p " ~ proto ~ " -m " ~ proto ~ " --dport " ~ hostPort ~ " -j DNAT --to-destination " ~ DOCKERMERGED.containers[container].ip ~ ":" ~ containerPort) %}
{%- else %} {%- else %}
{%- do D1.append("-A DOCKER ! -i " ~ BRIDGE ~ " -p " ~ proto ~ " -m " ~ proto ~ " --dport " ~ hostPort ~ " -j DNAT --to-destination " ~ DOCKERMERGED.containers[container].ip ~ ":" ~ containerPort) %} {%- do D1.append("-A DOCKER ! -i sobridge -p " ~ proto ~ " -m " ~ proto ~ " --dport " ~ hostPort ~ " -j DNAT --to-destination " ~ DOCKERMERGED.containers[container].ip ~ ":" ~ containerPort) %}
{%- endif %} {%- endif %}
{%- do D2.append("-A DOCKER -d " ~ DOCKERMERGED.containers[container].ip ~ "/32 ! -i " ~ BRIDGE ~ " -o " ~ BRIDGE ~ " -p " ~ proto ~ " -m " ~ proto ~ " --dport " ~ containerPort ~ " -j ACCEPT") %} {%- do D2.append("-A DOCKER -d " ~ DOCKERMERGED.containers[container].ip ~ "/32 ! -i sobridge -o sobridge -p " ~ proto ~ " -m " ~ proto ~ " --dport " ~ containerPort ~ " -j ACCEPT") %}
{%- endfor %} {%- endfor %}
{%- endif %} {%- endif %}
{%- endfor %} {%- endfor %}
@@ -60,15 +52,11 @@
:DOCKER - [0:0] :DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER -A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
{%- for NETNAME in NODE_NETWORKS %} -A POSTROUTING -s {{DOCKERMERGED.range}} ! -o sobridge -j MASQUERADE
-A POSTROUTING -s {{ DOCKERMERGED.networks[NETNAME].range }} ! -o {{ NETNAME }} -j MASQUERADE
{%- endfor %}
{%- for rule in PR %} {%- for rule in PR %}
{{ rule }} {{ rule }}
{%- endfor %} {%- endfor %}
{%- for NETNAME in NODE_NETWORKS %} -A DOCKER -i sobridge -j RETURN
-A DOCKER -i {{ NETNAME }} -j RETURN
{%- endfor %}
{%- for rule in D1 %} {%- for rule in D1 %}
{{ rule }} {{ rule }}
{%- endfor %} {%- endfor %}
@@ -109,12 +97,10 @@ COMMIT
{%- endif %} {%- endif %}
-A FORWARD -j DOCKER-USER -A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1 -A FORWARD -j DOCKER-ISOLATION-STAGE-1
{%- for NETNAME in NODE_NETWORKS %} -A FORWARD -o sobridge -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o {{ NETNAME }} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A FORWARD -o sobridge -j DOCKER
-A FORWARD -o {{ NETNAME }} -j DOCKER -A FORWARD -i sobridge ! -o sobridge -j ACCEPT
-A FORWARD -i {{ NETNAME }} ! -o {{ NETNAME }} -j ACCEPT -A FORWARD -i sobridge -o sobridge -j ACCEPT
-A FORWARD -i {{ NETNAME }} -o {{ NETNAME }} -j ACCEPT
{%- endfor %}
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i lo -j ACCEPT -A FORWARD -i lo -j ACCEPT
-A FORWARD -m conntrack --ctstate INVALID -j DROP -A FORWARD -m conntrack --ctstate INVALID -j DROP
@@ -126,18 +112,13 @@ COMMIT
{%- for rule in D2 %} {%- for rule in D2 %}
{{ rule }} {{ rule }}
{%- endfor %} {%- endfor %}
{% for NETNAME in NODE_NETWORKS %}
-A DOCKER-ISOLATION-STAGE-1 -i {{ NETNAME }} ! -o {{ NETNAME }} -j DOCKER-ISOLATION-STAGE-2 -A DOCKER-ISOLATION-STAGE-1 -i sobridge ! -o sobridge -j DOCKER-ISOLATION-STAGE-2
{%- endfor %}
-A DOCKER-ISOLATION-STAGE-1 -j RETURN -A DOCKER-ISOLATION-STAGE-1 -j RETURN
{%- for NETNAME in NODE_NETWORKS %} -A DOCKER-ISOLATION-STAGE-2 -o sobridge -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o {{ NETNAME }} -j DROP
{%- endfor %}
-A DOCKER-ISOLATION-STAGE-2 -j RETURN -A DOCKER-ISOLATION-STAGE-2 -j RETURN
{%- for NETNAME in NODE_NETWORKS %} -A DOCKER-USER ! -i sobridge -o sobridge -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-USER ! -i {{ NETNAME }} -o {{ NETNAME }} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-USER ! -i sobridge -o sobridge -j LOGGING
-A DOCKER-USER ! -i {{ NETNAME }} -o {{ NETNAME }} -j LOGGING
{%- endfor %}
-A DOCKER-USER -j RETURN -A DOCKER-USER -j RETURN
-A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables-dropped: " -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables-dropped: "
-A LOGGING -j DROP -A LOGGING -j DROP
+2 -6
View File
@@ -4,12 +4,8 @@
{# add our ip to self #} {# add our ip to self #}
{% do FIREWALL_DEFAULT.firewall.hostgroups.self.append(GLOBALS.node_ip) %} {% do FIREWALL_DEFAULT.firewall.hostgroups.self.append(GLOBALS.node_ip) %}
{# add dockernet ranges #} {# add dockernet range #}
{% for NETNAME, NETWORK in DOCKERMERGED.networks.items() %} {% do FIREWALL_DEFAULT.firewall.hostgroups.dockernet.append(DOCKERMERGED.range) %}
{% if not NETWORK.get('manager_only') or GLOBALS.get('is_manager', False) %}
{% do FIREWALL_DEFAULT.firewall.hostgroups.dockernet.append(NETWORK.range) %}
{% endif %}
{% endfor %}
{% if GLOBALS.role == 'so-idh' %} {% if GLOBALS.role == 'so-idh' %}
{% from 'idh/opencanary_config.map.jinja' import IDH_PORTGROUPS %} {% from 'idh/opencanary_config.map.jinja' import IDH_PORTGROUPS %}
+3 -3
View File
@@ -26,8 +26,8 @@ so-hydra:
- hostname: hydra - hostname: hydra
- name: so-hydra - name: so-hydra
- networks: - networks:
- soauth: - sobridge:
- ipv4_address: {{ DOCKERMERGED.containers['so-hydra'].ips['soauth'] }} - ipv4_address: {{ DOCKERMERGED.containers['so-hydra'].ip }}
- binds: - binds:
- /opt/so/conf/hydra/:/hydra-conf:ro - /opt/so/conf/hydra/:/hydra-conf:ro
- /opt/so/log/hydra/:/hydra-log:rw - /opt/so/log/hydra/:/hydra-log:rw
@@ -73,7 +73,7 @@ delete_so-hydra_so-status.disabled:
wait_for_hydra: wait_for_hydra:
http.wait_for_successful_query: http.wait_for_successful_query:
- name: 'http://{{ DOCKERMERGED.containers['so-hydra'].ips['soauth'] }}:4444/health/alive' - name: 'http://{{ GLOBALS.manager }}:4444/health/alive'
- ssl: True - ssl: True
- verify_ssl: False - verify_ssl: False
- status: - status:
-4
View File
@@ -21,16 +21,12 @@ hypervisor_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://hypervisor/tools/sbin - source: salt://hypervisor/tools/sbin
- user: root
- group: root
- file_mode: 744 - file_mode: 744
hypervisor_sbin_jinja: hypervisor_sbin_jinja:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://hypervisor/tools/sbin_jinja - source: salt://hypervisor/tools/sbin_jinja
- user: root
- group: root
- template: jinja - template: jinja
- file_mode: 744 - file_mode: 744
+2 -2
View File
@@ -86,8 +86,8 @@ idh_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://idh/tools/sbin - source: salt://idh/tools/sbin
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
#idh_sbin_jinja: #idh_sbin_jinja:
+2 -2
View File
@@ -41,8 +41,8 @@ influxdb_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://influxdb/tools/sbin - source: salt://influxdb/tools/sbin
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
#influxdb_sbin_jinja: #influxdb_sbin_jinja:
+4 -4
View File
@@ -30,16 +30,16 @@ kafka_sbin_tools:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://kafka/tools/sbin - source: salt://kafka/tools/sbin
- user: root - user: 960
- group: root - group: 960
- file_mode: 755 - file_mode: 755
kafka_sbin_jinja_tools: kafka_sbin_jinja_tools:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://kafka/tools/sbin_jinja - source: salt://kafka/tools/sbin_jinja
- user: root - user: 960
- group: root - group: 960
- file_mode: 755 - file_mode: 755
- template: jinja - template: jinja
- defaults: - defaults:
+4 -4
View File
@@ -36,16 +36,16 @@ kibana_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://kibana/tools/sbin - source: salt://kibana/tools/sbin
- user: root - user: 932
- group: root - group: 939
- file_mode: 755 - file_mode: 755
kibana_sbin_jinja: kibana_sbin_jinja:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://kibana/tools/sbin_jinja - source: salt://kibana/tools/sbin_jinja
- user: root - user: 932
- group: root - group: 939
- file_mode: 755 - file_mode: 755
- template: jinja - template: jinja
- defaults: - defaults:
+3 -3
View File
@@ -19,8 +19,8 @@ so-kratos:
- hostname: kratos - hostname: kratos
- name: so-kratos - name: so-kratos
- networks: - networks:
- soauth: - sobridge:
- ipv4_address: {{ DOCKERMERGED.containers['so-kratos'].ips['soauth'] }} - ipv4_address: {{ DOCKERMERGED.containers['so-kratos'].ip }}
- binds: - binds:
- /opt/so/conf/kratos/:/kratos-conf:ro - /opt/so/conf/kratos/:/kratos-conf:ro
- /opt/so/log/kratos/:/kratos-log:rw - /opt/so/log/kratos/:/kratos-log:rw
@@ -71,7 +71,7 @@ delete_so-kratos_so-status.disabled:
wait_for_kratos: wait_for_kratos:
http.wait_for_successful_query: http.wait_for_successful_query:
- name: 'http://{{ DOCKERMERGED.containers['so-kratos'].ips['soauth'] }}:4434/' - name: 'http://{{ GLOBALS.manager }}:4434/'
- ssl: True - ssl: True
- verify_ssl: False - verify_ssl: False
- status: - status:
-2
View File
@@ -6,8 +6,6 @@ so-fix-salt-ldap_script:
file.managed: file.managed:
- name: /usr/sbin/so-fix-salt-ldap.py - name: /usr/sbin/so-fix-salt-ldap.py
- source: salt://libvirt/64962/scripts/so-fix-salt-ldap.py - source: salt://libvirt/64962/scripts/so-fix-salt-ldap.py
- user: root
- group: root
- mode: 744 - mode: 744
fix-salt-ldap: fix-salt-ldap:
+2 -2
View File
@@ -40,8 +40,8 @@ logstash_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://logstash/tools/sbin - source: salt://logstash/tools/sbin
- user: root - user: 931
- group: root - group: 939
- file_mode: 755 - file_mode: 755
#logstash_sbin_jinja: #logstash_sbin_jinja:
+7 -11
View File
@@ -113,8 +113,8 @@ manager_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://manager/tools/sbin - source: salt://manager/tools/sbin
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
- exclude_pat: - exclude_pat:
- "*_test.py" - "*_test.py"
@@ -124,8 +124,8 @@ manager_sbin_jinja:
file.recurse: file.recurse:
- name: /usr/sbin/ - name: /usr/sbin/
- source: salt://manager/tools/sbin_jinja/ - source: salt://manager/tools/sbin_jinja/
- user: root - user: socore
- group: root - group: socore
- file_mode: 755 - file_mode: 755
- template: jinja - template: jinja
- show_changes: False - show_changes: False
@@ -190,15 +190,11 @@ so_fleetagent_monitor:
- month: '*' - month: '*'
- dayweek: '*' - dayweek: '*'
# This tree is the source of every root-executed script (/usr/sbin, reactors, _runners, socore_own_saltstack_default:
# engines, salt-relay.sh). SOC mounts /opt/so/saltstack rw as uid 939 but only writes
# under local/. Do not add dir_mode/file_mode here -- SOC reads default/ and 750/640
# would break its config load.
root_own_saltstack_default:
file.directory: file.directory:
- name: /opt/so/saltstack/default - name: /opt/so/saltstack/default
- user: root - user: socore
- group: root - group: socore
- recurse: - recurse:
- user - user
- group - group
+8 -13
View File
@@ -106,8 +106,7 @@ while [[ $# -gt 0 ]]; do
esac esac
done done
hydraContainer=${HYDRA_CONTAINER:-so-hydra} hydraUrl=${HYDRA_URL:-http://127.0.0.1:4445}
hydraUrl=${HYDRA_URL:-http://localhost:4445}
socRolesFile=${SOC_ROLES_FILE:-/opt/so/conf/soc/soc_clients_roles} socRolesFile=${SOC_ROLES_FILE:-/opt/so/conf/soc/soc_clients_roles}
soUID=${SOCORE_UID:-939} soUID=${SOCORE_UID:-939}
soGID=${SOCORE_GID:-939} soGID=${SOCORE_GID:-939}
@@ -125,10 +124,6 @@ function fail() {
exit 1 exit 1
} }
function hydraCurl() {
docker exec "$hydraContainer" curl "$@"
}
function require() { function require() {
cmd=$1 cmd=$1
which "$1" 2>&1 > /dev/null which "$1" 2>&1 > /dev/null
@@ -138,8 +133,8 @@ function require() {
# Verify this environment is capable of running this script # Verify this environment is capable of running this script
function verifyEnvironment() { function verifyEnvironment() {
require "jq" require "jq"
require "docker" require "curl"
response=$(hydraCurl -Ss -L ${hydraUrl}/health/alive) response=$(curl -Ss -L ${hydraUrl}/health/alive)
[[ "$response" != '{"status":"ok"}' ]] && fail "Unable to communicate with Hydra; specify URL via HYDRA_URL environment variable" [[ "$response" != '{"status":"ok"}' ]] && fail "Unable to communicate with Hydra; specify URL via HYDRA_URL environment variable"
} }
@@ -169,7 +164,7 @@ function ensureRoleFileExists() {
} }
function listClients() { function listClients() {
response=$(hydraCurl -Ss -L -f ${hydraUrl}/admin/clients) response=$(curl -Ss -L -f ${hydraUrl}/admin/clients)
[[ $? != 0 ]] && fail "Unable to communicate with Hydra" [[ $? != 0 ]] && fail "Unable to communicate with Hydra"
clientIds=$(echo "${response}" | jq -r ".[] | .client_id" | sort) clientIds=$(echo "${response}" | jq -r ".[] | .client_id" | sort)
@@ -256,7 +251,7 @@ function createClient() {
EOF EOF
) )
response=$(hydraCurl -Ss -L --fail-with-body -X POST ${hydraUrl}/admin/clients -d "$body") response=$(curl -Ss -L --fail-with-body -X POST ${hydraUrl}/admin/clients -d "$body")
if [[ $? != 0 ]]; then if [[ $? != 0 ]]; then
error=$(echo $response | jq .error) error=$(echo $response | jq .error)
fail "Failed to submit request to Hydra: $error" fail "Failed to submit request to Hydra: $error"
@@ -288,7 +283,7 @@ function update() {
EOF EOF
) )
response=$(hydraCurl -Ss -L --fail-with-body -X PATCH ${hydraUrl}/admin/clients/$id -d "$body") response=$(curl -Ss -L --fail-with-body -X PATCH ${hydraUrl}/admin/clients/$id -d "$body")
if [[ $? != 0 ]]; then if [[ $? != 0 ]]; then
error=$(echo $response | jq .error) error=$(echo $response | jq .error)
fail "Failed to submit request to Hydra: $error" fail "Failed to submit request to Hydra: $error"
@@ -310,7 +305,7 @@ function generateSecret() {
EOF EOF
) )
response=$(hydraCurl -Ss -L --fail-with-body -X PATCH ${hydraUrl}/admin/clients/$id -d "$body") response=$(curl -Ss -L --fail-with-body -X PATCH ${hydraUrl}/admin/clients/$id -d "$body")
if [[ $? != 0 ]]; then if [[ $? != 0 ]]; then
error=$(echo $response | jq .error) error=$(echo $response | jq .error)
fail "Failed to submit request to Hydra: $error" fail "Failed to submit request to Hydra: $error"
@@ -322,7 +317,7 @@ function deleteClient() {
[[ ${identityId} == "" ]] && fail "Client not found" [[ ${identityId} == "" ]] && fail "Client not found"
response=$(hydraCurl -Ss -XDELETE -L --fail-with-body "${hydraUrl}/admin/clients/$identityId") response=$(curl -Ss -XDELETE -L --fail-with-body "${hydraUrl}/admin/clients/$identityId")
if [[ $? != 0 ]]; then if [[ $? != 0 ]]; then
error=$(echo $response | jq .error) error=$(echo $response | jq .error)
fail "Failed to submit request to Hydra: $error" fail "Failed to submit request to Hydra: $error"
+6 -84
View File
@@ -121,14 +121,8 @@ for i in "$@"; do
esac esac
done done
if [[ -n "$MINION_ID" && ! "$MINION_ID" =~ ^[A-Za-z0-9._-]{1,253}$ ]]; then PILLARFILE=/opt/so/saltstack/local/pillar/minions/$MINION_ID.sls
echo "Invalid minion id: $MINION_ID" ADVPILLARFILE=/opt/so/saltstack/local/pillar/minions/adv_$MINION_ID.sls
log "ERROR" "Invalid minion id: $MINION_ID"
exit 1
fi
readonly PILLARFILE=/opt/so/saltstack/local/pillar/minions/$MINION_ID.sls
readonly ADVPILLARFILE=/opt/so/saltstack/local/pillar/minions/adv_$MINION_ID.sls
function getinstallinfo() { function getinstallinfo() {
log "INFO" "Getting install info for minion $MINION_ID" log "INFO" "Getting install info for minion $MINION_ID"
@@ -139,23 +133,10 @@ function getinstallinfo() {
return 1 return 1
fi fi
# install.txt is controlled by the minion; only accept known keys and never eval or export them while read -r var; do export "$var"; done <<< "$INSTALLVARS"
local line key if [ $? -ne 0 ]; then
while IFS= read -r line; do log "ERROR" "Failed to source install variables"
[[ "$line" == *=* ]] || continue return 1
key=${line%%=*}
case "$key" in
MAINIP|MNIC|NODE_DESCRIPTION|ES_HEAP_SIZE|PATCHSCHEDULENAME|INTERFACE|NODETYPE|CORECOUNT|LSHOSTNAME|LSHEAP|CPUCORES|IDH_MGTRESTRICT|IDH_SERVICES)
printf -v "$key" '%s' "${line#*=}"
;;
*)
log "WARN" "Ignoring unexpected install var from $MINION_ID: ${key:0:64}"
;;
esac
done <<< "$INSTALLVARS"
if [[ "$NODE_DESCRIPTION" == \'*\' ]]; then
NODE_DESCRIPTION=${NODE_DESCRIPTION:1:-1}
fi fi
log "INFO" "Fetched install info for $MINION_ID (node type: ${NODETYPE:-unset})" log "INFO" "Fetched install info for $MINION_ID (node type: ${NODETYPE:-unset})"
@@ -195,12 +176,6 @@ function pcapspace() {
fi fi
fi fi
# Must be checked before arithmetic expansion, which evaluates array subscripts
if [[ ! "$SPACESIZE" =~ ^[0-9]+$ ]]; then
log "ERROR" "Invalid disk size for $MINION_ID: ${SPACESIZE:0:64}"
return 1
fi
local s=$(( $SPACESIZE / 1000000 )) local s=$(( $SPACESIZE / 1000000 ))
local s1=$(( $s / 4 * $PCAP_PERCENTAGE )) local s1=$(( $s / 4 * $PCAP_PERCENTAGE ))
@@ -1075,57 +1050,6 @@ function updateMineAndApplyStates() {
fi fi
} }
# Values end up in a Jinja-rendered pillar and in bash, and may come from the minion
function validate_minion_vars() {
local error_msg=""
# Inline rather than valid_ip4: so-common is not installed yet when setup runs -o=setup
local octet='(25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])'
local ip4_re="^($octet\.){3}$octet$"
case "$NODETYPE" in
EVAL|STANDALONE|MANAGER|MANAGERSEARCH|MANAGERHYPE|IMPORT)
# Manager pillars also rewrite the CA pillar, so never accept them from a remote node
[[ "$OPERATION" == "setup" ]] || error_msg="Node type $NODETYPE can only be configured during setup"
;;
FLEET|IDH|HEAVYNODE|SENSOR|SEARCHNODE|RECEIVER|HYPERVISOR|DESKTOP)
;;
*)
error_msg="Invalid node type: ${NODETYPE:0:64}"
;;
esac
if [[ -z "$error_msg" ]]; then
if [[ ! "$MAINIP" =~ $ip4_re ]]; then
error_msg="Invalid MAINIP: ${MAINIP:0:64}"
elif [[ ! "$MNIC" =~ ^[A-Za-z0-9._-]*$ ]]; then
error_msg="Invalid MNIC: ${MNIC:0:64}"
elif [[ ! "$INTERFACE" =~ ^[A-Za-z0-9._-]*$ ]]; then
error_msg="Invalid INTERFACE: ${INTERFACE:0:64}"
elif [[ ! "$LSHOSTNAME" =~ ^[A-Za-z0-9._-]*$ ]]; then
error_msg="Invalid LSHOSTNAME: ${LSHOSTNAME:0:64}"
elif [[ ! "$ES_HEAP_SIZE" =~ ^([0-9]+[kKmMgG]?)?$ ]]; then
error_msg="Invalid ES_HEAP_SIZE: ${ES_HEAP_SIZE:0:64}"
elif [[ ! "$LSHEAP" =~ ^([0-9]+[kKmMgG]?)?$ ]]; then
error_msg="Invalid LSHEAP: ${LSHEAP:0:64}"
elif [[ ! "$CORECOUNT" =~ ^[0-9]*$ ]]; then
error_msg="Invalid CORECOUNT: ${CORECOUNT:0:64}"
elif [[ ! "$CPUCORES" =~ ^[0-9]*$ ]]; then
error_msg="Invalid CPUCORES: ${CPUCORES:0:64}"
elif [[ ! "$IDH_MGTRESTRICT" =~ ^(True|False)?$ ]]; then
error_msg="Invalid IDH_MGTRESTRICT: ${IDH_MGTRESTRICT:0:64}"
fi
fi
if [[ -n "$error_msg" ]]; then
log "ERROR" "$error_msg"
echo "$error_msg"
return 1
fi
# Free text; removing braces is enough to prevent any Jinja delimiter
NODE_DESCRIPTION=${NODE_DESCRIPTION//[\{\}[:cntrl:]]/}
}
function setupMinionFiles() { function setupMinionFiles() {
log "INFO" "Setting up minion files for $MINION_ID (pillar: $PILLARFILE)" log "INFO" "Setting up minion files for $MINION_ID (pillar: $PILLARFILE)"
@@ -1137,8 +1061,6 @@ function setupMinionFiles() {
return 1 return 1
fi fi
validate_minion_vars || return 1
# Create the base minion files # Create the base minion files
create_minion_files || return 1 create_minion_files || return 1
+2 -2
View File
@@ -124,8 +124,8 @@ copy_new_files() {
rsync -a salt $default_salt_dir/ rsync -a salt $default_salt_dir/
rsync -a pillar $default_salt_dir/ rsync -a pillar $default_salt_dir/
chown -R root:root $default_salt_dir/salt chown -R socore:socore $default_salt_dir/salt
chown -R root:root $default_salt_dir/pillar chown -R socore:socore $default_salt_dir/pillar
chmod 755 $default_salt_dir/pillar/firewall/addfirewall.sh chmod 755 $default_salt_dir/pillar/firewall/addfirewall.sh
rm -rf /tmp/sogh rm -rf /tmp/sogh
+11 -16
View File
@@ -129,8 +129,7 @@ while [[ $# -gt 0 ]]; do
esac esac
done done
kratosContainer=${KRATOS_CONTAINER:-so-kratos} kratosUrl=${KRATOS_URL:-http://127.0.0.1:4434/admin}
kratosUrl=${KRATOS_URL:-http://localhost:4434/admin}
databasePath=${KRATOS_DB_PATH:-/nsm/kratos/db/db.sqlite} databasePath=${KRATOS_DB_PATH:-/nsm/kratos/db/db.sqlite}
databaseTimeout=${KRATOS_DB_TIMEOUT:-5000} databaseTimeout=${KRATOS_DB_TIMEOUT:-5000}
bcryptRounds=${BCRYPT_ROUNDS:-12} bcryptRounds=${BCRYPT_ROUNDS:-12}
@@ -155,10 +154,6 @@ function fail() {
exit 1 exit 1
} }
function kratosCurl() {
docker exec "$kratosContainer" curl "$@"
}
function require() { function require() {
cmd=$1 cmd=$1
which "$1" 2>&1 > /dev/null which "$1" 2>&1 > /dev/null
@@ -169,18 +164,18 @@ function require() {
function verifyEnvironment() { function verifyEnvironment() {
require "htpasswd" require "htpasswd"
require "jq" require "jq"
require "docker" require "curl"
require "openssl" require "openssl"
require "sqlite3" require "sqlite3"
[[ ! -f $databasePath ]] && fail "Unable to find database file; specify path via KRATOS_DB_PATH environment variable" [[ ! -f $databasePath ]] && fail "Unable to find database file; specify path via KRATOS_DB_PATH environment variable"
response=$(kratosCurl -Ss -L ${kratosUrl}/) response=$(curl -Ss -L ${kratosUrl}/)
[[ "$response" != "404 page not found" ]] && fail "Unable to communicate with Kratos; specify URL via KRATOS_URL environment variable" [[ "$response" != "404 page not found" ]] && fail "Unable to communicate with Kratos; specify URL via KRATOS_URL environment variable"
} }
function findIdByEmail() { function findIdByEmail() {
email=${1,,} email=${1,,}
response=$(kratosCurl -Ss -L ${kratosUrl}/identities) response=$(curl -Ss -L ${kratosUrl}/identities)
identityId=$(echo "${response}" | jq -r ".[] | select(.verifiable_addresses[0].value == \"$email\") | .id") identityId=$(echo "${response}" | jq -r ".[] | select(.verifiable_addresses[0].value == \"$email\") | .id")
echo $identityId echo $identityId
} }
@@ -421,7 +416,7 @@ function syncAll() {
} }
function listUsers() { function listUsers() {
response=$(kratosCurl -Ss -L ${kratosUrl}/identities) response=$(curl -Ss -L ${kratosUrl}/identities)
[[ $? != 0 ]] && fail "Unable to communicate with Kratos" [[ $? != 0 ]] && fail "Unable to communicate with Kratos"
users=$(echo "${response}" | jq -r ".[] | .verifiable_addresses[0].value" | sort) users=$(echo "${response}" | jq -r ".[] | .verifiable_addresses[0].value" | sort)
@@ -500,7 +495,7 @@ function createUser() {
EOF EOF
) )
response=$(kratosCurl -Ss -L ${kratosUrl}/identities -d "$addUserJson") response=$(curl -Ss -L ${kratosUrl}/identities -d "$addUserJson")
[[ $? != 0 ]] && fail "Unable to communicate with Kratos" [[ $? != 0 ]] && fail "Unable to communicate with Kratos"
identityId=$(echo "${response}" | jq -r ".id") identityId=$(echo "${response}" | jq -r ".id")
@@ -523,7 +518,7 @@ function updateStatus() {
identityId=$(findIdByEmail "$email") identityId=$(findIdByEmail "$email")
[[ ${identityId} == "" ]] && fail "User not found" [[ ${identityId} == "" ]] && fail "User not found"
response=$(kratosCurl -Ss -L "${kratosUrl}/identities/$identityId") response=$(curl -Ss -L "${kratosUrl}/identities/$identityId")
[[ $? != 0 ]] && fail "Unable to communicate with Kratos" [[ $? != 0 ]] && fail "Unable to communicate with Kratos"
schemaId=$(echo "$response" | jq -r .schema_id) schemaId=$(echo "$response" | jq -r .schema_id)
@@ -536,7 +531,7 @@ function updateStatus() {
state="inactive" state="inactive"
fi fi
body="{ \"schema_id\": \"$schemaId\", \"state\": \"$state\", \"traits\": $traitBlock }" body="{ \"schema_id\": \"$schemaId\", \"state\": \"$state\", \"traits\": $traitBlock }"
response=$(kratosCurl -fSsL -XPUT -H "Content-Type: application/json" "${kratosUrl}/identities/$identityId" -d "$body") response=$(curl -fSsL -XPUT -H "Content-Type: application/json" "${kratosUrl}/identities/$identityId" -d "$body")
[[ $? != 0 ]] && fail "Unable to update user" [[ $? != 0 ]] && fail "Unable to update user"
} }
@@ -555,7 +550,7 @@ function updateUserProfile() {
identityId=$(findIdByEmail "$email") identityId=$(findIdByEmail "$email")
[[ ${identityId} == "" ]] && fail "User not found" [[ ${identityId} == "" ]] && fail "User not found"
response=$(kratosCurl -Ss -L "${kratosUrl}/identities/$identityId") response=$(curl -Ss -L "${kratosUrl}/identities/$identityId")
[[ $? != 0 ]] && fail "Unable to communicate with Kratos" [[ $? != 0 ]] && fail "Unable to communicate with Kratos"
schemaId=$(echo "$response" | jq -r .schema_id) schemaId=$(echo "$response" | jq -r .schema_id)
@@ -564,7 +559,7 @@ function updateUserProfile() {
traitBlock="{\"email\":\"$email\",\"firstName\":\"$firstName\",\"lastName\":\"$lastName\",\"note\":\"$note\"}" traitBlock="{\"email\":\"$email\",\"firstName\":\"$firstName\",\"lastName\":\"$lastName\",\"note\":\"$note\"}"
body="{ \"schema_id\": \"$schemaId\", \"state\": \"$state\", \"traits\": $traitBlock }" body="{ \"schema_id\": \"$schemaId\", \"state\": \"$state\", \"traits\": $traitBlock }"
response=$(kratosCurl -fSsL -XPUT -H "Content-Type: application/json" "${kratosUrl}/identities/$identityId" -d "$body") response=$(curl -fSsL -XPUT -H "Content-Type: application/json" "${kratosUrl}/identities/$identityId" -d "$body")
[[ $? != 0 ]] && fail "Unable to update user" [[ $? != 0 ]] && fail "Unable to update user"
} }
@@ -574,7 +569,7 @@ function deleteUser() {
identityId=$(findIdByEmail "$email") identityId=$(findIdByEmail "$email")
[[ ${identityId} == "" ]] && fail "User not found" [[ ${identityId} == "" ]] && fail "User not found"
response=$(kratosCurl -Ss -XDELETE -L "${kratosUrl}/identities/$identityId") response=$(curl -Ss -XDELETE -L "${kratosUrl}/identities/$identityId")
[[ $? != 0 ]] && fail "Unable to communicate with Kratos" [[ $? != 0 ]] && fail "Unable to communicate with Kratos"
rolesTmpFile="${socRolesFile}.tmp" rolesTmpFile="${socRolesFile}.tmp"
-79
View File
@@ -28,7 +28,6 @@ INSTALLEDSALTVERSION=$(salt --versions-report | grep Salt: | awk '{print $2}')
# percentage like "25%"). Empty means so-soup-grid-highstate uses the salt:auto_apply:batch # percentage like "25%"). Empty means so-soup-grid-highstate uses the salt:auto_apply:batch
# pillar default. # pillar default.
BATCHSIZE= BATCHSIZE=
DEFAULT_DOCKER_RANGE='172.17.1.0/24'
SOUP_LOG=/root/soup.log SOUP_LOG=/root/soup.log
SOUP_DEBUG_LOG=/root/soup-debug.log SOUP_DEBUG_LOG=/root/soup-debug.log
WHATWOULDYOUSAYYAHDOHERE=soup WHATWOULDYOUSAYYAHDOHERE=soup
@@ -606,7 +605,6 @@ preupgrade_changes() {
[[ "$INSTALLEDVERSION" == "3.0.0" ]] && up_to_3.1.0 [[ "$INSTALLEDVERSION" == "3.0.0" ]] && up_to_3.1.0
[[ "$INSTALLEDVERSION" == "3.1.0" ]] && up_to_3.2.0 [[ "$INSTALLEDVERSION" == "3.1.0" ]] && up_to_3.2.0
[[ "$INSTALLEDVERSION" == "3.2.0" ]] && up_to_3.3.0 [[ "$INSTALLEDVERSION" == "3.2.0" ]] && up_to_3.3.0
[[ "$INSTALLEDVERSION" == "3.3.0" ]] && up_to_3.4.0
true true
} }
@@ -625,7 +623,6 @@ postupgrade_changes() {
[[ "$POSTVERSION" == "3.0.0" ]] && post_to_3.1.0 [[ "$POSTVERSION" == "3.0.0" ]] && post_to_3.1.0
[[ "$POSTVERSION" == "3.1.0" ]] && post_to_3.2.0 [[ "$POSTVERSION" == "3.1.0" ]] && post_to_3.2.0
[[ "$POSTVERSION" == "3.2.0" ]] && post_to_3.3.0 [[ "$POSTVERSION" == "3.2.0" ]] && post_to_3.3.0
[[ "$POSTVERSION" == "3.3.0" ]] && post_to_3.4.0
# All applicable post-upgrade steps completed; clear the resume marker. # All applicable post-upgrade steps completed; clear the resume marker.
rm -f "$POSTVERSION_FILE" rm -f "$POSTVERSION_FILE"
true true
@@ -1176,82 +1173,6 @@ post_to_3.3.0() {
} }
### 3.3.0 End ### ### 3.3.0 End ###
### 3.4.0 Scripts ###
up_to_3.4.0() {
set_soauth_range
echo "Removing so-kratos, so-hydra and so-soc so they are recreated on the soauth network."
docker rm -f so-kratos so-hydra so-soc >> $SOUP_LOG 2>&1
INSTALLEDVERSION=3.4.0
}
set_soauth_range() {
local pillar_file=/opt/so/saltstack/local/pillar/docker/soc_docker.sls
local current_range suggested authnet authgw input
[[ -f "$pillar_file" ]] || return 0
current_range=$(so-yaml.py get -r "$pillar_file" docker.range 2>/dev/null) || return 0
# A default range gets the 172.17.2.0/24 from docker/defaults.yaml, same as a fresh
# install, so there is nothing to ask about.
[[ -n "$current_range" && "$current_range" != "$DEFAULT_DOCKER_RANGE" ]] || return 0
if so-yaml.py get -r "$pillar_file" docker.networks.soauth.range >/dev/null 2>&1; then
return 0
fi
suggested=$(echo "${current_range%%/*}" | awk -F'.' '{ printf "%s.%s.%s.%s", $1, $2, ($3 + 1) % 256, $4 }')
if [[ -z $UNATTENDED ]]; then
echo ""
echo "This grid uses a custom Docker range ($current_range). The authentication"
echo "services are moving to their own isolated network, which needs a second /24"
echo "that does not overlap it."
echo ""
while :; do
read -rp "Enter the network without the /24 suffix, or press Enter for ${suggested}: " input
[[ -z "$input" ]] && input="$suggested"
if valid_soauth_range "$input" "$current_range"; then
authnet="$input"
break
fi
echo "That range must be a valid IPv4 network, must not be within 172.17.0.0/24, and must not overlap ${current_range}."
done
else
if ! valid_soauth_range "$suggested" "$current_range"; then
FINAL_MESSAGE_QUEUE+=("WARNING: Unable to pick a range for the authentication network alongside $current_range. Set it manually before the next highstate:")
FINAL_MESSAGE_QUEUE+=(" - so-yaml.py add $pillar_file docker.networks.soauth.range <network>/24")
FINAL_MESSAGE_QUEUE+=(" - so-yaml.py add $pillar_file docker.networks.soauth.gateway <gateway>")
return 0
fi
authnet="$suggested"
FINAL_MESSAGE_QUEUE+=("NOTE: The authentication services moved to an isolated Docker network and were assigned ${authnet}/24.")
FINAL_MESSAGE_QUEUE+=(" - If that conflicts with your environment, update docker.networks.soauth in $pillar_file and run so-checkin.")
fi
authgw=$(echo "$authnet" | awk -F'.' '{print $1,$2,$3,1}' OFS='.')
echo "Assigning the authentication network the range ${authnet}/24."
so-yaml.py add "$pillar_file" docker.networks.soauth.range "${authnet}/24" >> $SOUP_LOG 2>&1
so-yaml.py add "$pillar_file" docker.networks.soauth.gateway "$authgw" >> $SOUP_LOG 2>&1
}
valid_soauth_range() {
local candidate=$1 docker_range=$2
valid_ip4 "$candidate" || return 1
[[ $candidate =~ ^172\.17\.0\. ]] && return 1
[[ "${candidate}/24" == "$docker_range" ]] && return 1
return 0
}
post_to_3.4.0() {
set_postversion 3.4.0
}
### 3.4.0 End ###
repo_sync() { repo_sync() {
echo "Sync the local repo." echo "Sync the local repo."
+2 -2
View File
@@ -57,8 +57,8 @@ nginx_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://nginx/tools/sbin - source: salt://nginx/tools/sbin
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
#nginx_sbin_jinja: #nginx_sbin_jinja:
+1 -1
View File
@@ -183,7 +183,7 @@ http {
ssl_prefer_server_ciphers on; ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2 TLSv1.3; ssl_protocols TLSv1.2 TLSv1.3;
location ~* (^/login|^/login/.*|^/js/.*|^/css/.*|^/images/.*|^/pages/.*|^/docs/.*) { location ~* (^/login/.*|^/js/.*|^/css/.*|^/images/.*|^/pages/.*|^/docs/.*) {
proxy_pass http://{{ GLOBALS.manager }}:9822; proxy_pass http://{{ GLOBALS.manager }}:9822;
proxy_read_timeout 90; proxy_read_timeout 90;
proxy_connect_timeout 90; proxy_connect_timeout 90;
+4 -4
View File
@@ -50,16 +50,16 @@ redis_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://redis/tools/sbin - source: salt://redis/tools/sbin
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
redis_sbin_jinja: redis_sbin_jinja:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://redis/tools/sbin_jinja - source: salt://redis/tools/sbin_jinja
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
- template: jinja - template: jinja
+2 -4
View File
@@ -3,8 +3,6 @@ salt_bootstrap:
file.managed: file.managed:
- name: /usr/sbin/bootstrap-salt.sh - name: /usr/sbin/bootstrap-salt.sh
- source: salt://salt/scripts/bootstrap-salt.sh - source: salt://salt/scripts/bootstrap-salt.sh
- user: root
- group: root
- mode: 755 - mode: 755
- show_changes: False - show_changes: False
@@ -12,6 +10,6 @@ salt_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://salt/tools/sbin - source: salt://salt/tools/sbin
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
-2
View File
@@ -35,8 +35,6 @@ combine_bond_script:
file.managed: file.managed:
- name: /usr/sbin/so-combine-bond - name: /usr/sbin/so-combine-bond
- source: salt://sensor/tools/sbin_jinja/so-combine-bond - source: salt://sensor/tools/sbin_jinja/so-combine-bond
- user: root
- group: root
- mode: 755 - mode: 755
- template: jinja - template: jinja
- defaults: - defaults:
+2 -2
View File
@@ -64,8 +64,8 @@ sensoroni_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://sensoroni/tools/sbin - source: salt://sensoroni/tools/sbin
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
#sensoroni_sbin_jinja: #sensoroni_sbin_jinja:
@@ -1,3 +1,2 @@
requests>=2.34.0 requests>=2.31.0
whoisit>=4.0.5 whoisit>=2.7.0
anyio>=4.15.1
+2 -2
View File
@@ -171,8 +171,8 @@ soc_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://soc/tools/sbin - source: salt://soc/tools/sbin
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
#soc_sbin_jinja: #soc_sbin_jinja:
-2
View File
@@ -14,8 +14,6 @@
{% do SOCDEFAULTS.soc.config.server.modules[module].update({'hostUrl': application_url}) %} {% do SOCDEFAULTS.soc.config.server.modules[module].update({'hostUrl': application_url}) %}
{% endfor %} {% endfor %}
{% do SOCDEFAULTS.soc.config.server.modules.kratos.update({'publicHostUrl': 'http://' ~ DOCKERMERGED.containers['so-kratos'].ips['soauth'] ~ ':4433/'}) %}
{# add all grid heavy nodes to soc.server.modules.elastic.remoteHostUrls #} {# add all grid heavy nodes to soc.server.modules.elastic.remoteHostUrls #}
{% for node_type, minions in salt['pillar.get']('elasticsearch:nodes', {}).items() %} {% for node_type, minions in salt['pillar.get']('elasticsearch:nodes', {}).items() %}
{% if node_type in ['heavynode'] %} {% if node_type in ['heavynode'] %}
-68
View File
@@ -1380,7 +1380,6 @@ soc:
retryFailureMaxAttempts: 5 retryFailureMaxAttempts: 5
kratos: kratos:
hostUrl: hostUrl:
publicHostUrl:
hydra: hydra:
hostUrl: hostUrl:
elastalertengine: elastalertengine:
@@ -1466,7 +1465,6 @@ soc:
- core - core
- emerging_threats_addon - emerging_threats_addon
useEsql: false useEsql: false
esqlCaseInsensitive: true
elastic: elastic:
hostUrl: hostUrl:
remoteHostUrls: [] remoteHostUrls: []
@@ -1494,9 +1492,6 @@ soc:
org: Security Onion org: Security Onion
bucket: telegraf/so_short_term bucket: telegraf/so_short_term
verifyCert: false verifyCert: false
notification:
dismissedPruneDays: 30
enabled: false
playbook: playbook:
autoUpdateEnabled: true autoUpdateEnabled: true
playbookImportFrequencySeconds: 86400 playbookImportFrequencySeconds: 86400
@@ -1561,69 +1556,6 @@ soc:
reconcilePersona: "" reconcilePersona: ""
toolUseTurnAttempts: 12 toolUseTurnAttempts: 12
toolUseTurnDelayMs: 175 toolUseTurnDelayMs: 175
tools:
filterEventFields:
- "@timestamp"
- "client.name"
- "destination.ip"
- "destination.port"
- "destination.geo.country_name"
- "dns.query.name"
- "dns.query_name"
- "event.action"
- "event.category"
- "event.module"
- "event.dataset"
- "event.outcome"
- "event.severity"
- "event.severity_label"
- "event.type"
- "event_data.agent.name"
- "event_data.host.os.name"
- "file.mime_type"
- "file.name"
- "hash.md5"
- "hash.sha1"
- "host.mac"
- "host.name"
- "host.os.name"
- "http.method"
- "http.useragent"
- "http.virtual_host"
- "log.id.uid"
- "network.community_id"
- "network.protocol"
- "network.transport"
- "notice.message"
- "observer.name"
- "process.name"
- "process.executable"
- "process.entity_id"
- "process.command_line"
- "process.Ext.ancestry"
- "process.parent.entity_id"
- "process.parent.command_line"
- "rule.category"
- "rule.name"
- "rule.uuid"
- "software.name"
- "software.type"
- "software.version.unparsed"
- "source.ip"
- "source.port"
- "source.geo.country_name"
- "ssh.cypher_algorithm"
- "ssh.client"
- "ssh.server"
- "ssl.cipher"
- "ssl.server_name"
- "ssl.version"
- "system.auth.sudo.command"
- "user.name"
- "user.domain"
- "user.effective.name"
- "weird.name"
- "tags"
onionconfig: onionconfig:
saltstackDir: /opt/so/saltstack saltstackDir: /opt/so/saltstack
bypassEnabled: false bypassEnabled: false
+2 -2
View File
@@ -18,8 +18,8 @@ hypervisor_annotation:
- name: /opt/so/saltstack/default/salt/hypervisor/soc_hypervisor.yaml - name: /opt/so/saltstack/default/salt/hypervisor/soc_hypervisor.yaml
- source: salt://soc/dyanno/hypervisor/soc_hypervisor.yaml.jinja - source: salt://soc/dyanno/hypervisor/soc_hypervisor.yaml.jinja
- template: jinja - template: jinja
- user: root - user: socore
- group: root - group: socore
- defaults: - defaults:
HYPERVISORS: {{ HYPERVISORS }} HYPERVISORS: {{ HYPERVISORS }}
baseDomainStatus: {{ salt['pillar.get']('baseDomain:status', 'Initialized') }} baseDomainStatus: {{ salt['pillar.get']('baseDomain:status', 'Initialized') }}
+1 -3
View File
@@ -23,9 +23,7 @@ so-soc:
- name: so-soc - name: so-soc
- networks: - networks:
- sobridge: - sobridge:
- ipv4_address: {{ DOCKERMERGED.containers['so-soc'].ips['sobridge'] }} - ipv4_address: {{ DOCKERMERGED.containers['so-soc'].ip }}
- soauth:
- ipv4_address: {{ DOCKERMERGED.containers['so-soc'].ips['soauth'] }}
- binds: - binds:
- /nsm/rules:/nsm/rules:rw - /nsm/rules:/nsm/rules:rw
- /opt/so/conf/strelka:/opt/sensoroni/yara:rw - /opt/so/conf/strelka:/opt/sensoroni/yara:rw
-25
View File
@@ -1,31 +1,6 @@
name: Security Onion Baseline Pipeline name: Security Onion Baseline Pipeline
priority: 90 priority: 90
transformations: transformations:
# ES|QL scalar == returns null on multivalued fields; the
# backend reads this key and emits MV_INTERSECTS instead.
- id: declare_multivalue_fields
type: set_state
key: multivalue_fields
val:
- event.type
- event.action
- event.category
- tags
- process.args
- related.ip
- dns.resolved_ip
- id: esql_default_index
type: set_state
key: index
val: .ds-logs-*
- id: esql_source_metadata
type: set_state
key: metadata
val: "_id, _index, _source"
- id: esql_source_keep
type: set_state
key: keep
val: "_id, _index, _source"
- id: baseline_field_name_mapping - id: baseline_field_name_mapping
type: field_name_mapping type: field_name_mapping
mapping: mapping:
-37
View File
@@ -155,14 +155,6 @@ soc:
description: Path to custom markdown templates for PDF report generation. All markdown files in this directory will be available as custom reports in the SOC Reports interface. description: Path to custom markdown templates for PDF report generation. All markdown files in this directory will be available as custom reports in the SOC Reports interface.
global: True global: True
advanced: True advanced: True
schedules:
title: Schedules
description: Schedules that are shared across the Security Onion product. Modify via one of the SOC Schedules view.
readonlyUi: True
global: True
forcedType: string
syntax: json
storage: db
subgrids: subgrids:
title: Subordinate Grids title: Subordinate Grids
description: | description: |
@@ -404,11 +396,6 @@ soc:
global: True global: True
advanced: True advanced: True
forcedType: bool forcedType: bool
esqlCaseInsensitive:
description: "Match string values case-insensitively when converting Sigma rules. Applies to ES|QL only"
global: True
advanced: True
forcedType: bool
elastic: elastic:
index: index:
description: Comma-separated list of indices or index patterns (wildcard "*" supported) that SOC will search for records. description: Comma-separated list of indices or index patterns (wildcard "*" supported) that SOC will search for records.
@@ -489,24 +476,6 @@ soc:
global: True global: True
advanced: True advanced: True
forcedType: bool forcedType: bool
notification:
destinations:
title: Notification Destinations
description: JSON list of notifications. Modify via the SOC Notifications view.
readonlyUi: True
global: True
forcedType: string
syntax: json
storage: db
dismissedPruneDays:
title: Dismissed Retention Days
description: The number of days to retain dismissed notifications. When a notification is dismissed, it will be pruned after this many days. Only one user need dismiss a notification for it to be pruned.
forcedType: int
global: True
enabled:
description: Enables or disables the SOC notification module.
forcedType: bool
global: True
postgres: postgres:
host: host:
description: Hostname or IP address of the PostgreSQL server used by SOC. Defaults to the manager hostname. description: Hostname or IP address of the PostgreSQL server used by SOC. Defaults to the manager hostname.
@@ -791,7 +760,6 @@ soc:
- gemini - gemini
- openai_responses - openai_responses
- openai_chat - openai_chat
- openai_embeddings
- field: apiUrl - field: apiUrl
label: API URL label: API URL
required: False required: False
@@ -948,11 +916,6 @@ soc:
description: The number of times to retry extracting memories from a session if errors occur. description: The number of times to retry extracting memories from a session if errors occur.
global: True global: True
advanced: True advanced: True
tools:
filterEventFields:
description: A whitelist of fields to return when OnionAI uses the query_events tool. All other fields are removed. One field per line.
global: True
multiline: True
client: client:
assistant: assistant:
enabled: enabled:
+2 -2
View File
@@ -51,8 +51,8 @@ strelka_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://strelka/tools/sbin - source: salt://strelka/tools/sbin
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
{% else %} {% else %}
+4 -4
View File
@@ -76,16 +76,16 @@ suricata_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://suricata/tools/sbin - source: salt://suricata/tools/sbin
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
suricata_sbin_jinja: suricata_sbin_jinja:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://suricata/tools/sbin_jinja - source: salt://suricata/tools/sbin_jinja
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
- template: jinja - template: jinja
+2 -2
View File
@@ -65,8 +65,8 @@ telegraf_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://telegraf/tools/sbin - source: salt://telegraf/tools/sbin
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
#telegraf_sbin_jinja: #telegraf_sbin_jinja:
+2 -2
View File
@@ -54,8 +54,8 @@
{% {%
do GLOBALS.update({ do GLOBALS.update({
'application_urls': { 'application_urls': {
'hydra': 'http://' ~ DOCKERMERGED.containers['so-hydra'].ips['soauth'] ~ ':4445/', 'hydra': 'http://' ~ GLOBALS.manager ~ ':4445/',
'kratos': 'http://' ~ DOCKERMERGED.containers['so-kratos'].ips['soauth'] ~ ':4434/', 'kratos': 'http://' ~ GLOBALS.manager ~ ':4434/',
'elastic': 'https://' ~ GLOBALS.manager ~ ':9200/', 'elastic': 'https://' ~ GLOBALS.manager ~ ':9200/',
'influxdb': 'https://' ~ GLOBALS.manager ~ ':8086/' 'influxdb': 'https://' ~ GLOBALS.manager ~ ':8086/'
} }
+2 -2
View File
@@ -101,8 +101,8 @@ zeek_sbin:
file.recurse: file.recurse:
- name: /usr/sbin - name: /usr/sbin
- source: salt://zeek/tools/sbin - source: salt://zeek/tools/sbin
- user: root - user: 939
- group: root - group: 939
- file_mode: 755 - file_mode: 755
#zeek_sbin_jinja: #zeek_sbin_jinja:
-1
View File
@@ -18,7 +18,6 @@ zeek:
StatsLogEnable: 0 StatsLogEnable: 0
StatsLogExpireInterval: 0 StatsLogExpireInterval: 0
StatusCmdShowAll: 0 StatusCmdShowAll: 0
StopWait: 1
CrashExpireInterval: 0 CrashExpireInterval: 0
SitePolicyScripts: local.zeek SitePolicyScripts: local.zeek
LogDir: /nsm/zeek/logs LogDir: /nsm/zeek/logs
-10
View File
@@ -9,19 +9,9 @@
include: include:
- zeek.sostatus - zeek.sostatus
# Stop first so the entrypoint's SIGTERM trap can archive the final logs; docker_container.absent
# with force is a 'docker rm -f', which never delivers SIGTERM. force stays so the state still
# converges if the stop overruns.
so-zeek_stopped:
docker_container.stopped:
- name: so-zeek
- error_on_absent: False
so-zeek: so-zeek:
docker_container.absent: docker_container.absent:
- force: True - force: True
- require:
- docker_container: so-zeek_stopped
so-zeek_so-status.disabled: so-zeek_so-status.disabled:
file.comment: file.comment:
-4
View File
@@ -19,10 +19,6 @@ so-zeek:
- restart_policy: unless-stopped - restart_policy: unless-stopped
- start: True - start: True
- privileged: True - privileged: True
# Docker's default 10s grace is not enough for the entrypoint's SIGTERM trap to run
# 'zeekctl stop' and let StopWait archive the final logs. Overrunning it means SIGKILL,
# which strands those logs in spool/tmp and marks every node crashed on the next start.
- stop_timeout: 180
{% if DOCKERMERGED.containers['so-zeek'].ulimits %} {% if DOCKERMERGED.containers['so-zeek'].ulimits %}
- ulimits: - ulimits:
{% for ULIMIT in DOCKERMERGED.containers['so-zeek'].ulimits %} {% for ULIMIT in DOCKERMERGED.containers['so-zeek'].ulimits %}
-12
View File
@@ -99,18 +99,6 @@ zeek:
regexFailureMessage: You must enter a whole number of days, or 0 to keep crash directories forever. regexFailureMessage: You must enter a whole number of days, or 0 to keep crash directories forever.
helpLink: zeek helpLink: zeek
advanced: True advanced: True
StopWait:
description: >-
Set to 1 to make "zeekctl stop" wait for the final logs to be archived instead of
letting that finish in the background. Security Onion stops Zeek by stopping its
container, so anything still running in the background is killed when the container
exits - without this, the last logs of each run are stranded unarchived in
/nsm/zeek/spool/tmp and never reach Elasticsearch. It is read only for that reason.
regex: ^[01]$
regexFailureMessage: You must enter 0 or 1.
helpLink: zeek
advanced: True
readonly: True
MinDiskSpace: MinDiskSpace:
description: >- description: >-
Percentage of free disk space below which ZeekControl reports a warning, or 0 to disable the check Percentage of free disk space below which ZeekControl reports a warning, or 0 to disable the check
-22
View File
@@ -276,20 +276,9 @@ collect_dockernet() {
whiptail_invalid_input whiptail_invalid_input
whiptail_dockernet_sosnet "$DOCKERNET" whiptail_dockernet_sosnet "$DOCKERNET"
done done
whiptail_authnet_sosnet "$(adjacent_net "$DOCKERNET")"
while ! valid_ip4 "$AUTHNET" || [[ $AUTHNET =~ "172.17.0." ]] || [[ "$AUTHNET" == "$DOCKERNET" ]]; do
whiptail_invalid_input
whiptail_authnet_sosnet "$AUTHNET"
done
fi fi
} }
adjacent_net() {
echo "$1" | awk -F'.' '{ printf "%s.%s.%s.%s", $1, $2, ($3 + 1) % 256, $4 }'
}
collect_gateway() { collect_gateway() {
whiptail_management_interface_gateway whiptail_management_interface_gateway
@@ -1410,15 +1399,6 @@ docker_pillar() {
"docker:"\ "docker:"\
" range: '$DOCKERNET/24'"\ " range: '$DOCKERNET/24'"\
" gateway: '$DOCKERGATEWAY'" > $docker_pillar_file " gateway: '$DOCKERGATEWAY'" > $docker_pillar_file
if [ ! -z "$AUTHNET" ]; then
AUTHGATEWAY=$(echo $AUTHNET | awk -F'.' '{print $1,$2,$3,1}' OFS='.')
printf '%s\n'\
" networks:"\
" soauth:"\
" range: '$AUTHNET/24'"\
" gateway: '$AUTHGATEWAY'" >> $docker_pillar_file
fi
fi fi
} }
@@ -2125,8 +2105,6 @@ setup_salt_master_dirs() {
info "Chown the salt dirs on the manager for socore" info "Chown the salt dirs on the manager for socore"
logCmd "chown -R socore:socore /opt/so" logCmd "chown -R socore:socore /opt/so"
# The default tree is root-executed code; SOC reads it but never writes it.
logCmd "chown -R root:root $default_salt_dir"
} }
set_progress_str() { set_progress_str() {
-13
View File
@@ -365,18 +365,6 @@ whiptail_dockernet_sosnet() {
} }
whiptail_authnet_sosnet() {
[ -n "$TESTING" ] && return
AUTHNET=$(whiptail --title "$whiptail_title" --inputbox \
"\nEnter a second /24 size network range WITHOUT the /24 suffix. The authentication services are isolated on their own network so that the identity provider is not reachable from other containers. It must not overlap the range you just entered, and any range within 172.17.0.0/24 cannot be used." 13 65 "$1" 3>&1 1>&2 2>&3)
local exitstatus=$?
whiptail_check_exitstatus $exitstatus
}
whiptail_end_settings() { whiptail_end_settings() {
[ -n "$TESTING" ] && return [ -n "$TESTING" ] && return
@@ -439,7 +427,6 @@ whiptail_end_settings() {
[[ -n $WEBUSER ]] && __append_end_msg "Web User: $WEBUSER" [[ -n $WEBUSER ]] && __append_end_msg "Web User: $WEBUSER"
[[ -n $DOCKERNET ]] && __append_end_msg "Docker network: $DOCKERNET/24" [[ -n $DOCKERNET ]] && __append_end_msg "Docker network: $DOCKERNET/24"
[[ -n $AUTHNET ]] && __append_end_msg "Authentication network: $AUTHNET/24"
if [[ ${#ntp_servers[@]} -gt 0 ]]; then if [[ ${#ntp_servers[@]} -gt 0 ]]; then
__append_end_msg "NTP Servers:" __append_end_msg "NTP Servers:"
for server in "${ntp_servers[@]}"; do for server in "${ntp_servers[@]}"; do