mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2025-12-06 09:12:45 +01:00
335 lines
10 KiB
Bash
Executable File
335 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Copyright 2014-2022 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 <http://www.gnu.org/licenses/>.
|
|
|
|
MYNAME="${0##*/}"
|
|
|
|
display_help() {
|
|
printf "%s" "${MYNAME}"
|
|
printf " [%s]" "-h" "-q|--quiet"
|
|
printf "\n"
|
|
printf "\t-%s\t%s\n" \
|
|
"h" "Show this message." \
|
|
"q,--quiet" "suppress the output and return a single status code of overall status"
|
|
printf "\nReturn Codes:\n"
|
|
printf "\t%s - %s\n" \
|
|
"0" "Ok" \
|
|
"1" "Error" \
|
|
"2" "Starting/Pending"\
|
|
"99" "Installing SO"
|
|
# exit with code 0, unless passed a number when called
|
|
exit "${1:-0}"
|
|
}
|
|
|
|
# Constants
|
|
QUIET=false
|
|
EXITCODE=0
|
|
SYSTEM_START_TIME=$(date -d "$(</proc/uptime awk '{print $1}') seconds ago" +%s)
|
|
# file populated by salt.lasthighstate state at end of successful highstate run
|
|
LAST_HIGHSTATE_END=$([ -e "/opt/so/log/salt/lasthighstate" ] && date -r /opt/so/log/salt/lasthighstate +%s || echo 0)
|
|
LAST_SOSETUP_LOG=$([ -e "/root/sosetup.log" ] && date -r /root/sosetup.log +%s || echo 0)
|
|
HIGHSTATE_RUNNING=$(salt-call --local saltutil.running --out=json | jq -r '.local[].fun' | grep -q 'state.highstate' && echo $?)
|
|
ERROR_STRING="ERROR"
|
|
SUCCESS_STRING="OK"
|
|
PENDING_STRING="PENDING"
|
|
MISSING_STRING='MISSING'
|
|
DISABLED_STRING='DISABLED'
|
|
WAIT_START_STRING='WAIT_START'
|
|
STARTING_STRING='STARTING'
|
|
CALLER=$(ps -o comm= $PPID)
|
|
declare -a BAD_STATUSES=("removing" "paused" "exited" "dead")
|
|
declare -a PENDING_STATUSES=("paused" "created" "restarting")
|
|
declare -a GOOD_STATUSES=("running")
|
|
declare -a DISABLED_CONTAINERS=()
|
|
mapfile -t DISABLED_CONTAINERS < <(sort -u /opt/so/conf/so-status/so-status.conf | grep "^\s*#" | tr -d "#")
|
|
|
|
|
|
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() {
|
|
|
|
mapfile -t expected_container_list < <(sort -u /opt/so/conf/so-status/so-status.conf | tr -d "#")
|
|
|
|
}
|
|
|
|
populate_container_lists() {
|
|
systemctl is-active --quiet docker
|
|
|
|
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=""
|
|
|
|
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)
|
|
|
|
temp_container_name_list+=( "${container_name}" )
|
|
temp_container_state_list+=( "${container_state}" )
|
|
done
|
|
|
|
compare_lists
|
|
}
|
|
|
|
parse_status() {
|
|
local service_name=${1}
|
|
local container_state=${2}
|
|
|
|
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() {
|
|
is_tty
|
|
local service_name="${1}"
|
|
local service_state ; service_state="$( parse_status "${1}" "${2}" )"
|
|
# XXX: What will we do if tput isn't avalable?
|
|
if [ "${__tty}" -eq 1 ]; then
|
|
NC="$(tput sgr0)" # no color
|
|
red="$(tput setaf 1 bold)"
|
|
green="$(tput setaf 2 bold)"
|
|
yellow="$(tput setaf 3 bold)"
|
|
fi
|
|
state_color="${NC}"
|
|
|
|
local PADDING_CONSTANT=16 # two tabs wide
|
|
|
|
if [[ $service_state = "$ERROR_STRING" ]] \
|
|
|| [[ $service_state = "$MISSING_STRING" ]]; then
|
|
state_color="${red:-}"
|
|
if [[ "$EXITCODE" -eq 0 ]]; then
|
|
EXITCODE=1
|
|
fi
|
|
elif [[ $service_state = "$SUCCESS_STRING" ]]; then
|
|
state_color="${green:-}"
|
|
elif [[ $service_state = "$PENDING_STRING" ]] \
|
|
|| [[ $service_state = "$DISABLED_STRING" ]] \
|
|
|| [[ $service_state = "$STARTING_STRING" ]] \
|
|
|| [[ $service_state = "$WAIT_START_STRING" ]]; then
|
|
state_color="${yellow:-}"
|
|
EXITCODE=2
|
|
fi
|
|
|
|
line=""
|
|
if [ "${__tty}" -eq 1 ]; then
|
|
# construct a line of '------' so that the names and states are all aligned
|
|
local columns ; columns=$(tput cols)
|
|
linewidth=$(( columns - PADDING_CONSTANT - ${#service_name} - ${#service_state} ))
|
|
for i in $(seq 0 "${linewidth}"); do
|
|
line="${line}-"
|
|
done
|
|
fi
|
|
service_state="${state_color:-}${service_state}${NC:-}"
|
|
printf "\t%s %s [ %s ]\n" "${service_name}" "${line}" "${service_state}"
|
|
}
|
|
|
|
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
|
|
print_line "Docker" "running"
|
|
else
|
|
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
|
|
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
|
|
|
|
|
|
|
|
is_tty() {
|
|
__tty=0
|
|
# don't print colors if NO_COLOR is set to anything
|
|
if [ "${#NO_COLOR}" -eq 0 ]
|
|
then
|
|
__tty=0
|
|
return "${__tty}"
|
|
fi
|
|
tty -s 2<&- >/dev/null \
|
|
&& __tty=1
|
|
return "${__tty}"
|
|
}
|
|
|
|
if ! [ "$(id -u)" = 0 ]; then
|
|
echo "${MYNAME}: This command must be run as root"
|
|
display_help 1
|
|
fi
|
|
|
|
while getopts ':hq' OPTION; do
|
|
case "$OPTION" in
|
|
h) display_help 0 ;;
|
|
q) QUIET=true ;;
|
|
\?) display_help 1 ;;
|
|
esac
|
|
done
|
|
|
|
main
|
|
|
|
exit $EXITCODE
|