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
-
-
-
-
-
-
-
-
-
-
-
-
-
-
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