diff --git a/files/master b/files/master
index 25252da0c..f14c4194c 100644
--- a/files/master
+++ b/files/master
@@ -57,3 +57,7 @@ pillar_roots:
peer:
.*:
- x509.sign_remote_certificate
+
+reactor:
+ - 'so/fleet':
+ - salt://reactor/fleet.sls
diff --git a/pillar/firewall/fleet_nodes.sls b/pillar/firewall/fleet_nodes.sls
new file mode 100644
index 000000000..ca2bd1ff3
--- /dev/null
+++ b/pillar/firewall/fleet_nodes.sls
@@ -0,0 +1,3 @@
+fleet_nodes:
+ - 127.0.0.1
+
diff --git a/pillar/top.sls b/pillar/top.sls
index 9b1d60035..f1cde7853 100644
--- a/pillar/top.sls
+++ b/pillar/top.sls
@@ -56,3 +56,10 @@ base:
- logstash
- logstash.helix
- minions.{{ grains.id }}
+
+ '*_fleet':
+ - static
+ - firewall.*
+ - data.*
+ - auth
+ - minions.{{ grains.id }}
diff --git a/salt/common/init.sls b/salt/common/init.sls
index e77e23970..8ba52ac34 100644
--- a/salt/common/init.sls
+++ b/salt/common/init.sls
@@ -1,6 +1,7 @@
{% set VERSION = salt['pillar.get']('static:soversion', 'HH1.1.4') %}
{% set MASTER = salt['grains.get']('master') %}
{% set GRAFANA = salt['pillar.get']('master:grafana', '0') %}
+{% set FLEETMASTER = salt['pillar.get']('static:fleet_master', False) %}
# Add socore Group
socoregroup:
group.present:
@@ -142,6 +143,9 @@ so-core:
- port_bindings:
- 80:80
- 443:443
+ {%- if FLEETMASTER %}
+ - 8090:8090
+ {%- endif %}
- watch:
- file: /opt/so/conf/nginx/nginx.conf
diff --git a/salt/common/nginx/nginx.conf.so-eval b/salt/common/nginx/nginx.conf.so-eval
index 7cc810a93..e322ab59d 100644
--- a/salt/common/nginx/nginx.conf.so-eval
+++ b/salt/common/nginx/nginx.conf.so-eval
@@ -1,4 +1,5 @@
{%- set masterip = salt['pillar.get']('master:mainip', '') %}
+{%- set FLEET_MASTER = salt['pillar.get']('static:fleet_master') %}
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
@@ -63,6 +64,29 @@ http {
return 301 https://$host$request_uri;
}
+{% if FLEET_MASTER %}
+ server {
+ listen 8090 ssl http2 default_server;
+ server_name _;
+ root /opt/socore/html;
+ index blank.html;
+
+ ssl_certificate "/etc/pki/nginx/server.crt";
+ ssl_certificate_key "/etc/pki/nginx/server.key";
+ ssl_session_cache shared:SSL:1m;
+ ssl_session_timeout 10m;
+ ssl_ciphers HIGH:!aNULL:!MD5;
+ ssl_prefer_server_ciphers on;
+
+ location ~ ^/kolide.agent.Api/(RequestEnrollment|RequestConfig|RequestQueries|PublishLogs|PublishResults|CheckHealth)$ {
+ grpc_pass grpcs://{{ masterip }}:8080;
+ grpc_set_header Host $host;
+ grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_buffering off;
+ }
+
+ }
+{% endif %}
# Settings for a TLS enabled server.
@@ -149,21 +173,8 @@ http {
}
- location /api/ {
- proxy_pass https://{{ masterip }}:8080/api/;
- proxy_read_timeout 90;
- proxy_connect_timeout 90;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "Upgrade";
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header Proxy "";
-
- }
-
location /fleet/ {
- proxy_pass https://{{ masterip }}:8080/fleet/;
+ proxy_pass https://{{ masterip }}:8080;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
diff --git a/salt/common/nginx/nginx.conf.so-fleet b/salt/common/nginx/nginx.conf.so-fleet
new file mode 100644
index 000000000..5665fcf4e
--- /dev/null
+++ b/salt/common/nginx/nginx.conf.so-fleet
@@ -0,0 +1,106 @@
+{%- set MAINIP = salt['pillar.get']('node:mainip', '') %}
+# For more information on configuration, see:
+# * Official English Documentation: http://nginx.org/en/docs/
+# * Official Russian Documentation: http://nginx.org/ru/docs/
+
+user nginx;
+worker_processes auto;
+error_log /var/log/nginx/error.log;
+pid /run/nginx.pid;
+
+# Load dynamic modules. See /usr/share/nginx/README.dynamic.
+include /usr/share/nginx/modules/*.conf;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ '$status $body_bytes_sent "$http_referer" '
+ '"$http_user_agent" "$http_x_forwarded_for"';
+
+ access_log /var/log/nginx/access.log main;
+
+ sendfile on;
+ tcp_nopush on;
+ tcp_nodelay on;
+ keepalive_timeout 65;
+ types_hash_max_size 2048;
+
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+
+ include /etc/nginx/conf.d/*.conf;
+
+ server {
+ listen 80 default_server;
+ server_name _;
+ return 301 https://$host$request_uri;
+ }
+
+ server {
+ listen 8090 ssl http2 default_server;
+ server_name _;
+ root /opt/socore/html;
+ index blank.html;
+
+ ssl_certificate "/etc/pki/nginx/server.crt";
+ ssl_certificate_key "/etc/pki/nginx/server.key";
+ ssl_session_cache shared:SSL:1m;
+ ssl_session_timeout 10m;
+ ssl_ciphers HIGH:!aNULL:!MD5;
+ ssl_prefer_server_ciphers on;
+
+ location ~ ^/kolide.agent.Api/(RequestEnrollment|RequestConfig|RequestQueries|PublishLogs|PublishResults|CheckHealth)$ {
+ grpc_pass grpcs://{{ MAINIP }}:8080;
+ grpc_set_header Host $host;
+ grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_buffering off;
+ }
+
+ }
+
+
+ server {
+ listen 443 ssl http2 default_server;
+ server_name _;
+ root /opt/socore/html;
+ index index.html;
+
+ ssl_certificate "/etc/pki/nginx/server.crt";
+ ssl_certificate_key "/etc/pki/nginx/server.key";
+ ssl_session_cache shared:SSL:1m;
+ ssl_session_timeout 10m;
+ ssl_ciphers HIGH:!aNULL:!MD5;
+ ssl_prefer_server_ciphers on;
+
+ location /fleet/ {
+ proxy_pass https://{{ MAINIP }}:8080;
+ proxy_read_timeout 90;
+ proxy_connect_timeout 90;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header Proxy "";
+
+ }
+
+
+ error_page 401 = @error401;
+
+ location @error401 {
+ add_header Set-Cookie "NSREDIRECT=http://{{ MAINIP }}$request_uri;Domain={{ MAINIP }};Path=/;Max-Age=60000";
+ return 302 http://{{ MAINIP }}/so-auth/loginpage/;
+ }
+
+ error_page 404 /404.html;
+ location = /40x.html {
+ }
+
+ error_page 500 502 503 504 /50x.html;
+ location = /50x.html {
+ }
+ }
+
+}
diff --git a/salt/common/nginx/nginx.conf.so-master b/salt/common/nginx/nginx.conf.so-master
index 4da4b99d6..ed9dfb253 100644
--- a/salt/common/nginx/nginx.conf.so-master
+++ b/salt/common/nginx/nginx.conf.so-master
@@ -1,4 +1,5 @@
{%- set masterip = salt['pillar.get']('master:mainip', '') %}
+{%- set FLEET_MASTER = salt['pillar.get']('static:fleet_master') %}
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
@@ -63,6 +64,29 @@ http {
return 301 https://$host$request_uri;
}
+{% if FLEET_MASTER %}
+ server {
+ listen 8090 ssl http2 default_server;
+ server_name _;
+ root /opt/socore/html;
+ index blank.html;
+
+ ssl_certificate "/etc/pki/nginx/server.crt";
+ ssl_certificate_key "/etc/pki/nginx/server.key";
+ ssl_session_cache shared:SSL:1m;
+ ssl_session_timeout 10m;
+ ssl_ciphers HIGH:!aNULL:!MD5;
+ ssl_prefer_server_ciphers on;
+
+ location ~ ^/kolide.agent.Api/(RequestEnrollment|RequestConfig|RequestQueries|PublishLogs|PublishResults|CheckHealth)$ {
+ grpc_pass grpcs://{{ masterip }}:8080;
+ grpc_set_header Host $host;
+ grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_buffering off;
+ }
+
+ }
+{% endif %}
# Settings for a TLS enabled server.
@@ -148,23 +172,8 @@ http {
}
- location /api/ {
- proxy_pass https://{{ masterip }}:8080/api/;
- proxy_read_timeout 90;
- proxy_connect_timeout 90;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "Upgrade";
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header Proxy "";
-
- }
-
location /fleet/ {
- rewrite /fleet/(.*) /$1 break;
- auth_request /so-auth/api/auth/;
- proxy_pass https://{{ masterip }}:8080/;
+ proxy_pass https://{{ masterip }}:8080;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
diff --git a/salt/common/nginx/nginx.conf.so-mastersearch b/salt/common/nginx/nginx.conf.so-mastersearch
index 1bd0ebd2f..1eb4e8e5c 100644
--- a/salt/common/nginx/nginx.conf.so-mastersearch
+++ b/salt/common/nginx/nginx.conf.so-mastersearch
@@ -1,4 +1,5 @@
{%- set masterip = salt['pillar.get']('master:mainip', '') %}
+{%- set FLEET_MASTER = salt['pillar.get']('static:fleet_master') %}
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
@@ -63,6 +64,29 @@ http {
return 301 https://$host$request_uri;
}
+{% if FLEET_MASTER %}
+ server {
+ listen 8090 ssl http2 default_server;
+ server_name _;
+ root /opt/socore/html;
+ index blank.html;
+
+ ssl_certificate "/etc/pki/nginx/server.crt";
+ ssl_certificate_key "/etc/pki/nginx/server.key";
+ ssl_session_cache shared:SSL:1m;
+ ssl_session_timeout 10m;
+ ssl_ciphers HIGH:!aNULL:!MD5;
+ ssl_prefer_server_ciphers on;
+
+ location ~ ^/kolide.agent.Api/(RequestEnrollment|RequestConfig|RequestQueries|PublishLogs|PublishResults|CheckHealth)$ {
+ grpc_pass grpcs://{{ masterip }}:8080;
+ grpc_set_header Host $host;
+ grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_buffering off;
+ }
+
+ }
+{% endif %}
# Settings for a TLS enabled server.
@@ -135,23 +159,8 @@ http {
}
- location /api/ {
- proxy_pass https://{{ masterip }}:8080/api/;
- proxy_read_timeout 90;
- proxy_connect_timeout 90;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "Upgrade";
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header Proxy "";
-
- }
-
location /fleet/ {
- rewrite /fleet/(.*) /$1 break;
- auth_request /so-auth/api/auth/;
- proxy_pass https://{{ masterip }}:8080/;
+ proxy_pass https://{{ masterip }}:8080;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
@@ -275,4 +284,4 @@ http {
}
}
-}
+}
\ No newline at end of file
diff --git a/salt/common/tools/sbin/so-allow b/salt/common/tools/sbin/so-allow
index 61df47fd0..bede282b3 100755
--- a/salt/common/tools/sbin/so-allow
+++ b/salt/common/tools/sbin/so-allow
@@ -56,7 +56,7 @@ if [ "$SKIP" -eq 0 ]; then
echo ""
echo "[a] - Analyst - ports 80/tcp and 443/tcp"
echo "[b] - Logstash Beat - port 5044/tcp"
- echo "[o] - Osquery endpoint - port 8080/tcp"
+ echo "[o] - Osquery endpoint - port 8090/tcp"
echo "[w] - Wazuh endpoint - port 1514"
echo ""
echo "Please enter your selection (a - analyst, b - beats, o - osquery, w - wazuh):"
diff --git a/salt/common/tools/sbin/so-status b/salt/common/tools/sbin/so-status
index 7f6e01eec..551a80fbd 100755
--- a/salt/common/tools/sbin/so-status
+++ b/salt/common/tools/sbin/so-status
@@ -26,6 +26,8 @@
{%- set pillar_val = 'sensor' -%}
{%- elif (salt['grains.get']('role') == 'so-eval') -%}
{%- set pillar_val = 'eval' -%}
+{%- elif (salt['grains.get']('role') == 'so-fleet') -%}
+ {%- set pillar_val = 'fleet' -%}
{%- elif (salt['grains.get']('role') == 'so-helix') -%}
{%- set pillar_val = 'helix' -%}
{%- elif (salt['grains.get']('role') == 'so-node') -%}
diff --git a/salt/launcher/init.sls b/salt/deprecated-launcher/init.sls
similarity index 100%
rename from salt/launcher/init.sls
rename to salt/deprecated-launcher/init.sls
diff --git a/salt/launcher/packages/info.txt b/salt/deprecated-launcher/packages/info.txt
similarity index 100%
rename from salt/launcher/packages/info.txt
rename to salt/deprecated-launcher/packages/info.txt
diff --git a/salt/filebeat/etc/filebeat.yml b/salt/filebeat/etc/filebeat.yml
index 3aa8fa565..792f0a959 100644
--- a/salt/filebeat/etc/filebeat.yml
+++ b/salt/filebeat/etc/filebeat.yml
@@ -8,8 +8,9 @@
{%- set HOSTNAME = salt['grains.get']('host', '') %}
{%- set BROVER = salt['pillar.get']('static:broversion', 'COMMUNITY') %}
{%- set WAZUHENABLED = salt['pillar.get']('static:wazuh_enabled', '1') %}
-{%- set FLEETENABLED = salt['pillar.get']('static:fleet_enabled', '1') %}
{%- set STRELKAENABLED = salt['pillar.get']('static:strelka_enabled', '1') %}
+{%- set FLEETMASTER = salt['pillar.get']('static:fleet_master', False) -%}
+{%- set FLEETNODE = salt['pillar.get']('static:fleet_node', False) -%}
name: {{ HOSTNAME }}
@@ -137,11 +138,11 @@ filebeat.inputs:
{%- endif %}
-{%- if FLEETENABLED == '1' %}
+{%- if FLEETMASTER or FLEETNODE %}
- type: log
paths:
- - /osquery/logs/result.log
+ - /nsm/osquery/fleet/result.log
fields:
type: osquery
diff --git a/salt/filebeat/init.sls b/salt/filebeat/init.sls
index 671530cd1..25fbbdd14 100644
--- a/salt/filebeat/init.sls
+++ b/salt/filebeat/init.sls
@@ -1,4 +1,4 @@
-# Copyright 2014,2015,2016,2017,2018 Security Onion Solutions, LLC
+# 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
@@ -59,7 +59,7 @@ so-filebeat:
- /opt/so/log/suricata:/suricata:ro
- /opt/so/wazuh/logs/alerts:/wazuh/alerts:ro
- /opt/so/wazuh/logs/archives:/wazuh/archives:ro
- - /opt/so/log/fleet/:/osquery/logs:ro
+ - /nsm/osquery/fleet/:/osquery/logs:ro
- /opt/so/conf/filebeat/etc/pki/filebeat.crt:/usr/share/filebeat/filebeat.crt:ro
- /opt/so/conf/filebeat/etc/pki/filebeat.key:/usr/share/filebeat/filebeat.key:ro
- /etc/ssl/certs/intca.crt:/usr/share/filebeat/intraca.crt:ro
diff --git a/salt/firewall/init.sls b/salt/firewall/init.sls
index 657ff7814..16492dd47 100644
--- a/salt/firewall/init.sls
+++ b/salt/firewall/init.sls
@@ -5,7 +5,10 @@
{%- set ip = salt['pillar.get']('node:mainip', '') %}
{%- elif grains['role'] == 'so-sensor' %}
{%- set ip = salt['pillar.get']('sensor:mainip', '') %}
+{%- elif grains['role'] == 'so-fleet' %}
+{%- set ip = salt['pillar.get']('node:mainip', '') %}
{%- endif %}
+
# Quick Fix for Docker being difficult
iptables_fix_docker:
iptables.chain_present:
@@ -232,14 +235,14 @@ enable_masternode_mysql_3306_{{ip}}:
- position: 1
- save: True
-enable_master_osquery_8080_{{ip}}:
+enable_master_osquery_8090_{{ip}}:
iptables.insert:
- table: filter
- chain: DOCKER-USER
- jump: ACCEPT
- proto: tcp
- source: {{ ip }}
- - dport: 8080
+ - dport: 8090
- position: 1
- save: True
@@ -466,14 +469,14 @@ enable_standard_beats_5044_{{ip}}:
# Allow OSQuery Endpoints to send their traffic
{% for ip in pillar.get('osquery_endpoint') %}
-enable_standard_osquery_8080_{{ip}}:
+enable_standard_osquery_8090_{{ip}}:
iptables.insert:
- table: filter
- chain: DOCKER-USER
- jump: ACCEPT
- proto: tcp
- source: {{ ip }}
- - dport: 8080
+ - dport: 8090
- position: 1
- save: True
@@ -702,3 +705,108 @@ enable_forwardnode_beats_5644_{{ip}}:
- position: 1
- save: True
{% endif %}
+
+
+# Rules if you are a Standalone Fleet node
+{% if grains['role'] == 'so-fleet' %}
+#This should be more granular
+iptables_allow_fleetnode_docker:
+ iptables.insert:
+ - table: filter
+ - chain: INPUT
+ - jump: ACCEPT
+ - source: 172.17.0.0/24
+ - position: 1
+ - save: True
+
+# Allow Redis
+enable_fleetnode_redis_6379_{{ip}}:
+ iptables.insert:
+ - table: filter
+ - chain: DOCKER-USER
+ - jump: ACCEPT
+ - proto: tcp
+ - source: {{ ip }}
+ - dport: 6379
+ - position: 1
+ - save: True
+
+enable_fleetnode_mysql_3306_{{ip}}:
+ iptables.insert:
+ - table: filter
+ - chain: DOCKER-USER
+ - jump: ACCEPT
+ - proto: tcp
+ - source: {{ ip }}
+ - dport: 3306
+ - position: 1
+ - save: True
+
+enable_fleet_osquery_8080_{{ip}}:
+ iptables.insert:
+ - table: filter
+ - chain: DOCKER-USER
+ - jump: ACCEPT
+ - proto: tcp
+ - source: {{ ip }}
+ - dport: 8080
+ - position: 1
+ - save: True
+
+
+enable_fleetnodetemp_mysql_3306_{{ip}}:
+ iptables.insert:
+ - table: filter
+ - chain: DOCKER-USER
+ - jump: ACCEPT
+ - proto: tcp
+ - source: 127.0.0.1
+ - dport: 3306
+ - position: 1
+ - save: True
+
+enable_fleettemp_osquery_8080_{{ip}}:
+ iptables.insert:
+ - table: filter
+ - chain: DOCKER-USER
+ - jump: ACCEPT
+ - proto: tcp
+ - source: 127.0.0.1
+ - dport: 8080
+ - position: 1
+ - save: True
+
+
+# Allow Analysts to access Fleet WebUI
+{% for ip in pillar.get('analyst') %}
+
+enable_fleetnode_fleet_443_{{ip}}:
+ iptables.insert:
+ - table: filter
+ - chain: DOCKER-USER
+ - jump: ACCEPT
+ - proto: tcp
+ - source: {{ ip }}
+ - dport: 443
+ - position: 1
+ - save: True
+
+{% endfor %}
+
+# Needed for osquery endpoints to checkin to Fleet API for mgt
+{% for ip in pillar.get('osquery_endpoint') %}
+
+enable_fleetnode_8090_{{ip}}:
+ iptables.insert:
+ - table: filter
+ - chain: DOCKER-USER
+ - jump: ACCEPT
+ - proto: tcp
+ - source: {{ ip }}
+ - dport: 8090
+ - position: 1
+ - save: True
+
+{% endfor %}
+
+{% endif %}
\ No newline at end of file
diff --git a/salt/fleet/event_enable-fleet.sls b/salt/fleet/event_enable-fleet.sls
new file mode 100644
index 000000000..8c3426e0d
--- /dev/null
+++ b/salt/fleet/event_enable-fleet.sls
@@ -0,0 +1,9 @@
+{% set ENROLLSECRET = salt['cmd.run']('docker exec so-fleet fleetctl get enroll-secret') %}
+
+so/fleet:
+ event.send:
+ - data:
+ action: 'enablefleet'
+ hostname: {{ grains.host }}
+ role: {{ grains.role }}
+ enroll-secret: {{ ENROLLSECRET }}
\ No newline at end of file
diff --git a/salt/fleet/event_gen-packages.sls b/salt/fleet/event_gen-packages.sls
new file mode 100644
index 000000000..affc9a72a
--- /dev/null
+++ b/salt/fleet/event_gen-packages.sls
@@ -0,0 +1,10 @@
+{% set ENROLLSECRET = salt['pillar.get']('auth:fleet_enroll-secret') %}
+
+so/fleet:
+ event.send:
+ - data:
+ action: 'genpackages'
+ hostname: {{ grains.host }}
+ role: {{ grains.role }}
+ mainip: {{ grains.host }}
+ enroll-secret: {{ ENROLLSECRET }}
\ No newline at end of file
diff --git a/salt/fleet/files/osquery-packages-sa.html b/salt/fleet/files/osquery-packages-sa.html
new file mode 100644
index 000000000..c35449522
--- /dev/null
+++ b/salt/fleet/files/osquery-packages-sa.html
@@ -0,0 +1,107 @@
+
+
+
+Security Onion - Hybrid Hunter
+
+
+
+
+
+
+
+
+
+
+
+
+
Osquery Packages
+
+
Notes
+
+ These packages are customized for this specific Fleet install and will only be generated after the Fleet setup script has been run. If you want vanilla osquery packages, you can get them directly from osquery.io
+ Packages are not signed.
+
+
Downloads
+
+
+
Known Issues
+
+
+
+
+
+
+
diff --git a/salt/fleet/osquery-packages.html b/salt/fleet/files/osquery-packages.html
similarity index 100%
rename from salt/fleet/osquery-packages.html
rename to salt/fleet/files/osquery-packages.html
diff --git a/salt/fleet/packs/PUT.PACKS.IN.HERE b/salt/fleet/files/packs/PUT.PACKS.IN.HERE
similarity index 100%
rename from salt/fleet/packs/PUT.PACKS.IN.HERE
rename to salt/fleet/files/packs/PUT.PACKS.IN.HERE
diff --git a/salt/fleet/packs/hh/hh-post-login.sh b/salt/fleet/files/packs/hh/hh-post-login.sh
similarity index 100%
rename from salt/fleet/packs/hh/hh-post-login.sh
rename to salt/fleet/files/packs/hh/hh-post-login.sh
diff --git a/salt/fleet/packs/hh/hhdefault.yml b/salt/fleet/files/packs/hh/hhdefault.yml
similarity index 100%
rename from salt/fleet/packs/hh/hhdefault.yml
rename to salt/fleet/files/packs/hh/hhdefault.yml
diff --git a/salt/fleet/packs/hh/osquery.conf b/salt/fleet/files/packs/hh/osquery.conf
similarity index 100%
rename from salt/fleet/packs/hh/osquery.conf
rename to salt/fleet/files/packs/hh/osquery.conf
diff --git a/salt/fleet/packs/palantir/Fleet/Endpoints/MacOS/osquery.yaml b/salt/fleet/files/packs/palantir/Fleet/Endpoints/MacOS/osquery.yaml
similarity index 100%
rename from salt/fleet/packs/palantir/Fleet/Endpoints/MacOS/osquery.yaml
rename to salt/fleet/files/packs/palantir/Fleet/Endpoints/MacOS/osquery.yaml
diff --git a/salt/fleet/packs/palantir/Fleet/Endpoints/Windows/osquery.yaml b/salt/fleet/files/packs/palantir/Fleet/Endpoints/Windows/osquery.yaml
similarity index 100%
rename from salt/fleet/packs/palantir/Fleet/Endpoints/Windows/osquery.yaml
rename to salt/fleet/files/packs/palantir/Fleet/Endpoints/Windows/osquery.yaml
diff --git a/salt/fleet/packs/palantir/Fleet/Endpoints/options.yaml b/salt/fleet/files/packs/palantir/Fleet/Endpoints/options.yaml
similarity index 100%
rename from salt/fleet/packs/palantir/Fleet/Endpoints/options.yaml
rename to salt/fleet/files/packs/palantir/Fleet/Endpoints/options.yaml
diff --git a/salt/fleet/packs/palantir/Fleet/Endpoints/packs/performance-metrics.yaml b/salt/fleet/files/packs/palantir/Fleet/Endpoints/packs/performance-metrics.yaml
similarity index 100%
rename from salt/fleet/packs/palantir/Fleet/Endpoints/packs/performance-metrics.yaml
rename to salt/fleet/files/packs/palantir/Fleet/Endpoints/packs/performance-metrics.yaml
diff --git a/salt/fleet/packs/palantir/Fleet/Endpoints/packs/security-tooling-checks.yaml b/salt/fleet/files/packs/palantir/Fleet/Endpoints/packs/security-tooling-checks.yaml
similarity index 100%
rename from salt/fleet/packs/palantir/Fleet/Endpoints/packs/security-tooling-checks.yaml
rename to salt/fleet/files/packs/palantir/Fleet/Endpoints/packs/security-tooling-checks.yaml
diff --git a/salt/fleet/packs/palantir/Fleet/Endpoints/packs/windows-application-security.yaml b/salt/fleet/files/packs/palantir/Fleet/Endpoints/packs/windows-application-security.yaml
similarity index 100%
rename from salt/fleet/packs/palantir/Fleet/Endpoints/packs/windows-application-security.yaml
rename to salt/fleet/files/packs/palantir/Fleet/Endpoints/packs/windows-application-security.yaml
diff --git a/salt/fleet/packs/palantir/Fleet/Endpoints/packs/windows-compliance.yaml b/salt/fleet/files/packs/palantir/Fleet/Endpoints/packs/windows-compliance.yaml
similarity index 100%
rename from salt/fleet/packs/palantir/Fleet/Endpoints/packs/windows-compliance.yaml
rename to salt/fleet/files/packs/palantir/Fleet/Endpoints/packs/windows-compliance.yaml
diff --git a/salt/fleet/packs/palantir/Fleet/Endpoints/packs/windows-registry-monitoring.yaml b/salt/fleet/files/packs/palantir/Fleet/Endpoints/packs/windows-registry-monitoring.yaml
similarity index 100%
rename from salt/fleet/packs/palantir/Fleet/Endpoints/packs/windows-registry-monitoring.yaml
rename to salt/fleet/files/packs/palantir/Fleet/Endpoints/packs/windows-registry-monitoring.yaml
diff --git a/salt/fleet/packs/palantir/Fleet/Servers/Linux/osquery.yaml b/salt/fleet/files/packs/palantir/Fleet/Servers/Linux/osquery.yaml
similarity index 100%
rename from salt/fleet/packs/palantir/Fleet/Servers/Linux/osquery.yaml
rename to salt/fleet/files/packs/palantir/Fleet/Servers/Linux/osquery.yaml
diff --git a/salt/fleet/packs/palantir/Fleet/Servers/options.yaml b/salt/fleet/files/packs/palantir/Fleet/Servers/options.yaml
similarity index 100%
rename from salt/fleet/packs/palantir/Fleet/Servers/options.yaml
rename to salt/fleet/files/packs/palantir/Fleet/Servers/options.yaml
diff --git a/salt/fleet/packs/palantir/LICENSE.md b/salt/fleet/files/packs/palantir/LICENSE.md
similarity index 100%
rename from salt/fleet/packs/palantir/LICENSE.md
rename to salt/fleet/files/packs/palantir/LICENSE.md
diff --git a/salt/fleet/packs/palantir/README.md b/salt/fleet/files/packs/palantir/README.md
similarity index 100%
rename from salt/fleet/packs/palantir/README.md
rename to salt/fleet/files/packs/palantir/README.md
diff --git a/salt/fleet/files/scripts/so-fleet-packages b/salt/fleet/files/scripts/so-fleet-packages
new file mode 100644
index 000000000..eed4bfb71
--- /dev/null
+++ b/salt/fleet/files/scripts/so-fleet-packages
@@ -0,0 +1,33 @@
+#!/bin/bash
+{% set MAIN_HOSTNAME = salt['grains.get']('host') %}
+{% set MAIN_IP = salt['pillar.get']('node:mainip') %}
+
+
+#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.* /opt/so/saltstack/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" /opt/so/saltstack/salt/fleet/osquery-packages.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
new file mode 100644
index 000000000..2f6628980
--- /dev/null
+++ b/salt/fleet/files/scripts/so-fleet-setup
@@ -0,0 +1,38 @@
+#!/bin/bash
+{% set MAIN_HOSTNAME = salt['grains.get']('host') %}
+{% set MAIN_IP = salt['pillar.get']('node:mainip') %}
+
+#so-fleet-setup.sh $FleetEmail
+
+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/options.yaml
+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'
+
+
+# Enable Fleet
+echo "Enabling Fleet..."
+salt-call state.apply fleet.event_enable-fleet queue=True >> /root/fleet-setup.log
+
+# Generate osquery install packages
+echo "Generating osquery install packages - will take some time..."
+salt-call state.apply fleet.event_gen-packages queue=True >> /root/fleet-setup.log
+sleep 180
+
+echo "Installing launcher via salt..."
+salt-call state.apply fleet.install_package 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 a27ad9eb6..15f55b594 100644
--- a/salt/fleet/init.sls
+++ b/salt/fleet/init.sls
@@ -1,8 +1,25 @@
-{%- set MYSQLPASS = salt['pillar.get']('auth:mysql', 'iwonttellyou') %}
-{%- set FLEETPASS = salt['pillar.get']('auth:fleet', 'bazinga') -%}
-{%- set MASTERIP = salt['pillar.get']('static:masterip', '') -%}
+{%- set MYSQLPASS = salt['pillar.get']('auth:mysql', None) -%}
+{%- set FLEETPASS = salt['pillar.get']('auth:fleet', None) -%}
+{%- set FLEETJWT = salt['pillar.get']('auth:fleet_jwt', None) -%}
{% set VERSION = salt['pillar.get']('static:soversion', 'HH1.1.4') %}
{% 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') %}
+{% else %}
+ {% set MAINIP = salt['pillar.get']('static:masterip') %}
+{% endif %}
+
+#{% if grains.id.split('_')|last in ['master', 'eval', 'fleet'] %}
+#so/fleet:
+# event.send:
+# - data:
+# action: 'enablefleet'
+# hostname: {{ grains.host }}
+#{% endif %}
# Fleet Setup
fleetcdir:
@@ -18,11 +35,18 @@ fleetpackcdir:
- user: 939
- group: 939
- makedirs: True
+
+fleetnsmdir:
+ file.directory:
+ - name: /nsm/osquery/fleet
+ - user: 939
+ - group: 939
+ - makedirs: True
fleetpacksync:
file.recurse:
- name: /opt/so/conf/fleet/packs
- - source: salt://fleet/packs
+ - source: salt://fleet/files/packs
- user: 939
- group: 939
@@ -33,24 +57,34 @@ fleetlogdir:
- group: 939
- makedirs: True
-fleetsetupscript:
- file.managed:
- - name: /opt/so/conf/fleet/so-fleet-setup.sh
- - source: salt://fleet/so-fleet-setup.sh
+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/osquery-packages.html
+ - source: salt://fleet/files/osquery-packages.html
fleetdb:
mysql_database.present:
- name: fleet
+ - connection_host: {{ MAINIP }}
+ - connection_port: 3306
+ - connection_user: root
+ - connection_pass: {{ MYSQLPASS }}
fleetdbuser:
mysql_user.present:
- host: 172.17.0.0/255.255.0.0
- password: {{ FLEETPASS }}
+ - connection_host: {{ MAINIP }}
+ - connection_port: 3306
- connection_user: root
- connection_pass: {{ MYSQLPASS }}
@@ -60,6 +94,21 @@ fleetdbpriv:
- database: fleet.*
- user: fleetdbuser
- host: 172.17.0.0/255.255.0.0
+ - connection_host: {{ MAINIP }}
+ - connection_port: 3306
+ - connection_user: root
+ - connection_pass: {{ MYSQLPASS }}
+
+
+{% if FLEETPASS == None or FLEETJWT == None %}
+
+fleet_password_none:
+ test.configurable_test_state:
+ - changes: False
+ - result: False
+ - comment: "Fleet MySQL Password or JWT Key Error - Not Starting Fleet"
+
+{% else %}
so-fleet:
docker_container.running:
@@ -68,22 +117,25 @@ so-fleet:
- port_bindings:
- 0.0.0.0:8080:8080
- environment:
- - KOLIDE_MYSQL_ADDRESS={{ MASTERIP }}:3306
+ - KOLIDE_MYSQL_ADDRESS={{ MAINIP }}:3306
+ - KOLIDE_REDIS_ADDRESS={{ MAINIP }}:6379
- KOLIDE_MYSQL_DATABASE=fleet
- KOLIDE_MYSQL_USERNAME=fleetdbuser
- KOLIDE_MYSQL_PASSWORD={{ FLEETPASS }}
- - KOLIDE_REDIS_ADDRESS={{ MASTERIP }}:6379
- KOLIDE_SERVER_CERT=/ssl/server.cert
- KOLIDE_SERVER_KEY=/ssl/server.key
- KOLIDE_LOGGING_JSON=true
- - KOLIDE_AUTH_JWT_KEY=thisisatest
- - KOLIDE_OSQUERY_STATUS_LOG_FILE=/var/log/osquery/status.log
+ - KOLIDE_AUTH_JWT_KEY= {{ FLEETJWT }}
+ - KOLIDE_OSQUERY_STATUS_LOG_FILE=/var/log/fleet/status.log
- KOLIDE_OSQUERY_RESULT_LOG_FILE=/var/log/osquery/result.log
- KOLIDE_SERVER_URL_PREFIX=/fleet
- binds:
- /etc/pki/fleet.key:/ssl/server.key:ro
- /etc/pki/fleet.crt:/ssl/server.cert:ro
- - /opt/so/log/fleet:/var/log/osquery
+ - /opt/so/log/fleet:/var/log/fleet
+ - /nsm/osquery/fleet:/var/log/osquery
- /opt/so/conf/fleet/packs:/packs
- watch:
- /opt/so/conf/fleet/etc
+
+{% endif %}
diff --git a/salt/fleet/install_package.sls b/salt/fleet/install_package.sls
new file mode 100644
index 000000000..7a87a5f92
--- /dev/null
+++ b/salt/fleet/install_package.sls
@@ -0,0 +1,13 @@
+{%- set FLEETMASTER = salt['pillar.get']('static:fleet_master', False) -%}
+{%- set FLEETNODE = salt['pillar.get']('static:fleet_node', False) -%}
+
+{%- if FLEETMASTER or FLEETNODE %}
+launcherpkg:
+ pkg.installed:
+ - sources:
+ {% if grains['os'] == 'CentOS' %}
+ - launcher-final: salt://fleet/packages/launcher.rpm
+ {% elif grains['os'] == 'Ubuntu' %}
+ - launcher-final: salt://fleet/packages/launcher.deb
+ {% endif %}
+{%- endif %}
diff --git a/salt/fleet/packages/info.txt b/salt/fleet/packages/info.txt
new file mode 100644
index 000000000..726dcf0d7
--- /dev/null
+++ b/salt/fleet/packages/info.txt
@@ -0,0 +1 @@
+Osquery Packages will be copied to this folder
\ No newline at end of file
diff --git a/salt/fleet/so-fleet-setup.sh b/salt/fleet/so-fleet-setup.sh
deleted file mode 100644
index cd082ff03..000000000
--- a/salt/fleet/so-fleet-setup.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/bash
-
-#so-fleet-setup.sh $MasterIP $FleetEmail
-
-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 fleetctl config set --address https://$1:443 --tls-skip-verify --url-prefix /fleet
-docker exec so-fleet fleetctl setup --email $2 --password $initpw
-
-docker exec so-fleet fleetctl apply -f /packs/palantir/Fleet/Endpoints/options.yaml
-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'
-
-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
-
-#Create the output directory
-mkdir /opt/so/conf/fleet/packages
-
-#At some point we should version launcher `latest` to avoid hard pinning here
-docker run \
- --rm \
- --mount type=bind,source=/opt/so/conf/fleet/packages,target=/output \
- --mount type=bind,source=/etc/pki/launcher.crt,target=/var/launcher/launcher.crt \
- docker.io/soshybridhunter/so-fleet-launcher:HH1.1.0 "$esecret" "$1":8080
-
-cp /opt/so/conf/fleet/packages/launcher.* /opt/so/saltstack/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" /opt/so/saltstack/salt/fleet/osquery-packages.html
-
-# Enable Fleet on all the other parts of the infrastructure
-sed -i 's/fleetsetup: 0/fleetsetup: 1/g' /opt/so/saltstack/pillar/static.sls
-
-# Install osquery locally
-#if cat /etc/os-release | grep -q 'debian'; then
-# dpkg -i /opt/so/conf/fleet/packages/launcher.deb
-#else
-# rpm -i /opt/so/conf/fleet/packages/launcher.rpm
-#fi
-echo "Installing launcher via salt"
-salt-call state.apply launcher queue=True > /root/launcher.log
-echo "Fleet Setup Complete - Login here: https://$1"
-echo "Your username is $2 and your password is $initpw"
diff --git a/salt/mysql/etc/mypass b/salt/mysql/etc/mypass
index 85ae1772b..2fb9844db 100644
--- a/salt/mysql/etc/mypass
+++ b/salt/mysql/etc/mypass
@@ -1,2 +1,2 @@
-{%- set MYSQLPASS = salt['pillar.get']('auth:mysql', 'iwonttellyou') -%}
+{%- set MYSQLPASS = salt['pillar.get']('auth:mysql', None) -%}
{{ MYSQLPASS }}
diff --git a/salt/mysql/init.sls b/salt/mysql/init.sls
index ac49953f1..981d27a73 100644
--- a/salt/mysql/init.sls
+++ b/salt/mysql/init.sls
@@ -1,8 +1,16 @@
-{%- set MYSQLPASS = salt['pillar.get']('auth:mysql', 'iwonttellyou') %}
-{%- set FLEETPASS = salt['pillar.get']('auth:fleet', 'bazinga') %}
+{%- set MYSQLPASS = salt['pillar.get']('auth:mysql', None) %}
{%- set MASTERIP = salt['pillar.get']('static:masterip', '') %}
{% set VERSION = salt['pillar.get']('static:soversion', 'HH1.1.4') %}
{% 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') %}
+{% else %}
+ {% set MAINIP = salt['pillar.get']('static:masterip') %}
+{% endif %}
+
# MySQL Setup
mysqlpkgs:
pkg.installed:
@@ -50,6 +58,16 @@ mysqldatadir:
- group: 939
- makedirs: True
+{% if MYSQLPASS == None %}
+
+mysql_password_none:
+ test.configurable_test_state:
+ - changes: False
+ - result: False
+ - comment: "MySQL Password Error - Not Starting MySQL"
+
+{% else %}
+
so-mysql:
docker_container.running:
- image: {{ MASTER }}:5000/soshybridhunter/so-mysql:{{ VERSION }}
@@ -58,7 +76,7 @@ so-mysql:
- port_bindings:
- 0.0.0.0:3306:3306
- environment:
- - MYSQL_ROOT_HOST={{ MASTERIP }}
+ - MYSQL_ROOT_HOST={{ MAINIP }}
- MYSQL_ROOT_PASSWORD=/etc/mypass
- binds:
- /opt/so/conf/mysql/etc/my.cnf:/etc/my.cnf:ro
@@ -67,3 +85,4 @@ so-mysql:
- /opt/so/log/mysql:/var/log/mysql:rw
- watch:
- /opt/so/conf/mysql/etc
+{% endif %}
\ No newline at end of file
diff --git a/salt/reactor/fleet.sls b/salt/reactor/fleet.sls
new file mode 100644
index 000000000..83a1d981c
--- /dev/null
+++ b/salt/reactor/fleet.sls
@@ -0,0 +1,48 @@
+#!py
+
+from time import gmtime, strftime
+import fileinput
+import logging
+import re
+import subprocess
+
+def run():
+ MINIONID = data['id']
+ ACTION = data['data']['action']
+ HOSTNAME = data['data']['hostname']
+ ROLE = data['data']['role']
+ ESECRET = data['data']['enroll-secret']
+ STATICFILE = '/opt/so/saltstack/pillar/static.sls'
+ AUTHFILE = '/opt/so/saltstack/pillar/auth.sls'
+
+ if MINIONID.split('_')[-1] in ['master','eval','fleet']:
+ if ACTION == 'enablefleet':
+ logging.info('so/fleet enablefleet reactor')
+
+ # Enable Fleet
+ for line in fileinput.input(STATICFILE, inplace=True):
+ if ROLE == 'so-fleet':
+ line = re.sub(r'fleet_node: \S*', f"fleet_node: True", line.rstrip())
+ else:
+ line = re.sub(r'fleet_master: \S*', f"fleet_master: True", line.rstrip())
+ print(line)
+
+ # Update the enroll secret
+ for line in fileinput.input(AUTHFILE, inplace=True):
+ line = re.sub(r'fleet_enroll-secret: \S*', f"fleet_enroll-secret: {ESECRET}", line.rstrip())
+ print(line)
+
+ if ACTION == 'genpackages':
+ logging.info('so/fleet genpackages reactor')
+
+ # Run Docker container that will build the packages
+ gen_packages = subprocess.run(["docker", "run","--rm", "--mount", "type=bind,source=/opt/so/saltstack/salt/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", \
+ f"{ESECRET}", f"{HOSTNAME}:8090"], 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):
+ line = re.sub(r'fleet_packages-timestamp: \S*', f"fleet_packages-timestamp: {strftime('%Y-%m-%d-%H:%M', gmtime())}", line.rstrip())
+ print(line)
+
+ return {}
diff --git a/salt/ssl/init.sls b/salt/ssl/init.sls
index dfaf131b9..86fce0fb0 100644
--- a/salt/ssl/init.sls
+++ b/salt/ssl/init.sls
@@ -1,5 +1,7 @@
{% 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 = [] %}
@@ -172,3 +174,45 @@ filebeatpkcs:
- name: "/usr/bin/openssl pkcs8 -in /opt/so/conf/filebeat/etc/pki/filebeat.key -topk8 -out /opt/so/conf/filebeat/etc/pki/filebeat.p8 -passout pass:"
{% endif %}
+
+{% if grains['role'] == 'so-fleet' %}
+
+# Create a cert for the reverse proxy
+/etc/pki/masterssl.crt:
+ x509.certificate_managed:
+ - ca_server: {{ ca_server }}
+ - signing_policy: masterssl
+ - public_key: /etc/pki/masterssl.key
+ - CN: {{ HOSTNAME }}
+ - days_remaining: 0
+ - days_valid: 820
+ - backup: True
+ - managed_private_key:
+ name: /etc/pki/masterssl.key
+ bits: 4096
+ backup: True
+
+
+# Create a private key and cert for Fleet
+/etc/pki/fleet.key:
+ x509.private_key_managed:
+ - CN: {{ HOSTNAME }}
+ - bits: 4096
+ - days_remaining: 0
+ - days_valid: 820
+ - backup: True
+
+/etc/pki/fleet.crt:
+ x509.certificate_managed:
+ - signing_private_key: /etc/pki/fleet.key
+ - CN: {{ HOSTNAME }}
+ - subjectAltName: DNS:{{ HOSTNAME }}, IP:{{ MAINIP }}
+ - days_remaining: 0
+ - days_valid: 820
+ - backup: True
+ - managed_private_key:
+ name: /etc/pki/fleet.key
+ bits: 4096
+ backup: True
+
+{% endif %}
diff --git a/salt/top.sls b/salt/top.sls
index 64d353208..5026caffd 100644
--- a/salt/top.sls
+++ b/salt/top.sls
@@ -1,10 +1,12 @@
{%- set BROVER = salt['pillar.get']('static:broversion', 'COMMUNITY') -%}
-{%- set OSQUERY = salt['pillar.get']('master:osquery', '0') -%}
{%- set WAZUH = salt['pillar.get']('master:wazuh', '0') -%}
{%- set THEHIVE = salt['pillar.get']('master:thehive', '0') -%}
{%- set PLAYBOOK = salt['pillar.get']('master:playbook', '0') -%}
{%- set FREQSERVER = salt['pillar.get']('master:freq', '0') -%}
{%- set DOMAINSTATS = salt['pillar.get']('master:domainstats', '0') -%}
+{%- set FLEETMASTER = salt['pillar.get']('static:fleet_master', False) -%}
+{%- set FLEETNODE = salt['pillar.get']('static:fleet_node', False) -%}
+
base:
'*':
@@ -38,8 +40,8 @@ base:
{%- endif %}
- wazuh
- filebeat
- {%- if OSQUERY != 0 %}
- - launcher
+ {%- if FLEETMASTER or FLEETNODE %}
+ - fleet.install_package
{%- endif %}
- schedule
@@ -53,7 +55,7 @@ base:
- firewall
- idstools
- auth
- {%- if OSQUERY != 0 %}
+ {%- if FLEETMASTER or FLEETNODE %}
- mysql
{%- endif %}
{%- if WAZUH != 0 %}
@@ -67,10 +69,10 @@ base:
- zeek
- curator
- elastalert
- {%- if OSQUERY != 0 %}
+ {%- if FLEETMASTER or FLEETNODE %}
- fleet
- redis
- - launcher
+ - fleet.install_package
{%- endif %}
- utility
- schedule
@@ -100,7 +102,7 @@ base:
- idstools
- redis
- auth
- {%- if OSQUERY != 0 %}
+ {%- if FLEETMASTER or FLEETNODE %}
- mysql
{%- endif %}
{%- if WAZUH != 0 %}
@@ -113,9 +115,9 @@ base:
- filebeat
- utility
- schedule
- {%- if OSQUERY != 0 %}
+ {%- if FLEETMASTER or FLEETNODE %}
- fleet
- - launcher
+ - fleet.install_package
{%- endif %}
- soctopus
{%- if THEHIVE != 0 %}
@@ -138,8 +140,8 @@ base:
- common
- firewall
- logstash
- {%- if OSQUERY != 0 %}
- - launcher
+ {%- if FLEETMASTER or FLEETNODE %}
+ - fleet.install_package
{%- endif %}
- schedule
@@ -150,8 +152,8 @@ base:
- logstash
- elasticsearch
- curator
- {%- if OSQUERY != 0 %}
- - launcher
+ {%- if FLEETMASTER or FLEETNODE %}
+ - fleet.install_package
{%- endif %}
- schedule
@@ -160,8 +162,8 @@ base:
- common
- firewall
- elasticsearch
- {%- if OSQUERY != 0 %}
- - launcher
+ {%- if FLEETMASTER or FLEETNODE %}
+ - fleet.install_package
{%- endif %}
- schedule
@@ -178,8 +180,8 @@ base:
- elasticsearch
- curator
- filebeat
- {%- if OSQUERY != 0 %}
- - launcher
+ {%- if FLEETMASTER or FLEETNODE %}
+ - fleet.install_package
{%- endif %}
- schedule
@@ -189,8 +191,8 @@ base:
- sensor
- master
- auth
- {%- if OSQUERY != 0 %}
- - launcher
+ {%- if FLEETMASTER or FLEETNODE %}
+ - fleet.install_package
{%- endif %}
- schedule
@@ -206,7 +208,7 @@ base:
- idstools
- redis
- auth
- {%- if OSQUERY != 0 %}
+ {%- if FLEETMASTER or FLEETNODE %}
- mysql
{%- endif %}
{%- if WAZUH != 0 %}
@@ -220,9 +222,9 @@ base:
- filebeat
- utility
- schedule
- {%- if OSQUERY != 0 %}
+ {%- if FLEETMASTER or FLEETNODE %}
- fleet
- - launcher
+ - fleet.install_package
{%- endif %}
- soctopus
{%- if THEHIVE != 0 %}
@@ -251,8 +253,8 @@ base:
- elasticsearch
- curator
- filebeat
- {%- if OSQUERY != 0 %}
- - launcher
+ {%- if FLEETMASTER or FLEETNODE %}
+ - fleet.install_package
{%- endif %}
- pcap
- suricata
@@ -261,3 +263,14 @@ base:
{%- endif %}
- filebeat
- schedule
+
+ '*_fleet':
+ - ca
+ - ssl
+ - common
+ - firewall
+ - mysql
+ - redis
+ - fleet
+ - fleet.install_package
+ - filebeat
diff --git a/setup/so-functions b/setup/so-functions
index 0d677942d..d7cf4c387 100755
--- a/setup/so-functions
+++ b/setup/so-functions
@@ -1,6 +1,6 @@
#!/bin/bash
-# Copyright 2014,2015,2016,2017,2018,2019 Security Onion Solutions, LLC
+# 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
@@ -87,6 +87,8 @@ auth_pillar(){
echo "auth:" >> /opt/so/saltstack/pillar/auth.sls
echo " mysql: $MYSQLPASS" >> /opt/so/saltstack/pillar/auth.sls
echo " fleet: $FLEETPASS" >> /opt/so/saltstack/pillar/auth.sls
+ echo " fleet_jwt: $FLEETJWT" >> /opt/so/saltstack/pillar/auth.sls
+ echo " fleet_enroll-secret: False" >> /opt/so/saltstack/pillar/auth.sls
fi
}
@@ -240,6 +242,9 @@ configure_minion() {
elif [ $TYPE == 'helix' ]; then
echo "master: $HOSTNAME" > /etc/salt/minion
echo "id: $MINION_ID" >> /etc/salt/minion
+ elif [ $TYPE == 'fleet' ]; then
+ echo "master: $MSRV" > /etc/salt/minion
+ echo "id: $MINION_ID" >> /etc/salt/minion
else
echo "master: $MSRV" > /etc/salt/minion
echo "id: $MINION_ID" >> /etc/salt/minion
@@ -577,10 +582,23 @@ fireeye_pillar() {
}
+fleet_pillar() {
+
+ PILLARFILE=$TMP/pillar/minions/$MINION_ID.sls
+
+ # Create the fleet pillar
+ touch $PILLARFILE
+ echo "fleet:" >> $PILLARFILE
+ echo " mainip: $MAINIP" >> $PILLARFILE
+ echo " master: $MSRV" >> $PILLARFILE
+ echo "" >> $PILLARFILE
+}
+
generate_passwords(){
# Generate Random Passwords for Things
MYSQLPASS=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1)
FLEETPASS=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1)
+ FLEETJWT=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1)
HIVEKEY=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1)
CORTEXKEY=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1)
CORTEXORGUSERKEY=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1)
@@ -760,7 +778,9 @@ master_static() {
echo " cortexorgname: SecurityOnion" >> /opt/so/saltstack/pillar/static.sls
echo " cortexorguser: soadmin" >> /opt/so/saltstack/pillar/static.sls
echo " cortexorguserkey: $CORTEXORGUSERKEY" >> /opt/so/saltstack/pillar/static.sls
- echo " fleetsetup: 0" >> /opt/so/saltstack/pillar/static.sls
+ echo " fleet_master: False" >> /opt/so/saltstack/pillar/static.sls
+ echo " fleet_node: False" >> /opt/so/saltstack/pillar/static.sls
+ echo " fleet_packages-timestamp: N/A" >> /opt/so/saltstack/pillar/static.sls
echo " sensoronikey: $SENSORONIKEY" >> /opt/so/saltstack/pillar/static.sls
if [[ $MASTERUPDATES == 'MASTER' ]]; then
echo " masterupdate: 1" >> /opt/so/saltstack/pillar/static.sls
@@ -1060,6 +1080,8 @@ EOF
if [ $INSTALLTYPE == 'MASTER' ] || [ $INSTALLTYPE == 'EVAL' ] || [ $INSTALLTYPE == 'HELIXSENSOR' ] || [ $INSTALLTYPE == 'MASTERSEARCH' ]; then
yum -y install salt-master-2019.2.3 python3 python36-m2crypto salt-minion-2019.2.3 python36-dateutil python36-mysql python36-docker
systemctl enable salt-master
+ elif [ $INSTALLTYPE == 'FLEET' ]; then
+ yum -y install salt-minion-2019.2.3 python3 python36-m2crypto python36-dateutil python36-docker python36-mysql
else
yum -y install salt-minion-2019.2.3 python3 python36-m2crypto python36-dateutil python36-docker
fi
@@ -1132,7 +1154,7 @@ EOF
echo "Using apt-key add to add SALTSTACK-GPG-KEY.pub and GPG-KEY-WAZUH"
apt-key add $TMP/gpg/SALTSTACK-GPG-KEY.pub
apt-key add $TMP/gpg/GPG-KEY-WAZUH
- echo "deb http://repo.saltstack.com/apt/ubuntu/$UVER/amd64/latest $OSVER main" > /etc/apt/sources.list.d/saltstack.list
+ echo "deb http://repo.saltstack.com/apt/ubuntu/$UVER/amd64/2019.2 $OSVER main" > /etc/apt/sources.list.d/saltstack.list
echo "deb https://packages.wazuh.com/3.x/apt/ stable main" | tee /etc/apt/sources.list.d/wazuh.list
# Initialize the new repos
apt-get update >> $SETUPLOG 2>&1
@@ -1281,7 +1303,7 @@ set_hostname() {
echo "::1 localhost localhost.localdomain localhost6 localhost6.localdomain6" >> /etc/hosts
echo $HOSTNAME > /etc/hostname
HOSTNAME=$(cat /etc/hostname)
- if [ $INSTALLTYPE != 'MASTER' || $INSTALLTYPE != 'EVAL' || $INSTALLTYPE == 'HELIXSENSOR' || $INSTALLTYPE == 'MASTERSEARCH' ]; then
+ if [[ ! $INSTALLTYPE =~ ^(MASTER|EVAL|HELIXSENSOR|MASTERSEARCH)$ ]]; then
if [[ $TESTHOST = *"not found"* ]] || [ -z $TESTHOST ] || [[ $TESTHOST = *"connection timed out"* ]]; then
if ! grep -q $MSRVIP /etc/hosts; then
echo "$MSRVIP $MSRV" >> /etc/hosts
@@ -1347,6 +1369,10 @@ set_initial_firewall_policy() {
ssh -i /root/.ssh/so.key socore@$MSRV sudo /opt/so/saltstack/pillar/data/addtotab.sh nodestab $MINION_ID $MAINIP $CPUCORES $RANDOMUID $MAININT $FSROOT $FSNSM
fi
+ if [ $INSTALLTYPE == 'FLEET' ]; then
+ ssh -i /root/.ssh/so.key socore@$MSRV sudo /opt/so/saltstack/pillar/firewall/addfirewall.sh minions $MAINIP
+ fi
+
if [ $INSTALLTYPE == 'PARSINGNODE' ]; then
echo "blah"
fi
diff --git a/setup/so-setup b/setup/so-setup
index d9d10cf8c..e6a3f4708 100755
--- a/setup/so-setup
+++ b/setup/so-setup
@@ -1,6 +1,6 @@
#!/bin/bash
-# Copyright 2014,2015,2016,2017,2018,2019 Security Onion Solutions, LLC
+# 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
@@ -928,12 +928,77 @@ if (whiptail_you_sure) ; then
fi
+###########################
+### Standalone Fleet ###
+###########################
-
-
-
-
-
+ if [ $INSTALLTYPE == 'FLEET' ]; then
+ whiptail_management_server
+ whiptail_master_updates
+ whiptail_make_changes
+ set_updates
+ set_hostname
+ clear_master
+ mkdir -p /nsm
+ get_filesystem_root
+ get_filesystem_nsm
+ if [ $INSTALLMETHOD == iso ]; then
+ add_admin_user
+ disable_onion_user
+ fi
+ copy_ssh_key >> $SETUPLOG 2>&1
+ {
+ sleep 0.5
+ echo -e "XXX\n0\nSetting Initial Firewall Policy... \nXXX"
+ set_initial_firewall_policy >> $SETUPLOG 2>&1
+ #echo -e "XXX\n4\nGenerating Fleet Pillar... \nXXX"
+ fleet_pillar >> $SETUPLOG 2>&1
+ echo -e "XXX\n5\nInstalling mysql dependencies for saltstack... \nXXX"
+ salt_install_mysql_deps >> $SETUPLOG 2>&1
+ echo "** Generating the patch pillar **" >> $SETUPLOG
+ patch_pillar >> $SETUPLOG 2>&1
+ node_pillar >> $SETUPLOG 2>&1
+ echo -e "XXX\n5\nInstalling Salt Components... \nXXX"
+ saltify >> $SETUPLOG 2>&1
+ echo -e "XXX\n20\nInstalling Docker... \nXXX"
+ docker_install >> $SETUPLOG 2>&1
+ echo -e "XXX\n22\nConfiguring Salt Minion... \nXXX"
+ configure_minion fleet >> $SETUPLOG 2>&1
+ echo -e "XXX\n24\nCopying Minion Pillars to Master... \nXXX"
+ copy_minion_tmp_files >> $SETUPLOG 2>&1
+ echo -e "XXX\n25\nSending Salt Key to Master... \nXXX"
+ salt_firstcheckin >> $SETUPLOG 2>&1
+ echo -e "XXX\n26\nTelling the Master to Accept Key... \nXXX"
+ # Accept the Salt Key
+ accept_salt_key_remote >> $SETUPLOG 2>&1
+ echo -e "XXX\n27\nApplying SSL Certificates... \nXXX"
+ salt-call state.apply ca >> $SETUPLOG 2>&1
+ salt-call state.apply ssl >> $SETUPLOG 2>&1
+ echo -e "XXX\n35\nInstalling Core Components... \nXXX"
+ salt-call state.apply common >> $SETUPLOG 2>&1
+ salt-call state.apply firewall >> $SETUPLOG 2>&1
+ echo -e "XXX\n50\nInstalling MySQL... \nXXX"
+ salt-call state.apply mysql >> $SETUPLOG 2>&1
+ echo -e "XXX\n50\nInstalling Redis... \nXXX"
+ salt-call state.apply redis >> $SETUPLOG 2>&1
+ echo -e "XXX\n60\nInstalling Fleet... \nXXX"
+ salt-call state.apply fleet >> $SETUPLOG 2>&1
+ checkin_at_boot >> $SETUPLOG 2>&1
+ echo -e "XX\n97\nFinishing touches... \nXXX"
+ filter_unused_nics >> $SETUPLOG 2>&1
+ network_setup >> $SETUPLOG 2>&1
+ echo -e "XXX\n98\nVerifying Setup... \nXXX"
+ salt-call state.highstate >> $SETUPLOG 2>&1
+ } |whiptail --title "Hybrid Hunter Install" --gauge "Please wait while installing" 6 60 0
+ GOODSETUP=$(tail -10 $SETUPLOG | grep Failed | awk '{ print $2}')
+ if [[ $GOODSETUP == '0' ]]; then
+ whiptail_setup_complete
+ shutdown -r now
+ else
+ whiptail_setup_failed
+ shutdown -r now
+ fi
+ fi
else
diff --git a/setup/so-whiptail b/setup/so-whiptail
index e828d39dc..2769150cd 100755
--- a/setup/so-whiptail
+++ b/setup/so-whiptail
@@ -256,12 +256,12 @@ whiptail_install_type() {
"MASTERSEARCH" "Master + Search Node" OFF \
"HEAVYNODE" "Sensor + Search Node" OFF \
"HELIXSENSOR" "Connect this sensor to FireEye Helix" OFF \
- "PARSINGNODE" "TODO Add a dedicated Parsing Node" OFF \
+ "FLEET" "Dedicated Fleet Osquery Node" OFF \
"HOTNODE" "TODO Add Hot Node (Search Node without Parsing)" OFF \
"WARMNODE" "TODO Add Warm Node to existing Hot or Search node" OFF \
"WAZUH" "TODO Stand Alone Wazuh Node" OFF \
"STRELKA" "TODO Stand Alone Strelka Node" OFF \
- "FLEET" "TODO Stand Alone Fleet OSQuery Node" OFF 3>&1 1>&2 2>&3 )
+ "PARSINGNODE" "TODO Add a dedicated Parsing Node" OFF 3>&1 1>&2 2>&3 )
local exitstatus=$?
whiptail_check_exitstatus $exitstatus
@@ -371,7 +371,7 @@ whiptail_management_server() {
# See if it resolves. Otherwise prompt to add to host file
TESTHOST=$(host $MSRV)
- if [[ $TESTHOST = *"not found"* ]] || [[ $TESTHOST = *"connection timed out"* ]]; then
+ if [[ $TESTHOST = *"not found"* ]] || [ -z $TESTHOST ] || [[ $TESTHOST = *"connection timed out"* ]]; then
add_master_hostfile
fi