diff --git a/pillar/logstash/master.sls b/pillar/logstash/master.sls index 61d1bb6d1..1ff41b43c 100644 --- a/pillar/logstash/master.sls +++ b/pillar/logstash/master.sls @@ -2,5 +2,6 @@ logstash: pipelines: master: config: + - so/0009_input_beats.conf - so/0010_input_hhbeats.conf - so/9999_output_redis.conf.jinja diff --git a/pillar/logstash/search.sls b/pillar/logstash/search.sls index b4e42a8a3..6b3d0422e 100644 --- a/pillar/logstash/search.sls +++ b/pillar/logstash/search.sls @@ -5,12 +5,12 @@ logstash: - so/0900_input_redis.conf.jinja - so/9000_output_zeek.conf.jinja - so/9002_output_import.conf.jinja + - so/9034_output_syslog.conf.jinja - so/9100_output_osquery.conf.jinja - so/9400_output_suricata.conf.jinja - so/9500_output_beats.conf.jinja - so/9600_output_ossec.conf.jinja - so/9700_output_strelka.conf.jinja templates: - - so/so-beats-template.json - so/so-common-template.json - so/so-zeek-template.json diff --git a/salt/common/init.sls b/salt/common/init.sls index 09d71114b..0ecba198d 100644 --- a/salt/common/init.sls +++ b/salt/common/init.sls @@ -62,6 +62,7 @@ commonpkgs: - python3-dateutil - python3-m2crypto - python3-mysqldb + - git heldpackages: pkg.installed: - pkgs: @@ -96,12 +97,13 @@ commonpkgs: - device-mapper-persistent-data - lvm2 - openssl + - git heldpackages: pkg.installed: - pkgs: - containerd.io: 1.2.13-3.2.el7 - - docker-ce: 3:19.03.9-3.el7 + - docker-ce: 3:19.03.11-3.el7 - hold: True - update_holds: True {% endif %} @@ -128,4 +130,4 @@ utilsyncscripts: - group: 0 - file_mode: 755 - template: jinja - - source: salt://common/tools/sbin \ No newline at end of file + - source: salt://common/tools/sbin diff --git a/salt/common/tools/sbin/so-docker-refresh b/salt/common/tools/sbin/so-docker-refresh new file mode 100644 index 000000000..3c1a2e301 --- /dev/null +++ b/salt/common/tools/sbin/so-docker-refresh @@ -0,0 +1,112 @@ +#!/bin/bash + +# Copyright 2014,2015,2016,2017,2018,2019,2020 Security Onion Solutions, LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +got_root(){ + if [ "$(id -u)" -ne 0 ]; then + echo "This script must be run using sudo!" + exit 1 + fi +} + +master_check() { + # Check to see if this is a master + MASTERCHECK=$(cat /etc/salt/grains | grep role | awk '{print $2}') + if [ $MASTERCHECK == 'so-eval' ] || [ $MASTERCHECK == 'so-master' ] || [ $MASTERCHECK == 'so-mastersearch' ] || [ $MASTERCHECK == 'so-standalone' ] || [ $MASTERCHECK == 'so-helix' ]; then + echo "This is a master. We can proceed" + else + echo "Please run soup on the master. The master controls all updates." + exit 1 + fi +} + +update_docker_containers() { + + # Download the containers from the interwebs + for i in "${TRUSTED_CONTAINERS[@]}" + do + # Pull down the trusted docker image + echo "Downloading $i" + docker pull --disable-content-trust=false docker.io/soshybridhunter/$i + # Tag it with the new registry destination + docker tag soshybridhunter/$i $HOSTNAME:5000/soshybridhunter/$i + docker push $HOSTNAME:5000/soshybridhunter/$i + done + +} + +version_check() { + if [ -f /etc/soversion ]; then + VERSION=$(cat /etc/soversion) + else + echo "Unable to detect version. I will now terminate." + exit 1 + fi +} +got_root +master_check +version_check + +# Use the hostname +HOSTNAME=$(hostname) +BUILD=HH +# List all the containers +if [ $MASTERCHECK != 'so-helix' ]; then + TRUSTED_CONTAINERS=( \ + "so-acng:$BUILD$VERSION" \ + "so-thehive-cortex:$BUILD$VERSION" \ + "so-curator:$BUILD$VERSION" \ + "so-domainstats:$BUILD$VERSION" \ + "so-elastalert:$BUILD$VERSION" \ + "so-elasticsearch:$BUILD$VERSION" \ + "so-filebeat:$BUILD$VERSION" \ + "so-fleet:$BUILD$VERSION" \ + "so-fleet-launcher:$BUILD$VERSION" \ + "so-freqserver:$BUILD$VERSION" \ + "so-grafana:$BUILD$VERSION" \ + "so-idstools:$BUILD$VERSION" \ + "so-influxdb:$BUILD$VERSION" \ + "so-kibana:$BUILD$VERSION" \ + "so-kratos:$BUILD$VERSION" \ + "so-logstash:$BUILD$VERSION" \ + "so-mysql:$BUILD$VERSION" \ + "so-navigator:$BUILD$VERSION" \ + "so-nginx:$BUILD$VERSION" \ + "so-playbook:$BUILD$VERSION" \ + "so-redis:$BUILD$VERSION" \ + "so-soc:$BUILD$VERSION" \ + "so-soctopus:$BUILD$VERSION" \ + "so-steno:$BUILD$VERSION" \ + "so-strelka:$BUILD$VERSION" \ + "so-suricata:$BUILD$VERSION" \ + "so-telegraf:$BUILD$VERSION" \ + "so-thehive:$BUILD$VERSION" \ + "so-thehive-es:$BUILD$VERSION" \ + "so-wazuh:$BUILD$VERSION" \ + "so-zeek:$BUILD$VERSION" ) + else + TRUSTED_CONTAINERS=( \ + "so-filebeat:$BUILD$VERSION" \ + "so-idstools:$BUILD$VERSION" \ + "so-logstash:$BUILD$VERSION" \ + "so-nginx:$BUILD$VERSION" \ + "so-redis:$BUILD$VERSION" \ + "so-steno:$BUILD$VERSION" \ + "so-suricata:$BUILD$VERSION" \ + "so-telegraf:$BUILD$VERSION" \ + "so-zeek:$BUILD$VERSION" ) + fi + +update_docker_containers \ No newline at end of file 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/common/tools/sbin/so-saltstack-update b/salt/common/tools/sbin/so-saltstack-update new file mode 100644 index 000000000..d4e380b61 --- /dev/null +++ b/salt/common/tools/sbin/so-saltstack-update @@ -0,0 +1,57 @@ +#!/bin/bash + +# Copyright 2014,2015,2016,2017,2018,2019,2020 Security Onion Solutions, LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +default_salt_dir=/opt/so/saltstack/default +clone_to_tmp() { + + # TODO Need to add a air gap option + # Make a temp location for the files + mkdir /tmp/sogh + cd /tmp/sogh + #git clone -b dev https://github.com/Security-Onion-Solutions/securityonion-saltstack.git + git clone https://github.com/Security-Onion-Solutions/securityonion-saltstack.git + cd /tmp + +} + +copy_new_files() { + + # Copy new files over to the salt dir + cd /tmp/sogh/securityonion-saltstack + git checkout $BRANCH + rsync -a --exclude-from 'exclude-list.txt' salt $default_salt_dir/ + rsync -a --exclude-from 'exclude-list.txt' pillar $default_salt_dir/ + chown -R socore:socore $default_salt_dir/salt + chown -R socore:socore $default_salt_dir/pillar + chmod 755 $default_salt_dir/pillar/firewall/addfirewall.sh + rm -rf /tmp/sogh +} + +got_root(){ + if [ "$(id -u)" -ne 0 ]; then + echo "This script must be run using sudo!" + exit 1 + fi +} + +got_root +if [ $# -ne 1 ] ; then + BRANCH=master +else + BRANCH=$1 +fi +clone_to_tmp +copy_new_files \ No newline at end of file diff --git a/salt/curator/init.sls b/salt/curator/init.sls index d064b9f20..37b4fac87 100644 --- a/salt/curator/init.sls +++ b/salt/curator/init.sls @@ -89,7 +89,7 @@ curdel: so-curatorcloseddeletecron: cron.present: - - name: /usr/sbin/so-curator-closed-delete + - name: /usr/sbin/so-curator-closed-delete > /opt/so/log/curator/cron-closed-delete.log 2>&1 - user: root - minute: '*' - hour: '*' @@ -99,7 +99,7 @@ so-curatorcloseddeletecron: so-curatorclosecron: cron.present: - - name: /usr/sbin/so-curator-close + - name: /usr/sbin/so-curator-close > /opt/so/log/curator/cron-close.log 2>&1 - user: root - minute: '*' - hour: '*' @@ -109,7 +109,7 @@ so-curatorclosecron: so-curatordeletecron: cron.present: - - name: /usr/sbin/so-curator-delete + - name: /usr/sbin/so-curator-delete > /opt/so/log/curator/cron-delete.log 2>&1 - user: root - minute: '*' - hour: '*' diff --git a/salt/elasticsearch/files/ingest/beats.common b/salt/elasticsearch/files/ingest/beats.common new file mode 100644 index 000000000..0e93abb03 --- /dev/null +++ b/salt/elasticsearch/files/ingest/beats.common @@ -0,0 +1,35 @@ +{ + "description" : "beats.common", + "processors" : [ + {"community_id": {"if": "ctx.winlog.event_data?.Protocol != null", "field":["winlog.event_data.SourceIp","winlog.event_data.SourcePort","winlog.event_data.DestinationIp","winlog.event_data.DestinationPort","winlog.event_data.Protocol"],"target_field":"network.community_id"}}, + { "set": { "if": "ctx.winlog?.channel != null", "field": "dataset", "value": "wel-{{winlog.channel}}", "override": true } }, + { "set": { "if": "ctx.agent?.type != null", "field": "module", "value": "{{agent.type}}", "override": true } }, + { "set": { "if": "ctx.winlog?.channel == 'Microsoft-Windows-Sysmon/Operational' && ctx.event?.code == 3", "field": "event.category", "value": "host,process,network", "override": true } }, + { "set": { "if": "ctx.winlog?.channel == 'Microsoft-Windows-Sysmon/Operational' && ctx.event?.code == 1", "field": "event.category", "value": "host,process", "override": true } }, + { "rename": { "field": "agent.hostname", "target_field": "agent.name", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.SubjectUserName", "target_field": "user.name", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.DestinationHostname", "target_field": "destination.hostname", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.DestinationIp", "target_field": "destination.ip", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.DestinationPort", "target_field": "destination.port", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.Image", "target_field": "process.executable", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.ProcessID", "target_field": "process.pid", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.ProcessGuid", "target_field": "process.entity_id", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.CommandLine", "target_field": "process.command_line", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.CurrentDirectory", "target_field": "process.working_directory", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.Description", "target_field": "process.pe.description", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.Product", "target_field": "process.pe.product", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.OriginalFileName", "target_field": "process.pe.original_file_name", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.FileVersion", "target_field": "process.pe.file_version", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.ParentCommandLine", "target_field": "process.parent.command_line", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.ParentImage", "target_field": "process.parent.executable", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.ParentProcessGuid", "target_field": "process.parent.entity_id", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.ParentProcessId", "target_field": "process.ppid", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.Protocol", "target_field": "network.transport", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.User", "target_field": "user.name", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.SourceHostname", "target_field": "source.hostname", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.SourceIp", "target_field": "source.ip", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.SourcePort", "target_field": "source.port", "ignore_missing": true } }, + { "rename": { "field": "winlog.event_data.targetFilename", "target_field": "file.target", "ignore_missing": true } }, + { "pipeline": { "name": "common" } } + ] +} \ No newline at end of file diff --git a/salt/elasticsearch/files/ingest/syslog b/salt/elasticsearch/files/ingest/syslog index d34e79d4a..1af0bc1c8 100644 --- a/salt/elasticsearch/files/ingest/syslog +++ b/salt/elasticsearch/files/ingest/syslog @@ -6,6 +6,10 @@ "field": "message", "pattern" : "%{message}", "on_failure": [ { "drop" : { } } ] + }, + "remove": { + "field": [ "type", "agent" ], + "ignore_failure": true } }, { "pipeline": { "name": "common" } } diff --git a/salt/filebeat/etc/filebeat.yml b/salt/filebeat/etc/filebeat.yml index be04effb0..76c26b51d 100644 --- a/salt/filebeat/etc/filebeat.yml +++ b/salt/filebeat/etc/filebeat.yml @@ -75,10 +75,10 @@ filebeat.modules: filebeat.inputs: #------------------------------ Log prospector -------------------------------- {%- if grains['role'] == 'so-sensor' or grains['role'] == "so-eval" or grains['role'] == "so-helix" or grains['role'] == "so-heavynode" or grains['role'] == "so-standalone" %} - - type: syslog + + - type: udp enabled: true - protocol.udp: - host: "0.0.0.0:514" + host: "0.0.0.0:514" fields: module: syslog dataset: syslog @@ -87,7 +87,20 @@ filebeat.inputs: processors: - drop_fields: fields: ["source", "prospector", "input", "offset", "beat"] + fields_under_root: true + - type: tcp + enabled: true + host: "0.0.0.0:514" + fields: + module: syslog + dataset: syslog + pipeline: "syslog" + index: "so-syslog-%{+yyyy.MM.dd}" + processors: + - drop_fields: + fields: ["source", "prospector", "input", "offset", "beat"] + fields_under_root: true {%- if BROVER != 'SURICATA' %} {%- for LOGNAME in salt['pillar.get']('brologs:enabled', '') %} - type: log 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/idstools/init.sls b/salt/idstools/init.sls index 9bda4dd58..d145a4e15 100644 --- a/salt/idstools/init.sls +++ b/salt/idstools/init.sls @@ -39,7 +39,7 @@ idstoolsetcsync: so-ruleupdatecron: cron.present: - - name: /usr/sbin/so-rule-update.sh > /opt/so/log/idstools/download.log + - name: /usr/sbin/so-rule-update > /opt/so/log/idstools/download.log 2>&1 - user: root - minute: '1' - hour: '7' diff --git a/salt/logstash/pipelines/config/so/0009_input_beats.conf b/salt/logstash/pipelines/config/so/0009_input_beats.conf new file mode 100644 index 000000000..a5c1d491c --- /dev/null +++ b/salt/logstash/pipelines/config/so/0009_input_beats.conf @@ -0,0 +1,6 @@ +input { + beats { + port => "5044" + tags => [ "beat-ext" ] + } +} \ No newline at end of file diff --git a/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja b/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja index 35d3cf7dc..7b35af576 100644 --- a/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja +++ b/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja @@ -3,24 +3,21 @@ {%- else %} {%- set ES = salt['pillar.get']('node:mainip', '') -%} {%- endif %} -# Author: Justin Henderson -# SANS Instructor and author of SANS SEC555: SIEM and Tactical Analytics -# Updated by: Doug Burks -# Last Update: 5/15/2017 filter { - if "syslog" in [tags] and "test_data" not in [tags] { + if [module] =~ "syslog" { mutate { - ##add_tag => [ "conf_file_9034"] - } + ##add_tag => [ "conf_file_9000"] + } } } output { - if "syslog" in [tags] and "test_data" not in [tags] { + if [module] =~ "syslog" { elasticsearch { + pipeline => "%{module}" hosts => "{{ ES }}" index => "so-syslog-%{+YYYY.MM.dd}" - template_name => "logstash" + template_name => "so-common" template => "/so-common-template.json" template_overwrite => true } diff --git a/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja b/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja index dcfefa852..e50c04eee 100644 --- a/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja +++ b/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja @@ -3,22 +3,15 @@ {%- else %} {%- set ES = salt['pillar.get']('node:mainip', '') -%} {%- endif %} -# Author: Wes Lambert -# Last Update: 09/14/2018 -filter { - if "beat" in [tags] { - mutate { - ##add_tag => [ "conf_file_9500"] - } - } -} + output { - if "beat" in [tags] { + if "beat-ext" in [tags] { elasticsearch { + pipeline => "beats.common" hosts => "{{ ES }}" index => "so-beats-%{+YYYY.MM.dd}" - template_name => "so-beats" - template => "/so-beats-template.json" + template_name => "so-common" + template => "/so-common-template.json" template_overwrite => true } } diff --git a/salt/logstash/pipelines/templates/so/so-beats-template.json b/salt/logstash/pipelines/templates/so/so-beats-template.json deleted file mode 100644 index 858f1d5e5..000000000 --- a/salt/logstash/pipelines/templates/so/so-beats-template.json +++ /dev/null @@ -1,1286 +0,0 @@ -{ - "index_patterns": [ - "so-beats-*" - ], - "mappings": { - "_meta": { - "version": "6.1.3" - }, - "date_detection": false, - "dynamic_templates": [ - { - "fields": { - "mapping": { - "type": "keyword" - }, - "match_mapping_type": "string", - "path_match": "fields.*" - } - }, - { - "docker.container.labels": { - "mapping": { - "type": "keyword" - }, - "match_mapping_type": "string", - "path_match": "docker.container.labels.*" - } - }, - { - "strings_as_keyword": { - "mapping": { - "ignore_above": 1024, - "type": "keyword" - }, - "match_mapping_type": "string" - } - } - ], - "properties": { - "@timestamp": { - "type": "date" - }, - "event_data": { - "type":"object", - "dynamic": true - }, - "beat_host": { - "type":"object", - "dynamic": true - }, - "activity_id": { - "ignore_above": 1024, - "type": "keyword" - }, - "beat": { - "properties": { - "hostname": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "timezone": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "username":{ - "type":"text", - "fields": { - "keyword":{ - "type":"keyword" - } - } - }, - "computer_name": { - "type": "text", - "fields":{ - "keyword":{ - "type":"keyword" - } - } - }, - "docker": { - "properties": { - "container": { - "properties": { - "id": { - "ignore_above": 1024, - "type": "keyword" - }, - "image": { - "ignore_above": 1024, - "type": "keyword" - }, - "labels": { - "type": "object" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "error": { - "properties": { - "code": { - "type": "long" - }, - "message": { - "norms": false, - "type": "text" - }, - "type": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "event_id": { - "type": "long" - }, - "fields": { - "type": "object" - }, - "keywords": { - "ignore_above": 1024, - "type": "keyword" - }, - "kubernetes": { - "properties": { - "annotations": { - "type": "object" - }, - "container": { - "properties": { - "image": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "labels": { - "type": "object" - }, - "namespace": { - "ignore_above": 1024, - "type": "keyword" - }, - "pod": { - "properties": { - "name": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "level": { - "ignore_above": 1024, - "type": "keyword" - }, - "log_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "norms": false, - "type": "text" - }, - "message_error": { - "ignore_above": 1024, - "type": "keyword" - }, - "meta": { - "properties": { - "cloud": { - "properties": { - "availability_zone": { - "ignore_above": 1024, - "type": "keyword" - }, - "instance_id": { - "ignore_above": 1024, - "type": "keyword" - }, - "instance_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "machine_type": { - "ignore_above": 1024, - "type": "keyword" - }, - "project_id": { - "ignore_above": 1024, - "type": "keyword" - }, - "provider": { - "ignore_above": 1024, - "type": "keyword" - }, - "region": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "opcode": { - "ignore_above": 1024, - "type": "keyword" - }, - "process_id": { - "type": "long" - }, - "provider_guid": { - "ignore_above": 1024, - "type": "keyword" - }, - "record_number": { - "ignore_above": 1024, - "type": "keyword" - }, - "related_activity_id": { - "ignore_above": 1024, - "type": "keyword" - }, - "source_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "tags": { - "ignore_above": 1024, - "type": "keyword" - }, - "task": { - "ignore_above": 1024, - "type": "keyword" - }, - "thread_id": { - "type": "long" - }, - "type": { - "ignore_above": 1024, - "type": "keyword" - }, - "user": { - "properties": { - "domain": { - "type": "keyword" - }, - "identifier": { - "type": "keyword" - }, - "name": { - "type": "keyword" - }, - "type": { - "type": "keyword" - } - } - }, - "user_data": { - "type": "object", - "dynamic": "true" - }, - "version": { - "type": "keyword" - }, - "xml": { - "norms": false, - "type": "text" - }, - "apache2": { - "properties": { - "access": { - "properties": { - "agent": { - "norms": false, - "type": "text" - }, - "body_sent": { - "properties": { - "bytes": { - "type": "long" - } - } - }, - "geoip": { - "properties": { - "city_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "continent_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "country_iso_code": { - "ignore_above": 1024, - "type": "keyword" - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "http_version": { - "ignore_above": 1024, - "type": "keyword" - }, - "method": { - "ignore_above": 1024, - "type": "keyword" - }, - "referrer": { - "ignore_above": 1024, - "type": "keyword" - }, - "remote_ip": { - "ignore_above": 1024, - "type": "keyword" - }, - "response_code": { - "type": "long" - }, - "url": { - "ignore_above": 1024, - "type": "keyword" - }, - "user_agent": { - "properties": { - "device": { - "ignore_above": 1024, - "type": "keyword" - }, - "major": { - "type": "long" - }, - "minor": { - "type": "long" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "os": { - "ignore_above": 1024, - "type": "keyword" - }, - "os_major": { - "type": "long" - }, - "os_minor": { - "type": "long" - }, - "os_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "patch": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "user_name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "error": { - "properties": { - "client": { - "ignore_above": 1024, - "type": "keyword" - }, - "code": { - "type": "long" - }, - "level": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "norms": false, - "type": "text" - }, - "module": { - "ignore_above": 1024, - "type": "keyword" - }, - "pid": { - "type": "long" - }, - "tid": { - "type": "long" - }, - "type": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "auditd": { - "properties": { - "log": { - "properties": { - "a0": { - "ignore_above": 1024, - "type": "keyword" - }, - "acct": { - "ignore_above": 1024, - "type": "keyword" - }, - "geoip": { - "properties": { - "city_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "continent_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "country_iso_code": { - "ignore_above": 1024, - "type": "keyword" - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "item": { - "ignore_above": 1024, - "type": "keyword" - }, - "items": { - "ignore_above": 1024, - "type": "keyword" - }, - "new_auid": { - "ignore_above": 1024, - "type": "keyword" - }, - "new_ses": { - "ignore_above": 1024, - "type": "keyword" - }, - "old_auid": { - "ignore_above": 1024, - "type": "keyword" - }, - "old_ses": { - "ignore_above": 1024, - "type": "keyword" - }, - "pid": { - "ignore_above": 1024, - "type": "keyword" - }, - "ppid": { - "ignore_above": 1024, - "type": "keyword" - }, - "record_type": { - "ignore_above": 1024, - "type": "keyword" - }, - "res": { - "ignore_above": 1024, - "type": "keyword" - }, - "sequence": { - "type": "long" - } - } - } - } - }, - "fileset": { - "properties": { - "module": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "icinga": { - "properties": { - "debug": { - "properties": { - "facility": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "norms": false, - "type": "text" - }, - "severity": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "main": { - "properties": { - "facility": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "norms": false, - "type": "text" - }, - "severity": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "startup": { - "properties": { - "facility": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "norms": false, - "type": "text" - }, - "severity": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "kafka": { - "properties": { - "log": { - "properties": { - "class": { - "norms": false, - "type": "text" - }, - "component": { - "ignore_above": 1024, - "type": "keyword" - }, - "level": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "norms": false, - "type": "text" - }, - "timestamp": { - "ignore_above": 1024, - "type": "keyword" - }, - "trace": { - "properties": { - "class": { - "ignore_above": 1024, - "type": "keyword" - }, - "full": { - "norms": false, - "type": "text" - }, - "message": { - "norms": false, - "type": "text" - } - } - } - } - } - } - }, - "logstash": { - "properties": { - "log": { - "properties": { - "level": { - "ignore_above": 1024, - "type": "keyword" - }, - "log_event": { - "type": "object" - }, - "message": { - "norms": false, - "type": "text" - }, - "module": { - "ignore_above": 1024, - "type": "keyword" - }, - "thread": { - "norms": false, - "type": "text" - } - } - }, - "slowlog": { - "properties": { - "event": { - "norms": false, - "type": "text" - }, - "level": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "norms": false, - "type": "text" - }, - "module": { - "ignore_above": 1024, - "type": "keyword" - }, - "plugin_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "plugin_params": { - "norms": false, - "type": "text" - }, - "plugin_params_object": { - "type": "object" - }, - "plugin_type": { - "ignore_above": 1024, - "type": "keyword" - }, - "thread": { - "norms": false, - "type": "text" - }, - "took_in_millis": { - "type": "long" - }, - "took_in_nanos": { - "type": "long" - } - } - } - } - }, - "mysql": { - "properties": { - "error": { - "properties": { - "level": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "norms": false, - "type": "text" - }, - "thread_id": { - "type": "long" - }, - "timestamp": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "slowlog": { - "properties": { - "host": { - "ignore_above": 1024, - "type": "keyword" - }, - "id": { - "type": "long" - }, - "ip": { - "ignore_above": 1024, - "type": "keyword" - }, - "lock_time": { - "properties": { - "sec": { - "type": "float" - } - } - }, - "query": { - "ignore_above": 1024, - "type": "keyword" - }, - "query_time": { - "properties": { - "sec": { - "type": "float" - } - } - }, - "rows_examined": { - "type": "long" - }, - "rows_sent": { - "type": "long" - }, - "timestamp": { - "type": "long" - }, - "user": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "nginx": { - "properties": { - "access": { - "properties": { - "agent": { - "norms": false, - "type": "text" - }, - "body_sent": { - "properties": { - "bytes": { - "type": "long" - } - } - }, - "geoip": { - "properties": { - "city_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "continent_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "country_iso_code": { - "ignore_above": 1024, - "type": "keyword" - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "http_version": { - "ignore_above": 1024, - "type": "keyword" - }, - "method": { - "ignore_above": 1024, - "type": "keyword" - }, - "referrer": { - "ignore_above": 1024, - "type": "keyword" - }, - "remote_ip": { - "ignore_above": 1024, - "type": "keyword" - }, - "response_code": { - "type": "long" - }, - "url": { - "ignore_above": 1024, - "type": "keyword" - }, - "user_agent": { - "properties": { - "device": { - "ignore_above": 1024, - "type": "keyword" - }, - "major": { - "type": "long" - }, - "minor": { - "type": "long" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "os": { - "ignore_above": 1024, - "type": "keyword" - }, - "os_major": { - "type": "long" - }, - "os_minor": { - "type": "long" - }, - "os_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "patch": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "user_name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "error": { - "properties": { - "connection_id": { - "type": "long" - }, - "level": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "norms": false, - "type": "text" - }, - "pid": { - "type": "long" - }, - "tid": { - "type": "long" - } - } - } - } - }, - "offset": { - "type": "long" - }, - "postgresql": { - "properties": { - "log": { - "properties": { - "database": { - "ignore_above": 1024, - "type": "keyword" - }, - "duration": { - "type": "float" - }, - "level": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "norms": false, - "type": "text" - }, - "query": { - "ignore_above": 1024, - "type": "keyword" - }, - "thread_id": { - "type": "long" - }, - "timestamp": { - "ignore_above": 1024, - "type": "keyword" - }, - "timezone": { - "ignore_above": 1024, - "type": "keyword" - }, - "user": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "prospector": { - "properties": { - "type": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "read_timestamp": { - "ignore_above": 1024, - "type": "keyword" - }, - "redis": { - "properties": { - "log": { - "properties": { - "level": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "norms": false, - "type": "text" - }, - "pid": { - "type": "long" - }, - "role": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "slowlog": { - "properties": { - "args": { - "ignore_above": 1024, - "type": "keyword" - }, - "cmd": { - "ignore_above": 1024, - "type": "keyword" - }, - "duration": { - "properties": { - "us": { - "type": "long" - } - } - }, - "id": { - "type": "long" - }, - "key": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "stream": { - "ignore_above": 1024, - "type": "keyword" - }, - "system": { - "properties": { - "auth": { - "properties": { - "groupadd": { - "properties": { - "gid": { - "type": "long" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "hostname": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "ignore_above": 1024, - "type": "keyword" - }, - "pid": { - "type": "long" - }, - "program": { - "ignore_above": 1024, - "type": "keyword" - }, - "ssh": { - "properties": { - "dropped_ip": { - "type": "ip" - }, - "event": { - "ignore_above": 1024, - "type": "keyword" - }, - "geoip": { - "properties": { - "city_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "continent_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "country_iso_code": { - "ignore_above": 1024, - "type": "keyword" - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "ip": { - "type": "ip" - }, - "method": { - "ignore_above": 1024, - "type": "keyword" - }, - "port": { - "type": "long" - }, - "signature": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "sudo": { - "properties": { - "command": { - "ignore_above": 1024, - "type": "keyword" - }, - "error": { - "ignore_above": 1024, - "type": "keyword" - }, - "pwd": { - "ignore_above": 1024, - "type": "keyword" - }, - "tty": { - "ignore_above": 1024, - "type": "keyword" - }, - "user": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "timestamp": { - "ignore_above": 1024, - "type": "keyword" - }, - "user": { - "ignore_above": 1024, - "type": "keyword" - }, - "useradd": { - "properties": { - "gid": { - "type": "long" - }, - "home": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "shell": { - "ignore_above": 1024, - "type": "keyword" - }, - "uid": { - "type": "long" - } - } - } - } - }, - "syslog": { - "properties": { - "hostname": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "ignore_above": 1024, - "type": "keyword" - }, - "pid": { - "ignore_above": 1024, - "type": "keyword" - }, - "program": { - "ignore_above": 1024, - "type": "keyword" - }, - "timestamp": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "traefik": { - "properties": { - "access": { - "properties": { - "agent": { - "norms": false, - "type": "text" - }, - "backend_url": { - "norms": false, - "type": "text" - }, - "body_sent": { - "properties": { - "bytes": { - "type": "long" - } - } - }, - "frontend_name": { - "norms": false, - "type": "text" - }, - "geoip": { - "properties": { - "city_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "continent_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "country_iso_code": { - "ignore_above": 1024, - "type": "keyword" - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "http_version": { - "ignore_above": 1024, - "type": "keyword" - }, - "method": { - "ignore_above": 1024, - "type": "keyword" - }, - "referrer": { - "ignore_above": 1024, - "type": "keyword" - }, - "remote_ip": { - "ignore_above": 1024, - "type": "keyword" - }, - "request_count": { - "type": "long" - }, - "response_code": { - "type": "long" - }, - "url": { - "ignore_above": 1024, - "type": "keyword" - }, - "user_agent": { - "properties": { - "device": { - "ignore_above": 1024, - "type": "keyword" - }, - "major": { - "type": "long" - }, - "minor": { - "type": "long" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "os": { - "ignore_above": 1024, - "type": "keyword" - }, - "os_major": { - "type": "long" - }, - "os_minor": { - "type": "long" - }, - "os_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "patch": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "user_name": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - } - } - }, - "order": 1, - "settings": { - "index": { - "mapping": { - "total_fields": { - "limit": 10000 - } - }, - "number_of_replicas": 0, - "number_of_shards": 1, - "refresh_interval": "30s" - } - } -} diff --git a/salt/master/init.sls b/salt/master/init.sls index 4dab12a68..3c6b81e5e 100644 --- a/salt/master/init.sls +++ b/salt/master/init.sls @@ -61,6 +61,7 @@ so-aptcacherng: docker_container.running: - image: {{ MASTER }}:5000/soshybridhunter/so-acng:{{ VERSION }} - hostname: so-acng + - restart_policy: always - port_bindings: - 0.0.0.0:3142:3142 - binds: 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-eval b/salt/nginx/etc/nginx.conf.so-eval index 579e5730f..193932ade 100644 --- a/salt/nginx/etc/nginx.conf.so-eval +++ b/salt/nginx/etc/nginx.conf.so-eval @@ -136,7 +136,7 @@ http { proxy_set_header X-Forwarded-Proto $scheme; } - location ~ ^/auth/.*?(whoami|login|logout) { + location ~ ^/auth/.*?(whoami|login|logout|settings) { rewrite /auth/(.*) /$1 break; proxy_pass http://{{ masterip }}:4433; proxy_read_timeout 90; diff --git a/salt/nginx/etc/nginx.conf.so-fleet b/salt/nginx/etc/nginx.conf.so-fleet index 2374af4f9..c4144447c 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/nginx/etc/nginx.conf.so-master b/salt/nginx/etc/nginx.conf.so-master index 4eaca57e7..64e1fa7d6 100644 --- a/salt/nginx/etc/nginx.conf.so-master +++ b/salt/nginx/etc/nginx.conf.so-master @@ -136,7 +136,7 @@ http { proxy_set_header X-Forwarded-Proto $scheme; } - location ~ ^/auth/.*?(whoami|login|logout) { + location ~ ^/auth/.*?(whoami|login|logout|settings) { rewrite /auth/(.*) /$1 break; proxy_pass http://{{ masterip }}:4433; proxy_read_timeout 90; diff --git a/salt/nginx/etc/nginx.conf.so-mastersearch b/salt/nginx/etc/nginx.conf.so-mastersearch index 4eaca57e7..64e1fa7d6 100644 --- a/salt/nginx/etc/nginx.conf.so-mastersearch +++ b/salt/nginx/etc/nginx.conf.so-mastersearch @@ -136,7 +136,7 @@ http { proxy_set_header X-Forwarded-Proto $scheme; } - location ~ ^/auth/.*?(whoami|login|logout) { + location ~ ^/auth/.*?(whoami|login|logout|settings) { rewrite /auth/(.*) /$1 break; proxy_pass http://{{ masterip }}:4433; proxy_read_timeout 90; diff --git a/salt/nginx/etc/nginx.conf.so-standalone b/salt/nginx/etc/nginx.conf.so-standalone index 4eaca57e7..64e1fa7d6 100644 --- a/salt/nginx/etc/nginx.conf.so-standalone +++ b/salt/nginx/etc/nginx.conf.so-standalone @@ -136,7 +136,7 @@ http { proxy_set_header X-Forwarded-Proto $scheme; } - location ~ ^/auth/.*?(whoami|login|logout) { + location ~ ^/auth/.*?(whoami|login|logout|settings) { rewrite /auth/(.*) /$1 break; proxy_pass http://{{ masterip }}:4433; proxy_read_timeout 90; diff --git a/salt/playbook/init.sls b/salt/playbook/init.sls index a5242f561..fec93b71e 100644 --- a/salt/playbook/init.sls +++ b/salt/playbook/init.sls @@ -86,15 +86,22 @@ so-playbook: {% endif %} +playbooklogdir: + file.directory: + - name: /opt/so/log/playbook + - user: 939 + - group: 939 + - makedirs: True + so-playbooksynccron: cron.present: - - name: /usr/sbin/so-playbook-sync + - name: /usr/sbin/so-playbook-sync > /opt/so/log/playbook/sync.log 2>&1 - user: root - minute: '*/5' so-playbookruleupdatecron: cron.present: - - name: /usr/sbin/so-playbook-ruleupdate + - name: /usr/sbin/so-playbook-ruleupdate > /opt/so/log/playbook/update.log 2>&1 - user: root - minute: '1' - hour: '6' \ No newline at end of file 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/registry/init.sls b/salt/registry/init.sls index ed56d25ae..9ee44d1de 100644 --- a/salt/registry/init.sls +++ b/salt/registry/init.sls @@ -42,6 +42,7 @@ so-dockerregistry: docker_container.running: - image: registry:2 - hostname: so-registry + - restart_policy: always - port_bindings: - 0.0.0.0:5000:5000 - binds: diff --git a/salt/sensoroni/files/sensoroni.json b/salt/sensoroni/files/sensoroni.json deleted file mode 100644 index d53fe0a66..000000000 --- a/salt/sensoroni/files/sensoroni.json +++ /dev/null @@ -1,25 +0,0 @@ -{%- set MASTERIP = salt['pillar.get']('static:masterip', '') -%} -{%- set SENSORONIKEY = salt['pillar.get']('static:sensoronikey', '') -%} -{ - "logFilename": "/opt/sensoroni/logs/sensoroni-server.log", - "server": { - "bindAddress": "0.0.0.0:9822", - "maxPacketCount": 5000, - "htmlDir": "html", - "modules": { - "filedatastore": { - "jobDir": "jobs" - }, - "securityonion": { - "elasticsearchHost": "http://{{ MASTERIP }}:9200", - "elasticsearchUsername": "", - "elasticsearchPassword": "", - "elasticsearchVerifyCert": false - }, - "statickeyauth": { - "anonymousCidr": "172.17.0.0/24", - "apiKey": "{{ SENSORONIKEY }}" - } - } - } -} diff --git a/salt/sensoroni/init.sls b/salt/sensoroni/init.sls deleted file mode 100644 index 441394df6..000000000 --- a/salt/sensoroni/init.sls +++ /dev/null @@ -1,45 +0,0 @@ -{% set VERSION = salt['pillar.get']('static:soversion', 'HH1.2.2') %} -{% set MASTER = salt['grains.get']('master') %} - -sensoronidir: - file.directory: - - name: /opt/so/conf/sensoroni - - user: 939 - - group: 939 - - makedirs: True - -sensoronidatadir: - file.directory: - - name: /nsm/sensoroni/jobs - - user: 939 - - group: 939 - - makedirs: True - -sensoronilogdir: - file.directory: - - name: /opt/so/log/sensoroni - - user: 939 - - group: 939 - - makedirs: True - -sensoronisync: - file.recurse: - - name: /opt/so/conf/sensoroni - - source: salt://sensoroni/files - - user: 939 - - group: 939 - - template: jinja - -so-sensoroni: - docker_container.running: - - image: {{ MASTER }}:5000/soshybridhunter/so-sensoroni:{{ VERSION }} - - hostname: sensoroni - - name: so-sensoroni - - binds: - - /nsm/sensoroni/jobs:/opt/sensoroni/jobs:rw - - /opt/so/conf/sensoroni/sensoroni.json:/opt/sensoroni/sensoroni.json:ro - - /opt/so/log/sensoroni/:/opt/sensoroni/logs/:rw - - port_bindings: - - 0.0.0.0:9822:9822 - - watch: - - file: /opt/so/conf/sensoroni diff --git a/salt/soc/files/kratos/kratos.yaml b/salt/soc/files/kratos/kratos.yaml index e5a970557..7939ec35b 100644 --- a/salt/soc/files/kratos/kratos.yaml +++ b/salt/soc/files/kratos/kratos.yaml @@ -42,7 +42,7 @@ urls: login_ui: https://{{ WEBACCESS }}/login/ registration_ui: https://{{ WEBACCESS }}/login/ error_ui: https://{{ WEBACCESS }}/login/ - settings_ui: https://{{ WEBACCESS }}/ + settings_ui: https://{{ WEBACCESS }}/?r=/settings verify_ui: https://{{ WEBACCESS }}/ mfa_ui: https://{{ WEBACCESS }}/ 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/salt/wazuh/init.sls b/salt/wazuh/init.sls index 54db40787..c483f07a0 100644 --- a/salt/wazuh/init.sls +++ b/salt/wazuh/init.sls @@ -80,11 +80,6 @@ wazuhmgrwhitelist: - mode: 755 - template: jinja -wazuhagentservice: - service.running: - - name: wazuh-agent - - enable: True - so-wazuh: docker_container.running: - image: {{ MASTER }}:5000/soshybridhunter/so-wazuh:{{ VERSION }} @@ -110,3 +105,8 @@ whitelistmanager: cmd.run: - name: /usr/sbin/wazuh-manager-whitelist - cwd: / + +wazuhagentservice: + service.running: + - name: wazuh-agent + - enable: True diff --git a/salt/zeek/cron/packetloss.sh b/salt/zeek/cron/packetloss.sh index 51812edf5..c8750dd92 100755 --- a/salt/zeek/cron/packetloss.sh +++ b/salt/zeek/cron/packetloss.sh @@ -1,2 +1,2 @@ #!/bin/bash -/usr/bin/docker exec so-zeek /opt/zeek/bin/zeekctl netstats | awk '{print $(NF-2),$(NF-1),$NF}' | awk -F '[ =]' '{RCVD += $2;DRP += $4;TTL += $6} END { print "rcvd: " RCVD, "dropped: " DRP, "total: " TTL}' >> /nsm/zeek/logs/packetloss.log +/usr/bin/docker exec so-zeek /opt/zeek/bin/zeekctl netstats | awk '{print $(NF-2),$(NF-1),$NF}' | awk -F '[ =]' '{RCVD += $2;DRP += $4;TTL += $6} END { print "rcvd: " RCVD, "dropped: " DRP, "total: " TTL}' >> /nsm/zeek/logs/packetloss.log 2>&1 diff --git a/setup/so-functions b/setup/so-functions index eeda4ea38..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 @@ -585,14 +614,18 @@ disable_misc_network_features() { filter_unused_nics if [ ${#filtered_nics[@]} -ne 0 ]; then for unused_nic in "${filtered_nics[@]}"; do - # Disable DHCPv4/v6 and autoconnect - nmcli con mod "$unused_nic" \ - ipv4.method disabled \ - ipv6.method ignore \ - connection.autoconnect "no" >> "$setup_log" 2>&1 + if [ -n "$unused_nic" ]; then + echo "Disabling unused NIC: $unused_nic" >> "$setup_log" 2>&1 - # Flush any existing IPs - ip addr flush "$unused_nic" >> "$setup_log" 2>&1 + # Disable DHCPv4/v6 and autoconnect + nmcli con mod "$unused_nic" \ + ipv4.method disabled \ + ipv6.method ignore \ + connection.autoconnect "no" >> "$setup_log" 2>&1 + + # Flush any existing IPs + ip addr flush "$unused_nic" >> "$setup_log" 2>&1 + fi done fi # Disable IPv6 @@ -609,9 +642,9 @@ docker_install() { { yum clean expire-cache; yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo; - yum -y install docker-ce-19.03.9-3.el7 containerd.io-1.2.6-3.el7; - yum versionlock docker-ce-19.03.9-3.el7; - yum versionlock containerd.io-1.2.6-3.el7 + yum -y install docker-ce-19.03.11-3.el7 containerd.io-1.2.13-3.2.el7; + yum versionlock docker-ce-19.03.11-3.el7; + yum versionlock containerd.io-1.2.13-3.2.el7 } >> "$setup_log" 2>&1 else @@ -812,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" @@ -904,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"\ @@ -1213,7 +1258,7 @@ salt_checkin() { # Run a salt command to generate the minion key salt_firstcheckin() { - salt-call state.show_top >> /dev/null # send output to /dev/null because we don't actually care about the ouput + salt-call state.show_top >> /dev/null 2>&1 # send output to /dev/null because we don't actually care about the ouput } set_base_heapsizes() { 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 9ba4ebc20..693e53162 100755 --- a/setup/so-whiptail +++ b/setup/so-whiptail @@ -24,7 +24,7 @@ whiptail_basic_bro() { [ -n "$TESTING" ] && return BASICBRO=$(whiptail --title "Security Onion Setup" --inputbox \ - "Enter the number of bro processes:" 10 75 "$lb_procs" 3>&1 1>&2 2>&3) + "Enter the number of zeek processes:" 10 75 "$lb_procs" 3>&1 1>&2 2>&3) local exitstatus=$? whiptail_check_exitstatus $exitstatus @@ -51,7 +51,7 @@ whiptail_bro_pins() { cpu_core_list_whiptail+=("$item" "OFF") done - BROPINS=$(whiptail --noitem --title "Pin Bro CPUS" --checklist "Please select $lb_procs cores to pin Bro to:" 20 75 12 "${cpu_core_list_whiptail[@]}" 3>&1 1>&2 2>&3 ) + BROPINS=$(whiptail --noitem --title "Pin Zeek CPUS" --checklist "Please select $lb_procs cores to pin Zeek to:" 20 75 12 "${cpu_core_list_whiptail[@]}" 3>&1 1>&2 2>&3 ) local exitstatus=$? whiptail_check_exitstatus $exitstatus @@ -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