#!/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!" fail_setup fi # Save the original argument array since we modify it original_args=("$@") cd "$(dirname "$0")" || fail_setup 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 test_profile=$2 WHATWOULDYOUSAYYAHDOHERE=setup 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-cidr="* ) export ALLOW_CIDR="${arg#*=}";; * ) if [[ "$arg" == "--"* ]]; then echo "Invalid option" fi esac done # Preserve old setup/error logs [ -f "$error_log" ] && mv "$error_log" "$error_log.$(date +%Y-%m-%dT%H:%M:%S)" [ -f "$setup_log" ] && mv "$setup_log" "$setup_log.$(date +%Y-%m-%dT%H:%M:%S)" # Let's see what OS we are dealing with here detect_os # Check to see if this is the setup type of "desktop". is_desktop= if [ "$setup_type" = 'desktop' ]; then is_desktop=true # Check to see if this is an ISO. Usually this dir on exists on ISO installs. if [ -d /root/SecurityOnion ]; then is_desktop_iso=true fi fi # Make sure if ISO is specified that we are dealing with CentOS or Rocky title "Detecting if this is an ISO install" 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." fail_setup fi fi # Check to see if this is an desktop install. If it is let's run things differently if [[ $is_desktop ]]; then title "This is a desktop install" # Make sure it's CentOS or Rocky Linux if [[ ! $is_rocky ]]; then info "Security Onion Desktop is only supported on Rocky Linux 9" exit 1 fi if ! whiptail_desktop_install; then if [[ $is_desktop_iso ]]; then if whiptail_desktop_nongrid_iso; then # Remove setup from auto launching parse_install_username sed -i '$ d' /home/$INSTALLUSERNAME/.bash_profile >> "$setup_log" 2>&1 info "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_desktop_nongrid_network; then info "" info "" info "Kicking off the automated setup of the Security Onion Desktop. This can take a while depending on your network connection." info "" info "" desktop_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 title "Checking to see if install has run before" if [[ -f /root/accept_changes ]]; then is_reinstall=true whiptail_reinstall info "Old setup detected. Preparing for reinstallation." reinstall_init reset_proxy fi title "Parsing Username for 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 fail_setup } # Add the progress function for manager node type installs progress() { local msg=${1:-'Please wait while installing...'} if [ -z "$TESTING" ]; then whiptail --title "$whiptail_title" --gauge "$msg" 6 70 0 # append to text else cat >> $setup_log 2>&1 fi } if [ -n "$test_profile" ]; then install_type="$(echo $test_profile |awk -F- '{print $1}')" if [[ "$install_type" == "distributed" ]]; then install_type=MANAGER else install_type=${install_type^^} fi # The below settings are hardcoded purely for automated testing purposes. TESTING=true if [[ "$test_profile" =~ "-sensor" ]]; then install_type=SENSOR HOSTNAME=sensor MSRVIP_OFFSET=-2 elif [[ "$test_profile" =~ "-search" ]]; then install_type=SEARCHNODE HOSTNAME=search MSRVIP_OFFSET=-1 else HOSTNAME=manager fi info "Activating test profile; profile=$test_profile; install_type=$install_type" MINION_CIDR=10.0.0.0/8 MSRV=manager if [[ "$test_profile" =~ "-net" ]] || [[ "$test_profile" =~ "-iso" ]]; then address_type=DHCP elif [[ "$test_profile" =~ "-cloud" ]]; then MSRVIP=10.99.1.20 elif [[ "$test_profile" =~ "-airgap" ]]; then is_airgap=true address_type=DHCP fi if [ -f "/root/public_ip" ]; then REDIRECTHOST=$(cat /root/public_ip) REDIRECTINFO=OTHER else REDIRECTINFO=IP fi ALLOW_CIDR=0.0.0.0/0 nic_list=$(ls -1 /sys/class/net | grep -v docker | grep -v lo) MNIC=$(echo "$nic_list" | head -1) BNICS=$(echo "$nic_list" | head -2 | tail -1) WEBUSER=onionuser@somewhere.invalid WEBPASSWD1=0n10nus3r WEBPASSWD2=0n10nus3r update_sudoers_for_testing fi # Make sure the setup type is suppoted. case "$setup_type" in iso | network | desktop) # Accepted values info "Beginning Security Onion $setup_type install" ;; *) error "Invalid install type, must be 'iso', 'network' or 'desktop'." fail_setup ;; esac # Allow execution of SO tools during setup local_sbin="$(pwd)/../salt/common/tools/sbin" manager_sbin="$(pwd)/../salt/manager/tools/sbin" export PATH=$PATH:$local_sbin:$manager_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 [ -z "$TESTING" ]; then TTY=$(tty) info "Setup is running on TTY $TTY" if echo $TTY | grep -q "/dev/tty"; then CONSOLEBLANK=$(cat /sys/module/kernel/parameters/consoleblank) info "Kernel consoleblank value before: $CONSOLEBLANK" if [ $CONSOLEBLANK -gt 0 ]; then info "Running 'setterm -blank 0' for TTY $TTY" TERM=linux setterm -blank 0 >$TTY <$TTY CONSOLEBLANK=$(cat /sys/module/kernel/parameters/consoleblank) info "Kernel consoleblank value after: $CONSOLEBLANK" fi fi fi # Begin prompting the user with whiptail. if ! [[ -f $install_opt_file ]]; then if (whiptail_you_sure); then true else info "User cancelled setup." whiptail_cancel fi # If this is an desktop install lets streamline the process. if [[ $is_desktop ]]; then # Prompt for hostname collect_hostname if [[ $is_desktop_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_desktop_iso ]]; then # This should be a network install whiptail_network_notice # Warn about the dangers of DHCP whiptail_dhcp_warn whiptail_management_nic fi # 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' ]] && [ -z "$TESTING" ]; then whiptail_first_menu_iso if [[ $option == "CONFIGURENETWORK" ]]; then collect_hostname network_init_whiptail 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_desktop ]]; 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 info "Setting up as node type eval" # waitforstate means we will run the full salt state at the end. This is for only nodes running the salt-master service waitforstate=true # Does this role have monitoring interfaces? monints=true # Prompt the user to accept the elastic license check_elastic_license # If it is an install from ISO is this airgap? [[ $is_iso ]] && whiptail_airgap # Make sure minimum requirements are met check_requirements "manager" # Do networking things networking_needful # Do we need a proxy? [[ ! $is_airgap ]] && collect_net_method # Do we need to change the dockernet subnet? collect_dockernet # Are we in the clouds? [[ ! $is_airgap ]] && detect_cloud # Sets some minion info set_minion_info set_default_log_size >> $setup_log 2>&1 info "Verifying all network devices are managed by Network Manager that should be" check_network_manager_conf set_network_dev_status_list # What NIC for watching network traffic? whiptail_sensor_nics # How many cores do we have? calculate_useable_cores # What is the web user? collect_webuser_inputs # How are we accessing the UI? get_redirect # Does the user want to allow access to the UI? collect_so_allow whiptail_end_settings elif [[ $is_standalone ]]; then waitforstate=true monints=true check_elastic_license [[ $is_iso ]] && whiptail_airgap check_requirements "manager" networking_needful [[ ! $is_airgap ]] && collect_net_method collect_dockernet [[ ! $is_airgap ]] && detect_cloud set_minion_info set_default_log_size >> $setup_log 2>&1 info "Verifying all network devices are managed by Network Manager that should be" check_network_manager_conf set_network_dev_status_list whiptail_sensor_nics calculate_useable_cores collect_webuser_inputs get_redirect collect_so_allow whiptail_end_settings elif [[ $is_manager ]]; then info "Setting up as node type manager" check_elastic_license waitforstate=true #ubuntu_check [[ $is_iso ]] && whiptail_airgap check_requirements "manager" networking_needful [[ ! $is_airgap ]] && collect_net_method collect_dockernet [[ ! $is_airgap ]] && detect_cloud set_minion_info set_default_log_size >> $setup_log 2>&1 info "Verifying all network devices are managed by Network Manager that should be" check_network_manager_conf set_network_dev_status_list calculate_useable_cores collect_webuser_inputs get_redirect collect_so_allow whiptail_end_settings elif [[ $is_managersearch ]]; then info "Setting up as node type managersearch" check_elastic_license waitforstate=true [[ $is_iso ]] && whiptail_airgap check_requirements "manager" networking_needful [[ ! $is_airgap ]] && collect_net_method collect_dockernet [[ ! $is_airgap ]] && detect_cloud set_minion_info set_default_log_size >> $setup_log 2>&1 info "Verifying all network devices are managed by Network Manager that should be" check_network_manager_conf set_network_dev_status_list calculate_useable_cores collect_webuser_inputs get_redirect collect_so_allow whiptail_end_settings elif [[ $is_sensor ]]; then info "Setting up as node type sensor" installer_prereq_packages 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_fleet ]]; then info "Setting up as node type fleet" check_requirements "fleet" 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_searchnode ]]; then info "Setting up as node type searchnode" installer_prereq_packages 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 info "Setting up as node type heavynode" installer_prereq_packages monints=true check_requirements "heavynode" 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_idh ]]; then info "Setting up as node type idh" installer_prereq_packages check_requirements "idh" networking_needful collect_mngr_hostname add_mngr_ip_to_hosts check_manager_connection collect_idh_preferences set_minion_info whiptail_end_settings elif [[ $is_import ]]; then info "Setting up as node type import" waitforstate=true [[ $is_iso ]] && whiptail_airgap check_elastic_license check_requirements "import" networking_needful [[ ! $is_airgap ]] && detect_cloud collect_dockernet [[ ! $is_airgap ]] && collect_net_method set_minion_info set_default_log_size >> $setup_log 2>&1 info "Verifying all network devices are managed by Network Manager that should be" check_network_manager_conf set_network_dev_status_list calculate_useable_cores collect_webuser_inputs get_redirect collect_so_allow whiptail_end_settings elif [[ $is_receiver ]]; then info "Setting up as node type receiver" installer_prereq_packages check_requirements "receiver" networking_needful collect_mngr_hostname add_mngr_ip_to_hosts check_manager_connection set_minion_info whiptail_end_settings fi if [[ $waitforstate ]]; then touch /root/accept_changes make_some_dirs percentage=0 es_heapsize ls_heapsize if [[ $needs_proxy ]]; then set_proxy fi set_redirect if [[ $monints ]]; then # Generate Interface Vars generate_interface_vars configure_network_sensor fi info "Reserving ports" reserve_ports info "Setting Paths" # Set the paths set_path echo "Disable auto start of setup" # Disable the setup from prompting at login disable_auto_start info "Setting the version" # Set the version mark_version info "Clearing the old manager" # Remove old manager if re-install clear_manager info "Generating Secrets" # Generate passwords generate_passwords info "Populating the secrets pillar" # Create the secrets pillar secrets_pillar info "Add socore user" # Add the socore user add_socore_user_manager create_local_directories setup_salt_master_dirs create_manager_pillars info "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 MNIC=$MNIC export NODE_DESCRIPTION=$NODE_DESCRIPTION export MAINIP=$MAINIP export PATCHSCHEDULENAME=$PATCHSCHEDULENAME export INTERFACE=$INTERFACE export CORECOUNT=$lb_procs export LSHOSTNAME=$HOSTNAME export LSHEAP=$LS_HEAP_SIZE export CPUCORES=$num_cpu_cores logCmd "so-minion -o=setup" title "Creating Global SLS" if [[ $is_airgap ]]; then # Airgap Rules airgap_rules fi manager_pillar # 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" check_sos_appliance logCmd "salt-key -yd $MINION_ID" sleep 2 # Debug RSA Key format errors logCmd "salt-call state.show_top" sleep 2 # Debug RSA Key format errors logCmd "salt-key -ya $MINION_ID" logCmd "salt-call state.apply common.packages" logCmd "salt-call state.apply common" logCmd "salt-call state.apply docker" firewall_generate_templates set_initial_firewall_policy # Download Elastic Agent Artifacts title "Downloading Elastic Agent Artifacts" download_elastic_agent_artifacts generate_ca generate_ssl logCmd "salt-call state.apply -l info firewall" # create these so the registry state can add so-registry to /opt/so/conf/so-status/so-status.conf logCmd "mkdir -p /opt/so/conf/so-status/ " logCmd "touch /opt/so/conf/so-status/so-status.conf" title "Importing Registry Docker" import_registry_docker title "Applying the registry state" logCmd "salt-call state.apply -l info registry" title "Seeding the docker registry" docker_seed_registry title "Applying the manager state" logCmd "salt-call state.apply -l info manager" logCmd "salt-call state.apply influxdb -l info" logCmd "salt-call state.highstate -l info" if [[ ! $is_airgap ]]; then title "Downloading IDS Rules" logCmd "so-rule-update" title "Restarting Suricata to pick up the new rules" logCmd "so-suricata-restart" title "Downloading YARA rules" logCmd "runuser -l socore 'so-yara-update'" title "Restarting Strelka to use new rules" logCmd "so-strelka-restart" fi title "Setting up Kibana Default Space" logCmd "so-kibana-space-defaults" add_web_user info "Restarting SOC to pick up initial user" logCmd "so-soc-restart" title "Setting up Elastic Fleet" logCmd "salt-call state.apply elasticfleet.config" logCmd "so-elastic-fleet-setup" if [[ ! $is_import ]]; then title "Setting up Playbook" logCmd "so-playbook-reset" fi checkin_at_boot set_initial_firewall_access systemctl restart salt-master systemctl restart salt-minion verify_setup else touch /root/accept_changes mkdir -p /opt/so es_heapsize ls_heapsize generate_interface_vars if [[ $monints ]]; then configure_network_sensor fi reserve_ports # Set the version mark_version # Disable the setup from prompting at login disable_auto_start info "Clearing the old manager" # Remove old manager if re-install clear_manager gpg_rpm_import securityonion_repo update_packages saltify configure_minion "$minion_type" check_sos_appliance drop_install_options checkin_at_boot logCmd "salt-call state.apply setup.highstate_cron --local --file-root=../salt/" verify_setup fi # Need to make sure the latest install is located on the web server of the manager to check the versions and download the code if required fi