From d518f754685ecb413c0ee4ac3aa0dfd50b19979b Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Thu, 11 Dec 2025 20:07:06 -0600 Subject: [PATCH 01/20] update deprecated config items --- .../pipelines/config/so/0011_input_endgame.conf | 4 ++-- .../so/0012_input_elastic_agent.conf.jinja | 4 ++-- .../config/so/0013_input_lumberjack_fleet.conf | 2 +- .../so/9805_output_elastic_agent.conf.jinja | 16 ++++++++-------- .../config/so/9900_output_endgame.conf.jinja | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/salt/logstash/pipelines/config/so/0011_input_endgame.conf b/salt/logstash/pipelines/config/so/0011_input_endgame.conf index 375585957..c6f9c59e8 100644 --- a/salt/logstash/pipelines/config/so/0011_input_endgame.conf +++ b/salt/logstash/pipelines/config/so/0011_input_endgame.conf @@ -5,10 +5,10 @@ input { codec => es_bulk request_headers_target_field => client_headers remote_host_target_field => client_host - ssl => true + ssl_enabled => true ssl_certificate_authorities => ["/usr/share/filebeat/ca.crt"] ssl_certificate => "/usr/share/logstash/filebeat.crt" ssl_key => "/usr/share/logstash/filebeat.key" - ssl_verify_mode => "peer" + ssl_client_authentication => "required" } } diff --git a/salt/logstash/pipelines/config/so/0012_input_elastic_agent.conf.jinja b/salt/logstash/pipelines/config/so/0012_input_elastic_agent.conf.jinja index 6ba29f8e5..a4d699aff 100644 --- a/salt/logstash/pipelines/config/so/0012_input_elastic_agent.conf.jinja +++ b/salt/logstash/pipelines/config/so/0012_input_elastic_agent.conf.jinja @@ -2,11 +2,11 @@ input { elastic_agent { port => 5055 tags => [ "elastic-agent", "input-{{ GLOBALS.hostname }}" ] - ssl => true + ssl_enabled => true ssl_certificate_authorities => ["/usr/share/filebeat/ca.crt"] ssl_certificate => "/usr/share/logstash/elasticfleet-logstash.crt" ssl_key => "/usr/share/logstash/elasticfleet-logstash.key" - ssl_verify_mode => "force_peer" + ssl_client_authentication => "required" ecs_compatibility => v8 } } diff --git a/salt/logstash/pipelines/config/so/0013_input_lumberjack_fleet.conf b/salt/logstash/pipelines/config/so/0013_input_lumberjack_fleet.conf index fd9a87a22..b31ffee8d 100644 --- a/salt/logstash/pipelines/config/so/0013_input_lumberjack_fleet.conf +++ b/salt/logstash/pipelines/config/so/0013_input_lumberjack_fleet.conf @@ -2,7 +2,7 @@ input { elastic_agent { port => 5056 tags => [ "elastic-agent", "fleet-lumberjack-input" ] - ssl => true + ssl_enabled => true ssl_certificate => "/usr/share/logstash/elasticfleet-lumberjack.crt" ssl_key => "/usr/share/logstash/elasticfleet-lumberjack.key" ecs_compatibility => v8 diff --git a/salt/logstash/pipelines/config/so/9805_output_elastic_agent.conf.jinja b/salt/logstash/pipelines/config/so/9805_output_elastic_agent.conf.jinja index be7ec6898..4fe138dd8 100644 --- a/salt/logstash/pipelines/config/so/9805_output_elastic_agent.conf.jinja +++ b/salt/logstash/pipelines/config/so/9805_output_elastic_agent.conf.jinja @@ -8,8 +8,8 @@ output { document_id => "%{[metadata][_id]}" index => "so-ip-mappings" silence_errors_in_log => ["version_conflict_engine_exception"] - ssl => true - ssl_certificate_verification => false + ssl_enabled => true + ssl_verification_mode => "none" } } else { @@ -25,8 +25,8 @@ output { document_id => "%{[metadata][_id]}" pipeline => "%{[metadata][pipeline]}" silence_errors_in_log => ["version_conflict_engine_exception"] - ssl => true - ssl_certificate_verification => false + ssl_enabled => true + ssl_verification_mode => "none" } } else { @@ -37,8 +37,8 @@ output { user => "{{ ES_USER }}" password => "{{ ES_PASS }}" pipeline => "%{[metadata][pipeline]}" - ssl => true - ssl_certificate_verification => false + ssl_enabled => true + ssl_verification_mode => "none" } } } @@ -49,8 +49,8 @@ output { data_stream => true user => "{{ ES_USER }}" password => "{{ ES_PASS }}" - ssl => true - ssl_certificate_verification => false + ssl_enabled => true + ssl_verification_mode=> "none" } } } diff --git a/salt/logstash/pipelines/config/so/9900_output_endgame.conf.jinja b/salt/logstash/pipelines/config/so/9900_output_endgame.conf.jinja index c056f5774..27e311fc4 100644 --- a/salt/logstash/pipelines/config/so/9900_output_endgame.conf.jinja +++ b/salt/logstash/pipelines/config/so/9900_output_endgame.conf.jinja @@ -13,8 +13,8 @@ output { user => "{{ ES_USER }}" password => "{{ ES_PASS }}" index => "endgame-%{+YYYY.MM.dd}" - ssl => true - ssl_certificate_verification => false + ssl_enabled => true + ssl_verification_mode => "none" } } } From 7977a020ac066f137fefe5e7e24d72029f1a7803 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Tue, 16 Dec 2025 16:03:47 -0600 Subject: [PATCH 02/20] elasticsearch 9.0.8 --- .../integrations/elastic-defend/elastic-defend-endpoints.json | 2 +- salt/elasticfleet/integration-defaults.map.jinja | 1 + .../sbin_jinja/so-elastic-fleet-optional-integrations-load | 2 +- salt/elasticsearch/defaults.yaml | 2 +- salt/elasticsearch/tools/sbin_jinja/so-catrust | 2 +- salt/logstash/defaults.yaml | 2 +- salt/logstash/soc_logstash.yaml | 2 +- 7 files changed, 7 insertions(+), 6 deletions(-) diff --git a/salt/elasticfleet/files/integrations/elastic-defend/elastic-defend-endpoints.json b/salt/elasticfleet/files/integrations/elastic-defend/elastic-defend-endpoints.json index fb9069e83..debfc73a3 100644 --- a/salt/elasticfleet/files/integrations/elastic-defend/elastic-defend-endpoints.json +++ b/salt/elasticfleet/files/integrations/elastic-defend/elastic-defend-endpoints.json @@ -5,7 +5,7 @@ "package": { "name": "endpoint", "title": "Elastic Defend", - "version": "8.18.1", + "version": "9.0.2", "requires_root": true }, "enabled": true, diff --git a/salt/elasticfleet/integration-defaults.map.jinja b/salt/elasticfleet/integration-defaults.map.jinja index 69ce7f3af..f85a95ec9 100644 --- a/salt/elasticfleet/integration-defaults.map.jinja +++ b/salt/elasticfleet/integration-defaults.map.jinja @@ -21,6 +21,7 @@ 'azure_application_insights.app_state': 'azure.app_state', 'azure_billing.billing': 'azure.billing', 'azure_functions.metrics': 'azure.function', + 'azure_ai_foundry.metrics': 'azure.ai_foundry', 'azure_metrics.compute_vm_scaleset': 'azure.compute_vm_scaleset', 'azure_metrics.compute_vm': 'azure.compute_vm', 'azure_metrics.container_instance': 'azure.container_instance', diff --git a/salt/elasticfleet/tools/sbin_jinja/so-elastic-fleet-optional-integrations-load b/salt/elasticfleet/tools/sbin_jinja/so-elastic-fleet-optional-integrations-load index 01777e5da..8c0f627ef 100644 --- a/salt/elasticfleet/tools/sbin_jinja/so-elastic-fleet-optional-integrations-load +++ b/salt/elasticfleet/tools/sbin_jinja/so-elastic-fleet-optional-integrations-load @@ -86,7 +86,7 @@ if [[ -f $STATE_FILE_SUCCESS ]]; then latest_package_list=$(/usr/sbin/so-elastic-fleet-package-list) echo '{ "packages" : []}' > $BULK_INSTALL_PACKAGE_LIST rm -f $INSTALLED_PACKAGE_LIST - echo $latest_package_list | jq '{packages: [.items[] | {name: .name, latest_version: .version, installed_version: .savedObject.attributes.install_version, subscription: .conditions.elastic.subscription }]}' >> $INSTALLED_PACKAGE_LIST + echo $latest_package_list | jq '{packages: [.items[] | {name: .name, latest_version: .version, installed_version: .installationInfo.version, subscription: .conditions.elastic.subscription }]}' >> $INSTALLED_PACKAGE_LIST while read -r package; do # get package details diff --git a/salt/elasticsearch/defaults.yaml b/salt/elasticsearch/defaults.yaml index 5cfb9a0e0..5e36602ca 100644 --- a/salt/elasticsearch/defaults.yaml +++ b/salt/elasticsearch/defaults.yaml @@ -1,6 +1,6 @@ elasticsearch: enabled: false - version: 8.18.8 + version: 9.0.8 index_clean: true config: action: diff --git a/salt/elasticsearch/tools/sbin_jinja/so-catrust b/salt/elasticsearch/tools/sbin_jinja/so-catrust index 16fd3ffdb..89cd9147d 100644 --- a/salt/elasticsearch/tools/sbin_jinja/so-catrust +++ b/salt/elasticsearch/tools/sbin_jinja/so-catrust @@ -15,7 +15,7 @@ set -e if [ ! -f /opt/so/saltstack/local/salt/elasticsearch/cacerts ]; then docker run -v /etc/pki/ca.crt:/etc/ssl/ca.crt --name so-elasticsearchca --user root --entrypoint jdk/bin/keytool {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-elasticsearch:$ELASTIC_AGENT_TARBALL_VERSION -keystore /usr/share/elasticsearch/jdk/lib/security/cacerts -alias SOSCA -import -file /etc/ssl/ca.crt -storepass changeit -noprompt docker cp so-elasticsearchca:/usr/share/elasticsearch/jdk/lib/security/cacerts /opt/so/saltstack/local/salt/elasticsearch/cacerts - docker cp so-elasticsearchca:/etc/ssl/certs/ca-certificates.crt /opt/so/saltstack/local/salt/elasticsearch/tls-ca-bundle.pem + docker cp so-elasticsearchca:/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem /opt/so/saltstack/local/salt/elasticsearch/tls-ca-bundle.pem docker rm so-elasticsearchca echo "" >> /opt/so/saltstack/local/salt/elasticsearch/tls-ca-bundle.pem echo "sosca" >> /opt/so/saltstack/local/salt/elasticsearch/tls-ca-bundle.pem diff --git a/salt/logstash/defaults.yaml b/salt/logstash/defaults.yaml index 5af366459..520182555 100644 --- a/salt/logstash/defaults.yaml +++ b/salt/logstash/defaults.yaml @@ -63,7 +63,7 @@ logstash: settings: lsheap: 500m config: - http_x_host: 0.0.0.0 + api_x_http_x_host: 0.0.0.0 path_x_logs: /var/log/logstash pipeline_x_workers: 1 pipeline_x_batch_x_size: 125 diff --git a/salt/logstash/soc_logstash.yaml b/salt/logstash/soc_logstash.yaml index b617abfdd..9560b5c36 100644 --- a/salt/logstash/soc_logstash.yaml +++ b/salt/logstash/soc_logstash.yaml @@ -56,7 +56,7 @@ logstash: helpLink: logstash.html global: False config: - http_x_host: + api_x_http_x_host: description: Host interface to listen to connections. helpLink: logstash.html readonly: True From e3a4f0873eebca3e26c3ad7f1f96fb18452098d5 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Wed, 17 Dec 2025 06:53:08 -0600 Subject: [PATCH 03/20] update expected version for elastalert state --- salt/elastalert/enabled.sls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/elastalert/enabled.sls b/salt/elastalert/enabled.sls index 6a1ff1440..e28a55958 100644 --- a/salt/elastalert/enabled.sls +++ b/salt/elastalert/enabled.sls @@ -60,7 +60,7 @@ so-elastalert: - watch: - file: elastaconf - onlyif: - - "so-elasticsearch-query / | jq -r '.version.number[0:1]' | grep -q 8" {# only run this state if elasticsearch is version 8 #} + - "so-elasticsearch-query / | jq -r '.version.number[0:1]' | grep -q 9" {# only run this state if elasticsearch is version 9 #} delete_so-elastalert_so-status.disabled: file.uncomment: From 5cb1e284afe5297eacca08b863f3c4cfca61d3ed Mon Sep 17 00:00:00 2001 From: Jorge Reyes <94730068+reyesj2@users.noreply.github.com> Date: Wed, 17 Dec 2025 06:54:32 -0600 Subject: [PATCH 04/20] Update VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 86df31761..7d52aac7f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.4.200 +2.4.0-foxtrot From b61885add5829d1c1271fff4d0861ecc47bf3346 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Wed, 17 Dec 2025 16:03:12 -0600 Subject: [PATCH 05/20] Fix Kafka output policy - singular topic key --- .../tools/sbin_jinja/so-kafka-fleet-output-policy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/elasticfleet/tools/sbin_jinja/so-kafka-fleet-output-policy b/salt/elasticfleet/tools/sbin_jinja/so-kafka-fleet-output-policy index d44a5cb6c..b44b467bc 100644 --- a/salt/elasticfleet/tools/sbin_jinja/so-kafka-fleet-output-policy +++ b/salt/elasticfleet/tools/sbin_jinja/so-kafka-fleet-output-policy @@ -47,7 +47,7 @@ if ! kafka_output=$(curl -sK /opt/so/conf/elasticsearch/curl.config -L "http://l --arg KAFKACA "$KAFKACA" \ --arg MANAGER_IP "{{ GLOBALS.manager_ip }}:9092" \ --arg KAFKA_OUTPUT_VERSION "$KAFKA_OUTPUT_VERSION" \ - '{"name":"grid-kafka", "id":"so-manager_kafka","type":"kafka","hosts":[ $MANAGER_IP ],"is_default":false,"is_default_monitoring":false,"config_yaml":"","ssl":{"certificate_authorities":[ $KAFKACA ],"certificate": $KAFKACRT ,"key":"","verification_mode":"full"},"proxy_id":null,"client_id":"Elastic","version": $KAFKA_OUTPUT_VERSION ,"compression":"none","auth_type":"ssl","partition":"round_robin","round_robin":{"group_events":10},"topics":[{"topic":"default-securityonion"}],"headers":[{"key":"","value":""}],"timeout":30,"broker_timeout":30,"required_acks":1,"secrets":{"ssl":{"key": $KAFKAKEY }}}' + '{"name":"grid-kafka", "id":"so-manager_kafka","type":"kafka","hosts":[ $MANAGER_IP ],"is_default":false,"is_default_monitoring":false,"config_yaml":"","ssl":{"certificate_authorities":[ $KAFKACA ],"certificate": $KAFKACRT ,"key":"","verification_mode":"full"},"proxy_id":null,"client_id":"Elastic","version": $KAFKA_OUTPUT_VERSION ,"compression":"none","auth_type":"ssl","partition":"round_robin","round_robin":{"group_events":10},"topic":"default-securityonion","headers":[{"key":"","value":""}],"timeout":30,"broker_timeout":30,"required_acks":1,"secrets":{"ssl":{"key": $KAFKAKEY }}}' ) if ! response=$(curl -sK /opt/so/conf/elasticsearch/curl.config -L -X POST "localhost:5601/api/fleet/outputs" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d "$JSON_STRING" --fail 2>/dev/null); then echo -e "\nFailed to setup Elastic Fleet output policy for Kafka...\n" @@ -67,7 +67,7 @@ elif kafka_output=$(curl -sK /opt/so/conf/elasticsearch/curl.config -L "http://l --arg ENABLED_DISABLED "$ENABLED_DISABLED"\ --arg KAFKA_OUTPUT_VERSION "$KAFKA_OUTPUT_VERSION" \ --argjson HOSTS "$HOSTS" \ - '{"name":"grid-kafka","type":"kafka","hosts":$HOSTS,"is_default":$ENABLED_DISABLED,"is_default_monitoring":$ENABLED_DISABLED,"config_yaml":"","ssl":{"certificate_authorities":[ $KAFKACA ],"certificate": $KAFKACRT ,"key":"","verification_mode":"full"},"proxy_id":null,"client_id":"Elastic","version": $KAFKA_OUTPUT_VERSION ,"compression":"none","auth_type":"ssl","partition":"round_robin","round_robin":{"group_events":10},"topics":[{"topic":"default-securityonion"}],"headers":[{"key":"","value":""}],"timeout":30,"broker_timeout":30,"required_acks":1,"secrets":{"ssl":{"key": $KAFKAKEY }}}' + '{"name":"grid-kafka","type":"kafka","hosts":$HOSTS,"is_default":$ENABLED_DISABLED,"is_default_monitoring":$ENABLED_DISABLED,"config_yaml":"","ssl":{"certificate_authorities":[ $KAFKACA ],"certificate": $KAFKACRT ,"key":"","verification_mode":"full"},"proxy_id":null,"client_id":"Elastic","version": $KAFKA_OUTPUT_VERSION ,"compression":"none","auth_type":"ssl","partition":"round_robin","round_robin":{"group_events":10},"topic":"default-securityonion","headers":[{"key":"","value":""}],"timeout":30,"broker_timeout":30,"required_acks":1,"secrets":{"ssl":{"key": $KAFKAKEY }}}' ) if ! response=$(curl -sK /opt/so/conf/elasticsearch/curl.config -L -X PUT "localhost:5601/api/fleet/outputs/so-manager_kafka" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d "$JSON_STRING" --fail 2>/dev/null); then echo -e "\nFailed to force update to Elastic Fleet output policy for Kafka...\n" From 6c879cbd137ea55c498d147d6e573729b114fd9d Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Wed, 17 Dec 2025 19:08:21 -0600 Subject: [PATCH 06/20] soup changes --- salt/manager/tools/sbin/soup | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/salt/manager/tools/sbin/soup b/salt/manager/tools/sbin/soup index 9fd9542c0..7d2f71400 100755 --- a/salt/manager/tools/sbin/soup +++ b/salt/manager/tools/sbin/soup @@ -427,6 +427,7 @@ preupgrade_changes() { [[ "$INSTALLEDVERSION" == 2.4.170 ]] && up_to_2.4.180 [[ "$INSTALLEDVERSION" == 2.4.180 ]] && up_to_2.4.190 [[ "$INSTALLEDVERSION" == 2.4.190 ]] && up_to_2.4.200 + [[ "$INSTALLEDVERSION" == 2.4.200 ]] && up_to_2.4.210 true } @@ -459,6 +460,7 @@ postupgrade_changes() { [[ "$POSTVERSION" == 2.4.170 ]] && post_to_2.4.180 [[ "$POSTVERSION" == 2.4.180 ]] && post_to_2.4.190 [[ "$POSTVERSION" == 2.4.190 ]] && post_to_2.4.200 + [[ "$POSTVERSION" == 2.4.200 ]] && post_to_2.4.210 true } @@ -615,9 +617,6 @@ post_to_2.4.180() { } post_to_2.4.190() { - echo "Regenerating Elastic Agent Installers" - /sbin/so-elastic-agent-gen-installers - # Only need to update import / eval nodes if [[ "$MINION_ROLE" == "import" ]] || [[ "$MINION_ROLE" == "eval" ]]; then update_import_fleet_output @@ -645,6 +644,13 @@ post_to_2.4.200() { POSTVERSION=2.4.200 } +post_to_2.4.210() { + echo "Regenerating Elastic Agent Installers" + /sbin/so-elastic-agent-gen-installers + + POSTVERSION=2.4.210 +} + repo_sync() { echo "Sync the local repo." su socore -c '/usr/sbin/so-repo-sync' || fail "Unable to complete so-repo-sync." @@ -906,9 +912,7 @@ up_to_2.4.180() { } up_to_2.4.190() { - # Elastic Update for this release, so download Elastic Agent files - determine_elastic_agent_upgrade - + echo "Nothing to do for 2.4.190" INSTALLEDVERSION=2.4.190 } @@ -921,6 +925,13 @@ up_to_2.4.200() { INSTALLEDVERSION=2.4.200 } +up_to_2.4.210() { + # Elastic Update for this release, so download Elastic Agent files + determine_elastic_agent_upgrade + + INSTALLEDVERSION=2.4.210 +} + add_hydra_pillars() { mkdir -p /opt/so/saltstack/local/pillar/hydra touch /opt/so/saltstack/local/pillar/hydra/soc_hydra.sls From 9345718967f13650da877f617b44a3e96ff10633 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Fri, 19 Dec 2025 16:15:05 -0600 Subject: [PATCH 07/20] verify pre-soup ES version is directly upgradable to post-soup ES version. --- salt/manager/tools/sbin/soup | 68 ++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/salt/manager/tools/sbin/soup b/salt/manager/tools/sbin/soup index 7d2f71400..49edc3072 100755 --- a/salt/manager/tools/sbin/soup +++ b/salt/manager/tools/sbin/soup @@ -87,6 +87,9 @@ check_err() { 113) echo 'No route to host' ;; + 160) + echo 'Incompatiable Elasticsearch upgrade' + ;; *) echo 'Unhandled error' echo "$err_msg" @@ -1619,6 +1622,69 @@ verify_latest_update_script() { fi } + +verify_es_version_compatibility() { + + # supported upgrade paths for SO-ES versions + declare -A es_upgrade_map=( + ["8.14.3"]="8.17.3 8.18.4 8.18.6 8.18.8" + ["8.17.3"]="8.18.4 8.18.6 8.18.8" + ["8.18.4"]="8.18.6 8.18.8 9.0.8" + ["8.18.6"]="8.18.8 9.0.8" + ["8.18.8"]="9.0.8" + ) + + # Elasticsearch MUST upgrade through these versions + declare -A es_to_so_version=( + ["8.18.8"]="2.4.190-20251024" + ) + + # Get current Elasticsearch version + if es_version_raw=$(so-elasticsearch-query / --fail --retry 5 --retry-delay 10); then + es_version=$(echo "$es_version_raw" | jq -r '.version.number' ) + else + echo "Could not determine current Elasticsearch version to validate compatibility with post soup Elasticsearch version." + exit 160 + fi + + if ! target_es_version=$(so-yaml.py get $UPDATE_DIR/salt/elasticsearch/defaults.yaml elasticsearch.version | sed -n '1p'); then + # so-yaml.py failed to get the ES version from upgrade versions elasticsearch/defaults.yaml file. Likely they are upgrading to an SO version older than 2.4.110 prior to the ES version pinning and should be OKAY to continue with the upgrade. + + # if so-yaml.py failed to get the ES version AND the version we are upgrading to is newer than 2.4.110 then we should bail + if [[ $(cat $UPDATE_DIR/VERSION | cut -d'.' -f3) > 110 ]]; then + echo "Couldn't determine the target Elasticsearch version (post soup version) to ensure compatibility with current Elasticsearch version. Exiting" + exit 160 + fi + + # allow upgrade to version < 2.4.110 without checking ES version compatibility + return 0 + + fi + + + if [[ " ${es_upgrade_map[$es_version]} " =~ " $target_es_version " ]]; then + # supported upgrade + return 0 + else + compatible_versions=${es_upgrade_map[$es_version]} + next_step_so_version=${es_to_so_version[${compatible_versions##* }]} + echo -e "\n##############################################################################################################################\n" + echo -e "You are currently running Security Onion $INSTALLEDVERSION. You will need to update to version $next_step_so_version before updating to $(cat $UPDATE_DIR/VERSION).\n" + + if [[ $is_airgap -eq 0 ]]; then + echo "You can download the $next_step_so_version ISO image from https://download.securityonion.net/file/securityonion/securityonion-$next_step_so_version.iso" + else + echo "You can use the following soup command to upgrade to $next_step_so_version;" + echo -e " sudo BRANCH=$next_step_so_version soup\n" + + fi + echo "*** Once you have updated to $next_step_so_version, you can then run soup again to update to $(cat $UPDATE_DIR/VERSION). ***" + echo -e "\n###############################################################################################################################\n" + exit 160 + fi + +} + # Keeping this block in case we need to do a hotfix that requires salt update apply_hotfix() { if [[ "$INSTALLEDVERSION" == "2.4.20" ]] ; then @@ -1715,6 +1781,8 @@ main() { echo "Verifying we have the latest soup script." verify_latest_update_script + verify_es_version_compatibility + echo "Let's see if we need to update Security Onion." upgrade_check upgrade_space From f666ad600f35d1dd22f52ee8cf9f02cf031b19a5 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Tue, 23 Dec 2025 16:27:22 -0600 Subject: [PATCH 08/20] accept same version 'upgrades' --- salt/manager/tools/sbin/soup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/manager/tools/sbin/soup b/salt/manager/tools/sbin/soup index 49edc3072..fc197f5b6 100755 --- a/salt/manager/tools/sbin/soup +++ b/salt/manager/tools/sbin/soup @@ -1662,7 +1662,7 @@ verify_es_version_compatibility() { fi - if [[ " ${es_upgrade_map[$es_version]} " =~ " $target_es_version " ]]; then + if [[ " ${es_upgrade_map[$es_version]} " =~ " $target_es_version " || "$es_version" == "$target_es_version" ]]; then # supported upgrade return 0 else From 9b411867df4d96b766ce17a2a4abe3e7b85bd8c9 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Mon, 29 Dec 2025 10:27:38 -0600 Subject: [PATCH 09/20] update version --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 7d52aac7f..b880b422c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.4.0-foxtrot +2.4.210 From 893aaafa1b55623558693e50fe5878813aee36f4 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Mon, 29 Dec 2025 15:52:00 -0600 Subject: [PATCH 10/20] foxtrot --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index b880b422c..7d52aac7f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.4.210 +2.4.0-foxtrot From af604c2ea85040e48932bc79c4b7c799a92ef91a Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Wed, 7 Jan 2026 09:45:26 -0600 Subject: [PATCH 11/20] autosoup functionality for non-airgap --- salt/manager/tools/sbin/soup | 181 +++++++++++++++++++++++++++++++++-- 1 file changed, 175 insertions(+), 6 deletions(-) diff --git a/salt/manager/tools/sbin/soup b/salt/manager/tools/sbin/soup index 3051fb108..e21b2e639 100755 --- a/salt/manager/tools/sbin/soup +++ b/salt/manager/tools/sbin/soup @@ -90,6 +90,9 @@ check_err() { 160) echo 'Incompatiable Elasticsearch upgrade' ;; + 161) + echo 'Required intermediate Elasticsearch upgrade not complete' + ;; *) echo 'Unhandled error' echo "$err_msg" @@ -1629,6 +1632,8 @@ verify_latest_update_script() { verify_es_version_compatibility() { + local es_required_version_statefile="/opt/so/state/so_es_required_upgrade_version.txt" + local es_verification_script="/tmp/so_intermediate_upgrade_verification.sh" # supported upgrade paths for SO-ES versions declare -A es_upgrade_map=( ["8.14.3"]="8.17.3 8.18.4 8.18.6 8.18.8" @@ -1665,6 +1670,26 @@ verify_es_version_compatibility() { fi + # if this statefile exists then we have done an intermediate upgrade and we need to ensure that ALL ES nodes have been upgraded to the version in the statefile before allowing soup to continue + if [[ -f "$es_required_version_statefile" ]]; then + # required so verification script should have already been created + if [[ ! -f "$es_verification_script" ]]; then + create_intermediate_upgrade_verification_script $es_verification_script + fi + + # create script using version in statefile + local es_required_version_statefile_value=$(cat $es_required_version_statefile) + timeout --foreground 3600 bash "$es_verification_script" "$es_required_version_statefile_value" "$es_required_version_statefile" + if [[ $? -ne 0 ]]; then + echo -e "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + + echo "A previous required intermediate Elasticsearch upgrade to $es_required_version_statefile_value has yet to successfully complete across the grid. Please allow time for all Searchnodes/Heavynodes to have upgraded Elasticsearch to $es_required_version_statefile_value before running soup again to avoid potential data loss!" + + echo -e "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + exit 161 + fi + + fi if [[ " ${es_upgrade_map[$es_version]} " =~ " $target_es_version " || "$es_version" == "$target_es_version" ]]; then # supported upgrade @@ -1675,20 +1700,164 @@ verify_es_version_compatibility() { echo -e "\n##############################################################################################################################\n" echo -e "You are currently running Security Onion $INSTALLEDVERSION. You will need to update to version $next_step_so_version before updating to $(cat $UPDATE_DIR/VERSION).\n" + echo "${compatible_versions##* }" > "$es_required_version_statefile" + + # We expect to upgrade to the latest compatiable minor version of ES + create_intermediate_upgrade_verification_script $es_verification_script + if [[ $is_airgap -eq 0 ]]; then echo "You can download the $next_step_so_version ISO image from https://download.securityonion.net/file/securityonion/securityonion-$next_step_so_version.iso" + echo "*** Once you have updated to $next_step_so_version, you can then run soup again to update to $(cat $UPDATE_DIR/VERSION). ***" + echo -e "\n##############################################################################################################################\n" + exit 160 else - echo "You can use the following soup command to upgrade to $next_step_so_version;" - echo -e " sudo BRANCH=$next_step_so_version soup\n" - + echo "Starting automated intermediate upgrade to $next_step_so_version." + echo "After completion, the system will automatically attempt to upgrade to the latest version." + echo -e "\n##############################################################################################################################\n" + exec bash -c "BRANCH=$next_step_so_version soup -y && BRANCH=$next_step_so_version soup -y && \ + echo -e \"\n##############################################################################################################################\n\" && \ + echo -e \"Verifying Elasticsearch was successfully upgraded to ${compatible_versions##* } across the grid. This part can take a while as Searchnodes/Heavynodes sync up with the Manager! \n\nOnce verification completes the next soup will begin automatically. If verification takes longer than 1 hour it will stop waiting and your grid will remain at $next_step_so_version. Allowing for all Searchnodes/Heavynodes to upgrade Elasticsearch to the required version on their own time.\n\" \ + && timeout --foreground 3600 bash /tmp/so_intermediate_upgrade_verification.sh ${compatible_versions##* } $es_required_version_statefile && \ + echo -e \"\n##############################################################################################################################\n\" \ + && soup -y && soup -y" fi - echo "*** Once you have updated to $next_step_so_version, you can then run soup again to update to $(cat $UPDATE_DIR/VERSION). ***" - echo -e "\n###############################################################################################################################\n" - exit 160 fi } +create_intermediate_upgrade_verification_script() { + # After an intermediate upgrade, verify that ALL nodes running Elasticsearch are at the expected version BEFORE proceeding to the next upgrade step. This is a CRITICAL step + local verification_script="$1" + + cat << 'EOF' > "$verification_script" + #!/bin/bash + + SOUP_INTERMEDIATE_UPGRADE_FAILURES_LOG_FILE="/root/so_intermediate_upgrade_verification_failures.log" + CURRENT_TIME=$(date +%Y%m%d.%H%M%S) + EXPECTED_ES_VERSION="$1" + + if [[ -z "$EXPECTED_ES_VERSION" ]]; then + echo -e "\nExpected Elasticsearch version not provided. Usage: $0 " + exit 1 + fi + + if [[ -f "$SOUP_INTERMEDIATE_UPGRADE_FAILURES_LOG_FILE" ]]; then + mv "$SOUP_INTERMEDIATE_UPGRADE_FAILURES_LOG_FILE" "$SOUP_INTERMEDIATE_UPGRADE_FAILURES_LOG_FILE.$CURRENT_TIME" + fi + + check_heavynodes_es_version() { + # Check if heavynodes are in this grid + if ! salt-key -l accepted | grep -q 'heavynode$'; then + + # No heavynodes, skip version check + echo "No heavynodes detected in this Security Onion deployment. Skipping heavynode Elasticsearch version verification." + return 0 + fi + + echo -e "\nOne or more heavynodes detected. Verifying their Elasticsearch versions." + + local retries=20 + local retry_count=0 + local delay=180 + local success=1 + while [[ $retry_count -lt $retries ]]; do + # keep stderr with variable for logging + heavynode_versions=$(salt -C 'G@role:so-heavynode' cmd.run 'so-elasticsearch-query / --retry 3 --retry-delay 10 | jq ".version.number"' shell=/bin/bash --out=json 2>&1) + local exit_status=$? + + # Check that all heavynodes returned good data + if [[ $exit_status -ne 0 ]]; then + echo "Failed to retrieve Elasticsearch version from one or more heavynodes... Retrying in $delay seconds. Attempt $((retry_count + 1)) of $retries." + ((retry_count++)) + sleep $delay + + continue + else + if echo "$heavynode_versions" | jq -s --arg expected "\"$EXPECTED_ES_VERSION\"" --exit-status 'all(.[]; . | to_entries | all(.[]; .value == $expected))' > /dev/null; then + echo -e "\nAll heavynodes are at the expected Elasticsearch version $EXPECTED_ES_VERSION." + + return 0 + else + echo "One or more heavynodes is not at the expected Elasticsearch version $EXPECTED_ES_VERSION. Rechecking in $delay seconds. Attempt $((retry_count + 1)) of $retries." + ((retry_count++)) + sleep $delay + + continue + fi + fi + done + + echo -e "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + echo "One or more heavynodes is not at the expected Elasticsearch version $EXPECTED_ES_VERSION." + echo "Current versions:" + echo "$heavynode_versions" | jq -s 'add' + echo "$heavynode_versions" | jq -s 'add' >> "$SOUP_INTERMEDIATE_UPGRADE_FAILURES_LOG_FILE" + echo -e "\n Stopping automatic upgrade to latest Security Onion version. Heavynodes must ALL be at Elasticsearch version $EXPECTED_ES_VERSION before proceeding with the next upgrade step to avoid potential data loss!" + echo -e "\n Heavynodes will upgrade themselves to Elasticsearch $EXPECTED_ES_VERSION on their own, but this process can take a long time depending on network link between Manager and Heavynodes." + echo -e "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + + return 1 + } + + check_searchnodes_es_version() { + local retries=20 + local retry_count=0 + local delay=180 + local success=1 + + while [[ $retry_count -lt $retries ]]; do + # keep stderr with variable for logging + cluster_versions=$(so-elasticsearch-query _nodes/_all/version --retry 5 --retry-delay 10 2>&1) + local exit_status=$? + + if [[ $exit_status -ne 0 ]]; then + echo "Failed to retrieve Elasticsearch versions from searchnodes... Retrying in $delay seconds. Attempt $((retry_count + 1)) of $retries." + ((retry_count++)) + sleep $delay + + continue + else + if echo "$cluster_versions" | jq --arg expected "$EXPECTED_ES_VERSION" --exit-status '.nodes | to_entries | all(.[].value.version; . == $expected)' > /dev/null; then + echo "All Searchnodes are at the expected Elasticsearch version $EXPECTED_ES_VERSION." + + return 0 + else + echo "One or more Searchnodes is not at the expected Elasticsearch version $EXPECTED_ES_VERSION. Rechecking in $delay seconds. Attempt $((retry_count + 1)) of $retries." + ((retry_count++)) + sleep $delay + + continue + fi + fi + done + + echo -e "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + echo "One or more Searchnodes is not at the expected Elasticsearch version $EXPECTED_ES_VERSION." + echo "Current versions:" + echo "$cluster_versions" | jq '.nodes | to_entries | map({(.value.name): .value.version}) | sort | add' + echo "$cluster_versions" >> "$SOUP_INTERMEDIATE_UPGRADE_FAILURES_LOG_FILE" + echo -e "\nStopping automatic upgrade to latest version. Searchnodes must ALL be at Elasticsearch version $EXPECTED_ES_VERSION before proceeding with the next upgrade step to avoid potential data loss!" + echo -e "\nSearchnodes will upgrade themselves to Elasticsearch $EXPECTED_ES_VERSION on their own, but this process can take a while depending on cluster size / network link between Manager and Searchnodes." + echo -e "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + + echo "$cluster_versions" > "$SOUP_INTERMEDIATE_UPGRADE_FAILURES_LOG_FILE" + + return 1 + + } + + # Need to add a check for heavynodes and ensure all heavynodes get their own "cluster" upgraded before moving on to final upgrade. + check_searchnodes_es_version || exit 1 + check_heavynodes_es_version || exit 1 + + # Remove required version state file after successful verification + rm -f "$2" + + exit 0 + +EOF +} + # Keeping this block in case we need to do a hotfix that requires salt update apply_hotfix() { if [[ "$INSTALLEDVERSION" == "2.4.20" ]] ; then From 752c7640665b88e73e9333ab087bfb36f025b61b Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Wed, 7 Jan 2026 10:03:46 -0600 Subject: [PATCH 12/20] autosoup preserve branch setting if set originally --- salt/manager/tools/sbin/soup | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/salt/manager/tools/sbin/soup b/salt/manager/tools/sbin/soup index e21b2e639..ed1edbd29 100755 --- a/salt/manager/tools/sbin/soup +++ b/salt/manager/tools/sbin/soup @@ -1711,6 +1711,13 @@ verify_es_version_compatibility() { echo -e "\n##############################################################################################################################\n" exit 160 else + # preserve BRANCH value if set originally + if [[ -n "$BRANCH" ]]; then + local originally_requested_so_version="$BRANCH" + else + local originally_requested_so_version="2.4/main" + fi + echo "Starting automated intermediate upgrade to $next_step_so_version." echo "After completion, the system will automatically attempt to upgrade to the latest version." echo -e "\n##############################################################################################################################\n" @@ -1719,7 +1726,7 @@ verify_es_version_compatibility() { echo -e \"Verifying Elasticsearch was successfully upgraded to ${compatible_versions##* } across the grid. This part can take a while as Searchnodes/Heavynodes sync up with the Manager! \n\nOnce verification completes the next soup will begin automatically. If verification takes longer than 1 hour it will stop waiting and your grid will remain at $next_step_so_version. Allowing for all Searchnodes/Heavynodes to upgrade Elasticsearch to the required version on their own time.\n\" \ && timeout --foreground 3600 bash /tmp/so_intermediate_upgrade_verification.sh ${compatible_versions##* } $es_required_version_statefile && \ echo -e \"\n##############################################################################################################################\n\" \ - && soup -y && soup -y" + && BRANCH=$originally_requested_so_version soup -y && BRANCH=$originally_requested_so_version soup -y" fi fi From 588aa435ecae6645b1bd7edf7a2280dfdb856044 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Wed, 7 Jan 2026 10:21:36 -0600 Subject: [PATCH 13/20] update version --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 7d52aac7f..b880b422c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.4.0-foxtrot +2.4.210 From cb1e59fa49d656f9aea6ec7e1c0435cf534e33b5 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Wed, 7 Jan 2026 10:30:45 -0600 Subject: [PATCH 14/20] Merge branch '2.4/dev' of github.com:Security-Onion-Solutions/securityonion into reyesj2/elastic9-autosoup --- salt/common/tools/sbin/so-log-check | 1 + salt/elasticsearch/defaults.yaml | 42 -------- salt/elasticsearch/files/ingest/kratos | 95 +++++++++++++++++-- salt/kratos/config.sls | 1 + salt/manager/tools/sbin/soup | 4 + .../standard/assistant_session_report.md | 91 ++++++++++++++++++ salt/sensoroni/soc_sensoroni.yaml | 9 +- salt/soc/defaults.yaml | 14 +-- 8 files changed, 200 insertions(+), 57 deletions(-) create mode 100644 salt/sensoroni/files/templates/reports/standard/assistant_session_report.md diff --git a/salt/common/tools/sbin/so-log-check b/salt/common/tools/sbin/so-log-check index 5960a7946..decb52abb 100755 --- a/salt/common/tools/sbin/so-log-check +++ b/salt/common/tools/sbin/so-log-check @@ -129,6 +129,7 @@ if [[ $EXCLUDE_STARTUP_ERRORS == 'Y' ]]; then EXCLUDED_ERRORS="$EXCLUDED_ERRORS|responded with status-code 503" # telegraf getting 503 from ES during startup EXCLUDED_ERRORS="$EXCLUDED_ERRORS|process_cluster_event_timeout_exception" # logstash waiting for elasticsearch to start EXCLUDED_ERRORS="$EXCLUDED_ERRORS|not configured for GeoIP" # SO does not bundle the maxminddb with Zeek + EXCLUDED_ERRORS="$EXCLUDED_ERRORS|HTTP 404: Not Found" # Salt loops until Kratos returns 200, during startup Kratos may not be ready fi if [[ $EXCLUDE_FALSE_POSITIVE_ERRORS == 'Y' ]]; then diff --git a/salt/elasticsearch/defaults.yaml b/salt/elasticsearch/defaults.yaml index b789fb90f..99403d9b8 100644 --- a/salt/elasticsearch/defaults.yaml +++ b/salt/elasticsearch/defaults.yaml @@ -857,53 +857,11 @@ elasticsearch: composed_of: - agent-mappings - dtc-agent-mappings - - base-mappings - - dtc-base-mappings - - client-mappings - - dtc-client-mappings - - container-mappings - - destination-mappings - - dtc-destination-mappings - - pb-override-destination-mappings - - dll-mappings - - dns-mappings - - dtc-dns-mappings - - ecs-mappings - - dtc-ecs-mappings - - error-mappings - - event-mappings - - dtc-event-mappings - - file-mappings - - dtc-file-mappings - - group-mappings - host-mappings - dtc-host-mappings - http-mappings - dtc-http-mappings - - log-mappings - metadata-mappings - - network-mappings - - dtc-network-mappings - - observer-mappings - - dtc-observer-mappings - - organization-mappings - - package-mappings - - process-mappings - - dtc-process-mappings - - related-mappings - - rule-mappings - - dtc-rule-mappings - - server-mappings - - service-mappings - - dtc-service-mappings - - source-mappings - - dtc-source-mappings - - pb-override-source-mappings - - threat-mappings - - tls-mappings - - url-mappings - - user_agent-mappings - - dtc-user_agent-mappings - common-settings - common-dynamic-mappings data_stream: diff --git a/salt/elasticsearch/files/ingest/kratos b/salt/elasticsearch/files/ingest/kratos index 9551dad24..d59f45587 100644 --- a/salt/elasticsearch/files/ingest/kratos +++ b/salt/elasticsearch/files/ingest/kratos @@ -1,9 +1,90 @@ { - "description" : "kratos", - "processors" : [ - {"set":{"field":"audience","value":"access","override":false,"ignore_failure":true}}, - {"set":{"field":"event.dataset","ignore_empty_value":true,"ignore_failure":true,"value":"kratos.{{{audience}}}","media_type":"text/plain"}}, - {"set":{"field":"event.action","ignore_failure":true,"copy_from":"msg" }}, - { "pipeline": { "name": "common" } } - ] + "description": "kratos", + "processors": [ + { + "set": { + "field": "audience", + "value": "access", + "override": false, + "ignore_failure": true + } + }, + { + "set": { + "field": "event.dataset", + "ignore_empty_value": true, + "ignore_failure": true, + "value": "kratos.{{{audience}}}", + "media_type": "text/plain" + } + }, + { + "set": { + "field": "event.action", + "ignore_failure": true, + "copy_from": "msg" + } + }, + { + "rename": { + "field": "http_request", + "target_field": "http.request", + "ignore_failure": true, + "ignore_missing": true + } + }, + { + "rename": { + "field": "http_response", + "target_field": "http.response", + "ignore_failure": true, + "ignore_missing": true + } + }, + { + "rename": { + "field": "http.request.path", + "target_field": "http.uri", + "ignore_failure": true, + "ignore_missing": true + } + }, + { + "rename": { + "field": "http.request.method", + "target_field": "http.method", + "ignore_failure": true, + "ignore_missing": true + } + }, + { + "rename": { + "field": "http.request.method", + "target_field": "http.method", + "ignore_failure": true, + "ignore_missing": true + } + }, + { + "rename": { + "field": "http.request.query", + "target_field": "http.query", + "ignore_failure": true, + "ignore_missing": true + } + }, + { + "rename": { + "field": "http.request.headers.user-agent", + "target_field": "http.useragent", + "ignore_failure": true, + "ignore_missing": true + } + }, + { + "pipeline": { + "name": "common" + } + } + ] } \ No newline at end of file diff --git a/salt/kratos/config.sls b/salt/kratos/config.sls index b9f5142f1..622522e0b 100644 --- a/salt/kratos/config.sls +++ b/salt/kratos/config.sls @@ -75,6 +75,7 @@ kratosconfig: - group: 928 - mode: 600 - template: jinja + - show_changes: False - defaults: KRATOSMERGED: {{ KRATOSMERGED }} diff --git a/salt/manager/tools/sbin/soup b/salt/manager/tools/sbin/soup index ed1edbd29..450095047 100755 --- a/salt/manager/tools/sbin/soup +++ b/salt/manager/tools/sbin/soup @@ -651,6 +651,10 @@ post_to_2.4.200() { } post_to_2.4.210() { + echo "Rolling over Kratos index to apply new index template" + + rollover_index "logs-kratos-so" + echo "Regenerating Elastic Agent Installers" /sbin/so-elastic-agent-gen-installers diff --git a/salt/sensoroni/files/templates/reports/standard/assistant_session_report.md b/salt/sensoroni/files/templates/reports/standard/assistant_session_report.md new file mode 100644 index 000000000..7879a7db0 --- /dev/null +++ b/salt/sensoroni/files/templates/reports/standard/assistant_session_report.md @@ -0,0 +1,91 @@ +Onion AI Session Report +========================== + +## Session Details + +**Session ID:** {{.Session.SessionId}} + +**Title:** {{.Session.Title}} + +**Created:** {{formatDateTime "Mon Jan 02 15:04:05 -0700 2006" .Session.CreateTime}} + +**Updated:** {{formatDateTime "Mon Jan 02 15:04:05 -0700 2006" .Session.UpdateTime}} + +{{ if .Session.DeleteTime }} +**Deleted:** {{ formatDateTime "Mon Jan 02 15:04:05 -0700 2006" .Session.DeleteTime}} +{{ end }} + +**User ID:** {{getUserDetail "email" .Session.UserId}} + +## Session Usage + +**Total Input Tokens** {{.Session.Usage.TotalInputTokens}} + +**Total Output Tokens** {{.Session.Usage.TotalOutputTokens}} + +**Total Credits:** {{.Session.Usage.TotalCredits}} + +**Total Messages:** {{.Session.Usage.TotalMessages}} + +## Messages + +{{ range $index, $msg := sortAssistantMessages "CreateTime" "asc" .History }} +#### Message {{ add $index 1 }} + +**Created:** {{formatDateTime "Mon Jan 02 15:04:05 -0700 2006" $msg.CreateTime}} + +**User ID:** {{getUserDetail "email" $msg.UserId}} + +**Role:** {{$msg.Message.Role}} + +{{ range $i, $block := $msg.Message.ContentBlocks }} + +--- + +{{ if eq $block.Type "text" }} +**Text:** {{ stripEmoji $block.Text }} +{{ else if eq $block.Type "tool_use" }} +**Tool:** {{ $block.Name }} +{{ if $block.Input }} +**Parameters:** +{{ range $key, $value := parseJSON $block.Input }} +{{ if eq $key "limit" }}- {{ $key }}: {{ $value }} +{{ else }}- {{ $key }}: "{{ $value }}" +{{ end }}{{ end }}{{ end }} +{{ else if $block.ToolResult }} +**Tool Result:** +{{ if $block.ToolResult.Content }} +{{ range $j, $contentBlock := $block.ToolResult.Content }} +{{ if gt $j 0 }} + +--- + +{{ end }} +{{ if $contentBlock.Text }} +{{ if $block.ToolResult.IsError }} +**Error:** {{ $contentBlock.Text }} +{{ else }} +{{ $contentBlock.Text }} +{{ end }} +{{ else if $contentBlock.Json }} +```json +{{ toJSON $contentBlock.Json }} +``` +{{ end }}{{ end }} +{{ end }}{{ end }}{{ end }} + +{{ if eq $msg.Message.Role "assistant" }}{{ if $msg.Message.Usage }} + +--- + +**Message Usage:** + +- Input Tokens: {{$msg.Message.Usage.InputTokens}} +- Output Tokens: {{$msg.Message.Usage.OutputTokens}} +- Credits: {{$msg.Message.Usage.Credits}} + +{{end}}{{end}} + +--- + +{{end}} \ No newline at end of file diff --git a/salt/sensoroni/soc_sensoroni.yaml b/salt/sensoroni/soc_sensoroni.yaml index cf69ec52a..aca6c8e3f 100644 --- a/salt/sensoroni/soc_sensoroni.yaml +++ b/salt/sensoroni/soc_sensoroni.yaml @@ -357,7 +357,7 @@ sensoroni: reports: standard: case_report__md: - title: Case report Template + title: Case Report Template description: The template used when generating a case report. Supports markdown format. file: True global: True @@ -370,6 +370,13 @@ sensoroni: global: True syntax: md helpLink: reports.html + assistant_session_report__md: + title: Assistant Session Report Template + description: The template used when generating an assistant session report. Supports markdown format. + file: True + global: True + syntax: md + helplink: reports.html custom: generic_report1__md: title: Custom Report 1 diff --git a/salt/soc/defaults.yaml b/salt/soc/defaults.yaml index 28db2ef5f..6f9fc0226 100644 --- a/salt/soc/defaults.yaml +++ b/salt/soc/defaults.yaml @@ -115,16 +115,16 @@ soc: ':kratos:': - soc_timestamp - event.dataset - - http_request.headers.x-real-ip + - http.request.headers.x-real-ip - user.name - - http_request.headers.user-agent + - http.useragent - msg ':hydra:': - soc_timestamp - event.dataset - - http_request.headers.x-real-ip + - http.request.headers.x-real-ip - user.name - - http_request.headers.user-agent + - http.useragent - msg '::conn': - soc_timestamp @@ -1747,7 +1747,7 @@ soc: showSubtitle: true - name: SOC - Auth description: Users authenticated to SOC grouped by IP address and identity - query: 'event.dataset:kratos.audit AND msg:*authenticated* | groupby http_request.headers.x-real-ip user.name' + query: 'event.dataset:kratos.audit AND msg:*authenticated* | groupby http.request.headers.x-real-ip user.name' showSubtitle: true - name: SOC - App description: Logs generated by the Security Onion Console (SOC) server and modules @@ -2027,10 +2027,10 @@ soc: query: '* | groupby event.category | groupby -sankey event.category event.module | groupby event.module | groupby -sankey event.module event.dataset | groupby event.dataset | groupby observer.name | groupby host.name | groupby source.ip | groupby destination.ip | groupby destination.port' - name: SOC Logins description: SOC (Security Onion Console) logins - query: 'event.dataset:kratos.audit AND msg:*authenticated* | groupby http_request.headers.x-real-ip | groupby -sankey http_request.headers.x-real-ip user.name | groupby user.name | groupby http_request.headers.user-agent' + query: 'event.dataset:kratos.audit AND msg:*authenticated* | groupby http.request.headers.x-real-ip | groupby -sankey http.request.headers.x-real-ip user.name | groupby user.name | groupby http.useragent' - name: SOC Login Failures description: SOC (Security Onion Console) login failures - query: 'event.dataset:kratos.audit AND msg:*Encountered*self-service*login*error* | groupby user.name | groupby http_request.headers.x-real-ip | groupby -sankey http_request.headers.x-real-ip http_request.headers.user-agent | groupby http_request.headers.user-agent' + query: 'event.dataset:kratos.audit AND msg:*Encountered*self-service*login*error* | groupby user.name | groupby http.request.headers.x-real-ip | groupby -sankey http.request.headers.x-real-ip http.useragent | groupby http.useragent' - name: Alerts description: Overview of all alerts query: 'tags:alert | groupby event.module* | groupby source.ip | groupby -sankey source.ip destination.ip | groupby destination.ip | groupby destination.port | groupby rule.name | groupby event.severity | groupby destination.as.organization.name' From 3effd30f7e96c28273945430c152c41b0e71b834 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Wed, 7 Jan 2026 14:49:19 -0600 Subject: [PATCH 15/20] unused var --- salt/manager/tools/sbin/soup | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/salt/manager/tools/sbin/soup b/salt/manager/tools/sbin/soup index 450095047..f57bf7c1c 100755 --- a/salt/manager/tools/sbin/soup +++ b/salt/manager/tools/sbin/soup @@ -1770,7 +1770,7 @@ create_intermediate_upgrade_verification_script() { local retries=20 local retry_count=0 local delay=180 - local success=1 + while [[ $retry_count -lt $retries ]]; do # keep stderr with variable for logging heavynode_versions=$(salt -C 'G@role:so-heavynode' cmd.run 'so-elasticsearch-query / --retry 3 --retry-delay 10 | jq ".version.number"' shell=/bin/bash --out=json 2>&1) @@ -1814,7 +1814,6 @@ create_intermediate_upgrade_verification_script() { local retries=20 local retry_count=0 local delay=180 - local success=1 while [[ $retry_count -lt $retries ]]; do # keep stderr with variable for logging From 150c31009e6ebef05a3424acfbe51e7a39dc6341 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Wed, 7 Jan 2026 19:18:20 -0600 Subject: [PATCH 16/20] make sure so-elasticsearch-query exits non-zero on failure --- salt/manager/tools/sbin/soup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/manager/tools/sbin/soup b/salt/manager/tools/sbin/soup index f57bf7c1c..4c0f989cd 100755 --- a/salt/manager/tools/sbin/soup +++ b/salt/manager/tools/sbin/soup @@ -1817,7 +1817,7 @@ create_intermediate_upgrade_verification_script() { while [[ $retry_count -lt $retries ]]; do # keep stderr with variable for logging - cluster_versions=$(so-elasticsearch-query _nodes/_all/version --retry 5 --retry-delay 10 2>&1) + cluster_versions=$(so-elasticsearch-query _nodes/_all/version --retry 5 --retry-delay 10 --fail 2>&1) local exit_status=$? if [[ $exit_status -ne 0 ]]; then From 8463bde90dd05f6e38056f48c9e8322c6c34a48c Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Wed, 7 Jan 2026 19:19:26 -0600 Subject: [PATCH 17/20] dont capture stderr from salt command failure 'ERROR: Minions returned with non-zero exit code' --- salt/manager/tools/sbin/soup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/manager/tools/sbin/soup b/salt/manager/tools/sbin/soup index 4c0f989cd..72947de88 100755 --- a/salt/manager/tools/sbin/soup +++ b/salt/manager/tools/sbin/soup @@ -1773,7 +1773,7 @@ create_intermediate_upgrade_verification_script() { while [[ $retry_count -lt $retries ]]; do # keep stderr with variable for logging - heavynode_versions=$(salt -C 'G@role:so-heavynode' cmd.run 'so-elasticsearch-query / --retry 3 --retry-delay 10 | jq ".version.number"' shell=/bin/bash --out=json 2>&1) + heavynode_versions=$(salt -C 'G@role:so-heavynode' cmd.run 'so-elasticsearch-query / --retry 3 --retry-delay 10 | jq ".version.number"' shell=/bin/bash --out=json 2> /dev/null) local exit_status=$? # Check that all heavynodes returned good data From 0d59c35d2aee5d0b499f0d42ff4cd8520dec978d Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Wed, 7 Jan 2026 19:20:27 -0600 Subject: [PATCH 18/20] phrasing/typo --- salt/manager/tools/sbin/soup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/manager/tools/sbin/soup b/salt/manager/tools/sbin/soup index 72947de88..5d752277d 100755 --- a/salt/manager/tools/sbin/soup +++ b/salt/manager/tools/sbin/soup @@ -1789,7 +1789,7 @@ create_intermediate_upgrade_verification_script() { return 0 else - echo "One or more heavynodes is not at the expected Elasticsearch version $EXPECTED_ES_VERSION. Rechecking in $delay seconds. Attempt $((retry_count + 1)) of $retries." + echo "One or more heavynodes are not at the expected Elasticsearch version $EXPECTED_ES_VERSION. Rechecking in $delay seconds. Attempt $((retry_count + 1)) of $retries." ((retry_count++)) sleep $delay From aa96cf44d4536ad5afd47f273e49ee8ec42094c6 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Wed, 7 Jan 2026 19:26:46 -0600 Subject: [PATCH 19/20] increase timeout commands timeout to account for time taken by salt minions to return data. add note informing user a previously required ES upgrade was detected and being verified before soup continues --- salt/manager/tools/sbin/soup | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/salt/manager/tools/sbin/soup b/salt/manager/tools/sbin/soup index 5d752277d..9fe3a641b 100755 --- a/salt/manager/tools/sbin/soup +++ b/salt/manager/tools/sbin/soup @@ -1681,9 +1681,11 @@ verify_es_version_compatibility() { create_intermediate_upgrade_verification_script $es_verification_script fi - # create script using version in statefile local es_required_version_statefile_value=$(cat $es_required_version_statefile) - timeout --foreground 3600 bash "$es_verification_script" "$es_required_version_statefile_value" "$es_required_version_statefile" + echo -e "\n##############################################################################################################################\n" + echo "A previously required intermediate Elasticsearch upgrade was detected. Verifying that all Searchnodes/Heavynodes have successfully upgraded Elasticsearch to $es_required_version_statefile_value before proceeding with soup to avoid potential data loss!" + # create script using version in statefile + timeout --foreground 4000 bash "$es_verification_script" "$es_required_version_statefile_value" "$es_required_version_statefile" if [[ $? -ne 0 ]]; then echo -e "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" @@ -1692,7 +1694,7 @@ verify_es_version_compatibility() { echo -e "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" exit 161 fi - + echo -e "\n##############################################################################################################################\n" fi if [[ " ${es_upgrade_map[$es_version]} " =~ " $target_es_version " || "$es_version" == "$target_es_version" ]]; then @@ -1728,7 +1730,7 @@ verify_es_version_compatibility() { exec bash -c "BRANCH=$next_step_so_version soup -y && BRANCH=$next_step_so_version soup -y && \ echo -e \"\n##############################################################################################################################\n\" && \ echo -e \"Verifying Elasticsearch was successfully upgraded to ${compatible_versions##* } across the grid. This part can take a while as Searchnodes/Heavynodes sync up with the Manager! \n\nOnce verification completes the next soup will begin automatically. If verification takes longer than 1 hour it will stop waiting and your grid will remain at $next_step_so_version. Allowing for all Searchnodes/Heavynodes to upgrade Elasticsearch to the required version on their own time.\n\" \ - && timeout --foreground 3600 bash /tmp/so_intermediate_upgrade_verification.sh ${compatible_versions##* } $es_required_version_statefile && \ + && timeout --foreground 4000 bash /tmp/so_intermediate_upgrade_verification.sh ${compatible_versions##* } $es_required_version_statefile && \ echo -e \"\n##############################################################################################################################\n\" \ && BRANCH=$originally_requested_so_version soup -y && BRANCH=$originally_requested_so_version soup -y" fi From db168a045286b23789073400ccfc77a7e70dff72 Mon Sep 17 00:00:00 2001 From: Matthew Wright Date: Thu, 8 Jan 2026 13:59:51 -0500 Subject: [PATCH 20/20] update case report for attached ai sessions --- .../templates/reports/standard/case_report.md | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/salt/sensoroni/files/templates/reports/standard/case_report.md b/salt/sensoroni/files/templates/reports/standard/case_report.md index 49f18e7c6..76a166f3f 100644 --- a/salt/sensoroni/files/templates/reports/standard/case_report.md +++ b/salt/sensoroni/files/templates/reports/standard/case_report.md @@ -130,4 +130,42 @@ Security Onion Case Report | ---- | ---- | ------ | --------- | {{ range sortHistory "CreateTime" "asc" .History -}} | {{formatDateTime "Mon Jan 02 15:04:05 -0700 2006" .CreateTime}} | {{getUserDetail "email" .UserId}} | {{.Kind}} | {{.Operation}} | +{{end}} + +## Attached Onion AI Sessions + +{{ range $idx, $session := sortAssistantSessionDetails "CreateTime" "desc" .AssistantSessions }} + +#### Session {{ add $idx 1 }} + +**Session ID:** {{$session.Session.SessionId}} + +**Title:** {{$session.Session.Title}} + +**User ID:** {{getUserDetail "email" $session.Session.UserId}} + +**Created:** {{formatDateTime "Mon Jan 02 15:04:05 -0700 2006" $session.Session.CreateTime}} + +**Updated:** {{formatDateTime "Mon Jan 02 15:04:05 -0700 2006" $session.Session.UpdateTime}} + +{{ if $session.Session.DeleteTime }} +**Deleted:** {{ formatDateTime "Mon Jan 02 15:04:05 -0700 2006" $session.Session.DeleteTime}} +{{ end }} + +#### Messages + +{{ range $index, $msg := sortAssistantMessages "CreateTime" "asc" $session.History }} +{{ range $i, $block := $msg.Message.ContentBlocks }} + +{{ if eq $block.Type "text" }} + +**Role:** {{$msg.Message.Role}} + +{{ stripEmoji $block.Text }} + +--- + +{{ end }}{{ end }} + +{{end}} {{end}} \ No newline at end of file