Feature/Fleet-Standalone

This commit is contained in:
Josh Brower
2020-03-24 20:57:24 -04:00
parent e4e598f0be
commit 9bcba41882
49 changed files with 854 additions and 165 deletions

View File

@@ -57,3 +57,7 @@ pillar_roots:
peer: peer:
.*: .*:
- x509.sign_remote_certificate - x509.sign_remote_certificate
reactor:
- 'so/fleet':
- salt://reactor/fleet.sls

View File

@@ -0,0 +1,3 @@
fleet_nodes:
- 127.0.0.1

View File

@@ -56,3 +56,10 @@ base:
- logstash - logstash
- logstash.helix - logstash.helix
- minions.{{ grains.id }} - minions.{{ grains.id }}
'*_fleet':
- static
- firewall.*
- data.*
- auth
- minions.{{ grains.id }}

View File

@@ -1,6 +1,7 @@
{% set VERSION = salt['pillar.get']('static:soversion', 'HH1.1.4') %} {% set VERSION = salt['pillar.get']('static:soversion', 'HH1.1.4') %}
{% set MASTER = salt['grains.get']('master') %} {% set MASTER = salt['grains.get']('master') %}
{% set GRAFANA = salt['pillar.get']('master:grafana', '0') %} {% set GRAFANA = salt['pillar.get']('master:grafana', '0') %}
{% set FLEETMASTER = salt['pillar.get']('static:fleet_master', False) %}
# Add socore Group # Add socore Group
socoregroup: socoregroup:
group.present: group.present:
@@ -142,6 +143,9 @@ so-core:
- port_bindings: - port_bindings:
- 80:80 - 80:80
- 443:443 - 443:443
{%- if FLEETMASTER %}
- 8090:8090
{%- endif %}
- watch: - watch:
- file: /opt/so/conf/nginx/nginx.conf - file: /opt/so/conf/nginx/nginx.conf

View File

@@ -1,4 +1,5 @@
{%- set masterip = salt['pillar.get']('master:mainip', '') %} {%- set masterip = salt['pillar.get']('master:mainip', '') %}
{%- set FLEET_MASTER = salt['pillar.get']('static:fleet_master') %}
# For more information on configuration, see: # For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/ # * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/
@@ -63,6 +64,29 @@ http {
return 301 https://$host$request_uri; 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. # 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/ { location /fleet/ {
proxy_pass https://{{ masterip }}:8080/fleet/; proxy_pass https://{{ masterip }}:8080;
proxy_read_timeout 90; proxy_read_timeout 90;
proxy_connect_timeout 90; proxy_connect_timeout 90;
proxy_set_header Host $host; proxy_set_header Host $host;

View File

@@ -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 {
}
}
}

View File

@@ -1,4 +1,5 @@
{%- set masterip = salt['pillar.get']('master:mainip', '') %} {%- set masterip = salt['pillar.get']('master:mainip', '') %}
{%- set FLEET_MASTER = salt['pillar.get']('static:fleet_master') %}
# For more information on configuration, see: # For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/ # * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/
@@ -63,6 +64,29 @@ http {
return 301 https://$host$request_uri; 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. # 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/ { location /fleet/ {
rewrite /fleet/(.*) /$1 break; proxy_pass https://{{ masterip }}:8080;
auth_request /so-auth/api/auth/;
proxy_pass https://{{ masterip }}:8080/;
proxy_read_timeout 90; proxy_read_timeout 90;
proxy_connect_timeout 90; proxy_connect_timeout 90;
proxy_set_header Host $host; proxy_set_header Host $host;

View File

@@ -1,4 +1,5 @@
{%- set masterip = salt['pillar.get']('master:mainip', '') %} {%- set masterip = salt['pillar.get']('master:mainip', '') %}
{%- set FLEET_MASTER = salt['pillar.get']('static:fleet_master') %}
# For more information on configuration, see: # For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/ # * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/
@@ -63,6 +64,29 @@ http {
return 301 https://$host$request_uri; 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. # 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/ { location /fleet/ {
rewrite /fleet/(.*) /$1 break; proxy_pass https://{{ masterip }}:8080;
auth_request /so-auth/api/auth/;
proxy_pass https://{{ masterip }}:8080/;
proxy_read_timeout 90; proxy_read_timeout 90;
proxy_connect_timeout 90; proxy_connect_timeout 90;
proxy_set_header Host $host; proxy_set_header Host $host;

View File

@@ -56,7 +56,7 @@ if [ "$SKIP" -eq 0 ]; then
echo "" echo ""
echo "[a] - Analyst - ports 80/tcp and 443/tcp" echo "[a] - Analyst - ports 80/tcp and 443/tcp"
echo "[b] - Logstash Beat - port 5044/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 "[w] - Wazuh endpoint - port 1514"
echo "" echo ""
echo "Please enter your selection (a - analyst, b - beats, o - osquery, w - wazuh):" echo "Please enter your selection (a - analyst, b - beats, o - osquery, w - wazuh):"

View File

@@ -26,6 +26,8 @@
{%- set pillar_val = 'sensor' -%} {%- set pillar_val = 'sensor' -%}
{%- elif (salt['grains.get']('role') == 'so-eval') -%} {%- elif (salt['grains.get']('role') == 'so-eval') -%}
{%- set pillar_val = 'eval' -%} {%- set pillar_val = 'eval' -%}
{%- elif (salt['grains.get']('role') == 'so-fleet') -%}
{%- set pillar_val = 'fleet' -%}
{%- elif (salt['grains.get']('role') == 'so-helix') -%} {%- elif (salt['grains.get']('role') == 'so-helix') -%}
{%- set pillar_val = 'helix' -%} {%- set pillar_val = 'helix' -%}
{%- elif (salt['grains.get']('role') == 'so-node') -%} {%- elif (salt['grains.get']('role') == 'so-node') -%}

View File

@@ -8,8 +8,9 @@
{%- set HOSTNAME = salt['grains.get']('host', '') %} {%- set HOSTNAME = salt['grains.get']('host', '') %}
{%- set BROVER = salt['pillar.get']('static:broversion', 'COMMUNITY') %} {%- set BROVER = salt['pillar.get']('static:broversion', 'COMMUNITY') %}
{%- set WAZUHENABLED = salt['pillar.get']('static:wazuh_enabled', '1') %} {%- 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 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 }} name: {{ HOSTNAME }}
@@ -137,11 +138,11 @@ filebeat.inputs:
{%- endif %} {%- endif %}
{%- if FLEETENABLED == '1' %} {%- if FLEETMASTER or FLEETNODE %}
- type: log - type: log
paths: paths:
- /osquery/logs/result.log - /nsm/osquery/fleet/result.log
fields: fields:
type: osquery type: osquery

View File

@@ -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 # 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 # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # 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/log/suricata:/suricata:ro
- /opt/so/wazuh/logs/alerts:/wazuh/alerts:ro - /opt/so/wazuh/logs/alerts:/wazuh/alerts:ro
- /opt/so/wazuh/logs/archives:/wazuh/archives: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.crt:/usr/share/filebeat/filebeat.crt:ro
- /opt/so/conf/filebeat/etc/pki/filebeat.key:/usr/share/filebeat/filebeat.key: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 - /etc/ssl/certs/intca.crt:/usr/share/filebeat/intraca.crt:ro

View File

@@ -5,7 +5,10 @@
{%- set ip = salt['pillar.get']('node:mainip', '') %} {%- set ip = salt['pillar.get']('node:mainip', '') %}
{%- elif grains['role'] == 'so-sensor' %} {%- elif grains['role'] == 'so-sensor' %}
{%- set ip = salt['pillar.get']('sensor:mainip', '') %} {%- set ip = salt['pillar.get']('sensor:mainip', '') %}
{%- elif grains['role'] == 'so-fleet' %}
{%- set ip = salt['pillar.get']('node:mainip', '') %}
{%- endif %} {%- endif %}
# Quick Fix for Docker being difficult # Quick Fix for Docker being difficult
iptables_fix_docker: iptables_fix_docker:
iptables.chain_present: iptables.chain_present:
@@ -232,14 +235,14 @@ enable_masternode_mysql_3306_{{ip}}:
- position: 1 - position: 1
- save: True - save: True
enable_master_osquery_8080_{{ip}}: enable_master_osquery_8090_{{ip}}:
iptables.insert: iptables.insert:
- table: filter - table: filter
- chain: DOCKER-USER - chain: DOCKER-USER
- jump: ACCEPT - jump: ACCEPT
- proto: tcp - proto: tcp
- source: {{ ip }} - source: {{ ip }}
- dport: 8080 - dport: 8090
- position: 1 - position: 1
- save: True - save: True
@@ -466,14 +469,14 @@ enable_standard_beats_5044_{{ip}}:
# Allow OSQuery Endpoints to send their traffic # Allow OSQuery Endpoints to send their traffic
{% for ip in pillar.get('osquery_endpoint') %} {% for ip in pillar.get('osquery_endpoint') %}
enable_standard_osquery_8080_{{ip}}: enable_standard_osquery_8090_{{ip}}:
iptables.insert: iptables.insert:
- table: filter - table: filter
- chain: DOCKER-USER - chain: DOCKER-USER
- jump: ACCEPT - jump: ACCEPT
- proto: tcp - proto: tcp
- source: {{ ip }} - source: {{ ip }}
- dport: 8080 - dport: 8090
- position: 1 - position: 1
- save: True - save: True
@@ -702,3 +705,108 @@ enable_forwardnode_beats_5644_{{ip}}:
- position: 1 - position: 1
- save: True - save: True
{% endif %} {% 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 %}

View File

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

View File

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

View File

@@ -0,0 +1,107 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Security Onion - Hybrid Hunter</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="favicon-16x16.png" sizes="16x16" />
<style>
* {
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
padding-left: 30px;
padding right: 30px;
}
body {
font-family: Arial, Helvetica, sans-serif;
background-color: #2a2a2a;
}
a {
color: #f2f2f2;
text-align: left;
padding: 0px;
}
/* Style the top navigation bar */
.topnav {
overflow: hidden;
background-color: #333;
width: 1080px;
}
/* Style the topnav links */
.topnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
/* Change color on hover */
.topnav a:hover {
background-color: #ddd;
color: black;
}
/* Style the content */
.content {
background-color: #2a2a2a;
padding: 10px;
padding-top: 20px;
padding-left: 60px;
color: #E3DBCC;
width: 1080px;
}
/* Style the footer */
.footer {
background-color: #2a2a2a;
padding: 60px;
color: #E3DBCC;
width: 1080px;
}
</style>
</head>
<body>
<div class="topnav">
<a href="/packages/" target="_blank">Fleet</a>
<a href="https://github.com/Security-Onion-Solutions/securityonion-saltstack/wiki/FAQ" target="_blank">Fleet & Osquery Docs</a>
</div>
<div class="content">
<p><center><h1>Osquery Packages</h1></center><br>
<h2>Notes</h2>
<ul>
<li>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 <a href="https://osquery.io/downloads">osquery.io</a></li>
<li>Packages are not signed.</li>
</ul>
<BR> <h2>Downloads</h2>
<ul>
Generated: N/A
<BR><BR>Packages:
<li><a href="/packages/launcher.msi" download="msi-launcher.msi">MSI (Windows)</a></li>
<li><a href="/packages/launcher.deb" download="deb-launcher.deb">DEB (Debian)</a></li>
<li><a href="/packages/launcher.rpm" download="rpm-launcher.rpm">RPM (RPM)</a></li>
<BR><BR>Config Files:
<li><a href="/packages/launcher.flags" download="launcher.flags.txt">RPM & DEB Flag File</a></li>
<li><a href="/packages/launcher-msi.flags" download="launcher-msi.flags.txt">MSI Flag File</a></li>
</ul>
<BR><h2>Known Issues</h2>
<ul>
<li>None</li>
</ul>
</p>
</div>
</body>
</html>

View File

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

View File

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

View File

@@ -1,8 +1,25 @@
{%- set MYSQLPASS = salt['pillar.get']('auth:mysql', 'iwonttellyou') %} {%- set MYSQLPASS = salt['pillar.get']('auth:mysql', None) -%}
{%- set FLEETPASS = salt['pillar.get']('auth:fleet', 'bazinga') -%} {%- set FLEETPASS = salt['pillar.get']('auth:fleet', None) -%}
{%- set MASTERIP = salt['pillar.get']('static:masterip', '') -%} {%- set FLEETJWT = salt['pillar.get']('auth:fleet_jwt', None) -%}
{% set VERSION = salt['pillar.get']('static:soversion', 'HH1.1.4') %} {% set VERSION = salt['pillar.get']('static:soversion', 'HH1.1.4') %}
{% set MASTER = salt['grains.get']('master') %} {% 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 # Fleet Setup
fleetcdir: fleetcdir:
@@ -19,10 +36,17 @@ fleetpackcdir:
- group: 939 - group: 939
- makedirs: True - makedirs: True
fleetnsmdir:
file.directory:
- name: /nsm/osquery/fleet
- user: 939
- group: 939
- makedirs: True
fleetpacksync: fleetpacksync:
file.recurse: file.recurse:
- name: /opt/so/conf/fleet/packs - name: /opt/so/conf/fleet/packs
- source: salt://fleet/packs - source: salt://fleet/files/packs
- user: 939 - user: 939
- group: 939 - group: 939
@@ -33,24 +57,34 @@ fleetlogdir:
- group: 939 - group: 939
- makedirs: True - makedirs: True
fleetsetupscript: fleetsetupscripts:
file.managed: file.recurse:
- name: /opt/so/conf/fleet/so-fleet-setup.sh - name: /usr/sbin
- source: salt://fleet/so-fleet-setup.sh - user: 0
- group: 0
- file_mode: 755
- template: jinja
- source: salt://fleet/files/scripts
osquerypackageswebpage: osquerypackageswebpage:
file.managed: file.managed:
- name: /opt/so/conf/fleet/packages/index.html - name: /opt/so/conf/fleet/packages/index.html
- source: salt://fleet/osquery-packages.html - source: salt://fleet/files/osquery-packages.html
fleetdb: fleetdb:
mysql_database.present: mysql_database.present:
- name: fleet - name: fleet
- connection_host: {{ MAINIP }}
- connection_port: 3306
- connection_user: root
- connection_pass: {{ MYSQLPASS }}
fleetdbuser: fleetdbuser:
mysql_user.present: mysql_user.present:
- host: 172.17.0.0/255.255.0.0 - host: 172.17.0.0/255.255.0.0
- password: {{ FLEETPASS }} - password: {{ FLEETPASS }}
- connection_host: {{ MAINIP }}
- connection_port: 3306
- connection_user: root - connection_user: root
- connection_pass: {{ MYSQLPASS }} - connection_pass: {{ MYSQLPASS }}
@@ -60,6 +94,21 @@ fleetdbpriv:
- database: fleet.* - database: fleet.*
- user: fleetdbuser - user: fleetdbuser
- host: 172.17.0.0/255.255.0.0 - 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: so-fleet:
docker_container.running: docker_container.running:
@@ -68,22 +117,25 @@ so-fleet:
- port_bindings: - port_bindings:
- 0.0.0.0:8080:8080 - 0.0.0.0:8080:8080
- environment: - environment:
- KOLIDE_MYSQL_ADDRESS={{ MASTERIP }}:3306 - KOLIDE_MYSQL_ADDRESS={{ MAINIP }}:3306
- KOLIDE_REDIS_ADDRESS={{ MAINIP }}:6379
- KOLIDE_MYSQL_DATABASE=fleet - KOLIDE_MYSQL_DATABASE=fleet
- KOLIDE_MYSQL_USERNAME=fleetdbuser - KOLIDE_MYSQL_USERNAME=fleetdbuser
- KOLIDE_MYSQL_PASSWORD={{ FLEETPASS }} - KOLIDE_MYSQL_PASSWORD={{ FLEETPASS }}
- KOLIDE_REDIS_ADDRESS={{ MASTERIP }}:6379
- KOLIDE_SERVER_CERT=/ssl/server.cert - KOLIDE_SERVER_CERT=/ssl/server.cert
- KOLIDE_SERVER_KEY=/ssl/server.key - KOLIDE_SERVER_KEY=/ssl/server.key
- KOLIDE_LOGGING_JSON=true - KOLIDE_LOGGING_JSON=true
- KOLIDE_AUTH_JWT_KEY=thisisatest - KOLIDE_AUTH_JWT_KEY= {{ FLEETJWT }}
- KOLIDE_OSQUERY_STATUS_LOG_FILE=/var/log/osquery/status.log - KOLIDE_OSQUERY_STATUS_LOG_FILE=/var/log/fleet/status.log
- KOLIDE_OSQUERY_RESULT_LOG_FILE=/var/log/osquery/result.log - KOLIDE_OSQUERY_RESULT_LOG_FILE=/var/log/osquery/result.log
- KOLIDE_SERVER_URL_PREFIX=/fleet - KOLIDE_SERVER_URL_PREFIX=/fleet
- binds: - binds:
- /etc/pki/fleet.key:/ssl/server.key:ro - /etc/pki/fleet.key:/ssl/server.key:ro
- /etc/pki/fleet.crt:/ssl/server.cert: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 - /opt/so/conf/fleet/packs:/packs
- watch: - watch:
- /opt/so/conf/fleet/etc - /opt/so/conf/fleet/etc
{% endif %}

View File

@@ -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 %}

View File

@@ -0,0 +1 @@
Osquery Packages will be copied to this folder

View File

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

View File

@@ -1,2 +1,2 @@
{%- set MYSQLPASS = salt['pillar.get']('auth:mysql', 'iwonttellyou') -%} {%- set MYSQLPASS = salt['pillar.get']('auth:mysql', None) -%}
{{ MYSQLPASS }} {{ MYSQLPASS }}

View File

@@ -1,8 +1,16 @@
{%- set MYSQLPASS = salt['pillar.get']('auth:mysql', 'iwonttellyou') %} {%- set MYSQLPASS = salt['pillar.get']('auth:mysql', None) %}
{%- set FLEETPASS = salt['pillar.get']('auth:fleet', 'bazinga') %}
{%- set MASTERIP = salt['pillar.get']('static:masterip', '') %} {%- set MASTERIP = salt['pillar.get']('static:masterip', '') %}
{% set VERSION = salt['pillar.get']('static:soversion', 'HH1.1.4') %} {% set VERSION = salt['pillar.get']('static:soversion', 'HH1.1.4') %}
{% set MASTER = salt['grains.get']('master') %} {% 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 # MySQL Setup
mysqlpkgs: mysqlpkgs:
pkg.installed: pkg.installed:
@@ -50,6 +58,16 @@ mysqldatadir:
- group: 939 - group: 939
- makedirs: True - 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: so-mysql:
docker_container.running: docker_container.running:
- image: {{ MASTER }}:5000/soshybridhunter/so-mysql:{{ VERSION }} - image: {{ MASTER }}:5000/soshybridhunter/so-mysql:{{ VERSION }}
@@ -58,7 +76,7 @@ so-mysql:
- port_bindings: - port_bindings:
- 0.0.0.0:3306:3306 - 0.0.0.0:3306:3306
- environment: - environment:
- MYSQL_ROOT_HOST={{ MASTERIP }} - MYSQL_ROOT_HOST={{ MAINIP }}
- MYSQL_ROOT_PASSWORD=/etc/mypass - MYSQL_ROOT_PASSWORD=/etc/mypass
- binds: - binds:
- /opt/so/conf/mysql/etc/my.cnf:/etc/my.cnf:ro - /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 - /opt/so/log/mysql:/var/log/mysql:rw
- watch: - watch:
- /opt/so/conf/mysql/etc - /opt/so/conf/mysql/etc
{% endif %}

48
salt/reactor/fleet.sls Normal file
View File

@@ -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 {}

View File

@@ -1,5 +1,7 @@
{% set master = salt['grains.get']('master') %} {% set master = salt['grains.get']('master') %}
{% set masterip = salt['pillar.get']('static:masterip', '') %} {% 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_text = [] %}
{% set global_ca_server = [] %} {% 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:" - 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 %} {% 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 %}

View File

@@ -1,10 +1,12 @@
{%- set BROVER = salt['pillar.get']('static:broversion', 'COMMUNITY') -%} {%- 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 WAZUH = salt['pillar.get']('master:wazuh', '0') -%}
{%- set THEHIVE = salt['pillar.get']('master:thehive', '0') -%} {%- set THEHIVE = salt['pillar.get']('master:thehive', '0') -%}
{%- set PLAYBOOK = salt['pillar.get']('master:playbook', '0') -%} {%- set PLAYBOOK = salt['pillar.get']('master:playbook', '0') -%}
{%- set FREQSERVER = salt['pillar.get']('master:freq', '0') -%} {%- set FREQSERVER = salt['pillar.get']('master:freq', '0') -%}
{%- set DOMAINSTATS = salt['pillar.get']('master:domainstats', '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: base:
'*': '*':
@@ -38,8 +40,8 @@ base:
{%- endif %} {%- endif %}
- wazuh - wazuh
- filebeat - filebeat
{%- if OSQUERY != 0 %} {%- if FLEETMASTER or FLEETNODE %}
- launcher - fleet.install_package
{%- endif %} {%- endif %}
- schedule - schedule
@@ -53,7 +55,7 @@ base:
- firewall - firewall
- idstools - idstools
- auth - auth
{%- if OSQUERY != 0 %} {%- if FLEETMASTER or FLEETNODE %}
- mysql - mysql
{%- endif %} {%- endif %}
{%- if WAZUH != 0 %} {%- if WAZUH != 0 %}
@@ -67,10 +69,10 @@ base:
- zeek - zeek
- curator - curator
- elastalert - elastalert
{%- if OSQUERY != 0 %} {%- if FLEETMASTER or FLEETNODE %}
- fleet - fleet
- redis - redis
- launcher - fleet.install_package
{%- endif %} {%- endif %}
- utility - utility
- schedule - schedule
@@ -100,7 +102,7 @@ base:
- idstools - idstools
- redis - redis
- auth - auth
{%- if OSQUERY != 0 %} {%- if FLEETMASTER or FLEETNODE %}
- mysql - mysql
{%- endif %} {%- endif %}
{%- if WAZUH != 0 %} {%- if WAZUH != 0 %}
@@ -113,9 +115,9 @@ base:
- filebeat - filebeat
- utility - utility
- schedule - schedule
{%- if OSQUERY != 0 %} {%- if FLEETMASTER or FLEETNODE %}
- fleet - fleet
- launcher - fleet.install_package
{%- endif %} {%- endif %}
- soctopus - soctopus
{%- if THEHIVE != 0 %} {%- if THEHIVE != 0 %}
@@ -138,8 +140,8 @@ base:
- common - common
- firewall - firewall
- logstash - logstash
{%- if OSQUERY != 0 %} {%- if FLEETMASTER or FLEETNODE %}
- launcher - fleet.install_package
{%- endif %} {%- endif %}
- schedule - schedule
@@ -150,8 +152,8 @@ base:
- logstash - logstash
- elasticsearch - elasticsearch
- curator - curator
{%- if OSQUERY != 0 %} {%- if FLEETMASTER or FLEETNODE %}
- launcher - fleet.install_package
{%- endif %} {%- endif %}
- schedule - schedule
@@ -160,8 +162,8 @@ base:
- common - common
- firewall - firewall
- elasticsearch - elasticsearch
{%- if OSQUERY != 0 %} {%- if FLEETMASTER or FLEETNODE %}
- launcher - fleet.install_package
{%- endif %} {%- endif %}
- schedule - schedule
@@ -178,8 +180,8 @@ base:
- elasticsearch - elasticsearch
- curator - curator
- filebeat - filebeat
{%- if OSQUERY != 0 %} {%- if FLEETMASTER or FLEETNODE %}
- launcher - fleet.install_package
{%- endif %} {%- endif %}
- schedule - schedule
@@ -189,8 +191,8 @@ base:
- sensor - sensor
- master - master
- auth - auth
{%- if OSQUERY != 0 %} {%- if FLEETMASTER or FLEETNODE %}
- launcher - fleet.install_package
{%- endif %} {%- endif %}
- schedule - schedule
@@ -206,7 +208,7 @@ base:
- idstools - idstools
- redis - redis
- auth - auth
{%- if OSQUERY != 0 %} {%- if FLEETMASTER or FLEETNODE %}
- mysql - mysql
{%- endif %} {%- endif %}
{%- if WAZUH != 0 %} {%- if WAZUH != 0 %}
@@ -220,9 +222,9 @@ base:
- filebeat - filebeat
- utility - utility
- schedule - schedule
{%- if OSQUERY != 0 %} {%- if FLEETMASTER or FLEETNODE %}
- fleet - fleet
- launcher - fleet.install_package
{%- endif %} {%- endif %}
- soctopus - soctopus
{%- if THEHIVE != 0 %} {%- if THEHIVE != 0 %}
@@ -251,8 +253,8 @@ base:
- elasticsearch - elasticsearch
- curator - curator
- filebeat - filebeat
{%- if OSQUERY != 0 %} {%- if FLEETMASTER or FLEETNODE %}
- launcher - fleet.install_package
{%- endif %} {%- endif %}
- pcap - pcap
- suricata - suricata
@@ -261,3 +263,14 @@ base:
{%- endif %} {%- endif %}
- filebeat - filebeat
- schedule - schedule
'*_fleet':
- ca
- ssl
- common
- firewall
- mysql
- redis
- fleet
- fleet.install_package
- filebeat

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/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 # 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 # 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 "auth:" >> /opt/so/saltstack/pillar/auth.sls
echo " mysql: $MYSQLPASS" >> /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: $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 fi
} }
@@ -240,6 +242,9 @@ configure_minion() {
elif [ $TYPE == 'helix' ]; then elif [ $TYPE == 'helix' ]; then
echo "master: $HOSTNAME" > /etc/salt/minion echo "master: $HOSTNAME" > /etc/salt/minion
echo "id: $MINION_ID" >> /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 else
echo "master: $MSRV" > /etc/salt/minion echo "master: $MSRV" > /etc/salt/minion
echo "id: $MINION_ID" >> /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_passwords(){
# Generate Random Passwords for Things # Generate Random Passwords for Things
MYSQLPASS=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1) 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) 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) 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) 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) 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 " cortexorgname: SecurityOnion" >> /opt/so/saltstack/pillar/static.sls
echo " cortexorguser: soadmin" >> /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 " 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 echo " sensoronikey: $SENSORONIKEY" >> /opt/so/saltstack/pillar/static.sls
if [[ $MASTERUPDATES == 'MASTER' ]]; then if [[ $MASTERUPDATES == 'MASTER' ]]; then
echo " masterupdate: 1" >> /opt/so/saltstack/pillar/static.sls echo " masterupdate: 1" >> /opt/so/saltstack/pillar/static.sls
@@ -1060,6 +1080,8 @@ EOF
if [ $INSTALLTYPE == 'MASTER' ] || [ $INSTALLTYPE == 'EVAL' ] || [ $INSTALLTYPE == 'HELIXSENSOR' ] || [ $INSTALLTYPE == 'MASTERSEARCH' ]; then 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 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 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 else
yum -y install salt-minion-2019.2.3 python3 python36-m2crypto python36-dateutil python36-docker yum -y install salt-minion-2019.2.3 python3 python36-m2crypto python36-dateutil python36-docker
fi fi
@@ -1132,7 +1154,7 @@ EOF
echo "Using apt-key add to add SALTSTACK-GPG-KEY.pub and GPG-KEY-WAZUH" 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/SALTSTACK-GPG-KEY.pub
apt-key add $TMP/gpg/GPG-KEY-WAZUH 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 echo "deb https://packages.wazuh.com/3.x/apt/ stable main" | tee /etc/apt/sources.list.d/wazuh.list
# Initialize the new repos # Initialize the new repos
apt-get update >> $SETUPLOG 2>&1 apt-get update >> $SETUPLOG 2>&1
@@ -1281,7 +1303,7 @@ set_hostname() {
echo "::1 localhost localhost.localdomain localhost6 localhost6.localdomain6" >> /etc/hosts echo "::1 localhost localhost.localdomain localhost6 localhost6.localdomain6" >> /etc/hosts
echo $HOSTNAME > /etc/hostname echo $HOSTNAME > /etc/hostname
HOSTNAME=$(cat /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 [[ $TESTHOST = *"not found"* ]] || [ -z $TESTHOST ] || [[ $TESTHOST = *"connection timed out"* ]]; then
if ! grep -q $MSRVIP /etc/hosts; then if ! grep -q $MSRVIP /etc/hosts; then
echo "$MSRVIP $MSRV" >> /etc/hosts 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 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 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 if [ $INSTALLTYPE == 'PARSINGNODE' ]; then
echo "blah" echo "blah"
fi fi

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/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 # 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 # it under the terms of the GNU General Public License as published by
@@ -928,12 +928,77 @@ if (whiptail_you_sure) ; then
fi 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 else

View File

@@ -256,12 +256,12 @@ whiptail_install_type() {
"MASTERSEARCH" "Master + Search Node" OFF \ "MASTERSEARCH" "Master + Search Node" OFF \
"HEAVYNODE" "Sensor + Search Node" OFF \ "HEAVYNODE" "Sensor + Search Node" OFF \
"HELIXSENSOR" "Connect this sensor to FireEye Helix" 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 \ "HOTNODE" "TODO Add Hot Node (Search Node without Parsing)" OFF \
"WARMNODE" "TODO Add Warm Node to existing Hot or Search node" OFF \ "WARMNODE" "TODO Add Warm Node to existing Hot or Search node" OFF \
"WAZUH" "TODO Stand Alone Wazuh Node" OFF \ "WAZUH" "TODO Stand Alone Wazuh Node" OFF \
"STRELKA" "TODO Stand Alone Strelka 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=$? local exitstatus=$?
whiptail_check_exitstatus $exitstatus whiptail_check_exitstatus $exitstatus
@@ -371,7 +371,7 @@ whiptail_management_server() {
# See if it resolves. Otherwise prompt to add to host file # See if it resolves. Otherwise prompt to add to host file
TESTHOST=$(host $MSRV) 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 add_master_hostfile
fi fi