From 1a90eeb1b14675049db475be640da62541c608d5 Mon Sep 17 00:00:00 2001 From: Wes Date: Thu, 15 Sep 2022 19:45:28 +0000 Subject: [PATCH 1/5] Remove Osquery live query Logstash output configuration --- .../9101_output_osquery_livequery.conf.jinja | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja diff --git a/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja b/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja deleted file mode 100644 index 8d661b8cc..000000000 --- a/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja +++ /dev/null @@ -1,37 +0,0 @@ -{%- set ES = salt['grains.get']('master') -%} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %} -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %} - -filter { - if [type] =~ "live_query" { - - mutate { - rename => { - "[host][hostname]" => "computer_name" - } - } - - prune { - blacklist_names => ["host"] - } - - split { - field => "rows" - } - } -} - - -output { - if [type] =~ "live_query" { - elasticsearch { - pipeline => "osquery.live_query" - hosts => "{{ ES }}" - user => "{{ ES_USER }}" - password => "{{ ES_PASS }}" - index => "so-osquery" - ssl => true - ssl_certificate_verification => false - } - } -} From d5debd9b6bcb9440272e55f8313b8c0f17a46a40 Mon Sep 17 00:00:00 2001 From: Josh Brower Date: Fri, 16 Sep 2022 09:06:09 -0400 Subject: [PATCH 2/5] Change ssl_ecdh_curve --- salt/nginx/etc/nginx.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/salt/nginx/etc/nginx.conf b/salt/nginx/etc/nginx.conf index 8979535e8..623dae701 100644 --- a/salt/nginx/etc/nginx.conf +++ b/salt/nginx/etc/nginx.conf @@ -55,6 +55,7 @@ http { ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_ciphers HIGH:!aNULL:!MD5; + ssl_ecdh_curve secp521r1:secp384r1; ssl_prefer_server_ciphers on; ssl_protocols TLSv1.2; } From 12e940f80984454d69d178f689092181ad58fb74 Mon Sep 17 00:00:00 2001 From: Wes Date: Fri, 16 Sep 2022 20:55:49 +0000 Subject: [PATCH 3/5] Change managed_by value from 'fleet' to 'security_onion' for Elastic Agent templates in defaults.yaml --- salt/elasticsearch/defaults.yaml | 44 ++++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/salt/elasticsearch/defaults.yaml b/salt/elasticsearch/defaults.yaml index bb22849e5..a14c03e2d 100644 --- a/salt/elasticsearch/defaults.yaml +++ b/salt/elasticsearch/defaults.yaml @@ -75,7 +75,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true composed_of: - "so-logs-elastic_agent.apm_server@package" @@ -86,7 +86,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true data_stream: hidden: false @@ -109,7 +109,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true composed_of: - "so-logs-elastic_agent.auditbeat@package" @@ -120,7 +120,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true data_stream: hidden: false @@ -143,7 +143,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true composed_of: - "so-logs-elastic_agent.cloudbeat@package" @@ -154,7 +154,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true data_stream: hidden: false @@ -177,7 +177,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true composed_of: - "so-logs-elastic_agent.endpoint_security@package" @@ -188,7 +188,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true data_stream: hidden: false @@ -211,7 +211,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true composed_of: - "so-logs-elastic_agent.filebeat@package" @@ -222,7 +222,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true data_stream: hidden: false @@ -245,7 +245,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true composed_of: - "so-logs-elastic_agent.fleet_server@package" @@ -256,7 +256,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true data_stream: hidden: false @@ -279,7 +279,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true composed_of: - "so-logs-elastic_agent.heartbeat@package" @@ -290,7 +290,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true data_stream: hidden: false @@ -313,7 +313,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true composed_of: - "so-logs-elastic_agent@package" @@ -324,7 +324,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true data_stream: hidden: false @@ -347,7 +347,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true composed_of: - "so-logs-elastic_agent.metricbeat@package" @@ -358,7 +358,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true data_stream: hidden: false @@ -381,7 +381,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true composed_of: - "so-logs-elastic_agent.osquerybeat@package" @@ -392,7 +392,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true data_stream: hidden: false @@ -415,7 +415,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true composed_of: - "so-logs-elastic_agent.packetbeat@package" @@ -426,7 +426,7 @@ elasticsearch: _meta: package: name: elastic_agent - managed_by: fleet + managed_by: security_onion managed: true data_stream: hidden: false From 9542a5ada20150f26fb94dd9f9e1ae058d123549 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Fri, 16 Sep 2022 17:46:52 -0400 Subject: [PATCH 4/5] complete rewrite of so-status --- salt/common/init.sls | 11 +- salt/common/tools/sbin/so-status | 408 ++++++++++-------------------- salt/soc/soc_soc.yaml | 2 + salt/telegraf/scripts/sostatus.sh | 6 +- 4 files changed, 151 insertions(+), 276 deletions(-) diff --git a/salt/common/init.sls b/salt/common/init.sls index c391c127e..f8d3c9503 100644 --- a/salt/common/init.sls +++ b/salt/common/init.sls @@ -192,9 +192,16 @@ sostatus_log: file.managed: - name: /opt/so/log/sostatus/status.log - mode: 644 - + +common_pip_dependencies: + pip.installed: + - user: root + - pkgs: + - rich + - target: /usr/lib64/python3.6/site-packages + # Install sostatus check cron -'/usr/sbin/so-status -q; echo $? > /opt/so/log/sostatus/status.log 2>&1': +'/usr/sbin/so-status -j > /opt/so/log/sostatus/status.log 2>&1': cron.present: - user: root - minute: '*/1' diff --git a/salt/common/tools/sbin/so-status b/salt/common/tools/sbin/so-status index 596070e4e..5e1487311 100644 --- a/salt/common/tools/sbin/so-status +++ b/salt/common/tools/sbin/so-status @@ -1,301 +1,165 @@ -#!/bin/bash +#!/usr/bin/env python3 # Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one # or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at # https://securityonion.net/license; you may not use this file except in compliance with the # Elastic License 2.0. -if ! [ "$(id -u)" = 0 ]; then - echo "This command must be run as root" - exit 1 -fi +import json +import os +from rich import box +from rich.console import Console +from rich.table import Table +import subprocess +import sys +import time -display_help() { -cat < 2: + item = json.loads(line) + if item['Names'] == container: + details['Status'] = item['State'] + details['Details'] = item['Status'] + container_list.append(details) + exists = True + if item['State'] != "running": + code = 1 + break - mapfile -t expected_container_list < <(sort -u /opt/so/conf/so-status/so-status.conf | tr -d "#") + if not exists: + container_list.append(details) + code = 1 + return code, container_list -} -populate_container_lists() { - systemctl is-active --quiet docker +def check_status(options, console): + container_list = [] + code = check_system_status(options, console) + if code == 0: + code, container_list = check_container_status(options, console) + output(options, console, code, container_list) + return code - if [[ $? = 0 ]]; then - mapfile -t docker_raw_list < <(curl -s --unix-socket /var/run/docker.sock http:/v1.40/containers/json?all=1 \ - | jq -c '.[] | { Name: .Names[0], State: .State }' \ - | tr -d '/{"}') - else - exit 1 - fi - local container_name="" - local container_state="" +def main(): + options = [] + args = sys.argv[1:] + for option in args: + if option.startswith("-"): + options.append(option) + args.remove(option) - for line in "${docker_raw_list[@]}"; do - container_name="$( echo $line | sed -e 's/Name:\(.*\),State:\(.*\)/\1/' )" # Get value in the first search group (container names) - container_state="$( echo $line | sed -e 's/Name:\(.*\),State:\(.*\)/\2/' )" # Get value in the second search group (container states) + if len(args) != 0 or "-h" in options: + showUsage(options, None) - temp_container_name_list+=( "${container_name}" ) - temp_container_state_list+=( "${container_state}" ) - done + if os.environ["USER"] != "root": + fail("This program must be run as root") + + console = Console() + sys.exit(check_status(options, console)) - compare_lists -} -parse_status() { - local service_name=${1} - local container_state=${2} +if __name__ == "__main__": + main() - for state in "${GOOD_STATUSES[@]}"; do - [[ $container_state = "$state" ]] && [[ $QUIET = "false" ]] && printf $SUCCESS_STRING && return 0 || [[ $container_state = "$state" ]] && return 0 - done - - for state in "${BAD_STATUSES[@]}"; do - [[ " ${DISABLED_CONTAINERS[@]} " =~ " ${service_name} " ]] && [[ $QUIET = "false" ]] && printf $DISABLED_STRING && return 0 || [[ " ${DISABLED_CONTAINERS[@]} " =~ " ${service_name} " ]] && return 0 - done - - # if a highstate has finished running since the system has started - # then the containers should be running so let's check the status - if [ $LAST_HIGHSTATE_END -ge $SYSTEM_START_TIME ]; then - - [[ $container_state = "missing" ]] && [[ $QUIET = "false" ]] && printf $MISSING_STRING && return 1 || [[ $container_state = "missing" ]] && [[ "$EXITCODE" -lt 2 ]] && EXITCODE=1 && return 1 - - for state in "${PENDING_STATUSES[@]}"; do - [[ $container_state = "$state" ]] && [[ $QUIET = "false" ]] && printf $PENDING_STRING && return 0 - done - - # This is technically not needed since the default is error state - for state in "${BAD_STATUSES[@]}"; do - [[ $container_state = "$state" ]] && [[ $QUIET = "false" ]] && printf $ERROR_STRING && return 1 || [[ $container_state = "$state" ]] && [[ "$EXITCODE" -lt 2 ]] && EXITCODE=1 && return 1 - done - - [[ $QUIET = "false" ]] && printf $ERROR_STRING && return 1 || [[ "$EXITCODE" -lt 2 ]] && EXITCODE=1 && return 1 - - # if a highstate has not run since system start time, but a highstate is currently running - # then show that the containers are STARTING - elif [[ "$HIGHSTATE_RUNNING" == 0 ]]; then - [[ $QUIET = "false" ]] && printf $STARTING_STRING && return 2 || EXITCODE=2 && return 2 - - # if a highstate has not finished running since system startup and isn't currently running - # then just show that the containers are WAIT_START; waiting to be started - else - [[ $QUIET = "false" ]] && printf $WAIT_START_STRING && return 2 || EXITCODE=2 && return 2 - - fi -} - -# {% raw %} - -print_line() { - local service_name=${1} - local service_state="$( parse_status ${1} ${2} )" - local columns=$(tput cols) - local state_color="\e[0m" - - local PADDING_CONSTANT=15 - - if [[ $service_state = "$ERROR_STRING" ]] || [[ $service_state = "$MISSING_STRING" ]]; then - state_color="\e[1;31m" - if [[ "$EXITCODE" -eq 0 ]]; then - EXITCODE=1 - fi - elif [[ $service_state = "$SUCCESS_STRING" ]]; then - state_color="\e[1;32m" - elif [[ $service_state = "$PENDING_STRING" ]] || [[ $service_state = "$DISABLED_STRING" ]] || [[ $service_state = "$STARTING_STRING" ]] || [[ $service_state = "$WAIT_START_STRING" ]]; then - state_color="\e[1;33m" - EXITCODE=2 - fi - - printf " $service_name " - for i in $(seq 0 $(( $columns - $PADDING_CONSTANT - ${#service_name} - ${#service_state} ))); do - printf "${state_color}%b\e[0m" "-" - done - printf " [ " - printf "${state_color}%b\e[0m" "$service_state" - printf "%s \n" " ]" -} - -non_term_print_line() { - local service_name=${1} - local service_state="$( parse_status ${1} ${2} )" - - if [[ $service_state = "$ERROR_STRING" ]] || [[ $service_state = "$MISSING_STRING" ]]; then - if [[ "$EXITCODE" -eq 0 ]]; then - EXITCODE=1 - fi - elif [[ $service_state = "$PENDING_STRING" ]] || [[ $service_state = "$DISABLED_STRING" ]] || [[ $service_state = "$STARTING_STRING" ]] || [[ $service_state = "$WAIT_START_STRING" ]]; then - EXITCODE=2 - fi - - printf " $service_name " - for i in $(seq 0 $(( 35 - ${#service_name} - ${#service_state} ))); do - printf "-" - done - printf " [ " - printf "$service_state" - printf "%s \n" " ]" -} - -main() { - - # if running from salt - if [ "$CALLER" == 'salt-call' ] || [ "$CALLER" == 'salt-minion' ]; then - printf "\n" - printf "Checking Docker status\n\n" - - systemctl is-active --quiet docker - if [[ $? = 0 ]]; then - non_term_print_line "Docker" "running" - else - non_term_print_line "Docker" "exited" - fi - - populate_container_lists - - printf "\n" - printf "Checking container statuses\n\n" - - local num_containers=${#container_name_list[@]} - - for i in $(seq 0 $(($num_containers - 1 ))); do - non_term_print_line ${container_name_list[$i]} ${container_state_list[$i]} - done - - printf "\n" - - # else if running from a terminal - else - - if [ "$QUIET" = true ]; then - if [ $SYSTEM_START_TIME -lt $LAST_SOSETUP_LOG ]; then - exit 99 - fi - print_or_parse="parse_status" - else - print_or_parse="print_line" - - local focus_color="\e[1;34m" - printf "\n" - printf "${focus_color}%b\e[0m" "Checking Docker status\n\n" - fi - - systemctl is-active --quiet docker - if [[ $? = 0 ]]; then - ${print_or_parse} "Docker" "running" - else - ${print_or_parse} "Docker" "exited" - fi - - populate_container_lists - - if [ "$QUIET" = false ]; then - printf "\n" - printf "${focus_color}%b\e[0m" "Checking container statuses\n\n" - fi - - local num_containers=${#container_name_list[@]} - - for i in $(seq 0 $(($num_containers - 1 ))); do - ${print_or_parse} ${container_name_list[$i]} ${container_state_list[$i]} - done - - if [ "$QUIET" = false ]; then - printf "\n" - fi - fi -} - -# {% endraw %} - -while getopts ':hq' OPTION; do - case "$OPTION" in - h) - display_help - exit 0 - ;; - q) - QUIET=true - ;; - \?) - display_help - exit 0 - ;; - esac -done - -main - -exit $EXITCODE \ No newline at end of file diff --git a/salt/soc/soc_soc.yaml b/salt/soc/soc_soc.yaml index 57afc11e3..f16f5da87 100644 --- a/salt/soc/soc_soc.yaml +++ b/salt/soc/soc_soc.yaml @@ -6,11 +6,13 @@ soc: description: Customize the login page with a specific markdown-formatted message. file: True global: True + syntax: md motd__md: title: Overview Page description: Customize the overview page with specific markdown-formatted content. Images can be used but must be hosted from another host that is accessible by the users' browser. file: True global: True + syntax: md custom__js: title: Custom Javascript description: Customize SOC UI behavior with custom Javascript code. Custom Javascript not provided by Security Onion Solutions is unsupported, and should be removed prior to requesting support and prior to performing upgrades. diff --git a/salt/telegraf/scripts/sostatus.sh b/salt/telegraf/scripts/sostatus.sh index 567e6b027..d1753eadb 100644 --- a/salt/telegraf/scripts/sostatus.sh +++ b/salt/telegraf/scripts/sostatus.sh @@ -11,10 +11,12 @@ if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then SOSTATUSLOG=/var/log/sostatus/status.log - SOSTATUSSTATUS=$(cat /var/log/sostatus/status.log) + SOSTATUSCODE=$(jq -r .status_code /var/log/sostatus/status.log) + SOSTATUSJSON=$(cat /var/log/sostatus/status.log) if [ -f "$SOSTATUSLOG" ]; then - echo "sostatus status=$SOSTATUSSTATUS" + echo "sostatus status=$SOSTATUSCODE" + echo "sostatus json=$SOSTATUSJSON" else exit 0 fi From 7d965b5cda8d791433deb2f10456f33a5d0ea0cb Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Mon, 19 Sep 2022 09:17:06 -0400 Subject: [PATCH 5/5] Ensure so-status does not get jinjafied --- salt/common/init.sls | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/salt/common/init.sls b/salt/common/init.sls index f8d3c9503..4bf779e2b 100644 --- a/salt/common/init.sls +++ b/salt/common/init.sls @@ -123,6 +123,13 @@ utilsyncscripts: - so-firewall - so-image-common - soup + - so-status + +so-status_script: + file.managed: + - name: /usr/sbin/so-status + - source: salt://common/tools/sbin/so-status + - mode: 755 {% if role in ['eval', 'standalone', 'sensor', 'heavynode'] %} # Add sensor cleanup