From 7c00e7c2861eca190fe5a6e2dedb5b23d48f0cc7 Mon Sep 17 00:00:00 2001 From: William Wernert Date: Thu, 6 Feb 2020 15:23:03 -0500 Subject: [PATCH] [feature] Final changes for so-status re: predefined container list --- pillar/docker/config.sls | 215 +++++++++++++++++++++++++ pillar/top.sls | 1 + salt/common/tools/sbin/so-auth-restart | 21 +++ salt/common/tools/sbin/so-auth-start | 20 +++ salt/common/tools/sbin/so-auth-stop | 20 +++ salt/common/tools/sbin/so-restart | 1 + salt/common/tools/sbin/so-start | 11 ++ salt/common/tools/sbin/so-status | 114 ++++++++++--- salt/common/tools/sbin/so-stop | 5 +- salt/top.sls | 8 +- setup/so-functions | 4 +- 11 files changed, 388 insertions(+), 32 deletions(-) create mode 100644 pillar/docker/config.sls create mode 100644 salt/common/tools/sbin/so-auth-restart create mode 100644 salt/common/tools/sbin/so-auth-start create mode 100644 salt/common/tools/sbin/so-auth-stop diff --git a/pillar/docker/config.sls b/pillar/docker/config.sls new file mode 100644 index 000000000..454eead49 --- /dev/null +++ b/pillar/docker/config.sls @@ -0,0 +1,215 @@ +{%- set OSQUERY = salt['pillar.get']('master:osquery', '0') -%} +{%- set WAZUH = salt['pillar.get']('master:wazuh', '0') -%} +{%- set THEHIVE = salt['pillar.get']('master:thehive', '0') -%} +{%- set PLAYBOOK = salt['pillar.get']('master:playbook', '0') -%} +{%- set FREQSERVER = salt['pillar.get']('master:freq', '0') -%} +{%- set DOMAINSTATS = salt['pillar.get']('master:domainstats', '0') -%} +{%- set BROVER = salt['pillar.get']('static:broversion', 'COMMUNITY') -%} + +eval: + containers: + - so-core + - so-telegraf + - so-influxdb + - so-grafana + - so-dockerregistry + - so-sensoroni + - so-idstools + - so-auth-api + - so-auth-ui + {%- if OSQUERY != 0 %} + - so-mysql + - so-fleet + - so-redis + {%- endif %} + - so-elasticsearch + - so-logstash + - so-kibana + - so-steno + - so-suricata + - so-zeek + - so-curator + - so-elasalert + {%- if WAZUH != 0 %} + - so-wazuh + {%- endif %} + - so-soctopus + {%- if THEHIVE != 0 %} + - so-thehive + - so-thehive-es + - so-cortex + {%- endif %} + {%- if PLAYBOOK != 0 %} + - so-playbook + - so-navigator + {%- endif %} + {%- if FREQSERVER != 0 %} + - so-freqserver + {%- endif %} + {%- if DOMAINSTATS != 0 %} + - so-domainstats + {%- endif %} +heavy_node: + containers: + - so-core + - so-telegraf + - so-influxdb + - so-grafana + - so-redis + - so-logstash + - so-elasticsearch + - so-curator + - so-steno + - so-suricata + - so-wazuh + - so-filebeat + {%- if BROVER != 'SURICATA' %} + - so-zeek + {%- endif %} +helix: + containers: + - so-core + - so-telegraf + - so-influxdb + - so-grafana + - so-idstools + - so-steno + - so-zeek + - so-zeek + - so-redis + - so-logstash + - so-filebeat +hot_node: + containers: + - so-core + - so-telegraf + - so-influxdb + - so-grafana + - so-logstash + - so-elasticsearch + - so-curator +master_search: + containers: + - so-core + - so-telegraf + - so-influxdb + - so-grafana + - so-sensoroni + - so-acng + - so-idstools + - so-redis + - so-auth-api + - so-auth-ui + - so-logstash + - so-elasticsearch + - so-curator + - so-kibana + - so-elasalert + - so-filebeat + - so-soctopus + {%- if OSQUERY != 0 %} + - so-mysql + - so-fleet + - so-redis + {%- endif %} + {%- if WAZUH != 0 %} + - so-wazuh + {%- endif %} + - so-soctopus + {%- if THEHIVE != 0 %} + - so-thehive + - so-thehive-es + - so-cortex + {%- endif %} + {%- if PLAYBOOK != 0 %} + - so-playbook + - so-navigator + {%- endif %} + {%- if FREQSERVER != 0 %} + - so-freqserver + {%- endif %} + {%- if DOMAINSTATS != 0 %} + - so-domainstats + {%- endif %} +master: + containers: + - so-dockerregistry + - so-core + - so-telegraf + - so-influxdb + - so-grafana + - so-sensoroni + - so-acng + - so-idstools + - so-redis + - so-auth-api + - so-auth-ui + - so-elasticsearch + - so-logstash + - so-kibana + - so-elasalert + - so-filebeat + {%- if OSQUERY != 0 %} + - so-mysql + - so-fleet + - so-redis + {%- endif %} + {%- if WAZUH != 0 %} + - so-wazuh + {%- endif %} + - so-soctopus + {%- if THEHIVE != 0 %} + - so-thehive + - so-thehive-es + - so-cortex + {%- endif %} + {%- if PLAYBOOK != 0 %} + - so-playbook + - so-navigator + {%- endif %} + {%- if FREQSERVER != 0 %} + - so-freqserver + {%- endif %} + {%- if DOMAINSTATS != 0 %} + - so-domainstats + {%- endif %} +parser_node: + containers: + - so-core + - so-telegraf + - so-influxdb + - so-grafana + - so-logstash +search_node: + containers: + - so-core + - so-telegraf + - so-influxdb + - so-grafana + - so-logstash + - so-elasticsearch + - so-curator + - so-filebeat + {%- if WAZUH != 0 %} + - so-wazuh + {%- endif %} +sensor: + containers: + - so-core + - so-telegraf + - so-influxdb + - so-grafana + - so-steno + - so-suricata + {%- if BROVER != 'SURICATA' %} + - so-zeek + {%- endif %} + - so-wazuh + - so-filebeat +warm_node: + containers: + - so-core + - so-telegraf + - so-influxdb + - so-grafana + - so-elasticsearch diff --git a/pillar/top.sls b/pillar/top.sls index 9eb5522fe..42d40ec10 100644 --- a/pillar/top.sls +++ b/pillar/top.sls @@ -1,6 +1,7 @@ base: '*': - patch.needs_restarting + - docker.config 'G@role:so-mastersearch or G@role:so-heavynode': - match: compound diff --git a/salt/common/tools/sbin/so-auth-restart b/salt/common/tools/sbin/so-auth-restart new file mode 100644 index 000000000..8659b1e3a --- /dev/null +++ b/salt/common/tools/sbin/so-auth-restart @@ -0,0 +1,21 @@ +#!/bin/bash + +# Copyright 2014,2015,2016,2017,2018,2019,2020 Security Onion Solutions, LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +. /usr/sbin/so-common + +/usr/sbin/so-restart auth $1 + diff --git a/salt/common/tools/sbin/so-auth-start b/salt/common/tools/sbin/so-auth-start new file mode 100644 index 000000000..5330f662d --- /dev/null +++ b/salt/common/tools/sbin/so-auth-start @@ -0,0 +1,20 @@ +#!/bin/bash + +# Copyright 2014,2015,2016,2017,2018,2019,2020 Security Onion Solutions, LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +. /usr/sbin/so-common + +/usr/sbin/so-start auth $1 diff --git a/salt/common/tools/sbin/so-auth-stop b/salt/common/tools/sbin/so-auth-stop new file mode 100644 index 000000000..5ca6db7e2 --- /dev/null +++ b/salt/common/tools/sbin/so-auth-stop @@ -0,0 +1,20 @@ +#!/bin/bash + +# Copyright 2014,2015,2016,2017,2018,2019,2020 Security Onion Solutions, LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +. /usr/sbin/so-common + +/usr/sbin/so-stop auth $1 diff --git a/salt/common/tools/sbin/so-restart b/salt/common/tools/sbin/so-restart index bbcfe4c20..3714e324a 100755 --- a/salt/common/tools/sbin/so-restart +++ b/salt/common/tools/sbin/so-restart @@ -32,5 +32,6 @@ fi case $1 in "cortex") docker stop so-thehive-cortex so-thehive && docker rm so-thehive-cortex so-thehive && salt-call state.apply hive queue=True;; "steno") docker stop so-steno && docker rm so-steno && salt-call state.apply pcap queue=True;; + "auth") docker stop so-auth-api; docker stop so-auth-ui; salt-cal state.apply auth queue=True;; *) docker stop so-$1 ; docker rm so-$1 ; salt-call state.apply $1 queue=True;; esac diff --git a/salt/common/tools/sbin/so-start b/salt/common/tools/sbin/so-start index a198377a1..889160122 100755 --- a/salt/common/tools/sbin/so-start +++ b/salt/common/tools/sbin/so-start @@ -32,5 +32,16 @@ fi case $1 in "all") salt-call state.highstate queue=True;; "steno") if docker ps | grep -q so-$1; then printf "\n$1 is already running!\n\n"; else docker rm so-$1 >/dev/null 2>&1 ; salt-call state.apply pcap queue=True; fi ;; + "auth") + if docker ps | grep -q so-auth-api; then + if docker ps | grep -q so-auth-ui; then + printf "\n$1 is already running!\n\n" + else + docker rm so-auth-api >/dev/null 2>&1; docker rm so-auth-ui >/dev/null 2>&1; salt-call state.apply $1 queue=True + fi + else + docker rm so-auth-api >/dev/null 2>&1; docker rm so-auth-ui >/dev/null 2>&1; salt-call state.apply $1 queue=True + fi + ;; *) if docker ps | grep -q so-$1; then printf "\n$1 is already running\n\n"; else docker rm so-$1 >/dev/null 2>&1 ; salt-call state.apply $1 queue=True; fi ;; esac diff --git a/salt/common/tools/sbin/so-status b/salt/common/tools/sbin/so-status index 45b52ae35..8d37395dc 100755 --- a/salt/common/tools/sbin/so-status +++ b/salt/common/tools/sbin/so-status @@ -15,7 +15,32 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -# {% raw %} +{%- set pillar_suffix = ':containers' -%} +{%- if (salt['grains.get']('role') == 'so-mastersearch') -%} + {%- set pillar_val = 'master_search' -%} +{%- elif (salt['grains.get']('role') == 'so-master') -%} + {%- set pillar_val = 'master' -%} +{%- elif (salt['grains.get']('role') == 'so-heavynode') -%} + {%- set pillar_val = 'heavy_node' -%} +{%- elif (salt['grains.get']('role') == 'so-sensor') -%} + {%- set pillar_val = 'sensor' -%} +{%- elif (salt['grains.get']('role') == 'so-eval') -%} + {%- set pillar_val = 'eval' -%} +{%- elif (salt['grains.get']('role') == 'so-helix') -%} + {%- set pillar_val = 'helix' -%} +{%- elif (salt['grains.get']('role') == 'so-node') -%} + {%- if (salt['pillar.get']('node:node_type') == 'parser') -%} + {%- set pillar_val = 'parser_node' -%} + {%- elif (salt['pillar.get']('node:node_type') == 'hot') -%} + {%- set pillar_val = 'hot_node' -%} + {%- elif (salt['pillar.get']('node:node_type') == 'warm') -%} + {%- set pillar_val = 'warm_node' -%} + {%- elif (salt['pillar.get']('node:node_type') == 'search') -%} + {%- set pillar_val = 'search_node' -%} + {%- endif -%} +{%- endif -%} +{%- set pillar_name = pillar_val ~ pillar_suffix -%} +{%- set container_list = salt['pillar.get'](pillar_name) %} if ! [ $(id -u)=0 ]; then echo "This command must be run as root" @@ -26,13 +51,56 @@ fi ERROR_STRING="ERROR" SUCCESS_STRING="OK" PENDING_STRING="PENDING" +MISSING_STRING='MISSING' declare -a BAD_STATUSES=("removing", "paused", "exited", "dead") declare -a PENDING_STATUSES=("paused", "created", "restarting") declare -a GOOD_STATUSES=("running") +declare -a temp_container_name_list=() +declare -a temp_container_state_list=() declare -a container_name_list=() declare -a container_state_list=() + +declare -a expected_container_list=() + +# {% raw %} + +compare_lists() { + local found=0 + + create_expected_container_list + + if [[ ${#expected_container_list[@]} = 0 ]]; then + container_name_list=$temp_container_name_list + container_state_list=$temp_container_state_list + return 1 + fi + + for intended_item in ${expected_container_list[@]}; do + found = 0 + for i in ${!temp_container_name_list[@]}; do + [[ ${temp_container_name_list[$i]} = $intended_item ]] \ + && found = 1 \ + && container_name_list+=("${temp_container_name_list[$i]}") \ + && container_state_list+=("${temp_container_state_list[$i]}") \ + && break + done + if [[ $found = 0 ]]; then + container_name_list+=("$intended_item") + container_state_list+=("missing") + fi + done +} + +# {% endraw %} + +create_expected_container_list() { + {% for item in container_list%} + expected_container_list+=("{{ item }}") + {% endfor %} +} + populate_container_lists() { systemctl is-active --quiet docker @@ -50,51 +118,51 @@ populate_container_lists() { 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) - container_name_list+=( "${container_name}" ) - container_state_list+=( "${container_state}" ) + + temp_container_name_list+=( "${container_name}" ) + temp_container_state_list+=( "${container_state}" ) done + + compare_lists } parse_status() { local container_state=${1} - local found=0 + + [[ $container_state = "missing" ]] && printf $MISSING_STRING && return 1 for state in "${GOOD_STATUSES[@]}"; do [[ $container_state = $state ]] && printf $SUCCESS_STRING && return 0 done - if [[ $found = 0 ]]; then - for state in "${PENDING_STATUSES[@]}"; do - [[ $container_state = $state ]] && printf $PENDING_STRING && return 0 - done - fi + for state in "${PENDING_STATUSES[@]}"; do + [[ $container_state = $state ]] && printf $PENDING_STRING && return 0 + done # This is technically not needed since the default is error state - if [[ $found = 0 ]]; then - for state in "${BAD_STATUSES[@]}"; do - [[ $container_state = $state ]] && printf $ERROR_STRING && return 1 - done - fi + for state in "${BAD_STATUSES[@]}"; do + [[ $container_state = $state ]] && printf $ERROR_STRING && return 1 + done printf $ERROR_STRING && return 1 } -columns=$(tput cols) +# {% raw %} print_line() { local service_name=${1} local service_state=$( parse_status ${2} ) - local PADDING_CONSTANT=14 + local columns=$(tput cols) local state_color="\e[0m" - if [[ $service_state = $ERROR_STRING ]]; then + local PADDING_CONSTANT=14 + + if [[ $service_state = $ERROR_STRING ]] || [[ $service_state = $MISSING_STRING ]]; then state_color="\e[1;31m" elif [[ $service_state = $SUCCESS_STRING ]]; then state_color="\e[1;32m" elif [[ $service_state = $PENDING_STRING ]]; then state_color="\e[1;33m" - else - state_color="\e[0m" fi printf " $service_name " @@ -121,13 +189,9 @@ main() { populate_container_lists printf "\n" - printf "${focus_color}%b\e[0m" "Checking container statuses\n\n" - local num_containers=${#docker_raw_list[@]} - local container_name="" - local container_state="" for i in $(seq 0 $(($num_containers - 1 ))); do print_line ${container_name_list[$i]} ${container_state_list[$i]} @@ -136,6 +200,8 @@ main() { printf "\n" } +# {% endraw %} + + main -# {% endraw %} \ No newline at end of file diff --git a/salt/common/tools/sbin/so-stop b/salt/common/tools/sbin/so-stop index 64d0a4298..8d5770b64 100755 --- a/salt/common/tools/sbin/so-stop +++ b/salt/common/tools/sbin/so-stop @@ -23,5 +23,8 @@ echo $banner printf "Stopping $1...\n" echo $banner -docker stop so-$1 ; docker rm so-$1 +case $1 in + "auth") docker stop so-auth-api; docker rm so-auth-api; docker stop so-auth-ui; docker rm so-auth-ui ;; + *) docker stop so-$1 ; docker rm so-$1 ;; +esac diff --git a/salt/top.sls b/salt/top.sls index ef2124a65..6f7763c62 100644 --- a/salt/top.sls +++ b/salt/top.sls @@ -1,7 +1,6 @@ {%- set BROVER = salt['pillar.get']('static:broversion', 'COMMUNITY') -%} {%- set OSQUERY = salt['pillar.get']('master:osquery', '0') -%} {%- set WAZUH = salt['pillar.get']('master:wazuh', '0') -%} -{%- set GRAFANA = salt['pillar.get']('master:grafana', '0') -%} {%- set THEHIVE = salt['pillar.get']('master:thehive', '0') -%} {%- set PLAYBOOK = salt['pillar.get']('master:playbook', '0') -%} {%- set FREQSERVER = salt['pillar.get']('master:freq', '0') -%} @@ -100,6 +99,7 @@ base: - master - idstools - redis + - auth {%- if OSQUERY != 0 %} - mysql {%- endif %} @@ -188,6 +188,7 @@ base: - firewall - sensor - master + - auth {%- if OSQUERY != 0 %} - launcher {%- endif %} @@ -204,6 +205,7 @@ base: - master - idstools - redis + - auth {%- if OSQUERY != 0 %} - mysql {%- endif %} @@ -257,9 +259,5 @@ base: {%- if BROVER != 'SURICATA' %} - zeek {%- endif %} - - wazuh - filebeat - {%- if OSQUERY != 0 %} - - launcher - {%- endif %} - schedule diff --git a/setup/so-functions b/setup/so-functions index 83f323b0b..61bd8542d 100755 --- a/setup/so-functions +++ b/setup/so-functions @@ -1036,7 +1036,7 @@ EOF fi yum clean expire-cache - yum -y install epel-release salt-minion-2019.2.3 yum-utils device-mapper-persistent-data lvm2 openssl + yum -y install epel-release salt-minion-2019.2.3 yum-utils device-mapper-persistent-data lvm2 openssl jq yum -y update exclude=salt* systemctl enable salt-minion @@ -1054,7 +1054,7 @@ EOF DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" upgrade # Add the pre-requisites for installing docker-ce - apt-get -y install ca-certificates curl software-properties-common apt-transport-https openssl >> $SETUPLOG 2>&1 + apt-get -y install ca-certificates curl software-properties-common apt-transport-https openssl jq >> $SETUPLOG 2>&1 # Grab the version from the os-release file UVER=$(grep VERSION_ID /etc/os-release | awk -F '[ "]' '{print $2}')