Merge remote-tracking branch 'remotes/origin/dev' into issue/90

This commit is contained in:
m0duspwnens
2020-03-25 09:03:16 -04:00
49 changed files with 854 additions and 165 deletions

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

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

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

View File

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

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

View File

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