#!/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. # Make sure you are root before doing anything uid="$(id -u)" if [ "$uid" -ne 0 ]; then echo "This script must be run using sudo!" exit 1 fi # Save the original argument array since we modify it original_args=("$@") cd "$(dirname "$0")" || exit 255 echo "Getting started..." # Source the generic function libraries that are also used by the product after # setup. These functions are intended to be reusable outside of the setup process. source ../salt/common/tools/sbin/so-common source ../salt/common/tools/sbin/so-image-common # Setup bash functionality is divided into functions and user-facing prompts. # Do not attempt to re-use any of this functionality outside of setup. Instead, # if needed, migrated generic functions into so-common. source ./so-functions source ./so-whiptail # Finally, source the default variable definitions, which require availability of # functions sourced above. source ./so-variables # Parse command line arguments setup_type=$1 automation=$2 WHATWOULDYOUSAYYAHDOHERE=setup # This is for automation 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 # Let's see what OS we are dealing with here detect_os # Check to see if this is the setup type of "analyst". is_analyst= if [ "$setup_type" = 'analyst' ]; then is_analyst=true # Check to see if this is an ISO. Usually this dir on exists on ISO installs. if [ -d /root/SecurityOnion ]; then is_analyst_iso=true fi fi # Make sure if ISO is specified that we are dealing with CentOS or Rocky if [[ "$setup_type" == 'iso' ]]; then if [[ $is_centos || $is_rocky ]]; then is_iso=true else echo "Only use 'so-setup iso' for an ISO install on Security Onion ISO images. Please run 'so-setup network' instead." exit 1 fi fi # Check to see if this is an analyst install. If it is let's run things differently if [[ $is_analyst ]]; then # Make sure it's CentOS or Rocky Linux if [[ ! $is_centos ]]; then echo "Analyst Workstation is only supported on CentOS 7 or Rocky Linux 8" exit 1 fi if ! whiptail_analyst_install; then if [[ $is_analyst_iso ]]; then if whiptail_analyst_nongrid_iso; then # Remove setup from auto launching parse_install_username sed -i '$ d' /home/$INSTALLUSERNAME/.bash_profile >> "$setup_log" 2>&1 echo "Enabling graphical interface and setting it to load at boot" systemctl set-default graphical.target startx exit 0 else # Abort! exit 0 fi else if whiptail_analyst_nongrid_network; then echo "" echo "" echo "Kicking off the automated setup of the analyst workstation. This can take a while depending on your network connection." echo "" echo "" analyst_salt_local else # Abort! exit 0 fi fi fi # If you got this far then you want to join the grid is_minion=true fi if ! [ -f $install_opt_file ] && [ -d /root/manager_setup/securityonion ] && [[ $(pwd) != /root/manager_setup/securityonion/setup ]]; then exec bash /root/manager_setup/securityonion/setup/so-setup "${original_args[@]}" fi if [[ -f /root/accept_changes ]]; then is_reinstall=true # Move last setup log to backup mv "$setup_log" "$setup_log.bak" [ -f "$error_log" ] && mv "$error_log" "$error_log.bak" fi # Figure out the user id that is running the install parse_install_username if ! [ -f $install_opt_file ]; then # Begin Installation pre-processing title "Initializing Setup" info "Installing as the $INSTALLUSERNAME user" analyze_system fi # Set up handler for setup to exit early (use `kill -SIGUSR1 "$setup_proc"; exit 1` in child scripts) trap 'catch $LINENO' SIGUSR1 setup_proc="$$" catch() { info "Fatal error occurred at $1 in so-setup, failing setup." grep --color=never "ERROR" "$setup_log" > "$error_log" whiptail_setup_failed exit 1 } automated=no # Add the progress function for manager node type installs progress() { local msg=${1:-'Please wait while installing...'} if [ $automated == no ]; then whiptail --title "$whiptail_title" --gauge "$msg" 6 70 0 # append to text else cat >> $setup_log 2>&1 fi } # If using automation let's do automation things. 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 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 if [[ ! $is_iso ]]; then echo "Installing sshpass for automated testing." >> $setup_log 2>&1 if [ "$OS" == ubuntu ]; then retry 50 10 "apt-get -y install sshpass" >> $setup_log 2>&1 || exit 1 else yum -y install sshpass >> $setup_log 2>&1 fi fi fi # Make sure the setup type is suppoted. case "$setup_type" in iso | network | analyst) # Accepted values echo "Beginning Security Onion $setup_type install" >> $setup_log 2>&1 ;; *) echo "Invalid install type, must be 'iso', 'network' or 'analyst'." | tee -a $setup_log exit 1 ;; esac # Allow execution of SO tools during setup local_sbin="$(pwd)/../salt/common/tools/sbin" export PATH=$PATH:$local_sbin # Ubuntu whiptail pallete to make it look the same as CentOS and Rocky. set_palette >> $setup_log 2>&1 # Kernel messages can overwrite whiptail screen #812 # https://github.com/Security-Onion-Solutions/securityonion/issues/812 dmesg -D # Kernel consoleblank is causing whiptail progress screen to appear to hang #1084 # https://github.com/Security-Onion-Solutions/securityonion/issues/1084 if [ "$automated" == no ]; then TTY=$(tty) echo "Setup is running on TTY $TTY" >> $setup_log 2>&1 if echo $TTY | grep -q "/dev/tty"; then CONSOLEBLANK=$(cat /sys/module/kernel/parameters/consoleblank) echo "Kernel consoleblank value before: $CONSOLEBLANK" >> $setup_log 2>&1 if [ $CONSOLEBLANK -gt 0 ]; then echo "Running 'setterm -blank 0' for TTY $TTY" >> $setup_log 2>&1 TERM=linux setterm -blank 0 >$TTY <$TTY CONSOLEBLANK=$(cat /sys/module/kernel/parameters/consoleblank) echo "Kernel consoleblank value after: $CONSOLEBLANK" >> $setup_log 2>&1 fi fi fi # Begin prompting the user with whiptail. if ! [[ -f $install_opt_file ]]; then if (whiptail_you_sure); then true else echo "User cancelled setup." | tee -a "$setup_log" whiptail_cancel fi # If this is an analyst install lets streamline the process. if [[ $is_analyst ]]; then # Prompt for hostname collect_hostname if [[ $is_analyst_iso ]]; then # Prompt Network Setup whiptail_management_nic whiptail_dhcp_or_static if [ "$address_type" != 'DHCP' ]; then collect_int_ip_mask collect_gateway collect_dns collect_dns_domain fi fi if [[ ! $is_analyst_iso ]]; then # This should be a network install whiptail_network_notice # Warn about the dangers of DHCP whiptail_dhcp_warn whiptail_management_nic fi whiptail_network_init_notice # Initializing the network based on the previous information network_init printf '%s\n' \ "MNIC=$MNIC" \ "HOSTNAME=$HOSTNAME" > "$net_init_file" set_main_ip compare_main_nic_ip fi if [[ $setup_type == 'iso' ]] && [ "$automated" == no ]; then whiptail_first_menu_iso if [[ $option == "CONFIGURENETWORK" ]]; then collect_hostname network_init_whiptail whiptail_network_init_notice network_init printf '%s\n' \ "MNIC=$MNIC" \ "HOSTNAME=$HOSTNAME" > "$net_init_file" set_main_ip compare_main_nic_ip whiptail_net_setup_complete else true fi fi if [[ ! $is_analyst ]]; then whiptail_install_type fi else source $install_opt_file fi # Process the install type process_installtype # If this is not an automated install prompt if ! [[ -f $install_opt_file ]]; then # If you are a manager ask ALL the manager things here. I know there is code re-use but this makes it easier to add new roles. if [[ $is_eval ]]; then waitforstate=true monints=true check_elastic_license check_requirements "manager" networking_needful whiptail_airgap detect_cloud set_minion_info set_default_log_size >> $setup_log 2>&1 echo "Verifying all network devices are managed by Network Manager that should be" >> "$setup_log" 2>&1 check_network_manager_conf set_network_dev_status_list whiptail_sensor_nics calculate_useable_cores collect_webuser_inputs get_redirect collect_ntp_servers collect_so_allow whiptail_end_settings # Start the install elif [[ $is_standalone ]]; then waitforstate=true monints=true check_elastic_license check_requirements "manager" networking_needful whiptail_airgap detect_cloud set_minion_info set_default_log_size >> $setup_log 2>&1 echo "Verifying all network devices are managed by Network Manager that should be" >> "$setup_log" 2>&1 check_network_manager_conf set_network_dev_status_list whiptail_sensor_nics calculate_useable_cores collect_webuser_inputs get_redirect collect_ntp_servers collect_so_allow whiptail_end_settings elif [[ $is_manager ]]; then check_elastic_license waitforstate=true check_requirements "manager" networking_needful whiptail_airgap detect_cloud set_default_log_size >> $setup_log 2>&1 echo "Verifying all network devices are managed by Network Manager that should be" >> "$setup_log" 2>&1 check_network_manager_conf set_network_dev_status_list calculate_useable_cores collect_webuser_inputs get_redirect collect_ntp_servers collect_so_allow whiptail_end_settings elif [[ $is_managersearch ]]; then check_elastic_license waitforstate=true check_requirements "manager" networking_needful whiptail_airgap detect_cloud set_default_log_size >> $setup_log 2>&1 echo "Verifying all network devices are managed by Network Manager that should be" >> "$setup_log" 2>&1 check_network_manager_conf set_network_dev_status_list calculate_useable_cores collect_webuser_inputs get_redirect collect_ntp_servers collect_so_allow whiptail_end_settings elif [[ $is_sensor ]]; then monints=true check_requirements "sensor" calculate_useable_cores networking_needful check_network_manager_conf set_network_dev_status_list collect_mngr_hostname add_mngr_ip_to_hosts check_manager_connection detect_cloud whiptail_sensor_nics set_minion_info whiptail_end_settings elif [[ $is_searchnode ]]; then check_requirements "elasticsearch" networking_needful check_network_manager_conf set_network_dev_status_list collect_mngr_hostname add_mngr_ip_to_hosts check_manager_connection detect_cloud set_minion_info whiptail_end_settings elif [[ $is_heavynode ]]; then monints=true check_requirements "heavynode" calculate_useable_cores networking_needful collect_mngr_hostname add_mngr_ip_to_hosts check_manager_connection whiptail_end_settings elif [[ $is_idh ]]; then check_requirements "idh" networking_needful collect_mngr_hostname add_mngr_ip_to_hosts check_manager_connection whiptail_end_settings elif [[ $is_import ]]; then check_requirements "import" networking_needful collect_mngr_hostname add_mngr_ip_to_hosts check_manager_connection whiptail_end_settings elif [[ $is_receiver ]]; then check_requirements "receiver" networking_needful collect_mngr_hostname add_mngr_ip_to_hosts check_manager_connection whiptail_end_settings fi if [[ $waitforstate ]]; then percentage=0 es_heapsize ls_heapsize set_redirect # Generate Interface Vars generate_interface_vars if [[ $monints ]]; then configure_network_sensor fi # Configure NTP echo "Configuring NTP" [[ ${#ntp_servers[@]} -gt 0 ]] && configure_ntp >> $setup_log 2>&1 # Reserve the ports that SO needs echo "Reserving ports" reserve_ports echo "Setting Paths" # Set the paths set_path echo "Checking if this is a re-install" # Check to see if its a reinstall. THIS NEEDS REVIEW if [[ $is_reinstall ]]; then reinstall_init fi echo "Disable auto start of setup" # Disable the setup from prompting at login disable_auto_start echo "Setting the version" # Set the version mark_version echo "Clearing the old manager" # Remove old manager if re-install clear_manager echo "Generating Secrets" # Generate passwords generate_passwords echo "Populating the secrets pillar" # Create the secrets pillar secrets_pillar echo "Add socore user" # Add the socore user add_socore_user_manager create_local_directories setup_salt_master_dirs create_manager_pillars echo "Generating the minion pillar" # Create the minion defaults export NODETYPE=$install_type export MINION_ID=$MINION_ID export ES_HEAP_SIZE=$ES_HEAP_SIZE export IDHMGTRESTRICT=$IDHMGTRESTRICT export idh_services=$idh_services export MNIC=$MNIC export NODE_DESCRIPTION=$NODE_DESCRIPTION export MAINIP=$MAINIP export PATCHSCHEDULENAME=$PATCHSCHEDULENAME export INTERFACE="bond0" so-minion -o=setup echo "Creating Global SLS" if [[ $is_airgap ]]; then # Airgap Rules airgap_rules fi manager_pillar zeek_logs_enabled # Set up the repo to point to local file https://access.redhat.com/solutions/1355683 # reposync down the files is network and createrepo if CentOS # Import the GPG keys gpg_rpm_import # Create the local repo and point the box to use the local repo securityonion_repo # Update existing packages update_packages # Install salt saltify # Start the master service copy_salt_master_config configure_minion "$minion_type" salt-key -yd "$MINION_ID" #delete the minion key if it already exists salt-call state.show_top >> /dev/null 2>&1 #talk to the salt-master so the minion key is created on the salt-master salt-key -ya "$MINION_ID" #accept the key salt-call state.apply salt.helper-packages salt-call state.apply common.packages salt-call state.apply common salt-call state.apply docker # Set the initial firewall policy firewall_generate_templates; set_initial_firewall_policy generate_ca generate_ssl # create these so the registry state can add so-registry to /opt/so/conf/so-status/so-status.conf mkdir -p /opt/so/conf/so-status/ touch /opt/so/conf/so-status/so-status.conf echo "Importing Registry Docker" import_registry_docker echo "Applying the registry state" salt-call state.apply -l info registry echo "Seeding the docker registry" docker_seed_registry echo "Applying the manager state" salt-call state.apply -l info manager salt-call state.apply -l info firewall salt-call state.highstate -l info add_web_user so-elastic-fleet-setup echo "Setting up Playbook" so-playbook-reset whiptail_setup_complete else es_heapsize ls_heapsize generate_interface_vars if [[ $monints ]]; then configure_network_sensor fi reserve_ports # Set the version mark_version echo "Clearing the old manager" # Remove old manager if re-install clear_manager gpg_rpm_import securityonion_repo update_packages saltify configure_minion "$minion_type" drop_install_options whiptail_setup_complete fi # Need to make sure the latest install is located on the web server of the manager to check the versions and donwload the code if required fi