diff --git a/salt/airgap/files/yum.conf b/salt/airgap/files/yum.conf new file mode 100644 index 000000000..cbab7607d --- /dev/null +++ b/salt/airgap/files/yum.conf @@ -0,0 +1,12 @@ +[main] +cachedir=/var/cache/yum/$basearch/$releasever +keepcache=0 +debuglevel=2 +logfile=/var/log/yum.log +exactarch=1 +obsoletes=1 +gpgcheck=1 +plugins=1 +installonly_limit=2 +bugtracker_url=http://bugs.centos.org/set_project.php?project_id=23&ref=http://bugs.centos.org/bug_report_page.php?category=yum +distroverpkg=centos-release \ No newline at end of file diff --git a/salt/airgap/init.sls b/salt/airgap/init.sls new file mode 100644 index 000000000..b7ad3da1b --- /dev/null +++ b/salt/airgap/init.sls @@ -0,0 +1,60 @@ +{% set MANAGER = salt['grains.get']('master') %} +airgapyum: + file.managed: + - name: /etc/yum/yum.conf + - source: salt://airgap/files/yum.conf + +airgap_repo: + pkgrepo.managed: + - humanname: Airgap Repo + - baseurl: https://{{ MANAGER }}/repo + - gpgcheck: 0 + - sslverify: 0 + +agbase: + file.absent: + - name: /etc/yum.repos.d/CentOS-Base.repo + +agcr: + file.absent: + - name: /etc/yum.repos.d/CentOS-CR.repo + +agdebug: + file.absent: + - name: /etc/yum.repos.d/CentOS-Debuginfo.repo + +agfasttrack: + file.absent: + - name: /etc/yum.repos.d/CentOS-fasttrack.repo + +agmedia: + file.absent: + - name: /etc/yum.repos.d/CentOS-Media.repo + +agsources: + file.absent: + - name: /etc/yum.repos.d/CentOS-Sources.repo + +agvault: + file.absent: + - name: /etc/yum.repos.d/CentOS-Vault.repo + +agkernel: + file.absent: + - name: /etc/yum.repos.d/CentOS-x86_64-kernel.repo + +agepel: + file.absent: + - name: /etc/yum.repos.d/epel.repo + +agtesting: + file.absent: + - name: /etc/yum.repos.d/epel-testing.repo + +agssrepo: + file.absent: + - name: /etc/yum.repos.d/saltstack.repo + +agwazrepo: + file.absent: + - name: /etc/yum.repos.d/wazuh.repo \ No newline at end of file diff --git a/salt/common/maps/so-status.map.jinja b/salt/common/maps/so-status.map.jinja index 21dd14ec9..fb23e6708 100644 --- a/salt/common/maps/so-status.map.jinja +++ b/salt/common/maps/so-status.map.jinja @@ -5,6 +5,9 @@ # to the list predefined by the role / minion id affix {% macro append_containers(pillar_name, k, compare )%} {% if salt['pillar.get'](pillar_name~':'~k, {}) != compare %} + {% if k == 'enabled' %} + {% set k = pillar_name %} + {% endif %} {% from 'common/maps/'~k~'.map.jinja' import docker as d with context %} {% for li in d['containers'] %} {{ docker['containers'].append(li) }} @@ -21,7 +24,7 @@ {% if role in ['eval', 'managersearch', 'manager', 'standalone'] %} {{ append_containers('manager', 'grafana', 0) }} {{ append_containers('global', 'fleet_manager', 0) }} - {{ append_containers('manager', 'wazuh', 0) }} + {{ append_containers('global', 'wazuh', 0) }} {{ append_containers('manager', 'thehive', 0) }} {{ append_containers('manager', 'playbook', 0) }} {{ append_containers('manager', 'freq', 0) }} @@ -29,7 +32,7 @@ {% endif %} {% if role in ['eval', 'heavynode', 'sensor', 'standalone'] %} - {{ append_containers('global', 'strelka', 0) }} + {{ append_containers('strelka', 'enabled', 0) }} {% endif %} {% if role in ['heavynode', 'standalone'] %} diff --git a/salt/common/tools/sbin/so-cortex-user-add b/salt/common/tools/sbin/so-cortex-user-add index 43126f709..dbb5b9716 100755 --- a/salt/common/tools/sbin/so-cortex-user-add +++ b/salt/common/tools/sbin/so-cortex-user-add @@ -48,6 +48,7 @@ if [[ "$resp" =~ \"status\":\"Ok\" ]]; then echo "Successfully added user to Cortex." else echo "Unable to add user to Cortex; user might already exist." + echo $resp exit 2 fi \ No newline at end of file diff --git a/salt/common/tools/sbin/so-cortex-user-enable b/salt/common/tools/sbin/so-cortex-user-enable index 63cd2f089..cbfdceb25 100755 --- a/salt/common/tools/sbin/so-cortex-user-enable +++ b/salt/common/tools/sbin/so-cortex-user-enable @@ -51,6 +51,7 @@ if [[ "$resp" =~ \"status\":\"Locked\" || "$resp" =~ \"status\":\"Ok\" ]]; then echo "Successfully updated user in Cortex." else echo "Failed to update user in Cortex." + echo $resp exit 2 fi \ No newline at end of file diff --git a/salt/common/tools/sbin/so-fleet-user-add b/salt/common/tools/sbin/so-fleet-user-add index 9637aa63c..5560b0522 100755 --- a/salt/common/tools/sbin/so-fleet-user-add +++ b/salt/common/tools/sbin/so-fleet-user-add @@ -54,5 +54,6 @@ if [[ $? -eq 0 ]]; then echo "Successfully added user to Fleet." else echo "Unable to add user to Fleet; user might already exist." + echo $resp exit 2 fi \ No newline at end of file diff --git a/salt/common/tools/sbin/so-fleet-user-enable b/salt/common/tools/sbin/so-fleet-user-enable index 0ea826391..a632844bb 100755 --- a/salt/common/tools/sbin/so-fleet-user-enable +++ b/salt/common/tools/sbin/so-fleet-user-enable @@ -53,5 +53,6 @@ if [[ $? -eq 0 ]]; then echo "Successfully updated user in Fleet." else echo "Failed to update user in Fleet." + echo $resp exit 2 fi \ No newline at end of file diff --git a/salt/common/tools/sbin/so-status b/salt/common/tools/sbin/so-status index 7a7d6c783..8658f4757 100755 --- a/salt/common/tools/sbin/so-status +++ b/salt/common/tools/sbin/so-status @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . {%- from 'common/maps/so-status.map.jinja' import docker with context %} -{%- set container_list = docker['containers'] | sort %} +{%- set container_list = docker['containers'] | sort | unique %} if ! [ "$(id -u)" = 0 ]; then echo "This command must be run as root" @@ -71,9 +71,9 @@ compare_lists() { # {% endraw %} create_expected_container_list() { - {% for item in container_list%} + {% for item in container_list -%} expected_container_list+=("{{ item }}") - {% endfor %} + {% endfor -%} } populate_container_lists() { diff --git a/salt/common/tools/sbin/so-thehive-user-add b/salt/common/tools/sbin/so-thehive-user-add index 0c9553abc..fc7a56f63 100755 --- a/salt/common/tools/sbin/so-thehive-user-add +++ b/salt/common/tools/sbin/so-thehive-user-add @@ -47,5 +47,6 @@ if [[ "$resp" =~ \"status\":\"Ok\" ]]; then echo "Successfully added user to TheHive." else echo "Unable to add user to TheHive; user might already exist." + echo $resp exit 2 fi diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index 4616be3f5..e354bcce4 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -11,12 +11,13 @@ . /usr/sbin/so-common if [[ $# < 1 || $# > 2 ]]; then - echo "Usage: $0 [email]" + echo "Usage: $0 [email]" echo "" echo " list: Lists all user email addresses currently defined in the identity system" echo " add: Adds a new user to the identity system; requires 'email' parameter" echo " update: Updates a user's password; requires 'email' parameter" - echo " delete: Deletes an existing user; requires 'email' parameter" + echo " enable: Enables a user; requires 'email' parameter" + echo " disable: Disables a user; requires 'email' parameter" echo " validate: Validates that the given email address and password are acceptable for defining a new user; requires 'email' parameter" echo " valemail: Validates that the given email address is acceptable for defining a new user; requires 'email' parameter" echo " valpass: Validates that a password is acceptable for defining a new user" @@ -63,7 +64,7 @@ function findIdByEmail() { email=$1 response=$(curl -Ss ${kratosUrl}/identities) - identityId=$(echo "${response}" | jq ".[] | select(.addresses[0].value == \"$email\") | .id") + identityId=$(echo "${response}" | jq ".[] | select(.verifiable_addresses[0].value == \"$email\") | .id") echo $identityId } @@ -113,7 +114,7 @@ function listUsers() { response=$(curl -Ss ${kratosUrl}/identities) [[ $? != 0 ]] && fail "Unable to communicate with Kratos" - echo "${response}" | jq -r ".[] | .addresses[0].value" | sort + echo "${response}" | jq -r ".[] | .verifiable_addresses[0].value" | sort } function createUser() { @@ -122,17 +123,8 @@ function createUser() { now=$(date -u +%FT%TZ) addUserJson=$(cat <> /etc/yum/pluginconf.d/versionlock.list + +# NetworkMiner has a compatibility issue with Mono 6 right now +0:mono-complete-4.2.1.102-0.xamarin.1.* +0:mono-core-4.2.1.102-0.xamarin.1.* +0:mono-data-4.2.1.102-0.xamarin.1.* +0:mono-data-oracle-4.2.1.102-0.xamarin.1.* +0:mono-data-sqlite-4.2.1.102-0.xamarin.1.* +0:mono-devel-4.2.1.102-0.xamarin.1.* +0:mono-extras-4.2.1.102-0.xamarin.1.* +0:mono-locale-extras-4.2.1.102-0.xamarin.1.* +0:mono-mvc-4.2.1.102-0.xamarin.1.* +0:mono-nunit-4.2.1.102-0.xamarin.1.* +0:mono-reactive-4.2.1.102-0.xamarin.1.* +0:mono-wcf-4.2.1.102-0.xamarin.1.* +0:mono-web-4.2.1.102-0.xamarin.1.* +0:mono-winforms-4.2.1.102-0.xamarin.1.* +0:mono-winfxcore-4.2.1.102-0.xamarin.1.* +EOF + +fi # Install Mono - prereq for NetworkMiner rpmkeys --import "http://pool.sks-keyservers.net/pks/lookup?op=get&search=0x3fa7e0328081bff6a14da29aa6a19b38d3d831ef"; curl https://download.mono-project.com/repo/centos7-stable.repo | tee /etc/yum.repos.d/mono-centos7-stable.repo; -yum -y install mono-devel; +yum -y install mono-core mono-basic mono-winforms expect # Install NetworkMiner yum -y install libcanberra-gtk2; -wget https://www.netresec.com/?download=NetworkMiner -O /tmp/nm.zip; +wget https://www.netresec.com/?download=NetworkMiner_2-4 -O /tmp/nm.zip; mkdir -p /opt/networkminer/ unzip /tmp/nm.zip -d /opt/networkminer/; rm /tmp/nm.zip; diff --git a/setup/so-functions b/setup/so-functions index 73828b091..01dc15c78 100755 --- a/setup/so-functions +++ b/setup/so-functions @@ -480,72 +480,6 @@ check_requirements() { fi } -copy_salt_master_config() { - - # Copy the Salt master config template to the proper directory - if [ "$setup_type" = 'iso' ]; then - cp /root/SecurityOnion/files/master /etc/salt/master >> "$setup_log" 2>&1 - else - cp ../files/master /etc/salt/master >> "$setup_log" 2>&1 - fi - - # Restart the service so it picks up the changes - systemctl restart salt-master >> "$setup_log" 2>&1 -} - -copy_minion_tmp_files() { - case "$install_type" in - 'MANAGER' | 'EVAL' | 'HELIXSENSOR' | 'MANAGERSEARCH' | 'STANDALONE' | 'IMPORT') - echo "Copying pillar and salt files in $temp_install_dir to $local_salt_dir" - cp -Rv "$temp_install_dir"/pillar/ $local_salt_dir/ >> "$setup_log" 2>&1 - if [ -d "$temp_install_dir"/salt ] ; then - cp -Rv "$temp_install_dir"/salt/ $local_salt_dir/ >> "$setup_log" 2>&1 - fi - ;; - *) - { - echo "scp pillar and salt files in $temp_install_dir to manager $local_salt_dir"; - ssh -i /root/.ssh/so.key soremote@"$MSRV" mkdir -p /tmp/"$MINION_ID"/pillar; - ssh -i /root/.ssh/so.key soremote@"$MSRV" mkdir -p /tmp/"$MINION_ID"/schedules; - scp -prv -i /root/.ssh/so.key "$temp_install_dir"/pillar/minions/* soremote@"$MSRV":/tmp/"$MINION_ID"/pillar/; - if [ -d $temp_install_dir/salt/patch/os/schedules/ ]; then - if [ "$(ls -A $temp_install_dir/salt/patch/os/schedules/)" ]; then - scp -prv -i /root/.ssh/so.key $temp_install_dir/salt/patch/os/schedules/* soremote@$MSRV:/tmp/$MINION_ID/schedules; - fi - fi - ssh -i /root/.ssh/so.key soremote@"$MSRV" sudo $default_salt_dir/salt/manager/files/add_minion.sh "$MINION_ID"; - } >> "$setup_log" 2>&1 - ;; - esac -} - -copy_ssh_key() { - - echo "Generating SSH key" - # Generate SSH key - mkdir -p /root/.ssh - ssh-keygen -f /root/.ssh/so.key -t rsa -q -N "" < /dev/zero - chown -R "$SUDO_USER":"$SUDO_USER" /root/.ssh - echo "Copying the SSH key to the manager" - #Copy the key over to the manager - ssh-copy-id -f -i /root/.ssh/so.key soremote@"$MSRV" -} - -create_local_directories() { - echo "Creating local pillar and salt directories" - PILLARSALTDIR=${SCRIPTDIR::-5} - for i in "pillar" "salt"; do - for d in $(find $PILLARSALTDIR/$i -type d); do - suffixdir=${d//$PILLARSALTDIR/} - if [ ! -d "$local_salt_dir/$suffixdir" ]; then - mkdir -v "$local_salt_dir$suffixdir" >> "$setup_log" 2>&1 - fi - done - chown -R socore:socore "$local_salt_dir/$i" - done - -} - configure_network_sensor() { echo "Setting up sensor interface" >> "$setup_log" 2>&1 local nic_error=0 @@ -630,6 +564,77 @@ configure_network_sensor() { fi } +copy_salt_master_config() { + + # Copy the Salt master config template to the proper directory + if [ "$setup_type" = 'iso' ]; then + cp /root/SecurityOnion/files/master /etc/salt/master >> "$setup_log" 2>&1 + else + cp ../files/master /etc/salt/master >> "$setup_log" 2>&1 + fi + + # Restart the service so it picks up the changes + systemctl restart salt-master >> "$setup_log" 2>&1 +} + +copy_minion_tmp_files() { + case "$install_type" in + 'MANAGER' | 'EVAL' | 'HELIXSENSOR' | 'MANAGERSEARCH' | 'STANDALONE' | 'IMPORT') + echo "Copying pillar and salt files in $temp_install_dir to $local_salt_dir" + cp -Rv "$temp_install_dir"/pillar/ $local_salt_dir/ >> "$setup_log" 2>&1 + if [ -d "$temp_install_dir"/salt ] ; then + cp -Rv "$temp_install_dir"/salt/ $local_salt_dir/ >> "$setup_log" 2>&1 + fi + ;; + *) + { + echo "scp pillar and salt files in $temp_install_dir to manager $local_salt_dir"; + ssh -i /root/.ssh/so.key soremote@"$MSRV" mkdir -p /tmp/"$MINION_ID"/pillar; + ssh -i /root/.ssh/so.key soremote@"$MSRV" mkdir -p /tmp/"$MINION_ID"/schedules; + scp -prv -i /root/.ssh/so.key "$temp_install_dir"/pillar/minions/* soremote@"$MSRV":/tmp/"$MINION_ID"/pillar/; + if [ -d $temp_install_dir/salt/patch/os/schedules/ ]; then + if [ "$(ls -A $temp_install_dir/salt/patch/os/schedules/)" ]; then + scp -prv -i /root/.ssh/so.key $temp_install_dir/salt/patch/os/schedules/* soremote@$MSRV:/tmp/$MINION_ID/schedules; + fi + fi + ssh -i /root/.ssh/so.key soremote@"$MSRV" sudo $default_salt_dir/salt/manager/files/add_minion.sh "$MINION_ID"; + } >> "$setup_log" 2>&1 + ;; + esac +} + +copy_ssh_key() { + + echo "Generating SSH key" + # Generate SSH key + mkdir -p /root/.ssh + ssh-keygen -f /root/.ssh/so.key -t rsa -q -N "" < /dev/zero + chown -R "$SUDO_USER":"$SUDO_USER" /root/.ssh + echo "Copying the SSH key to the manager" + #Copy the key over to the manager + ssh-copy-id -f -i /root/.ssh/so.key soremote@"$MSRV" +} + +create_local_directories() { + echo "Creating local pillar and salt directories" + PILLARSALTDIR=${SCRIPTDIR::-5} + for i in "pillar" "salt"; do + for d in $(find $PILLARSALTDIR/$i -type d); do + suffixdir=${d//$PILLARSALTDIR/} + if [ ! -d "$local_salt_dir/$suffixdir" ]; then + mkdir -v "$local_salt_dir$suffixdir" >> "$setup_log" 2>&1 + fi + done + chown -R socore:socore "$local_salt_dir/$i" + done + +} + +create_repo() { + # Create the repo for airgap + createrepo /nsm/repo +} + detect_cloud() { echo "Testing if setup is running on a cloud instance..." >> "$setup_log" 2>&1 if ( curl --fail -s -m 5 http://169.254.169.254/latest/meta-data/instance-id > /dev/null ) || ( dmidecode -s bios-vendor | grep -q Google > /dev/null); then export is_cloud="true"; fi @@ -1096,6 +1101,14 @@ manager_global() { " ids: $NIDS"\ " url_base: $REDIRECTIT"\ " managerip: $MAINIP" > "$global_pillar" + + if [[ $is_airgap ]]; then + printf '%s\n'\ + " airgap: True"\ >> "$global_pillar" + else + printf '%s\n'\ + " airgap: False"\ >> "$global_pillar" + fi # Check if TheHive is enabled. If so, add creds and other details if [[ "$THEHIVE" == "1" ]]; then @@ -1860,8 +1873,10 @@ set_redirect() { set_updates() { if [ "$MANAGERUPDATES" = '1' ]; then if [ "$OS" = 'centos' ]; then - if ! grep -q "$MSRV" /etc/yum.conf; then - echo "proxy=http://$MSRV:3142" >> /etc/yum.conf + if [[ ! $is_airgap ]]; then + if ! grep -q "$MSRV" /etc/yum.conf; then + echo "proxy=http://$MSRV:3142" >> /etc/yum.conf + fi fi else # Set it up so the updates roll through the manager diff --git a/setup/so-setup b/setup/so-setup index 30bc10479..f771d7d57 100755 --- a/setup/so-setup +++ b/setup/so-setup @@ -193,16 +193,16 @@ if [[ "$setup_type" == 'iso' ]]; then is_iso=true fi -#Check if this is an airgap install +# Check if this is an airgap install -#if [[ $is_manager ]]; then -# if [[ $is_iso ]]; then -# whiptail_airgap -# if [[ "$INTERWEBS" == 'AIRGAP' ]]; then -# is_airgap=true -# fi -# fi -#fi +if [[ $is_manager ]]; then + if [[ $is_iso ]]; then + whiptail_airgap + if [[ "$INTERWEBS" == 'AIRGAP' ]]; then + is_airgap=true + fi + fi +fi if [[ $is_manager && $is_sensor ]]; then check_requirements "standalone" @@ -411,6 +411,8 @@ if [[ $is_manager || $is_import ]]; then whiptail_so_allow; fi whiptail_make_changes +# From here on changes will be made. + if [[ -n "$TURBO" ]]; then use_turbo_proxy fi @@ -460,6 +462,11 @@ fi # Set initial percentage to 0 export percentage=0 + if [[ $is_manager && $is_airgap ]]; then + info "Creating airgap repo" + create_repo >> $setup_log 2>&1 + fi + if [[ $is_minion ]]; then set_progress_str 1 'Configuring firewall' set_initial_firewall_policy >> $setup_log 2>&1 diff --git a/setup/so-whiptail b/setup/so-whiptail index e590a30d9..2996969fa 100755 --- a/setup/so-whiptail +++ b/setup/so-whiptail @@ -97,8 +97,8 @@ whiptail_zeek_version() { [ -n "$TESTING" ] && return - ZEEKVERSION=$(whiptail --title "Security Onion Setup" --radiolist "What tool would you like to use to generate meta data?" 20 75 4 "ZEEK" "Install Zeek (aka Bro)" ON \ - "SURICATA" "Use Suricata 5" OFF 3>&1 1>&2 2>&3) + ZEEKVERSION=$(whiptail --title "Security Onion Setup" --radiolist "What tool would you like to use to generate metadata?" 20 75 4 "ZEEK" "Zeek (formerly known as Bro)" ON \ + "SURICATA" "Suricata" OFF 3>&1 1>&2 2>&3) local exitstatus=$? whiptail_check_exitstatus $exitstatus @@ -412,6 +412,13 @@ whiptail_enable_components() { [ -n "$TESTING" ] && return + GRAFANA=0 + OSQUERY=0 + WAZUH=0 + THEHIVE=0 + PLAYBOOK=0 + STRELKA=0 + COMPONENTS=$(whiptail --title "Security Onion Setup" --checklist \ "Select Components to install" 20 75 8 \ GRAFANA "Enable Grafana for system monitoring" ON \ @@ -621,9 +628,8 @@ whiptail_nids() { [ -n "$TESTING" ] && return NIDS=$(whiptail --title "Security Onion Setup" --radiolist \ - "Choose which IDS to run. \n - Snort 3.0 support will be added once it is out of beta:" 25 75 4 \ - "Suricata" "Suricata 4.X" ON \ + "Choose which IDS to run. \n\n(Snort 3.0 support will be added once it is out of beta.)" 25 75 4 \ + "Suricata" "Suricata" ON \ "Snort" "Placeholder for Snort 3.0 " OFF 3>&1 1>&2 2>&3 ) local exitstatus=$?