Merge branch 'dev' into feature/soctopus-conf

This commit is contained in:
William Wernert
2020-03-31 15:08:07 -04:00
49 changed files with 2321 additions and 1406 deletions

View File

@@ -17,10 +17,9 @@ eval:
- so-grafana
{% endif %}
- so-dockerregistry
- so-sensoroni
- so-soc
- so-kratos
- so-idstools
- so-auth-api
- so-auth-ui
{% if OSQUERY != '0' %}
- so-mysql
- so-fleet
@@ -89,12 +88,11 @@ master_search:
containers:
- so-core
- so-telegraf
- so-sensoroni
- so-soc
- so-kratos
- so-acng
- so-idstools
- so-redis
- so-auth-api
- so-auth-ui
- so-logstash
- so-elasticsearch
- so-curator
@@ -135,12 +133,11 @@ master:
- so-influxdb
- so-grafana
{% endif %}
- so-sensoroni
- so-soc
- so-kratos
- so-acng
- so-idstools
- so-redis
- so-auth-api
- so-auth-ui
- so-elasticsearch
- so-logstash
- so-kibana

View File

@@ -0,0 +1,5 @@
healthcheck:
enabled: False
schedule: 10
checks:
- zeek

View File

@@ -0,0 +1,5 @@
healthcheck:
enabled: False
schedule: 10
checks:
- zeek

View File

@@ -13,6 +13,7 @@ base:
- static
- firewall.*
- brologs
- healthcheck.sensor
- minions.{{ grains.id }}
'*_master or *_mastersearch':
@@ -20,7 +21,6 @@ base:
- static
- firewall.*
- data.*
- auth
- minions.{{ grains.id }}
'*_master':
@@ -32,9 +32,9 @@ base:
- firewall.*
- data.*
- brologs
- auth
- logstash
- logstash.eval
- healthcheck.eval
- minions.{{ grains.id }}
'*_node':
@@ -61,5 +61,4 @@ base:
- static
- firewall.*
- data.*
- auth
- minions.{{ grains.id }}

View File

@@ -0,0 +1,76 @@
#!py
import logging
import sys
allowed_functions = ['zeek']
states_to_apply = []
def apply_states(states=''):
calling_func = sys._getframe().f_back.f_code.co_name
logging.debug('healthcheck module: apply_states function caller: %s' % calling_func)
if not states:
states = ','.join(states_to_apply)
if states:
logging.info('healthcheck module: apply_states states: %s' % str(states))
__salt__['state.apply'](states)
def docker_restart(container):
try:
stopdocker = __salt__['docker.rm'](container, 'stop=True')
except Exception as e:
logging.error('healthcheck module: %s' % e)
def run(checks=''):
retval = []
calling_func = sys._getframe().f_back.f_code.co_name
logging.debug('healthcheck module: run function caller: %s' % calling_func)
if checks:
checks = checks.split(',')
else:
checks = __salt__['pillar.get']('healthcheck:checks', {})
logging.debug('healthcheck module: run checks to be run: %s' % str(checks))
for check in checks:
if check in allowed_functions:
retval.append(check)
check = getattr(sys.modules[__name__], check)
check()
else:
logging.warning('healthcheck module: attempted to run function %s' % check)
# If you want to apply states at the end of the run,
# be sure to append the state name to states_to_apply[]
apply_states()
return retval
def zeek():
calling_func = sys._getframe().f_back.f_code.co_name
logging.debug('healthcheck module: zeek function caller: %s' % calling_func)
retcode = __salt__['zeekctl.status'](verbose=False)
logging.debug('zeekctl.status retcode: %i' % retcode)
if retcode:
docker_restart('so-zeek')
states_to_apply.append('zeek')
zeek_restarted = True
else:
zeek_restarted = False
if calling_func == 'execute':
apply_states()
__salt__['telegraf.send']('healthcheck zeek_restarted=%s' % str(zeek_restarted))
return 'zeek_restarted: %s' % str(zeek_restarted)

16
salt/_modules/telegraf.py Normal file
View File

@@ -0,0 +1,16 @@
#!py
import logging
import socket
def send(data):
mainint = __salt__['pillar.get']('node:mainint')
mainip = __salt__['grains.get']('ip_interfaces').get(mainint)[0]
dstport = 8094
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sent = sock.sendto(data.encode('utf-8'), (mainip, dstport))
return sent

View File

@@ -134,10 +134,13 @@ def start():
return retval
def status():
def status(verbose=True):
cmd = "runuser -l zeek -c '/opt/zeek/bin/zeekctl status'"
retval = __salt__['docker.run']('so-zeek', cmd)
if not verbose:
retval = __context__['retcode']
return retval

View File

@@ -2,6 +2,7 @@
{% set MASTER = salt['grains.get']('master') %}
{% set GRAFANA = salt['pillar.get']('master:grafana', '0') %}
{% set FLEETMASTER = salt['pillar.get']('static:fleet_master', False) %}
{% set FLEETNODE = salt['pillar.get']('static:fleet_node', False) %}
# Add socore Group
socoregroup:
group.present:
@@ -103,13 +104,6 @@ nginxconf:
- template: jinja
- source: salt://common/nginx/nginx.conf.{{ grains.role }}
copyindex:
file.managed:
- name: /opt/so/conf/nginx/index.html
- user: 939
- group: 939
- source: salt://common/nginx/index.html
nginxlogdir:
file.directory:
- name: /opt/so/log/nginx/
@@ -132,7 +126,6 @@ so-core:
- binds:
- /opt/so:/opt/so:rw
- /opt/so/conf/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- /opt/so/conf/nginx/index.html:/opt/socore/html/index.html:ro
- /opt/so/log/nginx/:/var/log/nginx:rw
- /opt/so/tmp/nginx/:/var/lib/nginx:rw
- /opt/so/tmp/nginx/:/run:rw
@@ -143,7 +136,7 @@ so-core:
- port_bindings:
- 80:80
- 443:443
{%- if FLEETMASTER %}
{%- if FLEETMASTER or FLEETNODE %}
- 8090:8090
{%- endif %}
- watch:
@@ -191,6 +184,8 @@ so-telegraf:
- HOST_SYS=/host/sys
- HOST_MOUNT_PREFIX=/host
- network_mode: host
- port_bindings:
- 127.0.0.1:8094:8094
- binds:
- /opt/so/log/telegraf:/var/log/telegraf:rw
- /opt/so/conf/telegraf/etc/telegraf.conf:/etc/telegraf/telegraf.conf:ro
@@ -312,7 +307,9 @@ grafanaconf:
- source: salt://common/grafana/etc
{% if salt['pillar.get']('mastertab', False) %}
{%- for SN, SNDATA in salt['pillar.get']('mastertab', {}).items() %}
{% for SN, SNDATA in salt['pillar.get']('mastertab', {}).items() %}
{% set NODETYPE = SN.split('_')|last %}
{% set SN = SN | regex_replace('_' ~ NODETYPE, '') %}
dashboard-master:
file.managed:
- name: /opt/so/conf/grafana/grafana_dashboards/master/{{ SN }}-Master.json
@@ -329,11 +326,13 @@ dashboard-master:
ROOTFS: {{ SNDATA.rootfs }}
NSMFS: {{ SNDATA.nsmfs }}
{%- endfor %}
{% endfor %}
{% endif %}
{% if salt['pillar.get']('sensorstab', False) %}
{%- for SN, SNDATA in salt['pillar.get']('sensorstab', {}).items() %}
{% for SN, SNDATA in salt['pillar.get']('sensorstab', {}).items() %}
{% set NODETYPE = SN.split('_')|last %}
{% set SN = SN | regex_replace('_' ~ NODETYPE, '') %}
dashboard-{{ SN }}:
file.managed:
- name: /opt/so/conf/grafana/grafana_dashboards/forward_nodes/{{ SN }}-Sensor.json
@@ -354,7 +353,9 @@ dashboard-{{ SN }}:
{% endif %}
{% if salt['pillar.get']('nodestab', False) %}
{%- for SN, SNDATA in salt['pillar.get']('nodestab', {}).items() %}
{% for SN, SNDATA in salt['pillar.get']('nodestab', {}).items() %}
{% set NODETYPE = SN.split('_')|last %}
{% set SN = SN | regex_replace('_' ~ NODETYPE, '') %}
dashboardsearch-{{ SN }}:
file.managed:
- name: /opt/so/conf/grafana/grafana_dashboards/search_nodes/{{ SN }}-Node.json
@@ -375,7 +376,9 @@ dashboardsearch-{{ SN }}:
{% endif %}
{% if salt['pillar.get']('evaltab', False) %}
{%- for SN, SNDATA in salt['pillar.get']('evaltab', {}).items() %}
{% for SN, SNDATA in salt['pillar.get']('evaltab', {}).items() %}
{% set NODETYPE = SN.split('_')|last %}
{% set SN = SN | regex_replace('_' ~ NODETYPE, '') %}
dashboard-{{ SN }}:
file.managed:
- name: /opt/so/conf/grafana/grafana_dashboards/eval/{{ SN }}-Node.json

View File

@@ -4,7 +4,6 @@
# * 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;
@@ -107,10 +106,42 @@ http {
# Load configuration files for the default server block.
#include /etc/nginx/default.d/*.conf;
#location / {
# try_files $uri $uri.html /index.html;
# }
location ~* (^/login/|^/js/.*|^/css/.*|^/images/.*) {
proxy_pass http://{{ masterip }}:9822;
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 "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location / {
auth_request /auth/sessions/whoami;
proxy_pass http://{{ masterip }}:9822/;
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 "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /auth/ {
rewrite /auth/(.*) /$1 break;
proxy_pass http://{{ masterip }}:4433/;
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 "";
}
location /grafana/ {
rewrite /grafana/(.*) /$1 break;
proxy_pass http://{{ masterip }}:3000/;
@@ -124,7 +155,7 @@ http {
}
location /kibana/ {
auth_request /so-auth/api/auth/;
auth_request /auth/sessions/whoami;
rewrite /kibana/(.*) /$1 break;
proxy_pass http://{{ masterip }}:5601/;
proxy_read_timeout 90;
@@ -162,7 +193,7 @@ http {
location /navigator/ {
auth_request /so-auth/api/auth/;
auth_request /auth/sessions/whoami;
proxy_pass http://{{ masterip }}:4200/navigator/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
@@ -219,22 +250,8 @@ http {
}
location /sensoroni/ {
auth_request /so-auth/api/auth/;
proxy_pass http://{{ masterip }}:9822/;
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 "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /kibana/app/sensoroni/ {
rewrite ^/kibana/app/sensoroni/(.*) /sensoroni/$1 permanent;
location /kibana/app/soc/ {
rewrite ^/kibana/app/soc/(.*) /soc/$1 permanent;
}
location /kibana/app/fleet/ {
@@ -255,23 +272,11 @@ http {
proxy_set_header Proxy "";
}
location /so-auth/loginpage/ {
proxy_pass http://{{ masterip }}:4242/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /so-auth/api/ {
proxy_pass http://{{ masterip }}:5656/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
}
error_page 401 = @error401;
location @error401 {
add_header Set-Cookie "NSREDIRECT=http://{{ masterip }}$request_uri;Domain={{ masterip }};Path=/;Max-Age=60000";
return 302 http://{{ masterip }}/so-auth/loginpage/;
return 302 /auth/self-service/browser/flows/login;
}
error_page 404 /404.html;

View File

@@ -65,7 +65,7 @@ http {
server {
listen 443 ssl http2 default_server;
server_name _;
root /opt/socore/html;
root /opt/socore/html/packages;
index index.html;
ssl_certificate "/etc/pki/nginx/server.crt";

View File

@@ -4,7 +4,6 @@
# * 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;
@@ -59,9 +58,9 @@ http {
# }
#}
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
{% if FLEET_MASTER %}
@@ -107,13 +106,45 @@ http {
# Load configuration files for the default server block.
#include /etc/nginx/default.d/*.conf;
#location / {
# try_files $uri $uri.html /index.html;
# }
location ~* (^/login/|^/js/.*|^/css/.*|^/images/.*) {
proxy_pass http://{{ masterip }}:9822;
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 "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location / {
auth_request /auth/sessions/whoami;
proxy_pass http://{{ masterip }}:9822/;
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 "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /auth/ {
rewrite /auth/(.*) /$1 break;
proxy_pass http://{{ masterip }}:4433/;
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 "";
}
location /grafana/ {
rewrite /grafana/(.*) /$1 break;
proxy_pass http://{{ masterip }}:3000/;
rewrite /grafana/(.*) /$1 break;
proxy_pass http://{{ masterip }}:3000/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
@@ -124,9 +155,9 @@ http {
}
location /kibana/ {
auth_request /so-auth/api/auth/;
rewrite /kibana/(.*) /$1 break;
proxy_pass http://{{ masterip }}:5601/;
auth_request /auth/sessions/whoami;
rewrite /kibana/(.*) /$1 break;
proxy_pass http://{{ masterip }}:5601/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
@@ -150,7 +181,7 @@ http {
}
location /playbook/ {
proxy_pass http://{{ masterip }}:3200/playbook/;
proxy_pass http://{{ masterip }}:3200/playbook/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
@@ -160,9 +191,10 @@ http {
}
location /navigator/ {
auth_request /so-auth/api/auth/;
proxy_pass http://{{ masterip }}:4200/navigator/;
auth_request /auth/sessions/whoami;
proxy_pass http://{{ masterip }}:4200/navigator/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
@@ -184,10 +216,10 @@ http {
}
location /thehive/ {
proxy_pass http://{{ masterip }}:9000/thehive/;
proxy_pass http://{{ masterip }}:9000/thehive/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_http_version 1.1; # this is essential for chunked responses to work
proxy_http_version 1.1; # this is essential for chunked responses to work
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@@ -196,19 +228,19 @@ http {
}
location /cortex/ {
proxy_pass http://{{ masterip }}:9001/cortex/;
proxy_pass http://{{ masterip }}:9001/cortex/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_http_version 1.1; # this is essential for chunked responses to work
proxy_http_version 1.1; # this is essential for chunked responses to work
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 /soctopus/ {
proxy_pass http://{{ masterip }}:7000/;
proxy_pass http://{{ masterip }}:7000/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
@@ -218,22 +250,8 @@ http {
}
location /sensoroni/ {
auth_request /so-auth/api/auth/;
proxy_pass http://{{ masterip }}:9822/;
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 "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /kibana/app/sensoroni/ {
rewrite ^/kibana/app/sensoroni/(.*) /sensoroni/$1 permanent;
location /kibana/app/soc/ {
rewrite ^/kibana/app/soc/(.*) /soc/$1 permanent;
}
location /kibana/app/fleet/ {
@@ -244,36 +262,21 @@ http {
rewrite ^/kibana/app/soctopus/(.*) /soctopus/$1 permanent;
}
location /sensoroniagents/ {
proxy_pass http://{{ masterip }}:9822/;
proxy_pass http://{{ masterip }}:9822/;
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 "";
}
location /so-auth/loginpage/ {
proxy_pass http://{{ masterip }}:4242/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /so-auth/api/ {
proxy_pass http://{{ masterip }}:5656/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
}
error_page 401 = @error401;
location @error401 {
add_header Set-Cookie "NSREDIRECT=http://{{ masterip }}$request_uri;Domain={{ masterip }};Path=/;Max-Age=60000";
return 302 http://{{ masterip }}/so-auth/loginpage/;
return 302 /auth/self-service/browser/flows/login;
}
error_page 404 /404.html;

View File

@@ -4,7 +4,6 @@
# * 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;
@@ -59,9 +58,9 @@ http {
# }
#}
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
{% if FLEET_MASTER %}
@@ -107,13 +106,45 @@ http {
# Load configuration files for the default server block.
#include /etc/nginx/default.d/*.conf;
#location / {
# try_files $uri $uri.html /index.html;
# }
location ~* (^/login/|^/js/.*|^/css/.*|^/images/.*) {
proxy_pass http://{{ masterip }}:9822;
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 "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location / {
auth_request /auth/sessions/whoami;
proxy_pass http://{{ masterip }}:9822/;
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 "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /auth/ {
rewrite /auth/(.*) /$1 break;
proxy_pass http://{{ masterip }}:4433/;
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 "";
}
location /grafana/ {
rewrite /grafana/(.*) /$1 break;
proxy_pass http://{{ masterip }}:3000/;
rewrite /grafana/(.*) /$1 break;
proxy_pass http://{{ masterip }}:3000/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
@@ -124,9 +155,9 @@ http {
}
location /kibana/ {
auth_request /so-auth/api/auth/;
rewrite /kibana/(.*) /$1 break;
proxy_pass http://{{ masterip }}:5601/;
auth_request /auth/sessions/whoami;
rewrite /kibana/(.*) /$1 break;
proxy_pass http://{{ masterip }}:5601/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
@@ -136,8 +167,21 @@ http {
}
location /playbook/ {
proxy_pass http://{{ masterip }}:3200/playbook/;
location /nodered/ {
proxy_pass http://{{ masterip }}:1880/;
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 Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Proxy "";
}
location /playbook/ {
proxy_pass http://{{ masterip }}:3200/playbook/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
@@ -147,9 +191,10 @@ http {
}
location /navigator/ {
auth_request /so-auth/api/auth/;
proxy_pass http://{{ masterip }}:4200/navigator/;
auth_request /auth/sessions/whoami;
proxy_pass http://{{ masterip }}:4200/navigator/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
@@ -171,10 +216,10 @@ http {
}
location /thehive/ {
proxy_pass http://{{ masterip }}:9000/thehive/;
proxy_pass http://{{ masterip }}:9000/thehive/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_http_version 1.1; # this is essential for chunked responses to work
proxy_http_version 1.1; # this is essential for chunked responses to work
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@@ -183,31 +228,19 @@ http {
}
location /cortex/ {
proxy_pass http://{{ masterip }}:9001/cortex/;
proxy_pass http://{{ masterip }}:9001/cortex/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_http_version 1.1; # this is essential for chunked responses to work
proxy_http_version 1.1; # this is essential for chunked responses to work
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 /cyberchef/ {
proxy_pass http://{{ masterip }}:9080/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_http_version 1.1; # this is essential for chunked responses to work
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 /soctopus/ {
proxy_pass http://{{ masterip }}:7000/;
proxy_pass http://{{ masterip }}:7000/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
@@ -217,22 +250,8 @@ http {
}
location /sensoroni/ {
auth_request /so-auth/api/auth/;
proxy_pass http://{{ masterip }}:9822/;
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 "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /kibana/app/sensoroni/ {
rewrite ^/kibana/app/sensoroni/(.*) /sensoroni/$1 permanent;
location /kibana/app/soc/ {
rewrite ^/kibana/app/soc/(.*) /soc/$1 permanent;
}
location /kibana/app/fleet/ {
@@ -243,36 +262,21 @@ http {
rewrite ^/kibana/app/soctopus/(.*) /soctopus/$1 permanent;
}
location /sensoroniagents/ {
proxy_pass http://{{ masterip }}:9822/;
proxy_pass http://{{ masterip }}:9822/;
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 "";
}
location /so-auth/loginpage/ {
proxy_pass http://{{ masterip }}:4242/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /so-auth/api/ {
proxy_pass http://{{ masterip }}:5656/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
}
error_page 401 = @error401;
location @error401 {
add_header Set-Cookie "NSREDIRECT=http://{{ masterip }}$request_uri;Domain={{ masterip }};Path=/;Max-Age=60000";
return 302 http://{{ masterip }}/so-auth/loginpage/;
return 302 /auth/self-service/browser/flows/login;
}
error_page 404 /404.html;
@@ -284,4 +288,4 @@ http {
}
}
}
}

View File

@@ -498,10 +498,10 @@
[[inputs.disk]]
## By default stats will be gathered for all mount points.
## Set mount_points will restrict the stats to only the specified mount points.
# mount_points = ["/"]
mount_points = ["/","/nsm"]
## Ignore mount points by filesystem type.
ignore_fs = ["tmpfs", "devtmpfs", "devfs", "overlay", "aufs", "squashfs"]
#ignore_fs = ["tmpfs", "devtmpfs", "devfs", "overlay", "aufs", "squashfs"]
# Read metrics about disk IO by device
@@ -2053,6 +2053,9 @@
# ## more about them here:
# ## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
# # data_format = "influx"
[[inputs.socket_listener]]
service_address = "udp://:8094"
data_format = "influx"
# # Statsd UDP/TCP Server

View File

@@ -1,5 +1,5 @@
#!/bin/bash
INFLUXSIZE=$(du -s -B1 /host/nsm/influxdb | awk {'print $1'}
INFLUXSIZE=$(du -s -B1 /host/nsm/influxdb | awk {'print $1'})
echo "influxsize bytes=$INFLUXSIZE"

View File

@@ -17,4 +17,4 @@
. /usr/sbin/so-common
docker exec so-soctopus python3 playbook_play-sync.py
docker exec so-soctopus python3 playbook_play-sync.py >> /opt/so/log/soctopus/so-playbook-sync.log 2>&1

View File

@@ -107,7 +107,7 @@ populate_container_lists() {
systemctl is-active --quiet docker
if [[ $? = 0 ]]; then
mapfile -t docker_raw_list < <(curl -s --unix-socket /var/run/docker.sock http:/containers/json?all=1 \
mapfile -t docker_raw_list < <(curl -s --unix-socket /var/run/docker.sock http:/v2/containers/json?all=1 \
| jq -c '.[] | { Name: .Names[0], State: .State }' \
| tr -d '/{"}')
else

201
salt/common/tools/sbin/so-user Executable file
View File

@@ -0,0 +1,201 @@
#!/bin/bash
# Copyright 2020 Security Onion Solutions. All rights reserved.
#
# This program is distributed under the terms of version 2 of the
# GNU General Public License. See LICENSE for further details.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
got_root() {
# Make sure you are root
if [ "$(id -u)" -ne 0 ]; then
echo "This script must be run using sudo!"
exit 1
fi
}
# Make sure the user is root
got_root
if [[ $# < 1 || $# > 2 ]]; then
echo "Usage: $0 <list|add|update|delete|checkpw> [email]"
echo "Note that checkpw only checks that the given password meets the minimum requirements, it does not test that it matches for an existing user."
exit 1
fi
operation=$1
email=$2
kratosUrl=${KRATOS_URL:-http://127.0.0.1:4434}
databasePath=${KRATOS_DB_PATH:-/opt/so/conf/kratos/db/db.sqlite}
argon2Iterations=${ARGON2_ITERATIONS:-3}
argon2Memory=${ARGON2_MEMORY:-14}
argon2Parallelism=${ARGON2_PARALLELISM:-2}
argon2HashSize=${ARGON2_HASH_SIZE:-32}
function fail() {
msg=$1
echo "$1"
exit 1
}
function require() {
cmd=$1
which "$1" 2>&1 > /dev/null
[[ $? != 0 ]] && fail "This script requires the following command be installed: ${cmd}"
}
# Verify this environment is capable of running this script
require "argon2"
require "jq"
require "curl"
require "openssl"
require "sqlite3"
[[ ! -f $databasePath ]] && fail "Unable to find database file; specify path via KRATOS_DB_PATH environment variable"
response=$(curl -Ss ${kratosUrl}/)
[[ "$response" != "404 page not found" ]] && fail "Unable to communicate with Kratos; specify URL via KRATOS_URL environment variable"
function findIdByEmail() {
email=$1
response=$(curl -Ss ${kratosUrl}/identities)
identityId=$(echo "${response}" | jq ".[] | select(.addresses[0].value == \"$email\") | .id")
echo $identityId
}
function validatePassword() {
password=$1
len=$(expr length "$password")
if [[ $len -lt 6 ]]; then
echo "Password does not meet the minimum requirements"
exit 2
fi
}
function updatePassword() {
identityId=$1
# Read password from stdin (show prompt only if no stdin was piped in)
test -t 0
if [[ $? == 0 ]]; then
echo "Enter new password:"
fi
read -s password
validatePassword "$password"
if [[ -n $identityId ]]; then
# Generate password hash
salt=$(openssl rand -hex 8)
passwordHash=$(echo "${password}" | argon2 ${salt} -id -t $argon2Iterations -m $argon2Memory -p $argon2Parallelism -l $argon2HashSize -e)
# Update DB with new hash
echo "update identity_credentials set config=CAST('{\"hashed_password\":\"${passwordHash}\"}' as BLOB) where identity_id=${identityId};" | sqlite3 "$databasePath"
[[ $? != 0 ]] && fail "Unable to update password"
fi
}
function listUsers() {
response=$(curl -Ss ${kratosUrl}/identities)
[[ $? != 0 ]] && fail "Unable to communicate with Kratos"
echo "${response}" | jq -r ".[] | .addresses[0].value" | sort
}
function createUser() {
email=$1
now=$(date -u +%FT%TZ)
addUserJson=$(cat <<EOF
{
"addresses": [
{
"expires_at": "2099-01-31T12:00:00Z",
"value": "${email}",
"verified": true,
"verified_at": "${now}",
"via": "so-add-user"
}
],
"traits": {"email":"${email}"},
"traits_schema_id": "default"
}
EOF
)
response=$(curl -Ss ${kratosUrl}/identities -d "$addUserJson")
[[ $? != 0 ]] && fail "Unable to communicate with Kratos"
identityId=$(echo "${response}" | jq ".id")
if [[ ${identityId} == "null" ]]; then
code=$(echo "${response}" | jq ".error.code")
[[ "${code}" == "409" ]] && fail "User already exists"
reason=$(echo "${response}" | jq ".error.message")
[[ $? == 0 ]] && fail "Unable to add user: ${reason}"
fi
updatePassword $identityId
}
function updateUser() {
email=$1
identityId=$(findIdByEmail "$email")
[[ ${identityId} == "" ]] && fail "User not found"
updatePassword $identityId
}
function deleteUser() {
email=$1
identityId=$(findIdByEmail "$email")
[[ ${identityId} == "" ]] && fail "User not found"
response=$(curl -Ss -XDELETE "${kratosUrl}/identities/$identityId")
[[ $? != 0 ]] && fail "Unable to communicate with Kratos"
}
case "${operation}" in
"add")
[[ "$email" == "" ]] && fail "Email address must be provided"
createUser "$email"
echo "Successfully added new user"
;;
"list")
listUsers
;;
"update")
[[ "$email" == "" ]] && fail "Email address must be provided"
updateUser "$email"
echo "Successfully updated user"
;;
"delete")
[[ "$email" == "" ]] && fail "Email address must be provided"
deleteUser "$email"
echo "Successfully deleted user"
;;
"checkpw")
updatePassword
echo "Password is acceptable"
;;
*)
fail "Unsupported operation: $operation"
;;
esac
exit 0

View File

@@ -1,17 +1,2 @@
#!/bin/bash
USERNAME=$1
# Make sure a username is provided
[ $# -eq 0 ] && { echo "Usage: $0 username"; exit 1; }
# If the file is there already lets create it otherwise add the user
if [ ! -f /opt/so/conf/nginx/.htpasswd ]; then
# Create the password file
htpasswd -c /opt/so/conf/nginx/.htpasswd $USERNAME
else
htpasswd /opt/so/conf/nginx/.htpasswd $USERNAME
fi
so-user add $*

View File

@@ -34,8 +34,6 @@
#fi
# Avoid starting multiple instances
if pgrep -f "so-curator-closed-delete-delete" >/dev/null; then
echo "Script is already running."
else
if ! pgrep -f "so-curator-closed-delete-delete" >/dev/null; then
/usr/sbin/so-curator-closed-delete-delete
fi

View File

@@ -37,9 +37,11 @@
},
{ "rename": { "field": "module", "target_field": "event.module", "ignore_missing": true } },
{ "rename": { "field": "dataset", "target_field": "event.dataset", "ignore_missing": true } },
{ "rename": { "field": "category", "target_field": "event.category", "ignore_missing": true } },
{ "rename": { "field": "message2.community_id", "target_field": "network.community_id", "ignore_missing": true } },
{
"remove": {
"field": [ "index_name_prefix"],
"field": [ "index_name_prefix", "message2"],
"ignore_failure": false
}
}

View File

@@ -30,9 +30,9 @@
{ "rename": { "field": "data.win.eventdata.user", "target_field": "user.name", "ignore_missing": true } },
{ "rename": { "field": "data.win.system.eventID", "target_field": "event.code", "ignore_missing": true } },
{ "rename": { "field": "predecoder.program_name", "target_field": "process.name", "ignore_missing": true } },
{ "set": { "if": "ctx.rule.level == 1", "field": "category", "value": "None" } },
{ "set": { "if": "ctx.rule.level == 2", "field": "category", "value": "System low priority notification" } },
{ "set": { "if": "ctx.rule.level == 3", "field": "category", "value": "Successful/authorized event" } },
{ "set": { "if": "ctx.rule.level == 1", "field": "rule.category", "value": "None" } },
{ "set": { "if": "ctx.rule.level == 2", "field": "rule.category", "value": "System low priority notification" } },
{ "set": { "if": "ctx.rule.level == 3", "field": "rule.category", "value": "Successful/authorized event" } },
{ "set": { "if": "ctx.rule.level == 4", "field": "rule.category", "value": "System low priority error" } },
{ "set": { "if": "ctx.rule.level == 5", "field": "rule.category", "value": "User generated error" } },
{ "set": { "if": "ctx.rule.level == 6", "field": "rule.category", "value": "Low relevance attack" } },

View File

@@ -3,12 +3,12 @@
"processors" : [
{ "rename":{ "field": "message2.proto", "target_field": "network.transport", "ignore_failure": true } },
{ "rename":{ "field": "message2.flow_id", "target_field": "event.id", "ignore_failure": true } },
{ "rename":{ "field": "message2.comunity_id", "target_field": "network.comunity_id", "ignore_failure": true } },
{ "rename":{ "field": "message2.src_ip", "target_field": "source.ip", "ignore_failure": true } },
{ "rename":{ "field": "message2.src_port", "target_field": "source.port", "ignore_failure": true } },
{ "rename":{ "field": "message2.dest_ip", "target_field": "destination.ip", "ignore_failure": true } },
{ "rename":{ "field": "message2.dest_port", "target_field": "destination.port", "ignore_failure": true } },
{ "remove": { "field": ["message2", "agent"], "ignore_failure": true } },
{ "rename": { "field": "message2.community_id", "target_field": "network.community_id", "ignore_missing": true } },
{ "remove": { "field": ["agent"], "ignore_failure": true } },
{ "pipeline": { "name": "common" } }
]
}

View File

@@ -16,7 +16,7 @@
{ "rename": { "field": "message2.id.resp_p", "target_field": "destination.port", "ignore_missing": true } },
{ "set": { "field": "server.port", "value": "{{destination.port}}" } },
{ "date": { "field": "message2.ts", "target_field": "@timestamp", "formats": ["ISO8601", "UNIX"], "ignore_failure": true } },
{ "remove": { "field": ["message2.ts", "path", "agent"], "ignore_failure": true } },
{ "remove": { "field": ["agent"], "ignore_failure": true } },
{ "pipeline": { "name": "common" } }
]
}

View File

@@ -20,7 +20,7 @@ name: {{ HOSTNAME }}
# Sets log level. The default log level is info.
# Available log levels are: error, warning, info, debug
logging.level: error
logging.level: warning
# Enable debug output for selected components. To enable all selectors use ["*"]
# Other available selectors are "beat", "publish", "service"
@@ -82,7 +82,8 @@ filebeat.inputs:
- /nsm/zeek/logs/current/{{ LOGNAME }}.log
fields:
module: zeek
dataset: {{ LOGNAME }}
dataset: {{ LOGNAME }}
category: network
processors:
- drop_fields:
fields: ["source", "prospector", "input", "offset", "beat"]
@@ -100,6 +101,7 @@ filebeat.inputs:
fields:
module: suricata
dataset: alert
category: network
processors:
- drop_fields:
@@ -118,7 +120,7 @@ filebeat.inputs:
fields:
module: ossec
dataset: alert
category: host
processors:
- drop_fields:
fields: ["source", "prospector", "input", "offset", "beat"]

View File

@@ -1,9 +1,11 @@
{% set ENROLLSECRET = salt['cmd.run']('docker exec so-fleet fleetctl get enroll-secret') %}
{%- set MAINIP = salt['pillar.get']('node:mainip') -%}
so/fleet:
event.send:
- data:
action: 'enablefleet'
hostname: {{ grains.host }}
mainip: {{ MAINIP }}
role: {{ grains.role }}
enroll-secret: {{ ENROLLSECRET }}

View File

@@ -0,0 +1,127 @@
{%- set PACKAGESTS = salt['pillar.get']('static:fleet_packages-timestamp:', 'N/A') -%}
<!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;
}
.center-content {
margin: 0 auto;
}
/* Style the top navigation bar */
.topnav {
overflow: hidden;
background-color: #333;
width: 1080px;
display: flex;
align-content: center;
}
/* Style the topnav links */
.topnav a {
margin: auto;
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="center-content">
<div class="topnav center-content">
<a href="/fleet/" target="_blank">Fleet</a>
<a href="https://github.com/Security-Onion-Solutions/securityonion-saltstack/wiki/Configuring-Osquery-with-Security-Onion" target="_blank">Osquery/Fleet Docs</a>
<a href="https://www.securityonionsolutions.com" target="_blank">Security Onion Solutions</a>
</div>
<div class="content center-content">
<p>
<div style="text-align: center;">
<h1>Security Onion - Dedicated Fleet Node</h1>
<h2>Osquery Packages</h2>
</div>
<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>
<div>
Generated: {{ PACKAGESTS }}
<br/>
<br/>
Packages:
<ul>
<li><a href="/launcher.msi" download="msi-launcher.msi">MSI (Windows)</a></li>
<li><a href="/launcher.deb" download="deb-launcher.deb">DEB (Debian)</a></li>
<li><a href="/launcher.rpm" download="rpm-launcher.rpm">RPM (RPM)</a></li>
<li><a href="/launcher.pkg" download="pkg-launcher.pkg">PKG (MacOS)</a></li>
</ul>
<br/>
<br/>
Config Files:
<ul>
<li><a href="/launcher.flags" download="launcher.flags.txt">RPM & DEB Flag File</a></li>
<li><a href="/launcher-msi.flags" download="launcher-msi.flags.txt">MSI Flag File</a></li>
</ul>
</div>
<br/>
<h2>Known Issues</h2>
<ul>
<li>None</li>
</ul>
</p>
</div>
</div>
</body>
</html>

View File

@@ -1,107 +0,0 @@
<!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

@@ -1,3 +1,4 @@
{%- set PACKAGESTS = salt['pillar.get']('static:fleet_packages-timestamp:', 'N/A') -%}
<!DOCTYPE html>
<html lang="en">
<head>
@@ -102,7 +103,7 @@ a {
<br/>
<h2>Downloads</h2>
<div>
Generated: N/A
Generated: {{ PACKAGESTS }}
<br/>
<br/>
Packages:
@@ -110,6 +111,7 @@ a {
<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>
<li><a href="/packages/launcher.pkg" download="pkg-launcher.pkg">PKG (MacOS)</a></li>
</ul>
<br/>
<br/>

View File

@@ -25,11 +25,12 @@ docker exec so-fleet /bin/sh -c 'for pack in /packs/palantir/Fleet/Endpoints/pac
# Enable Fleet
echo "Enabling Fleet..."
salt-call state.apply fleet.event_enable-fleet queue=True >> /root/fleet-setup.log
salt-call state.apply common queue=True >> /root/fleet-setup.log
# Generate osquery install packages
echo "Generating osquery install packages - will take some time..."
echo "Generating osquery install packages - this will take some time..."
salt-call state.apply fleet.event_gen-packages queue=True >> /root/fleet-setup.log
sleep 180
sleep 120
echo "Installing launcher via salt..."
salt-call state.apply fleet.install_package queue=True >> /root/fleet-setup.log

View File

@@ -50,6 +50,13 @@ fleetpacksync:
- user: 939
- group: 939
fleetpackagessync:
file.recurse:
- name: /opt/so/conf/fleet/packages
- source: salt://fleet/packages/
- user: 939
- group: 939
fleetlogdir:
file.directory:
- name: /opt/so/log/fleet
@@ -69,7 +76,12 @@ fleetsetupscripts:
osquerypackageswebpage:
file.managed:
- name: /opt/so/conf/fleet/packages/index.html
{% if FLEETARCH == "so-fleet" %}
- source: salt://fleet/files/dedicated-index.html
{% else %}
- source: salt://fleet/files/osquery-packages.html
{% endif %}
- template: jinja
fleetdb:
mysql_database.present:

View File

@@ -1,7 +1,15 @@
{%- set FLEETMASTER = salt['pillar.get']('static:fleet_master', False) -%}
{%- set FLEETNODE = salt['pillar.get']('static:fleet_node', False) -%}
{%- set FLEETHOSTNAME = salt['pillar.get']('static:fleet_hostname', False) -%}
{%- set FLEETIP = salt['pillar.get']('static:fleet_ip', False) -%}
{%- if FLEETMASTER or FLEETNODE %}
{{ FLEETHOSTNAME }}:
host.present:
- ip: {{ FLEETIP }}
- clean: True
launcherpkg:
pkg.installed:
- sources:

25
salt/healthcheck/init.sls Normal file
View File

@@ -0,0 +1,25 @@
{% set CHECKS = salt['pillar.get']('healthcheck:checks', {}) %}
{% set ENABLED = salt['pillar.get']('healthcheck:enabled', False) %}
{% set SCHEDULE = salt['pillar.get']('healthcheck:schedule', 30) %}
{% if CHECKS and ENABLED %}
{% set STATUS = ['present','enabled'] %}
{% else %}
{% set STATUS = ['absent','disabled'] %}
nohealthchecks:
test.configurable_test_state:
- name: nohealthchecks
- changes: True
- result: True
- comment: 'No checks are enabled for the healthcheck schedule'
{% endif %}
healthcheck_schedule_{{ STATUS[0] }}:
schedule.{{ STATUS[0] }}:
- name: healthcheck
- function: healthcheck.run
- minutes: {{ SCHEDULE }}
healthcheck_schedule_{{ STATUS[1] }}:
schedule.{{ STATUS[1] }}:
- name: healthcheck

File diff suppressed because one or more lines are too long

View File

@@ -1,12 +1,13 @@
#!/bin/bash
MASTER={{ MASTER }}
VERSION="HH1.1.4"
VERSION="HH1.2.1"
TRUSTED_CONTAINERS=( \
"so-core:$VERSION" \
"so-cyberchef:$VERSION" \
"so-acng:$VERSION" \
"so-sensoroni:$VERSION" \
"so-soc:$VERSION" \
"so-kratos:$VERSION" \
"so-fleet:$VERSION" \
"so-soctopus:$VERSION" \
"so-steno:$VERSION" \

View File

@@ -12,6 +12,8 @@ def run():
HOSTNAME = data['data']['hostname']
ROLE = data['data']['role']
ESECRET = data['data']['enroll-secret']
MAINIP = data['data']['mainip']
STATICFILE = '/opt/so/saltstack/pillar/static.sls'
AUTHFILE = '/opt/so/saltstack/pillar/auth.sls'
@@ -27,10 +29,20 @@ def run():
line = re.sub(r'fleet_master: \S*', f"fleet_master: True", line.rstrip())
print(line)
# Update the enroll secret
# Update the enroll secret in the auth pillar
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)
print(line)
# Update the Fleet host in the static pillar
for line in fileinput.input(STATICFILE, inplace=True):
line = re.sub(r'fleet_hostname: \S*', f"fleet_hostname: {HOSTNAME}", line.rstrip())
print(line)
# Update the Fleet IP in the static pillar
for line in fileinput.input(STATICFILE, inplace=True):
line = re.sub(r'fleet_ip: \S*', f"fleet_ip: {MAINIP}", line.rstrip())
print(line)
if ACTION == 'genpackages':
logging.info('so/fleet genpackages reactor')

View File

@@ -0,0 +1,78 @@
{%- set WEBACCESS = salt['pillar.get']('kratos:redirect', '') -%}
{%- set KRATOSKEY = salt['pillar.get']('kratos:kratoskey', '') -%}
selfservice:
strategies:
password:
enabled: true
verify:
return_to: https://{{ WEBACCESS }}/
logout:
redirect_to: https://{{ WEBACCESS }}/login/
login:
request_lifespan: 10m
after:
password:
-
job: session
-
job: redirect
config:
default_redirect_url: https://{{ WEBACCESS }}/
allow_user_defined_redirect: true
registration:
request_lifespan: 10m
after:
password:
-
job: verify
-
job: session
-
job: redirect
config:
default_redirect_url: https://{{ WEBACCESS }}/
allow_user_defined_redirect: true
log:
level: debug
format: json
secrets:
session:
- {{ KRATOSKEY }}
urls:
login_ui: https://{{ WEBACCESS }}/login/
registration_ui: https://{{ WEBACCESS }}/login/
error_ui: https://{{ WEBACCESS }}/login/
profile_ui: https://{{ WEBACCESS }}/
verify_ui: https://{{ WEBACCESS }}/
mfa_ui: https://{{ WEBACCESS }}/
self:
public: https://{{ WEBACCESS }}/auth/
admin: https://{{ WEBACCESS }}/kratos/
default_return_to: https://{{ WEBACCESS }}/
whitelisted_return_to_domains:
- http://127.0.0.1
hashers:
argon2:
parallelism: 2
memory: 16384
iterations: 3
salt_length: 16
key_length: 32
identity:
traits:
default_schema_url: file:///kratos-conf/schema.json
courier:
smtp:
connection_uri: smtps://{{ WEBACCESS }}:25

View File

@@ -0,0 +1,28 @@
{
"$id": "securityonion.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Person",
"type": "object",
"properties": {
"email": {
"type": "string",
"format": "email",
"title": "E-Mail",
"minLength": 6,
"ory.sh/kratos": {
"credentials": {
"password": {
"identifier": true
}
},
"verification": {
"via": "email"
}
}
}
},
"required": [
"email"
],
"additionalProperties": false
}

View File

@@ -0,0 +1,23 @@
{
"title": "Introducing Hybrid Hunter 1.2.1 Beta",
"changes": [
{ "summary": "New authentication framework" },
{ "summary": "New Logstash pipeline setup. Now uses multiple pipelines." },
{ "summary": "New Master + Search node type and well as a Heavy Node type in the install." },
{ "summary": "Change all nodes to point to the docker registry on the Master. This cuts down on the calls to dockerhub." },
{ "summary": "Upgraded to Zeek 3.0" },
{ "summary": "Upgraded to Elastic 7.6" },
{ "summary": "New SO Start | Stop | Restart scripts for all components (eg. `so-playbook-restart`)." },
{ "summary": "BPF support for Suricata (NIDS), Steno (PCAP) & Zeek (<a target='new' href='https://github.com/Security-Onion-Solutions/securityonion-saltstack/wiki/BPF'>More Info</a>)." },
{ "summary": "Updated Domain Stats & Frequency Server containers to Python3 & created new Salt states for them." },
{ "summary": "Added so-status script which gives an easy to read look at container status." },
{ "summary": "Manage threshold.conf for Suricata using the thresholding pillar." },
{ "summary": "The ISO now includes all the docker containers for faster install speeds." },
{ "summary": "You now set the password for the onion account during the iso install. This account is temporary and will be removed after so-setup." },
{ "summary": "Updated Helix parsers for better compatibility." },
{ "summary": "Updated telegraf docker to include curl and jq." },
{ "summary": "CVE-2020-0601 Zeek Detection Script." },
{ "summary": "ISO Install now prompts you to create a password for the onion user during imaging. This account gets disabled during setup." },
{ "summary": "Check out the Hybrid Hunter Quick Start Guide." }
]
}

View File

@@ -0,0 +1,26 @@
{%- set MASTERIP = salt['pillar.get']('static:masterip', '') -%}
{%- set SENSORONIKEY = salt['pillar.get']('static:sensoronikey', '') -%}
{
"logFilename": "/opt/sensoroni/logs/sensoroni-server.log",
"server": {
"bindAddress": "0.0.0.0:9822",
"baseUrl": "/",
"maxPacketCount": 5000,
"htmlDir": "html",
"modules": {
"filedatastore": {
"jobDir": "jobs"
},
"securityonion": {
"elasticsearchHost": "http://{{ MASTERIP }}:9200",
"elasticsearchUsername": "",
"elasticsearchPassword": "",
"elasticsearchVerifyCert": false
},
"statickeyauth": {
"anonymousCidr": "172.17.0.0/24",
"apiKey": "{{ SENSORONIKEY }}"
}
}
}
}

97
salt/soc/init.sls Normal file
View File

@@ -0,0 +1,97 @@
{% set VERSION = salt['pillar.get']('static:soversion', 'HH1.2.1') %}
{% set MASTER = salt['grains.get']('master') %}
socdir:
file.directory:
- name: /opt/so/conf/soc
- user: 939
- group: 939
- makedirs: True
socdatadir:
file.directory:
- name: /nsm/soc/jobs
- user: 939
- group: 939
- makedirs: True
soclogdir:
file.directory:
- name: /opt/so/log/soc
- user: 939
- group: 939
- makedirs: True
socsync:
file.recurse:
- name: /opt/so/conf/soc
- source: salt://soc/files/soc
- user: 939
- group: 939
- template: jinja
so-soc:
docker_container.running:
- image: {{ MASTER }}:5000/soshybridhunter/so-soc:{{ VERSION }}
- hostname: soc
- name: so-soc
- binds:
- /nsm/soc/jobs:/opt/sensoroni/jobs:rw
- /opt/so/conf/soc/soc.json:/opt/sensoroni/sensoroni.json:ro
- /opt/so/conf/soc/changes.json:/opt/sensoroni/html/changes.json:ro
- /opt/so/log/soc/:/opt/sensoroni/logs/:rw
- port_bindings:
- 0.0.0.0:9822:9822
- watch:
- file: /opt/so/conf/soc
# Add Kratos Group
kratosgroup:
group.present:
- name: kratos
- gid: 928
# Add Kratos user
kratos:
user.present:
- uid: 928
- gid: 928
- home: /opt/so/conf/kratos
kratosdir:
file.directory:
- name: /opt/so/conf/kratos/db
- user: 928
- group: 928
- makedirs: True
kratoslogdir:
file.directory:
- name: /opt/so/log/kratos
- user: 928
- group: 928
- makedirs: True
kratossync:
file.recurse:
- name: /opt/so/conf/kratos
- source: salt://soc/files/kratos
- user: 928
- group: 928
- template: jinja
so-kratos:
docker_container.running:
- image: {{ MASTER }}:5000/soshybridhunter/so-kratos:{{ VERSION }}
- hostname: kratos
- name: so-kratos
- binds:
- /opt/so/conf/kratos/schema.json:/kratos-conf/schema.json:ro
- /opt/so/conf/kratos/kratos.yaml:/kratos-conf/kratos.yaml:ro
- /opt/so/log/kratos/:/kratos-log:rw
- /opt/so/conf/kratos/db:/kratos-data:rw
- port_bindings:
- 0.0.0.0:4433:4433
- 0.0.0.0:4434:4434
- watch:
- file: /opt/so/conf/kratos

View File

@@ -35,6 +35,7 @@ base:
- firewall
- pcap
- suricata
- healthcheck
{%- if BROVER != 'SURICATA' %}
- zeek
{%- endif %}
@@ -51,10 +52,10 @@ base:
- registry
- master
- common
- sensoroni
- soc
- firewall
- idstools
- auth
- healthcheck
{%- if FLEETMASTER or FLEETNODE %}
- mysql
{%- endif %}
@@ -96,12 +97,11 @@ base:
- ssl
- registry
- common
- sensoroni
- soc
- firewall
- master
- idstools
- redis
- auth
{%- if FLEETMASTER or FLEETNODE %}
- mysql
{%- endif %}
@@ -190,7 +190,6 @@ base:
- firewall
- sensor
- master
- auth
{%- if FLEETMASTER or FLEETNODE %}
- fleet.install_package
{%- endif %}
@@ -201,13 +200,11 @@ base:
- ssl
- registry
- common
- sensoroni
- auth
- soc
- firewall
- master
- idstools
- redis
- auth
{%- if FLEETMASTER or FLEETNODE %}
- mysql
{%- endif %}

View File

@@ -125,5 +125,8 @@ redef LogAscii::json_timestamps = JSON::TS_ISO8601;
# BPF Configuration
@load securityonion/bpfconf
# Community ID
@load securityonion/communityid
# Extracted files
@load securityonion/file-extraction
@load securityonion/file-extraction

View File

@@ -0,0 +1,25 @@
# Bro package & plugin for adding community hash IDs to conn.log.
# This is loaded when a user activates the plugin.
#
module CommunityID;
export {
# An unsigned 16-bit number to seed our hashing
const seed: count = 0 &redef;
# Whether to add a base64 pass over the hash digest.
# Enabled by default, since it shortens the output.
const do_base64: bool = T &redef;
# Verbose debugging log output to the console.
const verbose: bool = F &redef;
# Add the ID string field to the connection log record.
redef record Conn::Info += {
community_id: string &optional &log;
};
}
event connection_state_remove(c: connection) {
c$conn$community_id = hash_conn(c);
}

View File

@@ -1,9 +0,0 @@
#!/bin/bash
if [[ "$NM_DISPATCHER_ACTION" == "pre-up" ]]; then
if [[ "$DEVICE_IFACE" != "$MAININT" ]]; then
for i in rx tx sg tso ufo gso gro lro; do
ethtool -K "$DEVICE_IFACE" "$i" off;
done
fi
fi

View File

@@ -0,0 +1,8 @@
#!/bin/bash
if [[ "$DEVICE_IFACE" != "$MAININT" && "$DEVICE_IFACE" != *"docker"* ]]; then
for i in rx tx sg tso ufo gso gro lro; do
ethtool -K "$DEVICE_IFACE" "$i" off;
done
ip link set dev "$DEVICE_IFACE" arp off multicast off allmulticast off
fi

File diff suppressed because it is too large Load Diff

View File

@@ -300,6 +300,15 @@ if (whiptail_you_sure) ; then
check_socore_pass
done
# Get a password for the web admin user
whiptail_create_web_user
WPMATCH=no
while [ $WPMATCH != yes ]; do
whiptail_create_web_user_password1
whiptail_create_web_user_password2
check_web_pass
done
get_redirect
# Last Chance to back out
whiptail_make_changes
set_hostname
@@ -376,21 +385,23 @@ if (whiptail_you_sure) ; then
docker_seed_registry >> $SETUPLOG 2>&1
echo -e "XXX\n43\nInstalling Common Components... \nXXX"
salt-call state.apply common >> $SETUPLOG 2>&1
echo -e "XXX\n44\nInstalling SOC... \nXXX"
salt-call state.apply soc >> $SETUPLOG 2>&1
echo -e "XXX\n45\nApplying firewall rules... \nXXX"
salt-call state.apply firewall >> $SETUPLOG 2>&1
salt-call state.apply master >> $SETUPLOG 2>&1
salt-call state.apply idstools >> $SETUPLOG 2>&1
echo -e "XXX\n40\nInstalling Redis... \nXXX"
echo -e "XXX\n46\nInstalling Redis... \nXXX"
salt-call state.apply redis >> $SETUPLOG 2>&1
if [[ $OSQUERY == '1' ]]; then
echo -e "XXX\n41\nInstalling MySQL... \nXXX"
echo -e "XXX\n48\nInstalling MySQL... \nXXX"
salt-call state.apply mysql >> $SETUPLOG 2>&1
fi
if [[ $WAZUH == '1' ]]; then
echo -e "XXX\n68\nInstalling Wazuh... \nXXX"
echo -e "XXX\n48\nInstalling Wazuh... \nXXX"
salt-call state.apply wazuh >> $SETUPLOG 2>&1
fi
echo -e "XXX\n45\nInstalling Elastic Components... \nXXX"
echo -e "XXX\n49\nInstalling Elastic Components... \nXXX"
salt-call state.apply elasticsearch >> $SETUPLOG 2>&1
salt-call state.apply logstash >> $SETUPLOG 2>&1
salt-call state.apply kibana >> $SETUPLOG 2>&1
@@ -419,7 +430,9 @@ if (whiptail_you_sure) ; then
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"
echo -e "XXX\n98\nAdding user to SOC... \nXXX"
add_web_user >> $SETUPLOG 2>&1
echo -e "XXX\n99\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}')
@@ -570,6 +583,15 @@ if (whiptail_you_sure) ; then
check_socore_pass
done
fi
# Get a password for the web admin user
whiptail_create_web_user
WPMATCH=no
while [ $WPMATCH != yes ]; do
whiptail_create_web_user_password1
whiptail_create_web_user_password2
check_web_pass
done
get_redirect
whiptail_make_changes
set_hostname
set_version
@@ -616,14 +638,10 @@ if (whiptail_you_sure) ; then
master_pillar >> $SETUPLOG 2>&1
echo "** Generating the patch pillar **" >> $SETUPLOG
patch_pillar >> $SETUPLOG 2>&1
echo -e "XXX\n7\nConfiguring minion... \nXXX"
configure_minion $TYPE >> $SETUPLOG 2>&1
echo -e "XXX\n7\nSetting the node type to $TYPE... \nXXX"
set_node_type >> $SETUPLOG 2>&1
echo -e "XXX\n7\nSearch node pillar... \nXXX"
node_pillar >> $SETUPLOG 2>&1
echo -e "XXX\n8\nCreating firewall policies... \nXXX"
@@ -650,12 +668,13 @@ if (whiptail_you_sure) ; then
echo -e "XXX\n25\nInstalling master components... \nXXX"
salt-call state.apply master >> $SETUPLOG 2>&1
salt-call state.apply idstools >> $SETUPLOG 2>&1
echo -e "XXX\n26\nInstalling SOC... \nXXX"
salt-call state.apply soc >> $SETUPLOG 2>&1
if [[ $OSQUERY == '1' ]]; then
salt-call state.apply mysql >> $SETUPLOG 2>&1
fi
if [[ $WAZUH == '1' ]]; then
echo -e "XXX\n65\nInstalling Wazuh components... \nXXX"
echo -e "XXX\n27\nInstalling Wazuh components... \nXXX"
salt-call state.apply wazuh >> $SETUPLOG 2>&1
fi
echo -e "XXX\n35\nInstalling ElasticSearch... \nXXX"
@@ -700,10 +719,11 @@ if (whiptail_you_sure) ; then
echo -e "XXX\n95\nSetting checkin to run on boot... \nXXX"
checkin_at_boot >> $SETUPLOG 2>&1
echo -e "XX\n97\nFinishing touches... \nXXX"
salt-call state.apply auth >> $SETUPLOG 2>&1
filter_unused_nics >> $SETUPLOG 2>&1
network_setup >> $SETUPLOG 2>&1
echo -e "XXX\n98\nVerifying Setup... \nXXX"
echo -e "XXX\n98\nAdding user to SOC... \nXXX"
add_web_user >> $SETUPLOG 2>&1
echo -e "XXX\n99\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}')

View File

@@ -158,6 +158,34 @@ whiptail_create_socore_user_password2() {
}
whiptail_create_web_user() {
WEBUSER=$(whiptail --title "Security Onion Install" --inputbox \
"Please enter an email address to create an administrator account for the web interface." 10 60 3>&1 1>&2 2>&3)
}
whiptail_create_web_user_password1() {
WEBPASSWD1=$(whiptail --title "Security Onion Install" --passwordbox \
"Enter a password for $WEBUSER" 10 60 3>&1 1>&2 2>&3)
local exitstatus=$?
whiptail_check_exitstatus $exitstatus
}
whiptail_create_web_user_password2() {
WEBPASSWD2=$(whiptail --title "Security Onion Install" --passwordbox \
"Re-enter a password for $WEBUSER" 10 60 3>&1 1>&2 2>&3)
local exitstatus=$?
whiptail_check_exitstatus $exitstatus
}
whiptail_cur_close_days() {
CURCLOSEDAYS=$(whiptail --title "Security Onion Setup" --inputbox \
@@ -683,6 +711,28 @@ whiptail_set_hostname() {
}
whiptail_set_redirect() {
REDIRECTINFO=$(whiptail --title "Security Onion Setup" --radiolist \
"Choose the access method for the web interface:" 20 75 4 \
"IP" "Use IP to access the web interface" ON \
"HOSTNAME" "Use Hostname ($HOSTNAME) to access the web interface" OFF \
"OTHER" "Use a different name like a FQDN or Load Balancer" OFF 3>&1 1>&2 2>&3 )
local exitstatus=$?
whiptail_check_exitstatus $exitstatus
}
whiptail_set_redirect_host() {
REDIRECTHOST=$(whiptail --title "Security Onion Setup" --inputbox \
"Enter the Hostname or IP you would like to use for the web interface." 10 75 $HOSTNAME 3>&1 1>&2 2>&3)
local exitstatus=$?
whiptail_check_exitstatus $exitstatus
}
whiptail_set_redirect_info() {
whiptail --title "Security Onion Setup" --msgbox "The following selection refers to accessing the web interface. \n
For security reasons, we use strict cookie enforcement." 10 75
}
whiptail_setup_complete() {
whiptail --title "Security Onion Setup" --msgbox "Finished installing this as an $INSTALLTYPE. Press Enter to reboot." 8 75

View File

@@ -51,12 +51,13 @@ if [ $MASTERCHECK != 'so-helix' ]; then
"so-idstools:$BUILD$UPDATEVERSION" \
"so-influxdb:$BUILD$UPDATEVERSION" \
"so-kibana:$BUILD$UPDATEVERSION" \
"so-kratos:$BUILD$UPDATEVERSION" \
"so-logstash:$BUILD$UPDATEVERSION" \
"so-mysql:$BUILD$UPDATEVERSION" \
"so-navigator:$BUILD$UPDATEVERSION" \
"so-playbook:$BUILD$UPDATEVERSION" \
"so-redis:$BUILD$UPDATEVERSION" \
"so-sensoroni:$BUILD$UPDATEVERSION" \
"so-soc:$BUILD$UPDATEVERSION" \
"so-soctopus:$BUILD$UPDATEVERSION" \
"so-steno:$BUILD$UPDATEVERSION" \
"so-strelka:$BUILD$UPDATEVERSION" \
@@ -73,7 +74,6 @@ if [ $MASTERCHECK != 'so-helix' ]; then
"so-idstools:$BUILD$UPDATEVERSION" \
"so-logstash:$BUILD$UPDATEVERSION" \
"so-redis:$BUILD$UPDATEVERSION" \
"so-sensoroni:$BUILD$UPDATEVERSION" \
"so-steno:$BUILD$UPDATEVERSION" \
"so-suricata:$BUILD$UPDATEVERSION" \
"so-telegraf:$BUILD$UPDATEVERSION" \