#!/bin/bash # Copyright 2014-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 . cd "$(dirname "$0")" || exit 255 source ./so-functions source ./so-common-functions source ./so-whiptail source ./so-variables # Parse command line arguments setup_type=$1 automation=$2 while [[ $# -gt 0 ]]; do arg="$1" shift case "$arg" in "--turbo="* ) export TURBO="http://${arg#*=}";; "--proxy="* ) export {http,https,ftp,rsync,all}_proxy="${arg#*=}";; "--allow-role="* ) export ALLOW_ROLE="${arg#*=}";; "--allow-cidr="* ) export ALLOW_CIDR="${arg#*=}";; "--skip-reboot" ) export SKIP_REBOOT=1;; * ) if [[ "$arg" == "--"* ]]; then echo "Invalid option" fi esac done # Begin Installation pre-processing echo "---- Starting setup at $(date -u) ----" >> $setup_log 2>&1 automated=no function progress() { if [ $automated == no ]; then whiptail --title "Security Onion Install" --gauge 'Please wait while installing' 6 60 0 else cat >> $setup_log 2>&1 fi } if [[ -f automation/$automation && $(basename $automation) == $automation ]]; then echo "Preselecting variable values based on automated setup: $automation" >> $setup_log 2>&1 source automation/$automation automated=yes echo "Checking network configuration" >> $setup_log 2>&1 ip a >> $setup_log 2>&1 attempt=1 attempts=60 ip a | grep "$MNIC:" | grep "state UP" >> $setup_log 2>&1 while [ $? -ne 0 ]; do ip a >> $setup_log 2>&1 if [ $attempt -gt $attempts ]; then echo "Network unavailable - setup cannot continue" >> $setup_log 2>&1 exit 1 fi echo "Waiting for network to come up (attempt $attempt of $attempts)" >> $setup_log 2>&1 attempt=$((attempt + 1)) sleep 10; ip a | grep "$MNIC:" | grep "state UP" >> $setup_log 2>&1 done echo "Network is up on $MNIC" >> $setup_log 2>&1 fi case "$setup_type" in iso | network) # Accepted values echo "Beginning Security Onion $setup_type install" >> $setup_log 2>&1 ;; *) echo "Invalid install type, must be 'iso' or 'network'" | tee $setup_log exit 1 ;; esac # Allow execution of SO tools during setup export PATH=$PATH:../salt/common/tools/sbin got_root detect_os if [ "$OS" == ubuntu ]; then update-alternatives --set newt-palette /etc/newt/palette.original >> $setup_log 2>&1 fi setterm -blank 0 if [ "$setup_type" == 'iso' ] || (whiptail_you_sure); then true else echo "User cancelled setup." | tee $setup_log whiptail_cancel fi whiptail_install_type if [ "$install_type" = 'EVAL' ]; then is_node=true is_master=true is_sensor=true is_eval=true elif [ "$install_type" = 'STANDALONE' ]; then is_master=true is_distmaster=true is_node=true is_sensor=true elif [ "$install_type" = 'MASTERSEARCH' ]; then is_master=true is_distmaster=true is_node=true elif [ "$install_type" = 'MASTER' ]; then is_master=true is_distmaster=true elif [ "$install_type" = 'SENSOR' ]; then is_sensor=true is_minion=true STRELKA=1 elif [[ "$install_type" =~ ^('SEARCHNODE'|'HOTNODE'|'WARMNODE')$ ]]; then is_node=true is_minion=true elif [ "$install_type" = 'HEAVYNODE' ]; then is_node=true is_minion=true is_sensor=true elif [ "$install_type" = 'FLEET' ]; then is_minion=true is_fleet_standalone=true OSQUERY=1 elif [ "$install_type" = 'HELIXSENSOR' ]; then is_helix=true fi if [[ $is_eval ]]; then check_requirements "eval" elif [[ $is_fleet_standalone ]]; then check_requirements "dist" "fleet" elif [[ $is_sensor && ! $is_eval ]]; then check_requirements "dist" "sensor" elif [[ $is_distmaster || $is_minion ]]; then check_requirements "dist" fi whiptail_patch_schedule case "$setup_type" in 'iso') whiptail_set_hostname whiptail_management_nic whiptail_dhcp_or_static if [ "$address_type" != 'DHCP' ]; then whiptail_management_interface_ip whiptail_management_interface_mask whiptail_management_interface_gateway whiptail_management_interface_dns whiptail_management_interface_dns_search fi collect_adminuser_inputs ;; 'network') whiptail_network_notice whiptail_set_hostname whiptail_management_nic ;; esac short_name=$(echo "$HOSTNAME" | awk -F. '{print $1}') MINION_ID=$(echo "${short_name}_${install_type}" | tr '[:upper:]' '[:lower:]') export MINION_ID echo "MINION_ID = $MINION_ID" >> $setup_log 2>&1 minion_type=$(get_minion_type) # Set any variables needed set_default_log_size >> $setup_log 2>&1 if [[ $is_helix ]]; then RULESETUP=ETOPEN NSMSETUP=BASIC HNSENSOR=inherit MASTERUPDATES=0 fi if [[ $is_helix || ( $is_master && $is_node ) ]]; then RULESETUP=ETOPEN NSMSETUP=BASIC fi if [[ $is_master && $is_node ]]; then LSPIPELINEWORKERS=1 LSPIPELINEBATCH=125 LSINPUTTHREADS=1 LSINPUTBATCHCOUNT=125 NIDS=Suricata BROVERSION=ZEEK fi if [[ $is_node ]]; then CURCLOSEDAYS=30 fi # Start user prompts if [[ $is_helix || $is_sensor ]]; then whiptail_bond_nics calculate_useable_cores fi if [[ $is_helix || $is_master ]]; then whiptail_homenet_master fi if [[ $is_helix || $is_master || $is_node ]]; then set_base_heapsizes fi if [[ $is_master && ! $is_eval ]]; then whiptail_master_adv whiptail_bro_version whiptail_nids whiptail_rule_setup if [ "$RULESETUP" != 'ETOPEN' ]; then whiptail_oinkcode fi if [ "$MASTERADV" = 'ADVANCED' ] && [ "$BROVERSION" != 'SURICATA' ]; then whiptail_master_adv_service_brologs fi fi if [[ $is_master ]]; then whiptail_components_adv_warning whiptail_enable_components if [[ $STRELKA == 1 ]]; then whiptail_strelka_rules if [[ $STRELKARULES == 1 ]]; then strelka_yara_update fi fi collect_webuser_inputs get_redirect fi if [[ $is_distmaster || ( $is_sensor || $is_node || $is_fleet_standalone ) && ! $is_eval ]]; then whiptail_master_updates if [[ $setup_type == 'network' && $MASTERUPDATES == 1 ]]; then whiptail_master_updates_warning fi fi if [[ $is_minion ]]; then whiptail_management_server fi if [[ $is_distmaster ]]; then collect_soremote_inputs fi if [[ $is_sensor && ! $is_eval ]]; then whiptail_homenet_sensor whiptail_sensor_config if [ $NSMSETUP == 'ADVANCED' ]; then whiptail_bro_pins whiptail_suricata_pins whiptail_bond_nics_mtu else whiptail_basic_bro whiptail_basic_suri fi fi if [[ $is_node && ! $is_eval ]]; then whiptail_node_advanced if [ "$NODESETUP" == 'NODEADVANCED' ]; then whiptail_node_es_heap whiptail_node_ls_heap whiptail_node_ls_pipeline_worker whiptail_node_ls_pipline_batchsize whiptail_node_ls_input_threads whiptail_node_ls_input_batch_count whiptail_cur_close_days whiptail_log_size_limit else NODE_ES_HEAP_SIZE=$ES_HEAP_SIZE NODE_LS_HEAP_SIZE=$LS_HEAP_SIZE LSPIPELINEWORKERS=$num_cpu_cores LSPIPELINEBATCH=125 LSINPUTTHREADS=1 LSINPUTBATCHCOUNT=125 fi fi if [ "$install_type" == 'FLEET' ]; then collect_fleetuser_inputs collect_fleet_custom_hostname_inputs else FLEETNODEUSER=$WEBUSER FLEETNODEPASSWD1=$WEBPASSWD1 fi whiptail_make_changes if [[ -n "$TURBO" ]]; then use_turbo_proxy fi if [[ "$setup_type" == 'iso' ]]; then # Init networking so rest of install works set_hostname_iso set_management_interface add_admin_user disable_onion_user fi set_hostname >> $setup_log 2>&1 set_version >> $setup_log 2>&1 clear_master >> $setup_log 2>&1 if [[ $is_master ]]; then generate_passwords >> $setup_log 2>&1 secrets_pillar >> $setup_log 2>&1 add_socore_user_master >> $setup_log 2>&1 fi if [[ $is_master && ! $is_eval ]]; then add_soremote_user_master >> $setup_log 2>&1 fi set_main_ip >> $setup_log 2>&1 if [[ $is_minion ]]; then set_updates >> $setup_log 2>&1 copy_ssh_key >> $setup_log 2>&1 fi if [[ "$OSQUERY" = 1 ]]; then host_pillar >> $setup_log 2>&1 fi # Begin install { # Set initial percentage to 0 export percentage=0 if [[ $is_minion ]]; then set_progress_str 1 'Configuring firewall' set_initial_firewall_policy >> $setup_log 2>&1 fi set_progress_str 2 'Updating packages' update_packages >> $setup_log 2>&1 if [[ $is_sensor || $is_helix ]]; then set_progress_str 3 'Creating bond interface' create_sensor_bond >> $setup_log 2>&1 set_progress_str 4 'Generating sensor pillar' sensor_pillar >> $setup_log 2>&1 fi set_progress_str 5 'Installing Salt and dependencies' saltify 2>> $setup_log set_progress_str 7 'Installing Docker and dependencies' docker_install >> $setup_log 2>&1 set_progress_str 8 'Generating patch pillar' patch_pillar >> $setup_log 2>&1 set_progress_str 9 'Initializing Salt minion' configure_minion "$minion_type" >> $setup_log 2>&1 if [[ $is_master || $is_helix ]]; then set_progress_str 10 'Configuring Salt master' create_local_directories >> $setup_log 2>&1 addtotab_generate_templates >> $setup_log 2>&1 copy_master_config >> $setup_log 2>&1 setup_salt_master_dirs >> $setup_log 2>&1 firewall_generate_templates >> $setup_log 2>&1 set_progress_str 11 'Updating sudoers file for soremote user' update_sudoers >> $setup_log 2>&1 set_progress_str 12 'Generating master static pillar' master_static >> $setup_log 2>&1 set_progress_str 13 'Generating master pillar' master_pillar >> $setup_log 2>&1 fi set_progress_str 16 'Running first Salt checkin' salt_firstcheckin >> $setup_log 2>&1 if [[ $is_helix ]]; then set_progress_str 17 'Generating the FireEye pillar' fireeye_pillar >> $setup_log 2>&1 fi if [[ $is_node ]]; then set_progress_str 18 'Setting node type' set_node_type >> $setup_log 2>&1 set_progress_str 19 'Generating search node pillar' node_pillar >> $setup_log 2>&1 fi if [[ $is_minion ]]; then set_progress_str 20 'Accepting Salt key on master' accept_salt_key_remote >> $setup_log 2>&1 fi if [[ $is_master ]]; then set_progress_str 20 'Accepting Salt key' salt-key -ya "$MINION_ID" >> $setup_log 2>&1 fi set_progress_str 21 'Copying minion pillars to master' copy_minion_tmp_files >> $setup_log 2>&1 set_progress_str 22 'Generating CA and checking in' salt_checkin >> $setup_log 2>&1 if [[ $is_master || $is_helix ]]; then set_progress_str 25 'Configuring firewall' set_initial_firewall_policy >> $setup_log 2>&1 if [[ "$setup_type" == 'iso' ]]; then set_progress_str 26 'Copying containers from iso' else set_progress_str 26 'Downloading containers from the internet' fi salt-call state.apply -l info registry >> $setup_log 2>&1 docker_seed_registry 2>> "$setup_log" # ~ 60% when finished set_progress_str 60 "$(print_salt_state_apply 'master')" salt-call state.apply -l info master >> $setup_log 2>&1 set_progress_str 61 "$(print_salt_state_apply 'idstools')" salt-call state.apply -l info idstools >> $setup_log 2>&1 set_progress_str 61 "$(print_salt_state_apply 'suricata.master')" salt-call state.apply -l info suricata.master >> $setup_log 2>&1 fi set_progress_str 62 "$(print_salt_state_apply 'firewall')" salt-call state.apply -l info firewall >> $setup_log 2>&1 if [ $OS = 'centos' ]; then set_progress_str 63 'Installing Yum utilities' salt-call state.apply -l info yum.packages >> $setup_log 2>&1 fi set_progress_str 63 "$(print_salt_state_apply 'common')" salt-call state.apply -l info common >> $setup_log 2>&1 set_progress_str 64 "$(print_salt_state_apply 'nginx')" salt-call state.apply -l info nginx >> $setup_log 2>&1 if [[ $is_master || $is_node ]]; then set_progress_str 64 "$(print_salt_state_apply 'elasticsearch')" salt-call state.apply -l info elasticsearch >> $setup_log 2>&1 fi if [[ $is_sensor ]]; then set_progress_str 65 "$(print_salt_state_apply 'pcap')" salt-call state.apply -l info pcap >> $setup_log 2>&1 set_progress_str 66 "$(print_salt_state_apply 'suricata')" salt-call state.apply -l info suricata >> $setup_log 2>&1 set_progress_str 67 "$(print_salt_state_apply 'zeek')" salt-call state.apply -l info zeek >> $setup_log 2>&1 fi if [[ $is_node ]]; then set_progress_str 68 "$(print_salt_state_apply 'curator')" salt-call state.apply -l info curator >> $setup_log 2>&1 fi if [[ $is_master ]]; then set_progress_str 69 "$(print_salt_state_apply 'soc')" salt-call state.apply -l info soc >> $setup_log 2>&1 set_progress_str 70 "$(print_salt_state_apply 'kibana')" salt-call state.apply -l info kibana >> $setup_log 2>&1 set_progress_str 71 "$(print_salt_state_apply 'elastalert')" salt-call state.apply -l info elastalert >> $setup_log 2>&1 set_progress_str 72 "$(print_salt_state_apply 'soctopus')" salt-call state.apply -l info soctopus >> $setup_log 2>&1 fi if [[ "$OSQUERY" = 1 ]]; then set_progress_str 73 "$(print_salt_state_apply 'mysql')" salt-call state.apply -l info mysql >> $setup_log 2>&1 set_progress_str 73 "$(print_salt_state_apply 'fleet')" salt-call state.apply -l info fleet >> $setup_log 2>&1 set_progress_str 73 "$(print_salt_state_apply 'redis')" salt-call state.apply -l info redis >> $setup_log 2>&1 if [[ $is_fleet_standalone && $FLEETCUSTOMHOSTNAME != '' ]]; then set_progress_str 73 "$(print_salt_state_apply 'fleet.event_update-custom-hostname')" pillar_override="{\"static\":{\"fleet_custom_hostname\": \"$FLEETCUSTOMHOSTNAME\"}}" salt-call state.apply -l info fleet.event_update-custom-hostname pillar="$pillar_override" >> $setup_log 2>&1 fi set_progress_str 74 "$(print_salt_state_apply 'so-fleet-setup')" so-fleet-setup $FLEETNODEUSER $FLEETNODEPASSWD1 >> $setup_log 2>&1 fi if [[ "$WAZUH" = 1 ]]; then set_progress_str 75 "$(print_salt_state_apply 'wazuh')" salt-call state.apply -l info wazuh >> $setup_log 2>&1 fi if [[ "$THEHIVE" = 1 ]]; then set_progress_str 76 "$(print_salt_state_apply 'thehive')" salt-call state.apply -l info thehive >> $setup_log 2>&1 fi if [[ "$STRELKA" = 1 ]]; then set_progress_str 77 "$(print_salt_state_apply 'strelka')" salt-call state.apply -l info strelka >> $setup_log 2>&1 fi if [[ "$PLAYBOOK" = 1 ]]; then set_progress_str 78 "$(print_salt_state_apply 'playbook')" salt-call state.apply -l info playbook >> $setup_log 2>&1 fi if [[ "$NAVIGATOR" = 1 ]]; then set_progress_str 78 "$(print_salt_state_apply 'navigator')" salt-call state.apply -l info navigator >> $setup_log 2>&1 fi if [[ $is_master || $is_helix ]]; then set_progress_str 81 "$(print_salt_state_apply 'utility')" salt-call state.apply -l info utility >> $setup_log 2>&1 fi if [[ ( $is_helix || $is_master || $is_node ) && ! $is_eval ]]; then set_progress_str 82 "$(print_salt_state_apply 'logstash')" salt-call state.apply -l info logstash >> $setup_log 2>&1 set_progress_str 83 "$(print_salt_state_apply 'filebeat')" salt-call state.apply -l info filebeat >> $setup_log 2>&1 fi set_progress_str 85 'Applying finishing touches' filter_unused_nics >> $setup_log 2>&1 network_setup >> $setup_log 2>&1 if [[ $is_master ]]; then set_progress_str 87 'Adding user to SOC' add_web_user >> $setup_log 2>&1 fi set_progress_str 90 'Enabling checkin at boot' checkin_at_boot >> $setup_log 2>&1 set_progress_str 95 'Verifying setup' salt-call -l info state.highstate >> $setup_log 2>&1 } | progress success=$(tail -10 $setup_log | grep Failed | awk '{ print $2}') if [[ "$success" = 0 ]]; then whiptail_setup_complete if [[ -n $ALLOW_ROLE && -n $ALLOW_CIDR ]]; then export IP=$ALLOW_CIDR so-allow -$ALLOW_ROLE >> $setup_log 2>&1 fi if [[ $THEHIVE == 1 ]]; then check_hive_init fi else whiptail_setup_failed fi if [[ -z $SKIP_REBOOT ]]; then shutdown -r now fi