diff --git a/salt/common/init.sls b/salt/common/init.sls index c391c127e..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 @@ -192,9 +199,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/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 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 - } - } -} 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; } 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