diff --git a/salt/manager/tools/sbin/soup b/salt/manager/tools/sbin/soup index e7784fe4f..9fd9542c0 100755 --- a/salt/manager/tools/sbin/soup +++ b/salt/manager/tools/sbin/soup @@ -1113,7 +1113,7 @@ suricata_idstools_removal_pre() { install -d -o 939 -g 939 -m 755 /opt/so/conf/soc/fingerprints install -o 939 -g 939 -m 644 /dev/null /opt/so/conf/soc/fingerprints/suricataengine.syncBlock cat > /opt/so/conf/soc/fingerprints/suricataengine.syncBlock << EOF -Suricata ruleset sync is blocked until this file is removed. Make sure that you have manually added any custom Suricata rulesets via SOC config - review the documentation for more details: securityonion.net/docs +Suricata ruleset sync is blocked until this file is removed. **CRITICAL** Make sure that you have manually added any custom Suricata rulesets via SOC config before removing this file - review the documentation for more details: https://docs.securityonion.net/en/2.4/nids.html#sync-block EOF # Remove possible symlink & create salt local rules dir @@ -1131,6 +1131,7 @@ if [[ -f /opt/so/conf/soc/so-detections-backup.py ]]; then # Verify backup by comparing counts echo "Verifying detection overrides backup..." es_override_count=$(/sbin/so-elasticsearch-query 'so-detection/_count' \ + --retry 5 --retry-delay 10 --retry-all-errors \ -d '{"query": {"bool": {"must": [{"exists": {"field": "so_detection.overrides"}}]}}}' | jq -r '.count') || { echo " Error: Failed to query Elasticsearch for override count" exit 1 diff --git a/salt/soc/defaults.yaml b/salt/soc/defaults.yaml index 2de9aed2d..28db2ef5f 100644 --- a/salt/soc/defaults.yaml +++ b/salt/soc/defaults.yaml @@ -2652,13 +2652,6 @@ soc: thresholdColorRatioMed: 0.75 thresholdColorRatioMax: 1 availableModels: - - id: sonnet-4 - displayName: Claude Sonnet 4 ($$$) - origin: USA - contextLimitSmall: 200000 - contextLimitLarge: 1000000 - lowBalanceColorAlert: 500000 - enabled: true - id: sonnet-4.5 displayName: Claude Sonnet 4.5 ($$$) origin: USA diff --git a/salt/soc/merged.map.jinja b/salt/soc/merged.map.jinja index 4c301fa9d..349937983 100644 --- a/salt/soc/merged.map.jinja +++ b/salt/soc/merged.map.jinja @@ -70,7 +70,7 @@ {# Define the Detections custom ruleset that should always be present #} {% set CUSTOM_RULESET = { - 'name': 'custom', + 'name': '__custom__', 'description': 'User-created custom rules created via the Detections module in the SOC UI', 'sourceType': 'elasticsearch', 'sourcePath': 'so_detection.ruleset:__custom__', @@ -83,7 +83,7 @@ {# Always append the custom ruleset to suricataengine.rulesetSources if not already present #} {% if SOCMERGED.config.server.modules.suricataengine is defined and SOCMERGED.config.server.modules.suricataengine.rulesetSources is defined %} {% if SOCMERGED.config.server.modules.suricataengine.rulesetSources is not mapping %} -{% set custom_names = SOCMERGED.config.server.modules.suricataengine.rulesetSources | selectattr('name', 'equalto', 'custom') | list %} +{% set custom_names = SOCMERGED.config.server.modules.suricataengine.rulesetSources | selectattr('name', 'equalto', '__custom__') | list %} {% if custom_names | length == 0 %} {% do SOCMERGED.config.server.modules.suricataengine.rulesetSources.append(CUSTOM_RULESET) %} {% endif %} diff --git a/salt/soc/soc_soc.yaml b/salt/soc/soc_soc.yaml index cffcecaa1..11442afba 100644 --- a/salt/soc/soc_soc.yaml +++ b/salt/soc/soc_soc.yaml @@ -608,6 +608,18 @@ soc: label: Delete Unreferenced (Deletes rules that are no longer referenced by ruleset source) forcedType: bool required: False + - field: proxyURL + label: HTTP/HTTPS proxy URL for downloading the ruleset. + required: False + - field: proxyUsername + label: Proxy authentication username. + required: False + - field: proxyPassword + label: Proxy authentication password. + required: False + - field: proxyCACert + label: Path to CA certificate file for MITM proxy verification. + required: False airgap: *serulesetSources navigator: intervalMinutes: diff --git a/salt/suricata/cron/so-suricata-rulestats b/salt/suricata/cron/so-suricata-rulestats index 95b51c58a..459ab894f 100644 --- a/salt/suricata/cron/so-suricata-rulestats +++ b/salt/suricata/cron/so-suricata-rulestats @@ -17,14 +17,23 @@ query() { STATS=$(query "ruleset-stats") RELOAD=$(query "ruleset-reload-time") +[ -z "$RELOAD" ] && RELOAD='{}' -if echo "$STATS" | jq -e '.return == "OK"' > /dev/null 2>&1; then - LOADED=$(echo "$STATS" | jq -r '.message[0].rules_loaded') - FAILED=$(echo "$STATS" | jq -r '.message[0].rules_failed') - LAST_RELOAD=$(echo "$RELOAD" | jq -r '.message[0].last_reload') +# Outputs valid JSON on success, empty on failure +OUTPUT=$(jq -n \ + --argjson stats "$STATS" \ + --argjson reload "$RELOAD" \ + 'if $stats.return == "OK" and ($stats.message[0].rules_loaded | type) == "number" and ($stats.message[0].rules_failed | type) == "number" then + { + rules_loaded: $stats.message[0].rules_loaded, + rules_failed: $stats.message[0].rules_failed, + last_reload: ($reload.message[0].last_reload // ""), + return: "OK" + } + else empty end' 2>/dev/null) - jq -n --argjson loaded "$LOADED" --argjson failed "$FAILED" --arg reload "$LAST_RELOAD" \ - '{rules_loaded: $loaded, rules_failed: $failed, last_reload: $reload, return: "OK"}' > "$OUTFILE" +if [ -n "$OUTPUT" ]; then + echo "$OUTPUT" > "$OUTFILE" else echo '{"return":"FAIL"}' > "$OUTFILE" fi diff --git a/salt/telegraf/scripts/surirules.sh b/salt/telegraf/scripts/surirules.sh index b38d5df26..f4c6885e1 100644 --- a/salt/telegraf/scripts/surirules.sh +++ b/salt/telegraf/scripts/surirules.sh @@ -18,11 +18,15 @@ if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then if [ -f "$STATSFILE" ] && [ $(($(date +%s) - $(stat -c %Y "$STATSFILE"))) -lt 90 ] && jq -e '.return == "OK" and .rules_loaded != null and .rules_failed != null' "$STATSFILE" > /dev/null 2>&1; then LOADED=$(jq -r '.rules_loaded' "$STATSFILE") FAILED=$(jq -r '.rules_failed' "$STATSFILE") - RELOAD_TIME=$(jq -r '.last_reload // ""' "$STATSFILE") + RELOAD_TIME=$(jq -r 'if .last_reload then .last_reload else "" end' "$STATSFILE") - echo "surirules loaded=${LOADED}i,failed=${FAILED}i,reload_time=\"${RELOAD_TIME}\",status=\"ok\"" + if [ -n "$RELOAD_TIME" ]; then + echo "surirules loaded=${LOADED}i,failed=${FAILED}i,reload_time=\"${RELOAD_TIME}\",status=\"ok\"" + else + echo "surirules loaded=${LOADED}i,failed=${FAILED}i,status=\"ok\"" + fi else - echo "surirules loaded=0i,failed=0i,reload_time=\"\",status=\"unknown\"" + echo "surirules loaded=0i,failed=0i,status=\"unknown\"" fi fi