diff --git a/salt/common/tools/sbin/so-fleet-setup b/salt/common/tools/sbin/so-fleet-setup new file mode 100644 index 000000000..9801c803b --- /dev/null +++ b/salt/common/tools/sbin/so-fleet-setup @@ -0,0 +1,44 @@ +#!/bin/bash + +#so-fleet-setup $FleetEmail $FleetPassword + +if [[ $# -ne 2 ]] ; then + echo "Username or Password was not set - exiting now." + exit 1 +fi + +# Checking to see if required containers are started... +if [ ! "$(docker ps -q -f name=so-fleet)" ]; then + echo "Starting Docker Containers..." + salt-call state.apply mysql queue=True >> /root/fleet-setup.log + salt-call state.apply fleet queue=True >> /root/fleet-setup.log + salt-call state.apply redis queue=True >> /root/fleet-setup.log +fi + +docker exec so-fleet fleetctl config set --address https://localhost:8080 --tls-skip-verify --url-prefix /fleet +docker exec so-fleet fleetctl setup --email $1 --password $2 + +docker exec so-fleet fleetctl apply -f /packs/palantir/Fleet/Endpoints/MacOS/osquery.yaml +docker exec so-fleet fleetctl apply -f /packs/palantir/Fleet/Endpoints/Windows/osquery.yaml +docker exec so-fleet fleetctl apply -f /packs/so/so-default.yml +docker exec so-fleet /bin/sh -c 'for pack in /packs/palantir/Fleet/Endpoints/packs/*.yaml; do fleetctl apply -f "$pack"; done' +docker exec so-fleet fleetctl apply -f /packs/osquery-config.conf + + +# Enable Fleet +echo "Enabling Fleet..." +salt-call state.apply fleet.event_enable-fleet queue=True >> /root/fleet-setup.log +salt-call state.apply nginx queue=True >> /root/fleet-setup.log + +# Generate osquery install packages +echo "Generating osquery install packages - this will take some time..." +salt-call state.apply fleet.event_gen-packages queue=True >> /root/fleet-setup.log +sleep 120 + +echo "Installing launcher via salt..." +salt-call state.apply fleet.install_package queue=True >> /root/fleet-setup.log +salt-call state.apply filebeat queue=True >> /root/fleet-setup.log +docker stop so-nginx +salt-call state.apply nginx queue=True >> /root/fleet-setup.log + +echo "Fleet Setup Complete - Login with the username and password you ran the script with." diff --git a/salt/firewall/init.sls b/salt/firewall/init.sls index c2ddaf5c2..1f96df882 100644 --- a/salt/firewall/init.sls +++ b/salt/firewall/init.sls @@ -6,7 +6,8 @@ {% elif grains['role'] == 'so-sensor' %} {% set ip = salt['pillar.get']('sensor:mainip', '') %} {% elif grains['role'] == 'so-fleet' %} - {% set ip = salt['pillar.get']('node:mainip', '') %} + {% set MAININT = salt['pillar.get']('host:mainint') %} + {% set ip = salt['grains.get']('ip_interfaces').get(MAININT)[0] %} {% endif %} {% set FLEET_NODE = salt['pillar.get']('static:fleet_node') %} @@ -366,17 +367,6 @@ enable_minions_influxdb_8086_{{ip}}: - position: 1 - save: True -enable_minion_osquery_8080_{{ip}}: - iptables.insert: - - table: filter - - chain: DOCKER-USER - - jump: ACCEPT - - proto: tcp - - source: {{ ip }} - - dport: 8080 - - position: 1 - - save: True - enable_minion_osquery_8090_{{ip}}: iptables.insert: - table: filter @@ -803,7 +793,7 @@ enable_fleet_osquery_8080_{{ip}}: - save: True -enable_fleetnodetemp_mysql_3306_{{ip}}: +enable_fleetnode_mysql_3306_{{ip}}: iptables.insert: - table: filter - chain: DOCKER-USER @@ -814,7 +804,7 @@ enable_fleetnodetemp_mysql_3306_{{ip}}: - position: 1 - save: True -enable_fleettemp_osquery_8080_{{ip}}: +enable_fleet_osquery_8080_{{ip}}: iptables.insert: - table: filter - chain: DOCKER-USER @@ -858,4 +848,20 @@ enable_fleetnode_8090_{{ip}}: {% endfor %} +# Make it so all the minions can talk to fleet standalone node +{% for ip in pillar.get('minions') %} + +enable_minion_fleet_standalone_8090_{{ip}}: + iptables.insert: + - table: filter + - chain: DOCKER-USER + - jump: ACCEPT + - proto: tcp + - source: {{ ip }} + - dport: 8090 + - position: 1 + - save: True + +{% endfor %} + {% endif %} diff --git a/salt/fleet/event_enable-fleet.sls b/salt/fleet/event_enable-fleet.sls index 007f3690c..90bfec2d4 100644 --- a/salt/fleet/event_enable-fleet.sls +++ b/salt/fleet/event_enable-fleet.sls @@ -1,5 +1,6 @@ {% set ENROLLSECRET = salt['cmd.run']('docker exec so-fleet fleetctl get enroll-secret') %} -{%- set MAINIP = salt['pillar.get']('node:mainip') -%} +{% set MAININT = salt['pillar.get']('host:mainint') %} +{% set MAINIP = salt['grains.get']('ip_interfaces').get(MAININT)[0] %} so/fleet: event.send: diff --git a/salt/fleet/event_gen-packages.sls b/salt/fleet/event_gen-packages.sls index 3119ada51..1bdccea48 100644 --- a/salt/fleet/event_gen-packages.sls +++ b/salt/fleet/event_gen-packages.sls @@ -1,15 +1,24 @@ {% set MASTER = salt['grains.get']('master') %} {% set ENROLLSECRET = salt['pillar.get']('secrets:fleet_enroll-secret') %} {% set CURRENTPACKAGEVERSION = salt['pillar.get']('static:fleet_packages-version') %} +{% set VERSION = salt['pillar.get']('static:soversion') %} +{% set CUSTOM_FLEET_HOSTNAME = salt['pillar.get']('static:fleet_custom_hostname', None) %} + +{% if CUSTOM_FLEET_HOSTNAME != None && CUSTOM_FLEET_HOSTNAME != '' %} + {% set HOSTNAME = CUSTOM_FLEET_HOSTNAME %} +{% else %} + {% set HOSTNAME = grains.host %} +{% endif %} so/fleet: event.send: - data: action: 'genpackages' - hostname: {{ grains.host }} + package-hostname: {{ HOSTNAME }} role: {{ grains.role }} mainip: {{ grains.host }} enroll-secret: {{ ENROLLSECRET }} current-package-version: {{ CURRENTPACKAGEVERSION }} master: {{ MASTER }} + version: {{ VERSION }} \ No newline at end of file diff --git a/salt/fleet/event_update-custom-hostname.sls b/salt/fleet/event_update-custom-hostname.sls new file mode 100644 index 000000000..9278862ed --- /dev/null +++ b/salt/fleet/event_update-custom-hostname.sls @@ -0,0 +1,9 @@ +{% set CUSTOM_FLEET_HOSTNAME = salt['pillar.get']('static:fleet_custom_hostname', None) %} + +so/fleet: + event.send: + - data: + action: 'update_custom_hostname' + custom_hostname: {{ CUSTOM_FLEET_HOSTNAME }} + role: {{ grains.role }} + \ No newline at end of file diff --git a/salt/fleet/files/dedicated-index.html b/salt/fleet/files/dedicated-index.html deleted file mode 100644 index 4a27b6104..000000000 --- a/salt/fleet/files/dedicated-index.html +++ /dev/null @@ -1,96 +0,0 @@ -{%- set PACKAGESTS = salt['pillar.get']('static:fleet_packages-timestamp:', 'N/A') -%} - - - - -Security Onion - Hybrid Hunter - - - - - - - -
-
- Fleet - Osquery/Fleet Docs - Security Onion Solutions -
- -
-

-

-

Security Onion - Dedicated Fleet Node

-
-
-
-

-
-
- - diff --git a/salt/fleet/files/packs/PUT.PACKS.IN.HERE b/salt/fleet/files/packs/PUT.PACKS.IN.HERE deleted file mode 100644 index e69de29bb..000000000 diff --git a/salt/fleet/files/packs/hh/hh-post-login.sh b/salt/fleet/files/packs/hh/hh-post-login.sh deleted file mode 100644 index cc787decf..000000000 --- a/salt/fleet/files/packs/hh/hh-post-login.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -echo "Applying Post Configuration for Osquery" -#fleetctl apply -f /packs/hh/osquery.conf -fleetctl apply -f /packs/palantir/Fleet/Endpoints/options.yaml -fleetctl apply -f /packs/palantir/Fleet/Endpoints/MacOS/osquery.yaml -fleetctl apply -f /packs/palantir/Fleet/Endpoints/Windows/osquery.yaml -fleetctl apply -f /packs/hh/hhdefault.yml - -for pack in /packs/palantir/Fleet/Endpoints/packs/*.yaml; - do fleetctl apply -f "$pack" -done -echo "" -echo "You can now exit the container by typing exit" diff --git a/salt/fleet/files/packs/hh/osquery.conf b/salt/fleet/files/packs/osquery-config.conf similarity index 100% rename from salt/fleet/files/packs/hh/osquery.conf rename to salt/fleet/files/packs/osquery-config.conf diff --git a/salt/fleet/files/packs/hh/hhdefault.yml b/salt/fleet/files/packs/so/so-default.yml similarity index 100% rename from salt/fleet/files/packs/hh/hhdefault.yml rename to salt/fleet/files/packs/so/so-default.yml diff --git a/salt/fleet/files/scripts/so-fleet-packages b/salt/fleet/files/scripts/so-fleet-packages deleted file mode 100644 index e68517bde..000000000 --- a/salt/fleet/files/scripts/so-fleet-packages +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -{% set MAIN_HOSTNAME = salt['grains.get']('host') %} -{% set MAIN_IP = salt['pillar.get']('node:mainip') %} - -local_salt_dir=/opt/so/saltstack/local - -#so-fleet-packages $FleetHostname/IP - -#if [ ! "$(docker ps -q -f name=so-fleet)" ]; then -# echo "so-fleet container not running... Exiting..." -# exit 1 -#fi - -#docker exec so-fleet /bin/ash -c "echo {{ MAIN_IP }} {{ MAIN_HOSTNAME }} >> /etc/hosts" -#esecret=$(docker exec so-fleet fleetctl get enroll-secret) - -#Concat fleet.crt & ca.crt - this is required for launcher connectivity -#cat /etc/pki/fleet.crt /etc/pki/ca.crt > /etc/pki/launcher.crt -#Actually only need to use /etc/ssl/certs/intca.crt - -#Create the output directory -#mkdir /opt/so/conf/fleet/packages - -docker run \ - --rm \ - --mount type=bind,source=/opt/so/conf/fleet/packages,target=/output \ - --mount type=bind,source=/etc/ssl/certs/intca.crt,target=/var/launcher/launcher.crt \ - docker.io/soshybridhunter/so-fleet-launcher:HH1.1.0 "$esecret" "$1":8090 - -cp /opt/so/conf/fleet/packages/launcher.* $local_salt_dir/salt/launcher/packages/ - -#Update timestamp on packages webpage -sed -i "s@.*Generated.*@Generated: $(date '+%m%d%Y')@g" /opt/so/conf/fleet/packages/index.html -sed -i "s@.*Generated.*@Generated: $(date '+%m%d%Y')@g" $local_salt_dir/salt/fleet/files/dedicated-index.html \ No newline at end of file diff --git a/salt/fleet/files/scripts/so-fleet-setup b/salt/fleet/files/scripts/so-fleet-setup deleted file mode 100644 index 96ddd5156..000000000 --- a/salt/fleet/files/scripts/so-fleet-setup +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash -{% set MAIN_HOSTNAME = salt['grains.get']('host') %} -{% set MAIN_IP = salt['pillar.get']('node:mainip') %} - -#so-fleet-setup.sh $FleetEmail - -# Enable Fleet -echo "Starting Docker Containers..." -salt-call state.apply mysql queue=True >> /root/fleet-setup.log -salt-call state.apply fleet queue=True >> /root/fleet-setup.log -salt-call state.apply redis queue=True >> /root/fleet-setup.log - -if [ ! "$(docker ps -q -f name=so-fleet)" ]; then - echo "so-fleet container not running... Exiting..." - exit 1 -fi - -initpw=$(date +%s | sha256sum | base64 | head -c 16 ; echo) - -docker exec so-fleet /bin/ash -c "echo {{ MAIN_IP }} {{ MAIN_HOSTNAME }} >> /etc/hosts" -docker exec so-fleet fleetctl config set --address https://{{ MAIN_HOSTNAME }}:443 --tls-skip-verify --url-prefix /fleet -docker exec so-fleet fleetctl setup --email $1 --password $initpw - -docker exec so-fleet fleetctl apply -f /packs/palantir/Fleet/Endpoints/MacOS/osquery.yaml -docker exec so-fleet fleetctl apply -f /packs/palantir/Fleet/Endpoints/Windows/osquery.yaml -docker exec so-fleet fleetctl apply -f /packs/hh/hhdefault.yml -docker exec so-fleet /bin/sh -c 'for pack in /packs/palantir/Fleet/Endpoints/packs/*.yaml; do fleetctl apply -f "$pack"; done' -docker exec so-fleet fleetctl apply -f /packs/hh/osquery.conf - - -# Enable Fleet -echo "Enabling Fleet..." -salt-call state.apply fleet.event_enable-fleet queue=True >> /root/fleet-setup.log -salt-call state.apply nginx queue=True >> /root/fleet-setup.log - -# Generate osquery install packages -echo "Generating osquery install packages - this will take some time..." -salt-call state.apply fleet.event_gen-packages queue=True >> /root/fleet-setup.log -sleep 120 - -echo "Installing launcher via salt..." -salt-call state.apply fleet.install_package queue=True >> /root/fleet-setup.log -salt-call state.apply filebeat queue=True >> /root/fleet-setup.log -docker stop so-nginx -salt-call state.apply nginx queue=True >> /root/fleet-setup.log - -echo "Fleet Setup Complete - Login here: https://{{ MAIN_HOSTNAME }}" -echo "Your username is $2 and your password is $initpw" diff --git a/salt/fleet/init.sls b/salt/fleet/init.sls index 7785a3c20..65f32e213 100644 --- a/salt/fleet/init.sls +++ b/salt/fleet/init.sls @@ -3,12 +3,11 @@ {%- set FLEETJWT = salt['pillar.get']('secrets:fleet_jwt', None) -%} {% set VERSION = salt['pillar.get']('static:soversion', 'HH1.2.2') %} {% set MASTER = salt['grains.get']('master') %} -{% set MAINIP = salt['pillar.get']('node:mainip') %} {% set FLEETARCH = salt['grains.get']('role') %} - {% if FLEETARCH == "so-fleet" %} - {% set MAINIP = salt['pillar.get']('node:mainip') %} + {% set MAININT = salt['pillar.get']('host:mainint') %} + {% set MAINIP = salt['grains.get']('ip_interfaces').get(MAININT)[0] %} {% else %} {% set MAINIP = salt['pillar.get']('static:masterip') %} {% endif %} @@ -16,14 +15,6 @@ include: - mysql -#{% if grains.id.split('_')|last in ['master', 'eval', 'fleet'] %} -#so/fleet: -# event.send: -# - data: -# action: 'enablefleet' -# hostname: {{ grains.host }} -#{% endif %} - # Fleet Setup fleetcdir: file.directory: @@ -67,21 +58,6 @@ fleetlogdir: - group: 939 - makedirs: True -fleetsetupscripts: - file.recurse: - - name: /usr/sbin - - user: 0 - - group: 0 - - file_mode: 755 - - template: jinja - - source: salt://fleet/files/scripts - -osquerypackageswebpage: - file.managed: - - name: /opt/so/conf/fleet/packages/index.html - - source: salt://fleet/files/dedicated-index.html - - template: jinja - fleetdb: mysql_database.present: - name: fleet diff --git a/salt/mysql/init.sls b/salt/mysql/init.sls index f3ce61784..c96be214c 100644 --- a/salt/mysql/init.sls +++ b/salt/mysql/init.sls @@ -6,7 +6,8 @@ {% set FLEETARCH = salt['grains.get']('role') %} {% if FLEETARCH == "so-fleet" %} - {% set MAINIP = salt['pillar.get']('node:mainip') %} + {% set MAININT = salt['pillar.get']('host:mainint') %} + {% set MAINIP = salt['grains.get']('ip_interfaces').get(MAININT)[0] %} {% else %} {% set MAINIP = salt['pillar.get']('static:masterip') %} {% endif %} diff --git a/salt/nginx/etc/nginx.conf.so-fleet b/salt/nginx/etc/nginx.conf.so-fleet index 28372f448..7d6974532 100644 --- a/salt/nginx/etc/nginx.conf.so-fleet +++ b/salt/nginx/etc/nginx.conf.so-fleet @@ -1,4 +1,6 @@ -{%- set MAINIP = salt['pillar.get']('node:mainip', '') %} +{% set MAININT = salt['pillar.get']('host:mainint') %} +{% set MAINIP = salt['grains.get']('ip_interfaces').get(MAININT)[0] %} + # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ diff --git a/salt/reactor/fleet.sls b/salt/reactor/fleet.sls index 759cfaf58..9c8023a71 100644 --- a/salt/reactor/fleet.sls +++ b/salt/reactor/fleet.sls @@ -9,19 +9,19 @@ import subprocess def run(): MINIONID = data['id'] ACTION = data['data']['action'] - HOSTNAME = data['data']['hostname'] - ROLE = data['data']['role'] - ESECRET = data['data']['enroll-secret'] - MAINIP = data['data']['mainip'] local_salt_dir = /opt/so/saltstack/local STATICFILE = local_salt_dir + '/pillar/static.sls' SECRETSFILE = local_salt_dir + '/pillar/secrets.sls' - if MINIONID.split('_')[-1] in ['master','eval','fleet','mastersearch']: - + if MINIONID.split('_')[-1] in ['master','eval','fleet','mastersearch','standalone']: if ACTION == 'enablefleet': logging.info('so/fleet enablefleet reactor') + ESECRET = data['data']['enroll-secret'] + MAINIP = data['data']['mainip'] + ROLE = data['data']['role'] + HOSTNAME = data['data']['hostname'] + # Enable Fleet for line in fileinput.input(STATICFILE, inplace=True): if ROLE == 'so-fleet': @@ -49,15 +49,18 @@ def run(): logging.info('so/fleet genpackages reactor') PACKAGEVERSION = data['data']['current-package-version'] + PACKAGEHOSTNAME = data['data']['package-hostname'] MASTER = data['data']['master'] + VERSION = data['data']['version'] + ESECRET = data['data']['enroll-secret'] # Increment the package version by 1 PACKAGEVERSION += 1 # Run Docker container that will build the packages - gen_packages = subprocess.run(["docker", "run","--rm", "--mount", "type=bind,source=" + local_salt_dir + "/salt/fleet/packages,target=/output", \ - "--mount", "type=bind,source=/etc/ssl/certs/intca.crt,target=/var/launcher/launcher.crt", f"{ MASTER }:5000/soshybridhunter/so-fleet-launcher:HH1.3.0", \ - f"{ESECRET}", f"{HOSTNAME}:8090", f"{PACKAGEVERSION}.1.1"], stdout=subprocess.PIPE, encoding='ascii') + gen_packages = subprocess.run(["docker", "run","--rm", "--mount", "type=bind,ssource=" + local_salt_dir + "/salt/fleet/packages,target=/output", \ + "--mount", "type=bind,source=/etc/ssl/certs/intca.crt,target=/var/launcher/launcher.crt", f"{ MASTER }:5000/soshybridhunter/so-fleet-launcher:{ VERSION }", \ + f"{ESECRET}", f"{PACKAGEHOSTNAME}:8090", f"{PACKAGEVERSION}.1.1"], stdout=subprocess.PIPE, encoding='ascii') # Update the 'packages-built' timestamp on the webpage (stored in the static pillar) for line in fileinput.input(STATICFILE, inplace=True): @@ -70,6 +73,16 @@ def run(): print(line) # Copy over newly-built packages - copy_packages = subprocess.run(["salt-call", "state.apply","fleet"], stdout=subprocess.PIPE, encoding='ascii') + copy_packages = subprocess.run(["salt-call", "state.apply","fleet"], stdout=subprocess.PIPE, encoding='ascii') + + if ACTION == 'update_custom_hostname': + logging.info('so/fleet update_custom_hostname reactor') + + CUSTOMHOSTNAME = data['data']['custom_hostname'] + + # Update the Fleet host in the static pillar + for line in fileinput.input(STATICFILE, inplace=True): + line = re.sub(r'fleet_custom_hostname: \S*', f"fleet_custom_hostname: {CUSTOMHOSTNAME}", line.rstrip()) + print(line) return {} diff --git a/salt/ssl/init.sls b/salt/ssl/init.sls index 064207990..17ac6adf0 100644 --- a/salt/ssl/init.sls +++ b/salt/ssl/init.sls @@ -1,9 +1,11 @@ {% set master = salt['grains.get']('master') %} {% set masterip = salt['pillar.get']('static:masterip', '') %} {% set HOSTNAME = salt['grains.get']('host') %} -{% set MAINIP = salt['pillar.get']('node:mainip') %} {% set global_ca_text = [] %} {% set global_ca_server = [] %} +{% set MAININT = salt['pillar.get']('host:mainint') %} +{% set MAINIP = salt['grains.get']('ip_interfaces').get(MAININT)[0] %} +{% set CUSTOM_FLEET_HOSTNAME = salt['pillar.get']('static:fleet_custom_hostname', None) %} {% if grains.id.split('_')|last in ['master', 'eval', 'standalone'] %} {% set trusttheca_text = salt['mine.get'](grains.id, 'x509.get_pem_entries')[grains.id]['/etc/pki/ca.crt']|replace('\n', '') %} @@ -200,6 +202,7 @@ chownfilebeatp8: - signing_policy: masterssl - public_key: /etc/pki/masterssl.key - CN: {{ HOSTNAME }} + - subjectAltName: DNS:{{ HOSTNAME }}, IP:{{ MAINIP }} {% if CUSTOM_FLEET_HOSTNAME != None %},DNS:{{ CUSTOM_FLEET_HOSTNAME }} {% endif %} - days_remaining: 0 - days_valid: 820 - backup: True @@ -222,7 +225,7 @@ chownfilebeatp8: x509.certificate_managed: - signing_private_key: /etc/pki/fleet.key - CN: {{ HOSTNAME }} - - subjectAltName: DNS:{{ HOSTNAME }}, IP:{{ MAINIP }} + - subjectAltName: DNS:{{ HOSTNAME }}, IP:{{ MAINIP }} {% if CUSTOM_FLEET_HOSTNAME != None %},DNS:{{ CUSTOM_FLEET_HOSTNAME }} {% endif %} - days_remaining: 0 - days_valid: 820 - backup: True diff --git a/setup/so-functions b/setup/so-functions index 0f6f79d1d..fda0398a6 100755 --- a/setup/so-functions +++ b/setup/so-functions @@ -258,6 +258,10 @@ check_soremote_pass() { check_pass_match "$SOREMOTEPASS1" "$SOREMOTEPASS2" "SCMATCH" } +check_fleet_node_pass() { + check_pass_match "$FLEETNODEPASSWD1" "$FLEETNODEPASSWD2" "FPMATCH" +} + check_web_pass() { check_pass_match "$WEBPASSWD1" "$WEBPASSWD2" "WPMATCH" } @@ -295,6 +299,30 @@ collect_adminuser_inputs() { done } +collect_fleet_custom_hostname_inputs() { + whiptail_fleet_custom_hostname +} + +collect_fleetuser_inputs() { + # Get a username & password for the Fleet admin user + local valid_user=no + while [[ $valid_user != yes ]]; do + whiptail_create_fleet_node_user + if so-user valemail "$FLEETNODEUSER" >> "$setup_log" 2>&1; then + valid_user=yes + else + whiptail_invalid_user_warning + fi + done + + FPMATCH=no + while [[ $FPMATCH != yes ]]; do + whiptail_create_fleet_node_user_password1 + whiptail_create_fleet_node_user_password2 + check_fleet_node_pass + done +} + collect_webuser_inputs() { # Get a password for the web admin user @@ -390,6 +418,7 @@ check_requirements() { req_mem=8 req_cores=4 if [[ "$node_type" == 'sensor' ]]; then req_nics=2; else req_nics=1; fi + if [[ "$node_type" == 'fleet' ]]; then req_mem=4; fi fi if [[ $num_nics -lt $req_nics ]]; then @@ -816,6 +845,17 @@ get_minion_type() { echo "$minion_type" } +host_pillar() { + + local pillar_file="$temp_install_dir"/pillar/minions/"$MINION_ID".sls + + # Create the host pillar + printf '%s\n'\ + "host:"\ + " mainint: $MNIC"\ + "" > "$pillar_file" +} + install_cleanup() { echo "Installer removing the following files:" ls -lR "$temp_install_dir" @@ -908,6 +948,7 @@ master_static() { " cortexorgname: SecurityOnion"\ " cortexorguser: soadmin"\ " cortexorguserkey: $CORTEXORGUSERKEY"\ + " fleet_custom_hostname: "\ " fleet_master: False"\ " fleet_node: False"\ " fleet_packages-timestamp: N/A"\ diff --git a/setup/so-setup b/setup/so-setup index 94aad18a0..05aa0de27 100755 --- a/setup/so-setup +++ b/setup/so-setup @@ -145,6 +145,7 @@ elif [ "$install_type" = 'HEAVYNODE' ]; then 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 @@ -152,10 +153,12 @@ fi if [[ $is_eval ]]; then check_requirements "eval" -elif [[ $is_distmaster || $is_minion ]]; then - check_requirements "dist" +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 @@ -256,7 +259,7 @@ if [[ $is_master ]]; then get_redirect fi -if [[ $is_distmaster || ( $is_sensor || $is_node ) && ! $is_eval ]]; then +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 @@ -305,6 +308,14 @@ if [[ $is_node && ! $is_eval ]]; then 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 @@ -341,6 +352,10 @@ if [[ $is_minion ]]; then copy_ssh_key >> $setup_log 2>&1 fi +if [[ $is_fleet_standalone ]]; then + host_pillar >> $setup_log 2>&1 +fi + # Begin install { # Set initial percentage to 0 @@ -500,11 +515,24 @@ fi 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 74 "$(print_salt_state_apply 'redis')" + 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 diff --git a/setup/so-whiptail b/setup/so-whiptail index 1ec1823c9..693e53162 100755 --- a/setup/so-whiptail +++ b/setup/so-whiptail @@ -165,6 +165,38 @@ whiptail_create_admin_user_password2() { } +whiptail_create_fleet_node_user() { + + [ -n "$TESTING" ] && return + + FLEETNODEUSER=$(whiptail --title "Security Onion Install" --inputbox \ + "Please enter an email for use as the username for the Fleet admin user." 10 60 3>&1 1>&2 2>&3) + +} + +whiptail_create_fleet_node_user_password1() { + + [ -n "$TESTING" ] && return + + FLEETNODEPASSWD1=$(whiptail --title "Security Onion Install" --passwordbox \ + "Enter a password for $FLEETNODEUSER" 10 60 3>&1 1>&2 2>&3) + + local exitstatus=$? + whiptail_check_exitstatus $exitstatus +} + +whiptail_create_fleet_node_user_password2() { + + [ -n "$TESTING" ] && return + + FLEETNODEPASSWD2=$(whiptail --title "Security Onion Install" --passwordbox \ + "Re-enter a password for $FLEETNODEUSER" 10 60 3>&1 1>&2 2>&3) + + local exitstatus=$? + whiptail_check_exitstatus $exitstatus + +} + whiptail_create_soremote_user() { [ -n "$TESTING" ] && return @@ -238,6 +270,19 @@ whiptail_create_web_user_password2() { } +whiptail_fleet_custom_hostname() { + + [ -n "$TESTING" ] && return + + FLEETCUSTOMHOSTNAME=$(whiptail --title "Security Onion Install" --inputbox \ + "What FQDN should osquery clients use for connections to this Fleet node? Leave blank if the local system hostname will be used." 10 60 3>&1 1>&2 2>&3) + + local exitstatus=$? + whiptail_check_exitstatus $exitstatus +} + + + whiptail_requirements_error() { local requirement_needed=$1