mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2026-07-06 09:08:13 +02:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e9e221196 | |||
| 07d6b2cfdd | |||
| 89afea876a | |||
| 1243a25bd3 | |||
| 76f6947f36 | |||
| 92a55386c6 | |||
| e7352eb841 | |||
| 795aa898a3 | |||
| 69d77382f1 | |||
| dc9b4f3ce5 | |||
| 87b9276c79 | |||
| 99118f9bed | |||
| 24b75b4a2b | |||
| 395bd627f1 | |||
| 868b217549 | |||
| c33db9d00f | |||
| e88eb65a44 | |||
| dc8c80633b | |||
| 895aa18486 | |||
| ee36f5f84c | |||
| a3f586cf88 | |||
| 670d2b2757 | |||
| 3b8459c6ec | |||
| 52574e21c6 | |||
| 576c7bfedd | |||
| b3b7ecdded | |||
| 0af020b6c3 | |||
| 339a5af4a3 | |||
| 7952c274c4 | |||
| 67a9abadf2 | |||
| 94f31e1356 | |||
| 435e2b4182 | |||
| 13ebde61bd | |||
| b0b022c3ad | |||
| 27c1c35e62 | |||
| f45631af3a | |||
| 8e2753aeb8 | |||
| 698a746d6d |
@@ -1,59 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# This script adds sensors/nodes/etc to the nodes tab
|
|
||||||
default_salt_dir=/opt/so/saltstack/default
|
|
||||||
local_salt_dir=/opt/so/saltstack/local
|
|
||||||
TYPE=$1
|
|
||||||
NAME=$2
|
|
||||||
IPADDRESS=$3
|
|
||||||
CPUS=$4
|
|
||||||
GUID=$5
|
|
||||||
MANINT=$6
|
|
||||||
ROOTFS=$7
|
|
||||||
NSM=$8
|
|
||||||
MONINT=$9
|
|
||||||
#NODETYPE=$10
|
|
||||||
#HOTNAME=$11
|
|
||||||
|
|
||||||
echo "Seeing if this host is already in here. If so delete it"
|
|
||||||
if grep -q $NAME "$local_salt_dir/pillar/data/$TYPE.sls"; then
|
|
||||||
echo "Node Already Present - Let's re-add it"
|
|
||||||
awk -v blah=" $NAME:" 'BEGIN{ print_flag=1 }
|
|
||||||
{
|
|
||||||
if( $0 ~ blah )
|
|
||||||
{
|
|
||||||
print_flag=0;
|
|
||||||
next
|
|
||||||
}
|
|
||||||
if( $0 ~ /^ [a-zA-Z0-9]+:$/ )
|
|
||||||
{
|
|
||||||
print_flag=1;
|
|
||||||
}
|
|
||||||
if ( print_flag == 1 )
|
|
||||||
print $0
|
|
||||||
|
|
||||||
} ' $local_salt_dir/pillar/data/$TYPE.sls > $local_salt_dir/pillar/data/tmp.$TYPE.sls
|
|
||||||
mv $local_salt_dir/pillar/data/tmp.$TYPE.sls $local_salt_dir/pillar/data/$TYPE.sls
|
|
||||||
echo "Deleted $NAME from the tab. Now adding it in again with updated info"
|
|
||||||
fi
|
|
||||||
echo " $NAME:" >> $local_salt_dir/pillar/data/$TYPE.sls
|
|
||||||
echo " ip: $IPADDRESS" >> $local_salt_dir/pillar/data/$TYPE.sls
|
|
||||||
echo " manint: $MANINT" >> $local_salt_dir/pillar/data/$TYPE.sls
|
|
||||||
echo " totalcpus: $CPUS" >> $local_salt_dir/pillar/data/$TYPE.sls
|
|
||||||
echo " guid: $GUID" >> $local_salt_dir/pillar/data/$TYPE.sls
|
|
||||||
echo " rootfs: $ROOTFS" >> $local_salt_dir/pillar/data/$TYPE.sls
|
|
||||||
echo " nsmfs: $NSM" >> $local_salt_dir/pillar/data/$TYPE.sls
|
|
||||||
if [ $TYPE == 'sensorstab' ]; then
|
|
||||||
echo " monint: bond0" >> $local_salt_dir/pillar/data/$TYPE.sls
|
|
||||||
fi
|
|
||||||
if [ $TYPE == 'evaltab' ] || [ $TYPE == 'standalonetab' ]; then
|
|
||||||
echo " monint: bond0" >> $local_salt_dir/pillar/data/$TYPE.sls
|
|
||||||
if [ ! $10 ]; then
|
|
||||||
salt-call state.apply utility queue=True
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if [ $TYPE == 'nodestab' ]; then
|
|
||||||
salt-call state.apply elasticsearch queue=True
|
|
||||||
# echo " nodetype: $NODETYPE" >> $local_salt_dir/pillar/data/$TYPE.sls
|
|
||||||
# echo " hotname: $HOTNAME" >> $local_salt_dir/pillar/data/$TYPE.sls
|
|
||||||
fi
|
|
||||||
@@ -37,8 +37,7 @@
|
|||||||
'elasticfleet',
|
'elasticfleet',
|
||||||
'elasticfleet.manager',
|
'elasticfleet.manager',
|
||||||
'elasticsearch.cluster',
|
'elasticsearch.cluster',
|
||||||
'elastic-fleet-package-registry',
|
'elastic-fleet-package-registry'
|
||||||
'utility'
|
|
||||||
] %}
|
] %}
|
||||||
|
|
||||||
{% set sensor_states = [
|
{% set sensor_states = [
|
||||||
|
|||||||
@@ -291,6 +291,20 @@ download_and_verify() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# check if container with name is running and optionally stop it
|
||||||
|
docker_check_running() {
|
||||||
|
# show running containers, only names
|
||||||
|
if docker ps --format '{{.Names}}' | grep -q "^so-${1}$"; then
|
||||||
|
if [[ "$2" == "--stop" ]]; then
|
||||||
|
docker stop "so-${1}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
elastic_license() {
|
elastic_license() {
|
||||||
|
|
||||||
read -r -d '' message <<- EOM
|
read -r -d '' message <<- EOM
|
||||||
|
|||||||
Executable
+57
@@ -0,0 +1,57 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# so-kernel-upgrade — switch the boot default to the installed UEK8 (6.x) kernel.
|
||||||
|
#
|
||||||
|
# Security Onion is moving off the EL9 stock kernel / UEK7 (5.x) onto UEK8 (6.x).
|
||||||
|
# Installing the kernel-uek-core package adds a UEK8 boot entry but does NOT make it the
|
||||||
|
# default: kernel-install/grubby only auto-promote a new kernel within the running
|
||||||
|
# kernel's flavor lineage, and we're crossing from a 5.x kernel to the new 6.x UEK flavor.
|
||||||
|
# So even with UPDATEDEFAULT=yes and DEFAULTKERNEL=kernel-uek-core the box keeps booting
|
||||||
|
# the old kernel. This tool finds the newest installed 6.x UEK kernel and makes it the
|
||||||
|
# GRUB default via grubby so the next boot comes up on UEK8.
|
||||||
|
#
|
||||||
|
# Idempotent: if the UEK8 kernel is already the default it does nothing. It only sets the
|
||||||
|
# boot default; it does NOT reboot — the admin reboots the node on their own schedule.
|
||||||
|
|
||||||
|
log() { echo "[so-kernel-upgrade] $*"; }
|
||||||
|
|
||||||
|
[ "$(id -u)" -eq 0 ] || { log "must run as root"; exit 1; }
|
||||||
|
command -v grubby >/dev/null 2>&1 || { log "grubby not found"; exit 1; }
|
||||||
|
|
||||||
|
# Newest installed UEK8 (6.x) kernel known to the bootloader. UEK8 vmlinuz paths look like
|
||||||
|
# /boot/vmlinuz-6.12.0-203.76.7.5.el9uek.x86_64; the 5.x UEK7 and 5.14 RHCK won't match.
|
||||||
|
target="$(grubby --info=ALL 2>/dev/null \
|
||||||
|
| sed -n 's/^kernel="\(.*\)"$/\1/p' \
|
||||||
|
| grep -E '/vmlinuz-6\.[0-9]+.*uek' \
|
||||||
|
| sort -V | tail -1)"
|
||||||
|
|
||||||
|
if [ -z "$target" ]; then
|
||||||
|
log "no installed 6.x UEK (UEK8) kernel found — confirm the kernel repo is assigned and"
|
||||||
|
log "'dnf update' has installed kernel-uek-core. Nothing to do."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
current="$(grubby --default-kernel 2>/dev/null)"
|
||||||
|
if [ "$current" = "$target" ]; then
|
||||||
|
log "UEK8 kernel is already the boot default: $target"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "current default kernel: ${current:-unknown}"
|
||||||
|
log "switching boot default to UEK8 kernel: $target"
|
||||||
|
grubby --set-default="$target" || { log "ERROR: grubby --set-default failed for $target"; exit 1; }
|
||||||
|
|
||||||
|
# Verify the change actually took before claiming success.
|
||||||
|
now="$(grubby --default-kernel 2>/dev/null)"
|
||||||
|
if [ "$now" != "$target" ]; then
|
||||||
|
log "ERROR: default kernel is still '${now:-unknown}' after set-default"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "boot default is now $target"
|
||||||
|
log "REBOOT REQUIRED to start using the UEK8 kernel (currently running $(uname -r))."
|
||||||
@@ -5,27 +5,41 @@
|
|||||||
# https://securityonion.net/license; you may not use this file except in compliance with the
|
# https://securityonion.net/license; you may not use this file except in compliance with the
|
||||||
# Elastic License 2.0.
|
# Elastic License 2.0.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Usage: so-restart kibana | playbook
|
|
||||||
|
|
||||||
. /usr/sbin/so-common
|
. /usr/sbin/so-common
|
||||||
|
|
||||||
if [ $# -ge 1 ]; then
|
usage() {
|
||||||
|
echo "Usage: $0 <component> [args]"
|
||||||
|
echo ""
|
||||||
|
echo "Supported args:"
|
||||||
|
echo " --force | -f Force stop all Salt jobs before starting component."
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " $0 kibana Restart Kibana"
|
||||||
|
echo " $0 kibana --force Force stop all Salt jobs before restarting Kibana"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
echo $banner
|
if [[ $# -lt 1 ]]; then
|
||||||
printf "Restarting $1...\n\nThis could take a while if another Salt job is running. \nRun this command with --force to stop all Salt jobs before proceeding.\n"
|
usage
|
||||||
echo $banner
|
|
||||||
|
|
||||||
if [ "$2" = "--force" ]; then
|
|
||||||
printf "\nForce-stopping all Salt jobs before proceeding\n\n"
|
|
||||||
salt-call saltutil.kill_all_jobs
|
|
||||||
fi
|
|
||||||
|
|
||||||
case $1 in
|
|
||||||
"elastic-fleet") docker stop so-elastic-fleet && docker rm so-elastic-fleet && salt-call state.apply elasticfleet queue=True;;
|
|
||||||
*) docker stop so-$1 ; docker rm so-$1 ; salt-call state.apply $1 queue=True;;
|
|
||||||
esac
|
|
||||||
else
|
|
||||||
echo -e "\nPlease provide an argument by running like so-restart $component, or by using the component-specific script.\nEx. so-restart logstash, or so-logstash-restart\n"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#shellcheck disable=SC2154
|
||||||
|
echo "$banner"
|
||||||
|
printf "Restarting %s...\n\nThis could take a while if another Salt job is running. \nRun this command with --force to stop all Salt jobs before proceeding.\n" "$1"
|
||||||
|
echo "$banner"
|
||||||
|
if [[ "$2" = "--force" ]] || [[ "$2" = "-f" ]]; then
|
||||||
|
printf "\nForce-stopping all Salt jobs before proceeding\n\n"
|
||||||
|
salt-call saltutil.kill_all_jobs
|
||||||
|
fi
|
||||||
|
case $1 in
|
||||||
|
"elastic-fleet"|"elasticfleet")
|
||||||
|
docker_check_running "elastic-fleet" "--stop"
|
||||||
|
docker rm "so-elastic-fleet" 2> /dev/null
|
||||||
|
salt-call state.apply elasticfleet queue=True
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
docker_check_running "$1" "--stop"
|
||||||
|
docker rm "so-${1}" 2> /dev/null
|
||||||
|
salt-call state.apply "$1" queue=True
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|||||||
@@ -5,27 +5,54 @@
|
|||||||
# https://securityonion.net/license; you may not use this file except in compliance with the
|
# https://securityonion.net/license; you may not use this file except in compliance with the
|
||||||
# Elastic License 2.0.
|
# Elastic License 2.0.
|
||||||
|
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
|
||||||
# Usage: so-start all | kibana | playbook
|
|
||||||
|
|
||||||
. /usr/sbin/so-common
|
. /usr/sbin/so-common
|
||||||
|
|
||||||
if [ $# -ge 1 ]; then
|
usage() {
|
||||||
echo $banner
|
echo "Usage: $0 <component> [args]"
|
||||||
printf "Starting $1...\n\nThis could take a while if another Salt job is running. \nRun this command with --force to stop all Salt jobs before proceeding.\n"
|
echo ""
|
||||||
echo $banner
|
echo "Supported args:"
|
||||||
|
echo " --force | -f Force stop all Salt jobs before starting component."
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " $0 kibana Start Kibana"
|
||||||
|
echo " $0 kibana --force Force stop all Salt jobs before starting Kibana"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
if [ "$2" = "--force" ]; then
|
if [[ $# -lt 1 ]]; then
|
||||||
printf "\nForce-stopping all Salt jobs before proceeding\n\n"
|
usage
|
||||||
salt-call saltutil.kill_all_jobs
|
|
||||||
fi
|
|
||||||
|
|
||||||
case $1 in
|
|
||||||
"all") salt-call state.highstate queue=True;;
|
|
||||||
"elastic-fleet") 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 elasticfleet queue=True; fi ;;
|
|
||||||
*) if docker ps | grep -E -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
|
|
||||||
else
|
|
||||||
echo -e "\nPlease provide an argument by running like so-start $component, or by using the component-specific script.\nEx. so-start logstash, or so-logstash-start\n"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#shellcheck disable=SC2154
|
||||||
|
echo "$banner"
|
||||||
|
printf "Starting %s...\n\nThis could take a while if another Salt job is running. \nRun this command with --force to stop all Salt jobs before proceeding.\n" "$1"
|
||||||
|
echo "$banner"
|
||||||
|
if [[ "$2" = "--force" ]] || [[ "$2" == "-f" ]]; then
|
||||||
|
printf "\nForce-stopping all Salt jobs before proceeding\n\n"
|
||||||
|
salt-call saltutil.kill_all_jobs
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
"all")
|
||||||
|
salt-call state.highstate queue=True
|
||||||
|
;;
|
||||||
|
"elastic-fleet"|"elasticfleet")
|
||||||
|
if docker_check_running "elastic-fleet"; then
|
||||||
|
printf "\nso-%s is already running!\n\n" "elastic-fleet"
|
||||||
|
/usr/sbin/so-status
|
||||||
|
else
|
||||||
|
docker rm "so-elastic-fleet" 2> /dev/null
|
||||||
|
salt-call state.apply elasticfleet queue=True
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if docker_check_running "$1"; then
|
||||||
|
printf "\nso-%s is already running\n\n" "$1"
|
||||||
|
/usr/sbin/so-status
|
||||||
|
else
|
||||||
|
docker rm "so-${1}" 2> /dev/null
|
||||||
|
salt-call state.apply "$1" queue=True
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|||||||
@@ -5,21 +5,33 @@
|
|||||||
# https://securityonion.net/license; you may not use this file except in compliance with the
|
# https://securityonion.net/license; you may not use this file except in compliance with the
|
||||||
# Elastic License 2.0.
|
# Elastic License 2.0.
|
||||||
|
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
|
||||||
# Usage: so-stop kibana | playbook | thehive
|
|
||||||
|
|
||||||
. /usr/sbin/so-common
|
. /usr/sbin/so-common
|
||||||
|
|
||||||
if [ $# -ge 1 ]; then
|
usage() {
|
||||||
echo $banner
|
echo "Usage: $0 <component>"
|
||||||
printf "Stopping $1...\n"
|
echo ""
|
||||||
echo $banner
|
echo "Examples:"
|
||||||
|
echo " $0 kibana Stop Kibana"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
case $1 in
|
if [[ $# -lt 1 ]]; then
|
||||||
*) docker stop so-$1 ; docker rm so-$1 ;;
|
usage
|
||||||
esac
|
|
||||||
else
|
|
||||||
echo -e "\nPlease provide an argument by running like so-stop $component, or by using the component-specific script.\nEx. so-stop logstash, or so-logstash-stop\n"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
#shellcheck disable=SC2154
|
||||||
|
echo "$banner"
|
||||||
|
printf "Stopping %s...\n" "$1"
|
||||||
|
echo "$banner"
|
||||||
|
case $1 in
|
||||||
|
"elasticfleet"|"elastic-fleet")
|
||||||
|
docker_check_running "elastic-fleet" "--stop"
|
||||||
|
docker rm "so-elastic-fleet" 2> /dev/null
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
docker_check_running "$1" "--stop"
|
||||||
|
docker rm "so-${1}" 2> /dev/null
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ wait_for_so-kibana:
|
|||||||
- ssl: True
|
- ssl: True
|
||||||
- verify_ssl: False
|
- verify_ssl: False
|
||||||
- status: 200
|
- status: 200
|
||||||
- wait_for: 300
|
- wait_for: 600
|
||||||
- request_interval: 15
|
- request_interval: 15
|
||||||
- require:
|
- require:
|
||||||
- docker_container: so-kibana
|
- docker_container: so-kibana
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
https://repo.securityonion.net/file/so-repo/prod/3/oracle/9-uek8
|
||||||
|
https://repo-alt.securityonion.net/prod/3/oracle/9-uek8
|
||||||
@@ -11,3 +11,8 @@ name=Security Onion Repo repo
|
|||||||
mirrorlist=file:///opt/so/conf/reposync/mirror.txt
|
mirrorlist=file:///opt/so/conf/reposync/mirror.txt
|
||||||
enabled=1
|
enabled=1
|
||||||
gpgcheck=1
|
gpgcheck=1
|
||||||
|
[securityonionkernelsync]
|
||||||
|
name=Security Onion Kernel Repo repo
|
||||||
|
mirrorlist=file:///opt/so/conf/reposync/mirror-kernel.txt
|
||||||
|
enabled=1
|
||||||
|
gpgcheck=1
|
||||||
|
|||||||
@@ -86,6 +86,28 @@ repo_dir:
|
|||||||
- group
|
- group
|
||||||
- show_changes: False
|
- show_changes: False
|
||||||
|
|
||||||
|
kernelrepo_dir:
|
||||||
|
file.directory:
|
||||||
|
- name: /nsm/kernelrepo
|
||||||
|
- user: socore
|
||||||
|
- group: socore
|
||||||
|
- recurse:
|
||||||
|
- user
|
||||||
|
- group
|
||||||
|
- show_changes: False
|
||||||
|
|
||||||
|
# Ensure /nsm/kernelrepo is always a valid (if empty) repo before it is ever assigned to
|
||||||
|
# a client. Without repodata/repomd.xml an enabled file:///nsm/kernelrepo repo makes every
|
||||||
|
# dnf operation fail; so-repo-sync only populates it after the highstate, so seed an empty
|
||||||
|
# repo here. Only runs when repodata is missing, so it won't clobber a synced repo.
|
||||||
|
kernelrepo_init_empty:
|
||||||
|
cmd.run:
|
||||||
|
- name: createrepo /nsm/kernelrepo
|
||||||
|
- unless: 'test -e /nsm/kernelrepo/repodata/repomd.xml'
|
||||||
|
- require:
|
||||||
|
- file: kernelrepo_dir
|
||||||
|
- pkg: install_createrepo
|
||||||
|
|
||||||
manager_sbin:
|
manager_sbin:
|
||||||
file.recurse:
|
file.recurse:
|
||||||
- name: /usr/sbin
|
- name: /usr/sbin
|
||||||
@@ -122,6 +144,13 @@ so-repo-mirrorlist:
|
|||||||
- user: socore
|
- user: socore
|
||||||
- group: socore
|
- group: socore
|
||||||
|
|
||||||
|
so-repo-kernel-mirrorlist:
|
||||||
|
file.managed:
|
||||||
|
- name: /opt/so/conf/reposync/mirror-kernel.txt
|
||||||
|
- source: salt://manager/files/mirror-kernel.txt
|
||||||
|
- user: socore
|
||||||
|
- group: socore
|
||||||
|
|
||||||
so-repo-sync:
|
so-repo-sync:
|
||||||
{% if MANAGERMERGED.reposync.enabled %}
|
{% if MANAGERMERGED.reposync.enabled %}
|
||||||
cron.present:
|
cron.present:
|
||||||
|
|||||||
@@ -10,5 +10,16 @@ NOROOT=1
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
curl --retry 5 --retry-delay 60 -A "reposync/$(sync_options)" https://sigs.securityonion.net/checkup --output /tmp/checkup
|
curl --retry 5 --retry-delay 60 -A "reposync/$(sync_options)" https://sigs.securityonion.net/checkup --output /tmp/checkup
|
||||||
|
|
||||||
dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionsync --download-metadata -p /nsm/repo/
|
dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionsync --download-metadata -p /nsm/repo/
|
||||||
createrepo /nsm/repo
|
createrepo /nsm/repo
|
||||||
|
|
||||||
|
# The kernel repo section is deployed to repodownload.conf by the manager highstate, which
|
||||||
|
# runs AFTER this script during soup. On the first upgrade to a kernel-aware version the
|
||||||
|
# on-disk config still predates the section, so guard on its presence to avoid dnf's
|
||||||
|
# "Unknown repo: 'securityonionkernelsync'" aborting the sync (set -e). The next sync after the
|
||||||
|
# highstate deploys the section will pick it up.
|
||||||
|
if grep -q '^\[securityonionkernelsync\]' /opt/so/conf/reposync/repodownload.conf; then
|
||||||
|
dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionkernelsync --download-metadata -p /nsm/kernelrepo/
|
||||||
|
createrepo /nsm/kernelrepo
|
||||||
|
fi
|
||||||
|
|||||||
@@ -245,6 +245,7 @@ check_airgap() {
|
|||||||
UPDATE_DIR=/tmp/soagupdate/SecurityOnion
|
UPDATE_DIR=/tmp/soagupdate/SecurityOnion
|
||||||
AGDOCKER=/tmp/soagupdate/docker
|
AGDOCKER=/tmp/soagupdate/docker
|
||||||
AGREPO=/tmp/soagupdate/minimal/Packages
|
AGREPO=/tmp/soagupdate/minimal/Packages
|
||||||
|
AGUEKREPO=/tmp/soagupdate/uek/Packages
|
||||||
else
|
else
|
||||||
is_airgap=1
|
is_airgap=1
|
||||||
fi
|
fi
|
||||||
@@ -850,6 +851,28 @@ kibana_backport_streams_index_template() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Runs kafka-features.sh upgrade --release-version $1
|
||||||
|
# Upgrades Kafka KRaft cluster metadata
|
||||||
|
update_kafka_metadata() {
|
||||||
|
metadata_version="$1"
|
||||||
|
global_pillar="/opt/so/saltstack/local/pillar/global/soc_global.sls"
|
||||||
|
if PIPELINE=$(so-yaml.py get -r "$global_pillar" global.pipeline 2> /dev/null) && [[ "$PIPELINE" == "KAFKA" ]]; then
|
||||||
|
kafka_nodes_raw=$(salt-call pillar.get kafka:nodes --out=json)
|
||||||
|
if kafka_nodes=$(jq -er '.local | select(type == "object" and length > 0)' <<< "$kafka_nodes_raw"); then
|
||||||
|
bootstrap_servers=$(jq -r '[to_entries[] | select(.value.role | contains("broker")) | "\(.value.ip):9092"] | join(",")' <<< "$kafka_nodes")
|
||||||
|
echo "Upgrading Kafka KRaft cluster version"
|
||||||
|
so-kafka-cli kafka-features.sh --bootstrap-server "$bootstrap_servers" --command-config /opt/kafka/config/kraft/client.properties upgrade --release-version "$metadata_version" 2>/dev/null || true
|
||||||
|
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
FINAL_MESSAGE_QUEUE+=("WARNING: Unable to automatically perform Kafka KRaft cluster metadata update. This step can be performed manually using the following command (replacing \$BROKER_IP with the ip of atleast 1 available Kafka broker):")
|
||||||
|
FINAL_MESSAGE_QUEUE+=(" - so-kafka-cli kafka-features.sh --bootstrap-server \$BROKER_IP:9092 --command-config /opt/kafka/config/kraft/client.properties upgrade --release-version $metadata_version")
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Nothing to do!"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
up_to_3.2.0() {
|
up_to_3.2.0() {
|
||||||
fix_logstash_0013_lumberjack_pipeline_name
|
fix_logstash_0013_lumberjack_pipeline_name
|
||||||
|
|
||||||
@@ -867,6 +890,8 @@ post_to_3.2.0() {
|
|||||||
|
|
||||||
kibana_backport_streams_index_template
|
kibana_backport_streams_index_template
|
||||||
|
|
||||||
|
update_kafka_metadata "4.3"
|
||||||
|
|
||||||
POSTVERSION=3.2.0
|
POSTVERSION=3.2.0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -980,13 +1005,19 @@ update_airgap_rules() {
|
|||||||
rsync -a $UPDATE_DIR/agrules/securityonion-resources/* /nsm/securityonion-resources/
|
rsync -a $UPDATE_DIR/agrules/securityonion-resources/* /nsm/securityonion-resources/
|
||||||
}
|
}
|
||||||
|
|
||||||
update_airgap_repo() {
|
update_airgap_repos() {
|
||||||
# Update the files in the repo
|
# Update the files in the repo
|
||||||
echo "Syncing new updates to /nsm/repo"
|
echo "Syncing new updates to /nsm/repo & /nsm/kernelrepo"
|
||||||
rsync -a $AGREPO/* /nsm/repo/
|
# Airgap soup copies new files into the local repo, but doesn't remove old packages. Retaining the ability to rollback package updates
|
||||||
echo "Creating repo"
|
rsync -a "$AGREPO"/ /nsm/repo/
|
||||||
|
rsync -a "$AGUEKREPO"/ /nsm/kernelrepo/
|
||||||
|
|
||||||
dnf -y install yum-utils createrepo_c
|
dnf -y install yum-utils createrepo_c
|
||||||
|
|
||||||
|
echo "Running createrepo for /nsm/repo"
|
||||||
createrepo /nsm/repo
|
createrepo /nsm/repo
|
||||||
|
echo "Running createrepo for /nsm/kernelrepo"
|
||||||
|
createrepo /nsm/kernelrepo
|
||||||
}
|
}
|
||||||
|
|
||||||
update_salt_mine() {
|
update_salt_mine() {
|
||||||
@@ -1742,7 +1773,7 @@ main() {
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [[ $is_airgap -eq 0 ]]; then
|
if [[ $is_airgap -eq 0 ]]; then
|
||||||
update_airgap_repo
|
update_airgap_repos
|
||||||
dnf clean all
|
dnf clean all
|
||||||
check_os_updates
|
check_os_updates
|
||||||
elif [[ $OS == 'oracle' ]]; then
|
elif [[ $OS == 'oracle' ]]; then
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ so-nginx:
|
|||||||
- /opt/so/conf/navigator/layers/:/opt/socore/html/navigator/assets/so:ro
|
- /opt/so/conf/navigator/layers/:/opt/socore/html/navigator/assets/so:ro
|
||||||
- /opt/so/conf/navigator/config.json:/opt/socore/html/navigator/assets/config.json:ro
|
- /opt/so/conf/navigator/config.json:/opt/socore/html/navigator/assets/config.json:ro
|
||||||
- /nsm/repo:/opt/socore/html/repo:ro
|
- /nsm/repo:/opt/socore/html/repo:ro
|
||||||
|
- /nsm/kernelrepo:/opt/socore/html/kernelrepo:ro
|
||||||
- /nsm/rules:/nsm/rules:ro
|
- /nsm/rules:/nsm/rules:ro
|
||||||
{% if NGINXMERGED.external_suricata %}
|
{% if NGINXMERGED.external_suricata %}
|
||||||
- /opt/so/rules/nids/suri:/surirules:ro
|
- /opt/so/rules/nids/suri:/surirules:ro
|
||||||
|
|||||||
@@ -323,6 +323,16 @@ http {
|
|||||||
autoindex_localtime on;
|
autoindex_localtime on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /kernelrepo/ {
|
||||||
|
allow all;
|
||||||
|
sendfile on;
|
||||||
|
sendfile_max_chunk 1m;
|
||||||
|
autoindex on;
|
||||||
|
autoindex_exact_size off;
|
||||||
|
autoindex_format html;
|
||||||
|
autoindex_localtime on;
|
||||||
|
}
|
||||||
|
|
||||||
location /influxdb/ {
|
location /influxdb/ {
|
||||||
auth_request /auth/sessions/whoami;
|
auth_request /auth/sessions/whoami;
|
||||||
rewrite /influxdb/api/(.*) /api/$1 break;
|
rewrite /influxdb/api/(.*) /api/$1 break;
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
{% from 'repo/client/map.jinja' import REPOPATH with context %}
|
{% from 'repo/client/map.jinja' import REPOPATH with context %}
|
||||||
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
||||||
|
|
||||||
|
{% import_yaml 'salt/minion.defaults.yaml' as saltversion %}
|
||||||
|
{% set saltversion = saltversion.salt.minion.version %}
|
||||||
|
{% set INSTALLEDSALTVERSION = grains.saltversion %}
|
||||||
|
|
||||||
{% set role = grains.id.split('_') | last %}
|
{% set role = grains.id.split('_') | last %}
|
||||||
{% set MANAGER = salt['grains.get']('master') %}
|
{% set MANAGER = salt['grains.get']('master') %}
|
||||||
{% if grains['os'] == 'OEL' %}
|
{% if grains['os'] == 'OEL' %}
|
||||||
@@ -57,6 +61,32 @@ so_repo:
|
|||||||
- enabled: 1
|
- enabled: 1
|
||||||
- gpgcheck: 1
|
- gpgcheck: 1
|
||||||
|
|
||||||
|
# Only assign the kernel repo once this node's running salt matches the version this
|
||||||
|
# SO release ships. During a soup the grid is mid-salt-upgrade; gating here keeps the
|
||||||
|
# UEK8 kernel repo (and the kernel update it enables) from activating until the node is
|
||||||
|
# fully on the target salt, the same way other states defer across the upgrade window.
|
||||||
|
{% if saltversion | string == INSTALLEDSALTVERSION | string %}
|
||||||
|
so_kernel_repo:
|
||||||
|
pkgrepo.managed:
|
||||||
|
- name: securityonionkernel
|
||||||
|
- humanname: Security Onion Kernel Repo
|
||||||
|
{% if GLOBALS.is_manager %}
|
||||||
|
- baseurl: file:///nsm/kernelrepo/
|
||||||
|
{% else %}
|
||||||
|
- baseurl: https://{{ GLOBALS.repo_host }}/kernelrepo
|
||||||
|
{% endif %}
|
||||||
|
- enabled: 1
|
||||||
|
- gpgcheck: 1
|
||||||
|
# Supplementary kernel repo: tolerate it being empty/unreachable (e.g. before the
|
||||||
|
# manager has populated /nsm/kernelrepo) so a missing repomd.xml can't make every
|
||||||
|
# dnf/pkg operation on the grid fail.
|
||||||
|
- skip_if_unavailable: 1
|
||||||
|
# Only assign the kernel repo once physical NIC names are pinned by MAC, so the
|
||||||
|
# UEK8 kernel update can't renumber interfaces SO binds by name (see pin_nic_names
|
||||||
|
# in salt/common/init.sls, which drops this marker via /usr/sbin/so-nic-pin).
|
||||||
|
- onlyif: 'test -e /opt/so/state/nic_names_pinned'
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
# TODO: Add a pillar entry for custom repos
|
# TODO: Add a pillar entry for custom repos
|
||||||
|
|||||||
@@ -1771,13 +1771,13 @@ soc:
|
|||||||
enabled: true
|
enabled: true
|
||||||
queries:
|
queries:
|
||||||
- name: Default Query
|
- name: Default Query
|
||||||
description: Show all events grouped by the observer host
|
|
||||||
query: '* | groupby observer.name'
|
|
||||||
showSubtitle: true
|
|
||||||
- name: Log Type
|
|
||||||
description: Show all events grouped by module and dataset
|
description: Show all events grouped by module and dataset
|
||||||
query: '* | groupby event.module* event.dataset'
|
query: '* | groupby event.module* event.dataset'
|
||||||
showSubtitle: true
|
showSubtitle: true
|
||||||
|
- name: Observer
|
||||||
|
description: Show all events grouped by the observer host
|
||||||
|
query: '* | groupby observer.name'
|
||||||
|
showSubtitle: true
|
||||||
- name: SOC - Auth
|
- name: SOC - Auth
|
||||||
description: Users authenticated to SOC grouped by IP address and identity
|
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'
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ surirulereload:
|
|||||||
- name: /usr/sbin/so-suricata-reload-rules >> /opt/so/log/suricata/reload.log 2>&1
|
- name: /usr/sbin/so-suricata-reload-rules >> /opt/so/log/suricata/reload.log 2>&1
|
||||||
- onchanges:
|
- onchanges:
|
||||||
- file: surirulesync
|
- file: surirulesync
|
||||||
|
- onlyif: test -f /opt/so/rules/suricata/all-rulesets.rules
|
||||||
- require:
|
- require:
|
||||||
- docker_container: so-suricata
|
- docker_container: so-suricata
|
||||||
|
|
||||||
|
|||||||
@@ -7,5 +7,59 @@
|
|||||||
|
|
||||||
. /usr/sbin/so-common
|
. /usr/sbin/so-common
|
||||||
|
|
||||||
retry 60 3 'docker exec so-suricata /opt/suricata/bin/suricatasc -c reload-rules /var/run/suricata/suricata-command.socket' '{"message":"done","return":"OK"}' || fail "The Suricata container was not ready in time."
|
RULES_FILE="/opt/so/rules/suricata/all-rulesets.rules"
|
||||||
retry 60 3 'docker exec so-suricata /opt/suricata/bin/suricatasc -c ruleset-reload-nonblocking /var/run/suricata/suricata-command.socket' '{"message":"done","return":"OK"}' || fail "The Suricata container was not ready in time."
|
SOCKET="/var/run/suricata/suricata-command.socket"
|
||||||
|
SURICATASC="docker exec so-suricata /opt/suricata/bin/suricatasc"
|
||||||
|
|
||||||
|
# Format an epoch as a human-readable local timestamp for log messages.
|
||||||
|
fmt_time() { date -d "@$1" '+%Y-%m-%d %H:%M:%S %Z' 2>/dev/null; }
|
||||||
|
|
||||||
|
# Prefix each input line with the current timestamp.
|
||||||
|
timestamp_lines() { while IFS= read -r line; do printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S %Z')" "$line"; done; }
|
||||||
|
|
||||||
|
# Epoch of Suricata's last *completed* ruleset reload; non-zero return on failure.
|
||||||
|
suricata_reload_epoch() {
|
||||||
|
local out ts
|
||||||
|
out=$($SURICATASC -c ruleset-reload-time "$SOCKET" 2>/dev/null)
|
||||||
|
ts=$(echo "$out" | jq -r '.message[0].last_reload // empty' 2>/dev/null)
|
||||||
|
[ -n "$ts" ] || return 1
|
||||||
|
date -d "$ts" +%s 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Trigger a fresh reload and confirm Suricata is running a ruleset at least as new
|
||||||
|
# as the rules file. Returns 0 only when both hold, so retry keeps going until an
|
||||||
|
# in-progress reload clears and our own reload completes.
|
||||||
|
reload_and_verify() {
|
||||||
|
local out reload_epoch
|
||||||
|
out=$($SURICATASC -c reload-rules "$SOCKET")
|
||||||
|
echo "reload-rules: $out"
|
||||||
|
|
||||||
|
if [[ "$out" =~ "Reload already in progress" ]]; then
|
||||||
|
echo "A reload is already in progress; waiting for it to clear so a fresh reload can load the current ruleset."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [[ ! "$out" =~ '{"message":"done","return":"OK"}' ]]; then
|
||||||
|
echo "Suricata not ready or unexpected reload output; will retry."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
reload_epoch=$(suricata_reload_epoch) || { echo "Could not read ruleset-reload-time; will retry."; return 1; }
|
||||||
|
if [ "$reload_epoch" -ge "$target_mtime" ]; then
|
||||||
|
echo "Loaded ruleset is current: last reload ($(fmt_time "$reload_epoch")) is newer than rules file ($(fmt_time "$target_mtime"))."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "Loaded ruleset is stale: last reload ($(fmt_time "$reload_epoch")) is older than rules file ($(fmt_time "$target_mtime")); retrying."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run the reload/verify, timestamping every line of output (ours and the
|
||||||
|
# retry/fail helpers') so reload.log shows when each step ran. The pipeline is
|
||||||
|
# synchronous, so the log is fully flushed and ordered before we exit; the
|
||||||
|
# script's real exit code is preserved via PIPESTATUS.
|
||||||
|
{
|
||||||
|
# Epoch mtime of the ruleset we need Suricata to have loaded. Captured once so
|
||||||
|
# a file update mid-reload does not move the goalpost.
|
||||||
|
target_mtime=$(stat -c %Y "$RULES_FILE") || fail "Could not stat the Suricata rules file: $RULES_FILE"
|
||||||
|
retry 60 3 'reload_and_verify' || fail "Suricata did not load the current ruleset in time."
|
||||||
|
} 2>&1 | timestamp_lines
|
||||||
|
exit "${PIPESTATUS[0]}"
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ base:
|
|||||||
- zeek
|
- zeek
|
||||||
- strelka
|
- strelka
|
||||||
- elastalert
|
- elastalert
|
||||||
- utility
|
|
||||||
- elasticfleet
|
- elasticfleet
|
||||||
- pcap.cleanup
|
- pcap.cleanup
|
||||||
|
|
||||||
@@ -113,7 +112,6 @@ base:
|
|||||||
- zeek
|
- zeek
|
||||||
- strelka
|
- strelka
|
||||||
- elastalert
|
- elastalert
|
||||||
- utility
|
|
||||||
- elasticfleet
|
- elasticfleet
|
||||||
- stig
|
- stig
|
||||||
- kafka
|
- kafka
|
||||||
@@ -141,7 +139,6 @@ base:
|
|||||||
- elastic-fleet-package-registry
|
- elastic-fleet-package-registry
|
||||||
- kibana
|
- kibana
|
||||||
- elastalert
|
- elastalert
|
||||||
- utility
|
|
||||||
- elasticfleet
|
- elasticfleet
|
||||||
- stig
|
- stig
|
||||||
- kafka
|
- kafka
|
||||||
@@ -168,7 +165,6 @@ base:
|
|||||||
- elastic-fleet-package-registry
|
- elastic-fleet-package-registry
|
||||||
- kibana
|
- kibana
|
||||||
- elastalert
|
- elastalert
|
||||||
- utility
|
|
||||||
- elasticfleet
|
- elasticfleet
|
||||||
- kafka
|
- kafka
|
||||||
|
|
||||||
@@ -198,7 +194,6 @@ base:
|
|||||||
- elastic-fleet-package-registry
|
- elastic-fleet-package-registry
|
||||||
- kibana
|
- kibana
|
||||||
- elastalert
|
- elastalert
|
||||||
- utility
|
|
||||||
- elasticfleet
|
- elasticfleet
|
||||||
- stig
|
- stig
|
||||||
- kafka
|
- kafka
|
||||||
@@ -222,7 +217,6 @@ base:
|
|||||||
- elasticsearch
|
- elasticsearch
|
||||||
- elastic-fleet-package-registry
|
- elastic-fleet-package-registry
|
||||||
- kibana
|
- kibana
|
||||||
- utility
|
|
||||||
- suricata
|
- suricata
|
||||||
- zeek
|
- zeek
|
||||||
- elasticfleet
|
- elasticfleet
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Wait for ElasticSearch to come up, so that we can query for version infromation
|
|
||||||
echo -n "Waiting for ElasticSearch..."
|
|
||||||
COUNT=0
|
|
||||||
ELASTICSEARCH_CONNECTED="no"
|
|
||||||
while [[ "$COUNT" -le 30 ]]; do
|
|
||||||
curl -K /opt/so/conf/elasticsearch/curl.config -k --output /dev/null --silent --head --fail -L https://{{ GLOBALS.manager_ip }}:9200
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
ELASTICSEARCH_CONNECTED="yes"
|
|
||||||
echo "connected!"
|
|
||||||
break
|
|
||||||
else
|
|
||||||
((COUNT+=1))
|
|
||||||
sleep 1
|
|
||||||
echo -n "."
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [ "$ELASTICSEARCH_CONNECTED" == "no" ]; then
|
|
||||||
echo
|
|
||||||
echo -e "Connection attempt timed out. Unable to connect to ElasticSearch. \nPlease try: \n -checking log(s) in /var/log/elasticsearch/\n -running 'docker ps' \n -running 'sudo so-elastic-restart'"
|
|
||||||
echo
|
|
||||||
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Applying cross cluster search config..."
|
|
||||||
curl -K /opt/so/conf/elasticsearch/curl.config -s -k -XPUT -L https://{{ GLOBALS.manager_ip }}:9200/_cluster/settings \
|
|
||||||
-H 'Content-Type: application/json' \
|
|
||||||
-d "{\"persistent\": {\"search\": {\"remote\": {\"{{ grains.host }}\": {\"seeds\": [\"127.0.0.1:9300\"]}}}}}"
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
{% from 'allowed_states.map.jinja' import allowed_states %}
|
|
||||||
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
|
||||||
|
|
||||||
{% if sls in allowed_states %}
|
|
||||||
{% if grains['role'] in ['so-eval', 'so-import'] %}
|
|
||||||
fixsearch:
|
|
||||||
cmd.script:
|
|
||||||
- shell: /bin/bash
|
|
||||||
- cwd: /opt/so
|
|
||||||
- source: salt://utility/bin/eval
|
|
||||||
- template: jinja
|
|
||||||
- defaults:
|
|
||||||
GLOBALS: {{ GLOBALS }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
|
|
||||||
{{sls}}_state_not_allowed:
|
|
||||||
test.fail_without_changes:
|
|
||||||
- name: {{sls}}_state_not_allowed
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
+63
-15
@@ -29,8 +29,12 @@ title() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fail_setup() {
|
fail_setup() {
|
||||||
|
local err_msg=$1
|
||||||
|
if [[ -n "$err_msg" ]]; then
|
||||||
|
error "$err_msg"
|
||||||
|
fi
|
||||||
error "Setup encountered an unrecoverable failure, exiting"
|
error "Setup encountered an unrecoverable failure, exiting"
|
||||||
touch /root/failure
|
echo "setup incomplete: $err_msg" > /root/failure
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,7 +701,7 @@ compare_main_nic_ip() {
|
|||||||
EOM
|
EOM
|
||||||
|
|
||||||
[[ -n $TESTING ]] || whiptail --title "$whiptail_title" --msgbox "$message" 11 75
|
[[ -n $TESTING ]] || whiptail --title "$whiptail_title" --msgbox "$message" 11 75
|
||||||
kill -SIGINT "$(ps --pid $$ -oppid=)"; fail_setup
|
kill -SIGINT "$(ps --pid $$ -oppid=)"; fail_setup "Main IP mismatch"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# Setup uses MAINIP, but since we ignore the equality condition when using a VPN
|
# Setup uses MAINIP, but since we ignore the equality condition when using a VPN
|
||||||
@@ -755,8 +759,7 @@ configure_management_bond() {
|
|||||||
info "Setting up $bond_name management interface with mode $bond_mode"
|
info "Setting up $bond_name management interface with mode $bond_mode"
|
||||||
|
|
||||||
if [[ ${#MBNICS[@]} -eq 0 ]]; then
|
if [[ ${#MBNICS[@]} -eq 0 ]]; then
|
||||||
error "[ERROR] No management bond NICs were selected."
|
fail_setup "No management bond NICs selected"
|
||||||
fail_setup
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
nmcli -t -f NAME con show | grep -Fxq "$bond_name"
|
nmcli -t -f NAME con show | grep -Fxq "$bond_name"
|
||||||
@@ -886,6 +889,7 @@ create_repo() {
|
|||||||
title "Create the repo directory"
|
title "Create the repo directory"
|
||||||
logCmd "dnf -y install yum-utils createrepo_c"
|
logCmd "dnf -y install yum-utils createrepo_c"
|
||||||
logCmd "createrepo /nsm/repo"
|
logCmd "createrepo /nsm/repo"
|
||||||
|
logCmd "createrepo /nsm/kernelrepo"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -913,8 +917,7 @@ detect_os() {
|
|||||||
is_rpm=true
|
is_rpm=true
|
||||||
is_supported=true
|
is_supported=true
|
||||||
else
|
else
|
||||||
info "This OS is not supported. Security Onion requires Oracle Linux 9."
|
fail_setup "This OS is not supported. Security Onion requires Oracle Linux 9."
|
||||||
fail_setup
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
info "Found OS: $OS $OSVER"
|
info "Found OS: $OS $OSVER"
|
||||||
@@ -922,7 +925,7 @@ detect_os() {
|
|||||||
|
|
||||||
download_elastic_agent_artifacts() {
|
download_elastic_agent_artifacts() {
|
||||||
if ! update_elastic_agent 2>&1 | tee -a "$setup_log"; then
|
if ! update_elastic_agent 2>&1 | tee -a "$setup_log"; then
|
||||||
fail_setup
|
fail_setup "Failed to update Elastic Agent"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1566,7 +1569,7 @@ proxy_validate() {
|
|||||||
error "Received error: $proxy_test_err"
|
error "Received error: $proxy_test_err"
|
||||||
if [[ -n $TESTING ]]; then
|
if [[ -n $TESTING ]]; then
|
||||||
error "Exiting setup"
|
error "Exiting setup"
|
||||||
kill -SIGINT "$(ps --pid $$ -oppid=)"; fail_setup
|
kill -SIGINT "$(ps --pid $$ -oppid=)"; fail_setup "Proxy validation failed"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
return $ret
|
return $ret
|
||||||
@@ -1773,8 +1776,7 @@ ensure_pyyaml() {
|
|||||||
local result=$?
|
local result=$?
|
||||||
set +o pipefail
|
set +o pipefail
|
||||||
if [[ $result -ne 0 ]] || ! rpm -q python3-pyyaml >/dev/null 2>&1; then
|
if [[ $result -ne 0 ]] || ! rpm -q python3-pyyaml >/dev/null 2>&1; then
|
||||||
error "Failed to install python3-pyyaml (exit=$result)"
|
fail_setup "Failed to install python3-pyyaml (exit=$result)"
|
||||||
fail_setup
|
|
||||||
fi
|
fi
|
||||||
info "python3-pyyaml installed successfully"
|
info "python3-pyyaml installed successfully"
|
||||||
}
|
}
|
||||||
@@ -1812,6 +1814,16 @@ securityonion_repo() {
|
|||||||
echo "mirrorlist=file:///etc/yum/mirror.txt" >> /etc/yum.repos.d/securityonion.repo
|
echo "mirrorlist=file:///etc/yum/mirror.txt" >> /etc/yum.repos.d/securityonion.repo
|
||||||
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
|
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
|
||||||
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
|
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
|
||||||
|
echo "https://repo.securityonion.net/file/so-repo/prod/3/oracle/9-uek8" > /etc/yum/mirror-kernel.txt
|
||||||
|
echo "https://so-repo-east.s3.us-east-005.backblazeb2.com/prod/3/oracle/9-uek8" >> /etc/yum/mirror-kernel.txt
|
||||||
|
echo "[securityonionkernel]" > /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "name=Security Onion Kernel Repo repo" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "mirrorlist=file:///etc/yum/mirror-kernel.txt" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "enabled=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
# Supplementary kernel repo: tolerate it being empty/unreachable so a missing
|
||||||
|
# repomd.xml can't make every dnf operation fail before the repo is populated.
|
||||||
|
echo "skip_if_unavailable=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
logCmd "dnf repolist"
|
logCmd "dnf repolist"
|
||||||
else
|
else
|
||||||
echo "[securityonion]" > /etc/yum.repos.d/securityonion.repo
|
echo "[securityonion]" > /etc/yum.repos.d/securityonion.repo
|
||||||
@@ -1820,6 +1832,13 @@ securityonion_repo() {
|
|||||||
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
|
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
|
||||||
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
|
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
|
||||||
echo "sslverify=0" >> /etc/yum.repos.d/securityonion.repo
|
echo "sslverify=0" >> /etc/yum.repos.d/securityonion.repo
|
||||||
|
echo "[securityonionkernel]" > /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "name=Security Onion Kernel Repo" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "baseurl=https://$MSRV/kernelrepo" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "enabled=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "sslverify=0" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "skip_if_unavailable=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
logCmd "dnf repolist"
|
logCmd "dnf repolist"
|
||||||
fi
|
fi
|
||||||
elif [[ ! $waitforstate ]]; then
|
elif [[ ! $waitforstate ]]; then
|
||||||
@@ -1829,12 +1848,25 @@ securityonion_repo() {
|
|||||||
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
|
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
|
||||||
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
|
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
|
||||||
echo "sslverify=0" >> /etc/yum.repos.d/securityonion.repo
|
echo "sslverify=0" >> /etc/yum.repos.d/securityonion.repo
|
||||||
|
echo "[securityonionkernel]" > /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "name=Security Onion Kernel Repo" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "baseurl=https://$MSRV/kernelrepo" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "enabled=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "sslverify=0" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "skip_if_unavailable=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
elif [[ $waitforstate ]]; then
|
elif [[ $waitforstate ]]; then
|
||||||
echo "[securityonion]" > /etc/yum.repos.d/securityonion.repo
|
echo "[securityonion]" > /etc/yum.repos.d/securityonion.repo
|
||||||
echo "name=Security Onion Repo" >> /etc/yum.repos.d/securityonion.repo
|
echo "name=Security Onion Repo" >> /etc/yum.repos.d/securityonion.repo
|
||||||
echo "baseurl=file:///nsm/repo/" >> /etc/yum.repos.d/securityonion.repo
|
echo "baseurl=file:///nsm/repo/" >> /etc/yum.repos.d/securityonion.repo
|
||||||
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
|
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
|
||||||
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
|
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
|
||||||
|
echo "[securityonionkernel]" > /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "name=Security Onion Kernel Repo" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "baseurl=file:///nsm/kernelrepo/" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "enabled=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
|
echo "skip_if_unavailable=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||||
fi
|
fi
|
||||||
logCmd "dnf repolist all"
|
logCmd "dnf repolist all"
|
||||||
if [[ $waitforstate ]]; then
|
if [[ $waitforstate ]]; then
|
||||||
@@ -1850,9 +1882,12 @@ repo_sync_local() {
|
|||||||
# Sync the repo from the SO repo locally.
|
# Sync the repo from the SO repo locally.
|
||||||
info "Adding Repo Download Configuration"
|
info "Adding Repo Download Configuration"
|
||||||
mkdir -p /nsm/repo
|
mkdir -p /nsm/repo
|
||||||
|
mkdir -p /nsm/kernelrepo
|
||||||
mkdir -p /opt/so/conf/reposync/cache
|
mkdir -p /opt/so/conf/reposync/cache
|
||||||
echo "https://repo.securityonion.net/file/so-repo/prod/3/oracle/9" > /opt/so/conf/reposync/mirror.txt
|
echo "https://repo.securityonion.net/file/so-repo/prod/3/oracle/9" > /opt/so/conf/reposync/mirror.txt
|
||||||
echo "https://repo-alt.securityonion.net/prod/3/oracle/9" >> /opt/so/conf/reposync/mirror.txt
|
echo "https://repo-alt.securityonion.net/prod/3/oracle/9" >> /opt/so/conf/reposync/mirror.txt
|
||||||
|
echo "https://repo.securityonion.net/file/so-repo/prod/3/oracle/9-uek8" > /opt/so/conf/reposync/mirror-kernel.txt
|
||||||
|
echo "https://repo-alt.securityonion.net/prod/3/oracle/9-uek8" >> /opt/so/conf/reposync/mirror-kernel.txt
|
||||||
echo "[main]" > /opt/so/conf/reposync/repodownload.conf
|
echo "[main]" > /opt/so/conf/reposync/repodownload.conf
|
||||||
echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf
|
echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf
|
||||||
echo "installonly_limit=3" >> /opt/so/conf/reposync/repodownload.conf
|
echo "installonly_limit=3" >> /opt/so/conf/reposync/repodownload.conf
|
||||||
@@ -1866,12 +1901,18 @@ repo_sync_local() {
|
|||||||
echo "mirrorlist=file:///opt/so/conf/reposync/mirror.txt" >> /opt/so/conf/reposync/repodownload.conf
|
echo "mirrorlist=file:///opt/so/conf/reposync/mirror.txt" >> /opt/so/conf/reposync/repodownload.conf
|
||||||
echo "enabled=1" >> /opt/so/conf/reposync/repodownload.conf
|
echo "enabled=1" >> /opt/so/conf/reposync/repodownload.conf
|
||||||
echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf
|
echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf
|
||||||
|
echo "[securityonionkernel]" >> /opt/so/conf/reposync/repodownload.conf
|
||||||
|
echo "name=Security Onion Kernel Repo repo" >> /opt/so/conf/reposync/repodownload.conf
|
||||||
|
echo "mirrorlist=file:///opt/so/conf/reposync/mirror-kernel.txt" >> /opt/so/conf/reposync/repodownload.conf
|
||||||
|
echo "enabled=1" >> /opt/so/conf/reposync/repodownload.conf
|
||||||
|
echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf
|
||||||
|
|
||||||
logCmd "dnf repolist"
|
logCmd "dnf repolist"
|
||||||
|
|
||||||
if [[ ! $is_airgap ]]; then
|
if [[ ! $is_airgap ]]; then
|
||||||
curl --retry 5 --retry-delay 60 -A "netinstall/$SOVERSION/$OS/$(uname -r)/1" https://sigs.securityonion.net/checkup --output /tmp/install
|
curl --retry 5 --retry-delay 60 -A "netinstall/$SOVERSION/$OS/$(uname -r)/1" https://sigs.securityonion.net/checkup --output /tmp/install
|
||||||
retry 5 60 "dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionsync --download-metadata -p /nsm/repo/" >> "$setup_log" 2>&1 || fail_setup
|
retry 5 60 "dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionsync --download-metadata -p /nsm/repo/" >> "$setup_log" 2>&1 || fail_setup "Failed to sync repos"
|
||||||
|
retry 5 60 "dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionkernel --download-metadata -p /nsm/kernelrepo/" >> "$setup_log" 2>&1 || fail_setup "Failed to sync kernel repos"
|
||||||
# After the download is complete run createrepo
|
# After the download is complete run createrepo
|
||||||
create_repo
|
create_repo
|
||||||
fi
|
fi
|
||||||
@@ -1884,10 +1925,10 @@ saltify() {
|
|||||||
|
|
||||||
if [[ $waitforstate ]]; then
|
if [[ $waitforstate ]]; then
|
||||||
# install all for a manager
|
# install all for a manager
|
||||||
retry 30 10 "bash ../salt/salt/scripts/bootstrap-salt.sh -r -M -X stable $SALTVERSION" || fail_setup
|
retry 30 10 "bash ../salt/salt/scripts/bootstrap-salt.sh -r -M -X stable $SALTVERSION" || fail_setup "Failed to install salt master"
|
||||||
else
|
else
|
||||||
# just a minion
|
# just a minion
|
||||||
retry 30 10 "bash ../salt/salt/scripts/bootstrap-salt.sh -r -X stable $SALTVERSION" || fail_setup
|
retry 30 10 "bash ../salt/salt/scripts/bootstrap-salt.sh -r -X stable $SALTVERSION" || fail_setup "Failed to install salt minion"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
salt_install_module_deps
|
salt_install_module_deps
|
||||||
@@ -1959,7 +2000,7 @@ set_main_ip() {
|
|||||||
info "MAINIP=$MAINIP"
|
info "MAINIP=$MAINIP"
|
||||||
info "MNIC_IP=$MNIC_IP"
|
info "MNIC_IP=$MNIC_IP"
|
||||||
whiptail_error_message "The management IP could not be determined. Please check the log at /root/sosetup.log and verify the network configuration. Select OK to exit."
|
whiptail_error_message "The management IP could not be determined. Please check the log at /root/sosetup.log and verify the network configuration. Select OK to exit."
|
||||||
fail_setup
|
fail_setup "Could not determine MAINIP or MNIC_IP"
|
||||||
fi
|
fi
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
@@ -2163,7 +2204,7 @@ set_initial_firewall_access() {
|
|||||||
set_management_interface() {
|
set_management_interface() {
|
||||||
title "Setting up the main interface"
|
title "Setting up the main interface"
|
||||||
if [[ $MNIC == "bond1" ]]; then
|
if [[ $MNIC == "bond1" ]]; then
|
||||||
configure_management_bond || fail_setup
|
configure_management_bond || fail_setup "Failed to configure management bond"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$address_type" = 'DHCP' ]; then
|
if [ "$address_type" = 'DHCP' ]; then
|
||||||
@@ -2228,6 +2269,13 @@ update_sudoers_for_testing() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update_packages() {
|
update_packages() {
|
||||||
|
# Pin physical NIC names by MAC BEFORE pulling packages, so the UEK8 kernel that
|
||||||
|
# the update below installs can't renumber the interfaces SO binds by name. Doing
|
||||||
|
# it here (instead of waiting for the common highstate) also drops the
|
||||||
|
# /opt/so/state/nic_names_pinned marker that gates the kernel repo, so the kernel
|
||||||
|
# repo is assigned on the very first highstate and the kernel isn't downgraded and
|
||||||
|
# then re-upgraded. Run-once: so-nic-pin no-ops if the marker already exists.
|
||||||
|
logCmd "bash ../salt/common/tools/sbin/so-nic-pin"
|
||||||
logCmd "dnf repolist"
|
logCmd "dnf repolist"
|
||||||
logCmd "dnf -y update --allowerasing --exclude=salt*,docker*,containerd*"
|
logCmd "dnf -y update --allowerasing --exclude=salt*,docker*,containerd*"
|
||||||
RMREPOFILES=("oracle-linux-ol9.repo" "uek-ol9.repo" "virt-ol9.repo")
|
RMREPOFILES=("oracle-linux-ol9.repo" "uek-ol9.repo" "virt-ol9.repo")
|
||||||
|
|||||||
+5
-9
@@ -90,8 +90,7 @@ if [[ "$setup_type" == 'iso' ]]; then
|
|||||||
if [[ $is_rpm ]]; then
|
if [[ $is_rpm ]]; then
|
||||||
is_iso=true
|
is_iso=true
|
||||||
else
|
else
|
||||||
echo "Only use 'so-setup iso' for an ISO install on Security Onion ISO images. Please run 'so-setup network' instead."
|
fail_setup "Only use 'so-setup iso' for an ISO install on Security Onion ISO images. Please run 'so-setup network' instead."
|
||||||
fail_setup
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -130,7 +129,7 @@ catch() {
|
|||||||
info "Fatal error occurred at $1 in so-setup, failing setup."
|
info "Fatal error occurred at $1 in so-setup, failing setup."
|
||||||
grep --color=never "ERROR" "$setup_log" > "$error_log"
|
grep --color=never "ERROR" "$setup_log" > "$error_log"
|
||||||
whiptail_setup_failed
|
whiptail_setup_failed
|
||||||
fail_setup
|
fail_setup "Fatal error occurred at $1 in so-setup"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add the progress function for manager node type installs
|
# Add the progress function for manager node type installs
|
||||||
@@ -238,8 +237,7 @@ case "$setup_type" in
|
|||||||
info "Beginning Security Onion $setup_type install"
|
info "Beginning Security Onion $setup_type install"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
error "Invalid install type, must be 'iso', 'network' or 'desktop'."
|
fail_setup "Invalid install type, must be 'iso', 'network' or 'desktop'."
|
||||||
fail_setup
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@@ -773,8 +771,7 @@ if ! [[ -f $install_opt_file ]]; then
|
|||||||
logCmd "salt-call state.apply -l info registry"
|
logCmd "salt-call state.apply -l info registry"
|
||||||
title "Seeding the docker registry"
|
title "Seeding the docker registry"
|
||||||
if ! docker_seed_registry; then
|
if ! docker_seed_registry; then
|
||||||
error "Failed to seed the docker registry"
|
fail_setup "Failed to seed the docker registry"
|
||||||
fail_setup
|
|
||||||
fi
|
fi
|
||||||
title "Applying the manager state"
|
title "Applying the manager state"
|
||||||
logCmd "salt-call state.apply -l info manager"
|
logCmd "salt-call state.apply -l info manager"
|
||||||
@@ -797,8 +794,7 @@ if ! [[ -f $install_opt_file ]]; then
|
|||||||
title "Setting up Elastic Fleet"
|
title "Setting up Elastic Fleet"
|
||||||
logCmd "salt-call state.apply elasticfleet.config"
|
logCmd "salt-call state.apply elasticfleet.config"
|
||||||
if ! logCmd so-elastic-fleet-setup; then
|
if ! logCmd so-elastic-fleet-setup; then
|
||||||
error "Failed to run so-elastic-fleet-setup"
|
fail_setup "Failed to run so-elastic-fleet-setup"
|
||||||
fail_setup
|
|
||||||
fi
|
fi
|
||||||
mark_setup_complete
|
mark_setup_complete
|
||||||
set_initial_firewall_access
|
set_initial_firewall_access
|
||||||
|
|||||||
+3
-3
@@ -143,15 +143,15 @@ main() {
|
|||||||
cat $error_log
|
cat $error_log
|
||||||
echo "--------------------------"
|
echo "--------------------------"
|
||||||
exit_code=1
|
exit_code=1
|
||||||
touch /root/failure
|
echo "Found setup errors. Check $error_log for details" > /root/failure
|
||||||
elif using_iso && cron_error_in_mail_spool; then
|
elif using_iso && cron_error_in_mail_spool; then
|
||||||
echo "WARNING: Unexpected cron job output in mail spool"
|
echo "WARNING: Unexpected cron job output in mail spool"
|
||||||
exit_code=1
|
exit_code=1
|
||||||
touch /root/failure
|
echo "Unexpected cron job output found in /var/spool/mail/" > /root/failure
|
||||||
elif is_manager_node && status_failed; then
|
elif is_manager_node && status_failed; then
|
||||||
echo "WARNING: Containers are not in a healthy state"
|
echo "WARNING: Containers are not in a healthy state"
|
||||||
exit_code=1
|
exit_code=1
|
||||||
touch /root/failure
|
echo "Containers are not in a healthy state. Check so-status for details" > /root/failure
|
||||||
else
|
else
|
||||||
echo "Successfully completed setup!"
|
echo "Successfully completed setup!"
|
||||||
touch /root/success
|
touch /root/success
|
||||||
|
|||||||
Reference in New Issue
Block a user