From 9049f9cf032bc4142f6a2bfa6db3808ea5df7966 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Mon, 8 May 2023 15:56:26 -0400 Subject: [PATCH] enabled/disable elastalert via web ui --- salt/allowed_states.map.jinja | 3 +- salt/elastalert/config.sls | 103 ++++++++++++++ salt/elastalert/defaults.yaml | 1 + salt/elastalert/disabled.sls | 27 ++++ salt/elastalert/elastalert_config.map.jinja | 11 -- salt/elastalert/enabled.sls | 58 ++++++++ salt/elastalert/init.sls | 144 ++------------------ salt/elastalert/map.jinja | 15 ++ salt/elastalert/soc_elastalert.yaml | 3 + salt/elastalert/sostatus.sls | 21 +++ salt/manager/tools/sbin/so-minion | 49 ++++--- salt/pcap/config.map.jinja | 5 + salt/pcap/disabled.sls | 5 + salt/pcap/init.sls | 5 + salt/top.sls | 9 -- salt/zeek/enabled.sls | 2 +- 16 files changed, 284 insertions(+), 177 deletions(-) create mode 100644 salt/elastalert/config.sls create mode 100644 salt/elastalert/disabled.sls delete mode 100644 salt/elastalert/elastalert_config.map.jinja create mode 100644 salt/elastalert/enabled.sls create mode 100644 salt/elastalert/map.jinja create mode 100644 salt/elastalert/sostatus.sls diff --git a/salt/allowed_states.map.jinja b/salt/allowed_states.map.jinja index 0476bc8ed..d5eaa5599 100644 --- a/salt/allowed_states.map.jinja +++ b/salt/allowed_states.map.jinja @@ -3,7 +3,6 @@ # https://securityonion.net/license; you may not use this file except in compliance with the # Elastic License 2.0. -{% set ELASTALERT = salt['pillar.get']('elastalert:enabled', True) %} {% set ELASTICSEARCH = salt['pillar.get']('elasticsearch:enabled', True) %} {% set KIBANA = salt['pillar.get']('kibana:enabled', True) %} {% set LOGSTASH = salt['pillar.get']('logstash:enabled', True) %} @@ -243,7 +242,7 @@ {% do allowed_states.append('curator') %} {% endif %} - {% if ELASTALERT and grains.role in ['so-eval', 'so-manager', 'so-standalone', 'so-managersearch'] %} + {% if grains.role in ['so-eval', 'so-manager', 'so-standalone', 'so-managersearch'] %} {% do allowed_states.append('elastalert') %} {% endif %} diff --git a/salt/elastalert/config.sls b/salt/elastalert/config.sls new file mode 100644 index 000000000..252aa83c0 --- /dev/null +++ b/salt/elastalert/config.sls @@ -0,0 +1,103 @@ +# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one +# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at +# https://securityonion.net/license; you may not use this file except in compliance with the +# Elastic License 2.0. + +{% from 'allowed_states.map.jinja' import allowed_states %} +{% if sls.split('.')[0] in allowed_states %} + +{% from 'elastalert/map.jinja' import ELASTALERTMERGED %} + +# Create the group +elastagroup: + group.present: + - name: elastalert + - gid: 933 + +# Add user +elastalert: + user.present: + - uid: 933 + - gid: 933 + - home: /opt/so/conf/elastalert + - createhome: False + +elastalogdir: + file.directory: + - name: /opt/so/log/elastalert + - user: 933 + - group: 933 + - makedirs: True + +elastalert_sbin: + file.recurse: + - name: /usr/sbin + - source: salt://elastalert/tools/sbin + - user: 933 + - group: 939 + - file_mode: 755 + +#elastalert_sbin_jinja: +# file.recurse: +# - name: /usr/sbin +# - source: salt://elastalert/tools/sbin_jinja +# - user: 933 +# - group: 939 +# - file_mode: 755 +# - template: jinja + +elastarules: + file.directory: + - name: /opt/so/rules/elastalert + - user: 933 + - group: 933 + - makedirs: True + +elastaconfdir: + file.directory: + - name: /opt/so/conf/elastalert + - user: 933 + - group: 933 + - makedirs: True + +elastasomodulesdir: + file.directory: + - name: /opt/so/conf/elastalert/modules/so + - user: 933 + - group: 933 + - makedirs: True + +elastacustmodulesdir: + file.directory: + - name: /opt/so/conf/elastalert/modules/custom + - user: 933 + - group: 933 + - makedirs: True + +elastasomodulesync: + file.recurse: + - name: /opt/so/conf/elastalert/modules/so + - source: salt://elastalert/files/modules/so + - user: 933 + - group: 933 + - makedirs: True + +elastaconf: + file.managed: + - name: /opt/so/conf/elastalert/elastalert_config.yaml + - source: salt://elastalert/files/elastalert_config.yaml.jinja + - context: + elastalert_config: {{ ELASTALERTMERGED.config }} + - user: 933 + - group: 933 + - mode: 660 + - template: jinja + - show_changes: False + +{% else %} + +{{sls}}_state_not_allowed: + test.fail_without_changes: + - name: {{sls}}_state_not_allowed + +{% endif %} diff --git a/salt/elastalert/defaults.yaml b/salt/elastalert/defaults.yaml index 6a051354e..1083fa8fd 100644 --- a/salt/elastalert/defaults.yaml +++ b/salt/elastalert/defaults.yaml @@ -1,4 +1,5 @@ elastalert: + enabled: False config: rules_folder: /opt/elastalert/rules/ scan_subdirectories: true diff --git a/salt/elastalert/disabled.sls b/salt/elastalert/disabled.sls new file mode 100644 index 000000000..5830bbd8f --- /dev/null +++ b/salt/elastalert/disabled.sls @@ -0,0 +1,27 @@ +# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one +# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at +# https://securityonion.net/license; you may not use this file except in compliance with the +# Elastic License 2.0. + +{% from 'allowed_states.map.jinja' import allowed_states %} +{% if sls.split('.')[0] in allowed_states %} + +include: + - elastalert.sostatus + +so-elastalert: + docker_container.absent: + - force: True + +so-elastalert_so-status.disabled: + file.comment: + - name: /opt/so/conf/so-status/so-status.conf + - regex: ^so-elastalert$ + +{% else %} + +{{sls}}_state_not_allowed: + test.fail_without_changes: + - name: {{sls}}_state_not_allowed + +{% endif %} diff --git a/salt/elastalert/elastalert_config.map.jinja b/salt/elastalert/elastalert_config.map.jinja deleted file mode 100644 index 26ddc08c9..000000000 --- a/salt/elastalert/elastalert_config.map.jinja +++ /dev/null @@ -1,11 +0,0 @@ -{% from 'vars/globals.map.jinja' import GLOBALS %} -{% import_yaml 'elastalert/defaults.yaml' as ELASTALERT %} -{% set elastalert_pillar = salt['pillar.get']('elastalert:config', {}) %} - - -{% do ELASTALERT.elastalert.config.update({'es_host': GLOBALS.manager}) %} -{% do ELASTALERT.elastalert.config.update({'es_username': pillar.elasticsearch.auth.users.so_elastic_user.user}) %} -{% do ELASTALERT.elastalert.config.update({'es_password': pillar.elasticsearch.auth.users.so_elastic_user.pass}) %} - -{% do salt['defaults.merge'](ELASTALERT.elastalert.config, elastalert_pillar, in_place=True) %} - diff --git a/salt/elastalert/enabled.sls b/salt/elastalert/enabled.sls new file mode 100644 index 000000000..3e043b46c --- /dev/null +++ b/salt/elastalert/enabled.sls @@ -0,0 +1,58 @@ +# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one +# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at +# https://securityonion.net/license; you may not use this file except in compliance with the +# Elastic License 2.0. + +{% from 'allowed_states.map.jinja' import allowed_states %} +{% if sls.split('.')[0] in allowed_states %} +{% from 'vars/globals.map.jinja' import GLOBALS %} +{% from 'docker/docker.map.jinja' import DOCKER %} + +include: + - elastalert.config + - elastalert.sostatus + +wait_for_elasticsearch: + cmd.run: + - name: so-elasticsearch-wait + +so-elastalert: + docker_container.running: + - image: {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-elastalert:{{ GLOBALS.so_version }} + - hostname: elastalert + - name: so-elastalert + - user: so-elastalert + - networks: + - sobridge: + - ipv4_address: {{ DOCKER.containers['so-elastalert'].ip }} + - detach: True + - binds: + - /opt/so/rules/elastalert:/opt/elastalert/rules/:ro + - /opt/so/log/elastalert:/var/log/elastalert:rw + - /opt/so/conf/elastalert/modules/:/opt/elastalert/modules/:ro + - /opt/so/conf/elastalert/elastalert_config.yaml:/opt/elastalert/config.yaml:ro + - extra_hosts: + - {{ GLOBALS.manager }}:{{ GLOBALS.manager_ip }} + - require: + - cmd: wait_for_elasticsearch + - file: elastarules + - file: elastalogdir + - file: elastacustmodulesdir + - file: elastaconf + - watch: + - file: elastaconf + - onlyif: + - "so-elasticsearch-query / | jq -r '.version.number[0:1]' | grep -q 8" {# only run this state if elasticsearch is version 8 #} + +delete_so-elastalert_so-status.disabled: + file.uncomment: + - name: /opt/so/conf/so-status/so-status.conf + - regex: ^so-elastalert$ + +{% else %} + +{{sls}}_state_not_allowed: + test.fail_without_changes: + - name: {{sls}}_state_not_allowed + +{% endif %} diff --git a/salt/elastalert/init.sls b/salt/elastalert/init.sls index 148fe7e1b..d0e86d07f 100644 --- a/salt/elastalert/init.sls +++ b/salt/elastalert/init.sls @@ -1,141 +1,13 @@ # Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one -# or more contributor license agreements. Licensed under the Elastic License 2.0; you may not use -# this file except in compliance with the Elastic License 2.0. -{% from 'allowed_states.map.jinja' import allowed_states %} -{% if sls in allowed_states %} +# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at +# https://securityonion.net/license; you may not use this file except in compliance with the +# Elastic License 2.0. -{% from 'vars/globals.map.jinja' import GLOBALS %} -{% from 'docker/docker.map.jinja' import DOCKER %} -{% from 'elastalert/elastalert_config.map.jinja' import ELASTALERT as elastalert_config with context %} - -# Create the group -elastagroup: - group.present: - - name: elastalert - - gid: 933 - -# Add user -elastalert: - user.present: - - uid: 933 - - gid: 933 - - home: /opt/so/conf/elastalert - - createhome: False - -elastalogdir: - file.directory: - - name: /opt/so/log/elastalert - - user: 933 - - group: 933 - - makedirs: True - -elastalert_sbin: - file.recurse: - - name: /usr/sbin - - source: salt://elastalert/tools/sbin - - user: 933 - - group: 939 - - file_mode: 755 - -#elastalert_sbin_jinja: -# file.recurse: -# - name: /usr/sbin -# - source: salt://elastalert/tools/sbin_jinja -# - user: 933 -# - group: 939 -# - file_mode: 755 -# - template: jinja - -elastarules: - file.directory: - - name: /opt/so/rules/elastalert - - user: 933 - - group: 933 - - makedirs: True - -elastaconfdir: - file.directory: - - name: /opt/so/conf/elastalert - - user: 933 - - group: 933 - - makedirs: True - -elastasomodulesdir: - file.directory: - - name: /opt/so/conf/elastalert/modules/so - - user: 933 - - group: 933 - - makedirs: True - -elastacustmodulesdir: - file.directory: - - name: /opt/so/conf/elastalert/modules/custom - - user: 933 - - group: 933 - - makedirs: True - -elastasomodulesync: - file.recurse: - - name: /opt/so/conf/elastalert/modules/so - - source: salt://elastalert/files/modules/so - - user: 933 - - group: 933 - - makedirs: True - -elastaconf: - file.managed: - - name: /opt/so/conf/elastalert/elastalert_config.yaml - - source: salt://elastalert/files/elastalert_config.yaml.jinja - - context: - elastalert_config: {{ elastalert_config.elastalert.config }} - - user: 933 - - group: 933 - - mode: 660 - - template: jinja - - show_changes: False - -wait_for_elasticsearch: - cmd.run: - - name: so-elasticsearch-wait - -so-elastalert: - docker_container.running: - - image: {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-elastalert:{{ GLOBALS.so_version }} - - hostname: elastalert - - name: so-elastalert - - user: so-elastalert - - networks: - - sobridge: - - ipv4_address: {{ DOCKER.containers['so-elastalert'].ip }} - - detach: True - - binds: - - /opt/so/rules/elastalert:/opt/elastalert/rules/:ro - - /opt/so/log/elastalert:/var/log/elastalert:rw - - /opt/so/conf/elastalert/modules/:/opt/elastalert/modules/:ro - - /opt/so/conf/elastalert/elastalert_config.yaml:/opt/elastalert/config.yaml:ro - - extra_hosts: - - {{ GLOBALS.manager }}:{{ GLOBALS.manager_ip }} - - require: - - cmd: wait_for_elasticsearch - - file: elastarules - - file: elastalogdir - - file: elastacustmodulesdir - - file: elastaconf - - watch: - - file: elastaconf - - onlyif: - - "so-elasticsearch-query / | jq -r '.version.number[0:1]' | grep -q 8" {# only run this state if elasticsearch is version 8 #} - - -append_so-elastalert_so-status.conf: - file.append: - - name: /opt/so/conf/so-status/so-status.conf - - text: so-elastalert +{% from 'elastalert/map.jinja' import ELASTALERTMERGED %} +include: +{% if ELASTALERTMERGED.enabled %} + - elastalert.enabled {% else %} - -{{sls}}_state_not_allowed: - test.fail_without_changes: - - name: {{sls}}_state_not_allowed - + - elastalert.disabled {% endif %} diff --git a/salt/elastalert/map.jinja b/salt/elastalert/map.jinja new file mode 100644 index 000000000..cc395d8ee --- /dev/null +++ b/salt/elastalert/map.jinja @@ -0,0 +1,15 @@ +{# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one + or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at + https://securityonion.net/license; you may not use this file except in compliance with the + Elastic License 2.0. #} + +{% from 'vars/globals.map.jinja' import GLOBALS %} +{% import_yaml 'elastalert/defaults.yaml' as ELASTALERTDEFAULTS %} +{% set elastalert_pillar = salt['pillar.get']('elastalert:config', {}) %} + + +{% do ELASTALERTDEFAULTS.elastalert.config.update({'es_host': GLOBALS.manager}) %} +{% do ELASTALERTDEFAULTS.elastalert.config.update({'es_username': pillar.elasticsearch.auth.users.so_elastic_user.user}) %} +{% do ELASTALERTDEFAULTS.elastalert.config.update({'es_password': pillar.elasticsearch.auth.users.so_elastic_user.pass}) %} + +{% set ELASTALERTMERGED = salt['pillar.get']('elastalert', ELASTALERTDEFAULTS.elastalert, merge=True) %} diff --git a/salt/elastalert/soc_elastalert.yaml b/salt/elastalert/soc_elastalert.yaml index fe01f2458..cde09b83e 100644 --- a/salt/elastalert/soc_elastalert.yaml +++ b/salt/elastalert/soc_elastalert.yaml @@ -1,4 +1,7 @@ elastalert: + enabled: + description: You can enable or disable Elastalert. + helpLink: elastalert.html config: disable_rules_on_error: description: Disable rules on failure. diff --git a/salt/elastalert/sostatus.sls b/salt/elastalert/sostatus.sls new file mode 100644 index 000000000..609a4482f --- /dev/null +++ b/salt/elastalert/sostatus.sls @@ -0,0 +1,21 @@ +# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one +# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at +# https://securityonion.net/license; you may not use this file except in compliance with the +# Elastic License 2.0. + +{% from 'allowed_states.map.jinja' import allowed_states %} +{% if sls.split('.')[0] in allowed_states %} + +append_so-elastalert_so-status.conf: + file.append: + - name: /opt/so/conf/so-status/so-status.conf + - text: so-elastalert + - unless: grep -q so-elastalert /opt/so/conf/so-status/so-status.conf + +{% else %} + +{{sls}}_state_not_allowed: + test.fail_without_changes: + - name: {{sls}}_state_not_allowed + +{% endif %} diff --git a/salt/manager/tools/sbin/so-minion b/salt/manager/tools/sbin/so-minion index 5cddb3e68..b94bfac59 100755 --- a/salt/manager/tools/sbin/so-minion +++ b/salt/manager/tools/sbin/so-minion @@ -227,6 +227,14 @@ function add_playbook_to_minion() { " " >> $PILLARFILE } +# Add basic host info to the minion file +function add_elastalert_to_minion() { + printf '%s\n'\ + "elastalert:"\ + " enabled: True"\ + " " >> $PILLARFILE +} + function create_fleet_policy() { JSON_STRING=$( jq -n \ @@ -274,6 +282,29 @@ function createEVAL() { add_elastic_to_minion add_logstash_to_minion add_sensor_to_minion + add_elastalert_to_minion +} + +function createSTANDALONE() { + add_elastic_to_minion + add_logstash_to_minion + add_sensor_to_minion + add_playbook_to_minion + add_elastalert_to_minion +} + +function createMANAGER() { + add_elastic_to_minion + add_logstash_to_minion + add_playbook_to_minion + add_elastalert_to_minion +} + +function createMANAGERSEARCH() { + add_elastic_to_minion + add_logstash_to_minion + add_playbook_to_minion + add_elastalert_to_minion } function createFLEET() { @@ -300,18 +331,6 @@ function createHEAVYNODE() { add_sensor_to_minion } -function createMANAGER() { - add_elastic_to_minion - add_logstash_to_minion - add_playbook_to_minion -} - -function createMANAGERSEARCH() { - add_elastic_to_minion - add_logstash_to_minion - add_playbook_to_minion -} - function createSENSOR() { add_sensor_to_minion } @@ -323,12 +342,6 @@ function createSEARCHNODE() { apply_ES_state } -function createSTANDALONE() { - add_elastic_to_minion - add_logstash_to_minion - add_sensor_to_minion - add_playbook_to_minion -} function testConnection() { retry 15 3 "salt '$MINION_ID' test.ping" True diff --git a/salt/pcap/config.map.jinja b/salt/pcap/config.map.jinja index 88e3a83dd..7ed500f25 100644 --- a/salt/pcap/config.map.jinja +++ b/salt/pcap/config.map.jinja @@ -1,2 +1,7 @@ +{# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one + or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at + https://securityonion.net/license; you may not use this file except in compliance with the + Elastic License 2.0. #} + {% import_yaml 'pcap/defaults.yaml' as PCAPDEFAULTS %} {% set PCAPMERGED = salt['pillar.get']('pcap', PCAPDEFAULTS.pcap, merge=True) %} diff --git a/salt/pcap/disabled.sls b/salt/pcap/disabled.sls index eaa227303..5643fc870 100644 --- a/salt/pcap/disabled.sls +++ b/salt/pcap/disabled.sls @@ -1,3 +1,8 @@ +# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one +# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at +# https://securityonion.net/license; you may not use this file except in compliance with the +# Elastic License 2.0. + {% from 'allowed_states.map.jinja' import allowed_states %} {% if sls.split('.')[0] in allowed_states %} diff --git a/salt/pcap/init.sls b/salt/pcap/init.sls index 46ad04e95..9de272ad7 100644 --- a/salt/pcap/init.sls +++ b/salt/pcap/init.sls @@ -1,3 +1,8 @@ +# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one +# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at +# https://securityonion.net/license; you may not use this file except in compliance with the +# Elastic License 2.0. + {% from 'vars/globals.map.jinja' import GLOBALS %} {% from 'pcap/config.map.jinja' import PCAPMERGED %} diff --git a/salt/top.sls b/salt/top.sls index 49af8d21a..c108236b9 100644 --- a/salt/top.sls +++ b/salt/top.sls @@ -3,7 +3,6 @@ # https://securityonion.net/license; you may not use this file except in compliance with the # Elastic License 2.0. -{% set ELASTALERT = salt['pillar.get']('elastalert:enabled', True) %} {% set ELASTICSEARCH = salt['pillar.get']('elasticsearch:enabled', True) %} {% set KIBANA = salt['pillar.get']('kibana:enabled', True) %} {% set LOGSTASH = salt['pillar.get']('logstash:enabled', True) %} @@ -89,9 +88,7 @@ base: - strelka {%- endif %} - curator - {%- if ELASTALERT %} - elastalert - {%- endif %} - utility - soctopus - playbook @@ -133,9 +130,7 @@ base: - kibana.so_savedobjects_defaults {%- endif %} - curator - {%- if ELASTALERT %} - elastalert - {%- endif %} - utility - soctopus - playbook @@ -181,9 +176,7 @@ base: - strelka {%- endif %} - curator - {%- if ELASTALERT %} - elastalert - {%- endif %} - utility - soctopus - playbook @@ -238,9 +231,7 @@ base: - elastic-fleet-package-registry - kibana.so_savedobjects_defaults {%- endif %} - {%- if ELASTALERT %} - elastalert - {%- endif %} - utility - soctopus - playbook diff --git a/salt/zeek/enabled.sls b/salt/zeek/enabled.sls index 2a179a009..d2fc9fbc3 100644 --- a/salt/zeek/enabled.sls +++ b/salt/zeek/enabled.sls @@ -6,7 +6,7 @@ {% from 'allowed_states.map.jinja' import allowed_states %} {% if sls.split('.')[0] in allowed_states %} -{% from 'vars/globals.map.jinja' import GLOBALS %} +{% from 'vars/globals.map.jinja' import GLOBALS %} include: - zeek.config