diff --git a/salt/elastalert/defaults.yaml b/salt/elastalert/defaults.yaml index 1083fa8fd..c073e4ee6 100644 --- a/salt/elastalert/defaults.yaml +++ b/salt/elastalert/defaults.yaml @@ -13,9 +13,10 @@ elastalert: es_port: 9200 es_conn_timeout: 55 max_query_size: 5000 + eql: true use_ssl: true verify_certs: false - writeback_index: elastalert_status + writeback_index: elastalert alert_time_limit: days: 2 index_settings: diff --git a/salt/elastalert/files/modules/so/playbook-es.py b/salt/elastalert/files/modules/so/playbook-es.py index 62afab41e..680c81d53 100644 --- a/salt/elastalert/files/modules/so/playbook-es.py +++ b/salt/elastalert/files/modules/so/playbook-es.py @@ -31,8 +31,8 @@ class PlaybookESAlerter(Alerter): creds = (self.rule['es_username'], self.rule['es_password']) payload = {"rule": { "name": self.rule['play_title'],"case_template": self.rule['play_id'],"uuid": self.rule['play_id'],"category": self.rule['rule.category']},"event":{ "severity": self.rule['event.severity'],"module": self.rule['event.module'],"dataset": self.rule['event.dataset'],"severity_label": self.rule['sigma_level']},"kibana_pivot": self.rule['kibana_pivot'],"soc_pivot": self.rule['soc_pivot'],"play_url": self.rule['play_url'],"sigma_level": self.rule['sigma_level'],"event_data": match, "@timestamp": timestamp} - url = f"https://{self.rule['es_host']}:{self.rule['es_port']}/so-playbook-alerts-{today}/_doc/" + url = f"{self.rule['es_hosts']}/so-playbook-alerts-{today}/_doc/" requests.post(url, data=json.dumps(payload), headers=headers, verify=False, auth=creds) def get_info(self): - return {'type': 'PlaybookESAlerter'} \ No newline at end of file + return {'type': 'PlaybookESAlerter'} diff --git a/salt/elastalert/map.jinja b/salt/elastalert/map.jinja index cc395d8ee..7cec262d0 100644 --- a/salt/elastalert/map.jinja +++ b/salt/elastalert/map.jinja @@ -8,7 +8,7 @@ {% set elastalert_pillar = salt['pillar.get']('elastalert:config', {}) %} -{% do ELASTALERTDEFAULTS.elastalert.config.update({'es_host': GLOBALS.manager}) %} +{% do ELASTALERTDEFAULTS.elastalert.config.update({'es_hosts': 'https://' + GLOBALS.manager + ':' + ELASTALERTDEFAULTS.elastalert.config.es_port|string}) %} {% 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}) %} diff --git a/salt/elasticfleet/files/integrations/endpoints-initial/elastic-defend-endpoints.json b/salt/elasticfleet/files/integrations/endpoints-initial/elastic-defend-endpoints.json new file mode 100644 index 000000000..7d7f5bb35 --- /dev/null +++ b/salt/elasticfleet/files/integrations/endpoints-initial/elastic-defend-endpoints.json @@ -0,0 +1,28 @@ +{ + "name": "elastic-defend-endpoints", + "namespace": "default", + "description": "", + "package": { + "name": "endpoint", + "title": "Elastic Defend", + "version": "" + }, + "enabled": true, + "policy_id": "endpoints-initial", + "vars": {}, + "inputs": [{ + "type": "endpoint", + "enabled": true, + "streams": [], + "config": { + "integration_config": { + "value": { + "type": "endpoint", + "endpointConfig": { + "preset": "DataCollection" + } + } + } + } + }] +} \ No newline at end of file diff --git a/salt/elasticfleet/files/integrations/grid-nodes/zeek-logs.json b/salt/elasticfleet/files/integrations/grid-nodes/zeek-logs.json index a8f05f175..03543b124 100644 --- a/salt/elasticfleet/files/integrations/grid-nodes/zeek-logs.json +++ b/salt/elasticfleet/files/integrations/grid-nodes/zeek-logs.json @@ -20,7 +20,7 @@ "data_stream.dataset": "zeek", "tags": [], "processors": "- dissect:\n tokenizer: \"/nsm/zeek/logs/current/%{pipeline}.log\"\n field: \"log.file.path\"\n trim_chars: \".log\"\n target_prefix: \"\"\n- script:\n lang: javascript\n source: >\n function process(event) {\n var pl = event.Get(\"pipeline\");\n event.Put(\"@metadata.pipeline\", \"zeek.\" + pl);\n }\n- add_fields:\n target: event\n fields:\n category: network\n module: zeek\n- add_tags:\n tags: \"ics\"\n when:\n regexp:\n pipeline: \"^bacnet*|^bsap*|^cip*|^cotp*|^dnp3*|^ecat*|^enip*|^modbus*|^opcua*|^profinet*|^s7comm*\"", - "custom": "exclude_files: [\"broker|capture_loss|ecat_arp_info|loaded_scripts|packet_filter|stats|stderr|stdout.log$\"]\n" + "custom": "exclude_files: [\"broker|capture_loss|ecat_arp_info|known_hosts|known_services|loaded_scripts|ntp|packet_filter|reporter|stats|stderr|stdout.log$\"]\n" } } } diff --git a/salt/elasticsearch/files/ingest/zeek.dns b/salt/elasticsearch/files/ingest/zeek.dns index 5f39b8017..57a9347a5 100644 --- a/salt/elasticsearch/files/ingest/zeek.dns +++ b/salt/elasticsearch/files/ingest/zeek.dns @@ -25,7 +25,7 @@ { "rename": { "field": "message2.rejected", "target_field": "dns.query.rejected", "ignore_missing": true } }, { "script": { "lang": "painless", "source": "ctx.dns.query.length = ctx.dns.query.name.length()", "ignore_failure": true } }, { "set": { "if": "ctx._index == 'so-zeek'", "field": "_index", "value": "so-zeek_dns", "override": true } }, - { "pipeline": { "if": "ctx.dns.query?.name != null && ctx.dns.query.name.contains('.')", "name": "dns.tld" } }, + { "pipeline": { "if": "ctx.dns?.query?.name != null && ctx.dns.query.name.contains('.')", "name": "dns.tld" } }, { "pipeline": { "name": "zeek.common" } } ] } diff --git a/salt/influxdb/templates/alarm_high_redis_memory_usage.json b/salt/influxdb/templates/alarm_high_redis_memory_usage.json new file mode 100644 index 000000000..fe99ad430 --- /dev/null +++ b/salt/influxdb/templates/alarm_high_redis_memory_usage.json @@ -0,0 +1,28 @@ +[{ + "apiVersion": "influxdata.com/v2alpha1", + "kind": "CheckThreshold", + "metadata": { + "name": "high-redis-memory" + }, + "spec": { + "description": "Triggers when the average percent of used memory for Redis reaches a defined threshold. To tune this alert, modify the value for the appropriate alert level.", + "every": "1m", + "name": "High Redis Memory Usage", + "query": "from(bucket: \"telegraf/so_short_term\")\n |\u003e range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |\u003e filter(fn: (r) =\u003e r[\"_measurement\"] == \"redisqueue\")\n |\u003e filter(fn: (r) =\u003e r[\"_field\"] == \"mem_used\")\n |\u003e aggregateWindow(every: 1m, fn: mean, createEmpty: false)\n |\u003e yield(name: \"mean\")", + "status": "active", + "statusMessageTemplate": "The amount of available memory for Redis on the ${r.host} node has reached the ${r._level} threshold. The current percent of used memory is ${r.mem_used}.", + "thresholds": [ + { + "level": "WARN", + "type": "greater", + "value": 80 + }, + { + "level": "CRIT", + "type": "greater", + "value": 90 + } + ] + } +}] + diff --git a/salt/influxdb/templates/alarm_low_monitor_traffic.json b/salt/influxdb/templates/alarm_low_monitor_traffic.json new file mode 100644 index 000000000..167ae1b5a --- /dev/null +++ b/salt/influxdb/templates/alarm_low_monitor_traffic.json @@ -0,0 +1,22 @@ +[{ + "apiVersion": "influxdata.com/v2alpha1", + "kind": "CheckThreshold", + "metadata": { + "name": "monitor-interface-traffic" + }, + "spec": { + "description": "Triggers when the volume of network traffic (in MBs) received on the monitor interface, per sensor, falls below a defined threshold. To tune this alert, modify the value in MBs for the appropriate alert level.", + "every": "1m", + "name": "Low Traffic Volume on Monitor Interface", + "query": "from(bucket: \"telegraf/so_short_term\")\n |\u003e range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |\u003e filter(fn: (r) =\u003e r[\"_measurement\"] == \"net\")\n |\u003e filter(fn: (r) =\u003e r[\"_field\"] == \"bytes_recv\")\n |\u003e filter(fn: (r) =\u003e r[\"interface\"] == \"bond0\")\n |\u003e derivative(unit: 1s, nonNegative: true)\n |\u003e map(fn: (r) =\u003e ({r with \"_value\": r._value * 8.0 / 1000000.0}))\n |\u003e yield(name: \"nonnegative derivative\")", + "status": "active", + "statusMessageTemplate": "Interface ${r.interface} on node ${r.host} has reached the ${r._level} threshold. The current volume of traffic on interface ${r.interface} is ${r.bytes_recv}MB/s.", + "thresholds": [ + { + "level": "CRIT", + "type": "lesser", + "value": 5 + } + ] + } +}] diff --git a/salt/influxdb/templates/alarm_pcap_retention.json b/salt/influxdb/templates/alarm_pcap_retention.json new file mode 100644 index 000000000..969d462c9 --- /dev/null +++ b/salt/influxdb/templates/alarm_pcap_retention.json @@ -0,0 +1,27 @@ +[{ + "apiVersion": "influxdata.com/v2alpha1", + "kind": "CheckThreshold", + "metadata": { + "name": "alarm-pcap-retention" + }, + "spec": { + "description": "Triggers when the PCAP retention (in days), falls below the defined threshold. To tune this alert, modify the value for the appropriate alert level.", + "every": "1m0s", + "name": "Low PCAP Retention", + "query": "from(bucket: \"telegraf/so_short_term\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"pcapage\")\n |> filter(fn: (r) => r[\"_field\"] == \"seconds\")\n |> map(fn: (r) => ({ r with _value: r._value / (24.0 * 3600.0)})) |\u003e map(fn: (r) =\u003e ({r with _value: int(v: r._value)}))\n |> aggregateWindow(every: 1m, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "status": "active", + "statusMessageTemplate": "PCAP retention on node ${r.host} has reached the ${r._level} threshold. Node ${r.host} currently has approximately ${r.seconds} days of PCAP data.", + "thresholds": [ + { + "level": "CRIT", + "type": "lesser", + "value": 1 + }, + { + "level": "WARN", + "type": "lesser", + "value": 3 + } + ] + } +}] diff --git a/salt/influxdb/templates/alarm_steno_packet_loss.json b/salt/influxdb/templates/alarm_steno_packet_loss.json new file mode 100644 index 000000000..c5cfb4297 --- /dev/null +++ b/salt/influxdb/templates/alarm_steno_packet_loss.json @@ -0,0 +1,27 @@ +[{ + "apiVersion": "influxdata.com/v2alpha1", + "kind": "CheckThreshold", + "metadata": { + "name": "steno-packet-loss" + }, + "spec": { + "description": "Triggers when the average percent of packet loss is above the defined threshold. To tune this alert, modify the value for the appropriate alert level.", + "every": "1m", + "name": "Stenographer Packet Loss", + "query": "from(bucket: \"telegraf/so_short_term\")\n |\u003e range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |\u003e filter(fn: (r) =\u003e r[\"_measurement\"] == \"stenodrop\")\n |\u003e filter(fn: (r) =\u003e r[\"_field\"] == \"drop\")\n |\u003e aggregateWindow(every: 1m, fn: mean, createEmpty: false)\n |\u003e yield(name: \"mean\")", + "status": "active", + "statusMessageTemplate": "Stenographer Packet Loss on node ${r.host} has reached the ${ r._level } threshold. The current packet loss is ${ r.drop }%.", + "thresholds": [ + { + "level": "CRIT", + "type": "greater", + "value": 5 + }, + { + "level": "WARN", + "type": "greater", + "value": 3 + } + ] + } +}] diff --git a/salt/influxdb/templates/alarm_suricata_packet_loss.json b/salt/influxdb/templates/alarm_suricata_packet_loss.json new file mode 100644 index 000000000..8a4c3f5cf --- /dev/null +++ b/salt/influxdb/templates/alarm_suricata_packet_loss.json @@ -0,0 +1,27 @@ +[{ + "apiVersion": "influxdata.com/v2alpha1", + "kind": "CheckThreshold", + "metadata": { + "name": "suricata-packet-loss" + }, + "spec": { + "description": "Triggers when the average percent of packet loss is above the defined threshold. To tune this alert, modify the value for the appropriate alert level." + "every": "1m", + "name": "Suricata Packet Loss", + "query": "from(bucket: \"telegraf/so_short_term\")\n |\u003e range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |\u003e filter(fn: (r) =\u003e r[\"_measurement\"] == \"suridrop\")\n |\u003e filter(fn: (r) =\u003e r[\"_field\"] == \"drop\")\n |\u003e map(fn: (r) =\u003e ({r with \"_value\": r._value * 100.0}))\n |\u003e map(fn: (r) =\u003e ({ r with _value: int(v: r._value) }))\n |\u003e aggregateWindow(every: 1m, fn: mean, createEmpty: false)\n |\u003e yield(name: \"mean\")", + "status": "active", + "statusMessageTemplate": "Suricata packet loss on node ${r.host} has reached the ${ r._level } threshold. The current packet loss is ${ r.drop }%.", + "thresholds": [ + { + "level": "CRIT", + "type": "greater", + "value": 5 + }, + { + "level": "WARN", + "type": "greater", + "value": 3 + } + ] + } +}] diff --git a/salt/influxdb/templates/alarm_zeek_packet_loss.json b/salt/influxdb/templates/alarm_zeek_packet_loss.json new file mode 100644 index 000000000..cebd1dc50 --- /dev/null +++ b/salt/influxdb/templates/alarm_zeek_packet_loss.json @@ -0,0 +1,27 @@ +[{ + "apiVersion": "influxdata.com/v2alpha1", + "kind": "CheckThreshold", + "metadata": { + "name": "zeek-packet-loss" + }, + "spec": { + "description": "Triggers when the average percent of packet loss is above the defined threshold. To tune this alert, modify the value for the appropriate alert level." + "every": "1m", + "name": "Zeek Packet Loss", + "query": "from(bucket: \"telegraf/so_short_term\")\n |\u003e range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |\u003e filter(fn: (r) =\u003e r[\"_measurement\"] == \"zeekdrop\")\n |\u003e filter(fn: (r) =\u003e r[\"_field\"] == \"drop\")\n |\u003e map(fn: (r) =\u003e ({r with \"_value\": r._value * 100.0}))\n |\u003e map(fn: (r) =\u003e ({ r with _value: int(v: r._value) }))\n |\u003e aggregateWindow(every: 1m, fn: mean, createEmpty: false)\n |\u003e yield(name: \"mean\")", + "status": "active", + "statusMessageTemplate": "Zeek Packet Loss on node ${r.host} has reached the ${ r._level } threshold. The current packet loss is ${ r.drop }%.", + "thresholds": [ + { + "level": "CRIT", + "type": "greater", + "value": 5 + }, + { + "level": "WARN", + "type": "greater", + "value": 3 + } + ] + } +}] diff --git a/salt/kibana/files/config_saved_objects.ndjson b/salt/kibana/files/config_saved_objects.ndjson index e2eced11e..9b69eb781 100644 --- a/salt/kibana/files/config_saved_objects.ndjson +++ b/salt/kibana/files/config_saved_objects.ndjson @@ -1 +1 @@ -{"attributes": {"buildNum": 39457,"defaultIndex": "logs-*","defaultRoute": "/app/dashboards#/view/a8411b30-6d03-11ea-b301-3d6c35840645","discover:sampleSize": 100,"theme:darkMode": true,"timepicker:timeDefaults": "{\n \"from\": \"now-24h\",\n \"to\": \"now\"\n}"},"coreMigrationVersion": "8.7.0","id": "8.7.0","migrationVersion": {"config": "7.13.0"},"references": [],"type": "config","updated_at": "2021-10-10T10:10:10.105Z","version": "WzI5NzUsMl0="} +{"attributes": {"buildNum": 39457,"defaultIndex": "logs-*","defaultRoute": "/app/dashboards#/view/a8411b30-6d03-11ea-b301-3d6c35840645","discover:sampleSize": 100,"theme:darkMode": true,"timepicker:timeDefaults": "{\n \"from\": \"now-24h\",\n \"to\": \"now\"\n}"},"coreMigrationVersion": "8.7.1","id": "8.7.1","migrationVersion": {"config": "7.13.0"},"references": [],"type": "config","updated_at": "2021-10-10T10:10:10.105Z","version": "WzI5NzUsMl0="} diff --git a/salt/kibana/tools/sbin_jinja/so-kibana-config-load b/salt/kibana/tools/sbin_jinja/so-kibana-config-load index 12466cae1..e65955178 100644 --- a/salt/kibana/tools/sbin_jinja/so-kibana-config-load +++ b/salt/kibana/tools/sbin_jinja/so-kibana-config-load @@ -63,7 +63,7 @@ update() { IFS=$'\r\n' GLOBIGNORE='*' command eval 'LINES=($(cat $1))' for i in "${LINES[@]}"; do - RESPONSE=$(curl -K /opt/so/conf/elasticsearch/curl.config -X PUT "localhost:5601/api/saved_objects/config/8.7.0" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d " $i ") + RESPONSE=$(curl -K /opt/so/conf/elasticsearch/curl.config -X PUT "localhost:5601/api/saved_objects/config/8.7.1" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d " $i ") echo $RESPONSE; if [[ "$RESPONSE" != *"\"success\":true"* ]] && [[ "$RESPONSE" != *"updated_at"* ]] ; then RETURN_CODE=1;fi done diff --git a/salt/manager/tools/sbin/so-minion b/salt/manager/tools/sbin/so-minion index 7d0703653..66236492c 100755 --- a/salt/manager/tools/sbin/so-minion +++ b/salt/manager/tools/sbin/so-minion @@ -230,6 +230,7 @@ function add_sensor_to_minion() { echo " node:" >> $PILLARFILE echo " lb_procs: '$CORECOUNT'" >> $PILLARFILE echo "suricata:" >> $PILLARFILE + echo " enabled: True " >> $PILLARFILE echo " config:" >> $PILLARFILE echo " af-packet:" >> $PILLARFILE echo " threads: '$CORECOUNT'" >> $PILLARFILE @@ -266,7 +267,7 @@ function add_redis_to_minion() { " " >> $PILLARFILE } -function add_strelka_strelka_to_minion() { +function add_strelka_to_minion() { printf '%s\n'\ "strelka:"\ " backend:"\ @@ -407,7 +408,8 @@ function apply_ES_state() { function createEVAL() { add_elasticsearch_to_minion add_sensor_to_minion - add_strelka_strelka_to_minion + add_strelka_to_minion + add_playbook_to_minion add_elastalert_to_minion add_kibana_to_minion add_curator_to_minion @@ -427,7 +429,7 @@ function createSTANDALONE() { add_elasticsearch_to_minion add_logstash_to_minion add_sensor_to_minion - add_strelka_strelka_to_minion + add_strelka_to_minion add_playbook_to_minion add_elastalert_to_minion add_kibana_to_minion @@ -518,7 +520,7 @@ function createHEAVYNODE() { add_elasticsearch_to_minion add_logstash_to_minion add_sensor_to_minion - add_strelka_strelka_to_minion + add_strelka_to_minion add_redis_to_minion add_curator_to_minion add_telegraf_to_minion @@ -526,7 +528,7 @@ function createHEAVYNODE() { function createSENSOR() { add_sensor_to_minion - add_strelka_strelka_to_minion + add_strelka_to_minion add_telegraf_to_minion } diff --git a/salt/sensoroni/files/analyzers/whoislookup/requirements.txt b/salt/sensoroni/files/analyzers/whoislookup/requirements.txt index e19053e6c..a3901f38c 100755 --- a/salt/sensoroni/files/analyzers/whoislookup/requirements.txt +++ b/salt/sensoroni/files/analyzers/whoislookup/requirements.txt @@ -1 +1,2 @@ +requests==2.27.1 whoisit>=2.5.3 diff --git a/salt/soc/files/bin/salt-relay.sh b/salt/soc/files/bin/salt-relay.sh index 8a81fc715..a98a587a6 100755 --- a/salt/soc/files/bin/salt-relay.sh +++ b/salt/soc/files/bin/salt-relay.sh @@ -143,12 +143,12 @@ function manage_salt() { state) log "Performing '$op' for '$state' on minion '$minion'" state=$(echo "$request" | jq -r .state) - response=$($CMD_PREFIX salt --async "$minion" state.apply "$state" queue=True) + response=$($CMD_PREFIX salt --async "$minion" state.apply "$state" queue=2) exit_code=$? ;; highstate) log "Performing '$op' on minion $minion" - response=$($CMD_PREFIX salt --async "$minion" state.highstate queue=True) + response=$($CMD_PREFIX salt --async "$minion" state.highstate queue=2) exit_code=$? ;; activejobs) diff --git a/salt/soctopus/files/templates/generic.template b/salt/soctopus/files/templates/generic.template index 035d38b24..74b40bef9 100644 --- a/salt/soctopus/files/templates/generic.template +++ b/salt/soctopus/files/templates/generic.template @@ -12,3 +12,13 @@ play_url: "https://{{ GLOBALS.url_base }}/playbook/issues/6000" kibana_pivot: "https://{{ GLOBALS.url_base }}/kibana/app/kibana#/discover?_g=()&_a=(columns:!(_source),interval:auto,query:(language:lucene,query:'_id:{[_id]}'),sort:!('@timestamp',desc))" soc_pivot: "https://{{ GLOBALS.url_base }}/#/hunt" sigma_level: "" + +index: '.ds-logs-*' +name: EQL +priority: 3 +realert: + minutes: 0 +type: any +filter: +- query: + query_string: diff --git a/salt/suricata/config.sls b/salt/suricata/config.sls new file mode 100644 index 000000000..c8666ef2b --- /dev/null +++ b/salt/suricata/config.sls @@ -0,0 +1,163 @@ +# 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 'bpf/suricata.map.jinja' import SURICATABPF %} +{% from 'suricata/map.jinja' import SURICATAMERGED %} +{% set BPF_STATUS = 0 %} + +# Add Suricata Group +suricatagroup: + group.present: + - name: suricata + - gid: 940 + +# Add Suricata user +suricata: + user.present: + - uid: 940 + - gid: 940 + - home: /nsm/suricata + - createhome: False + +socoregroupwithsuricata: + group.present: + - name: socore + - gid: 939 + - addusers: + - suricata + +suricata_sbin: + file.recurse: + - name: /usr/sbin + - source: salt://suricata/tools/sbin + - user: 939 + - group: 939 + - file_mode: 755 + +suricata_sbin_jinja: + file.recurse: + - name: /usr/sbin + - source: salt://suricata/tools/sbin_jinja + - user: 939 + - group: 939 + - file_mode: 755 + - template: jinja + +suridir: + file.directory: + - name: /opt/so/conf/suricata + - user: 940 + - group: 940 + +suriruledir: + file.directory: + - name: /opt/so/conf/suricata/rules + - user: 940 + - group: 940 + - makedirs: True + +surilogdir: + file.directory: + - name: /opt/so/log/suricata + - user: 940 + - group: 939 + +suridatadir: + file.directory: + - name: /nsm/suricata/extracted + - user: 940 + - group: 939 + - mode: 770 + - makedirs: True + +surirulesync: + file.recurse: + - name: /opt/so/conf/suricata/rules/ + - source: salt://suricata/rules/ + - user: 940 + - group: 940 + - show_changes: False + +surilogscript: + file.managed: + - name: /usr/local/bin/surilogcompress + - source: salt://suricata/cron/surilogcompress + - mode: 755 + +surilogcompress: + cron.present: + - name: /usr/local/bin/surilogcompress + - identifier: surilogcompress + - user: suricata + - minute: '17' + - hour: '*' + - daymonth: '*' + - month: '*' + - dayweek: '*' + +suriconfig: + file.managed: + - name: /opt/so/conf/suricata/suricata.yaml + - source: salt://suricata/files/suricata.yaml.jinja + - context: + suricata_config: {{ SURICATAMERGED.config }} + - user: 940 + - group: 940 + - template: jinja + +surithresholding: + file.managed: + - name: /opt/so/conf/suricata/threshold.conf + - source: salt://suricata/files/threshold.conf.jinja + - user: 940 + - group: 940 + - template: jinja + +# BPF compilation and configuration +{% if SURICATABPF %} + {% set BPF_CALC = salt['cmd.script']('/usr/sbin/so-bpf-compile', GLOBALS.sensor.interface + ' ' + SURICATABPF|join(" "),cwd='/root') %} + {% if BPF_CALC['stderr'] == "" %} + {% set BPF_STATUS = 1 %} + {% else %} +suribpfcompilationfailure: + test.configurable_test_state: + - changes: False + - result: False + - comment: "BPF Syntax Error - Discarding Specified BPF" + {% endif %} +{% endif %} + +suribpf: + file.managed: + - name: /opt/so/conf/suricata/bpf + - user: 940 + - group: 940 + {% if BPF_STATUS %} + - contents: {{ SURICATABPF }} + {% else %} + - contents: + - "" + {% endif %} + +so-suricata-eve-clean: + file.managed: + - name: /usr/sbin/so-suricata-eve-clean + - user: root + - group: root + - mode: 755 + - template: jinja + - source: salt://suricata/cron/so-suricata-eve-clean + +{% else %} + +{{sls}}_state_not_allowed: + test.fail_without_changes: + - name: {{sls}}_state_not_allowed + +{% endif %} diff --git a/salt/suricata/defaults.yaml b/salt/suricata/defaults.yaml index cf7db31af..f154b5beb 100644 --- a/salt/suricata/defaults.yaml +++ b/salt/suricata/defaults.yaml @@ -1,4 +1,5 @@ suricata: + enabled: False config: threading: set-cpu-affinity: 'no' @@ -417,4 +418,4 @@ suricata: - all.rules classification-file: /etc/suricata/classification.config reference-config-file: /etc/suricata/reference.config - threshold-file: /etc/suricata/threshold.conf \ No newline at end of file + threshold-file: /etc/suricata/threshold.conf diff --git a/salt/suricata/disabled.sls b/salt/suricata/disabled.sls new file mode 100644 index 000000000..60754ed3c --- /dev/null +++ b/salt/suricata/disabled.sls @@ -0,0 +1,32 @@ +# 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: + - suricata.sostatus + +so-suricata: + docker_container.absent: + - force: True + +so-kibana_so-status.disabled: + file.comment: + - name: /opt/so/conf/so-status/so-status.conf + - regex: ^so-suricata$ + +# Remove eve clean cron +clean_suricata_eve_files: + cron.absent: + - identifier: clean_suricata_eve_files + +{% else %} + +{{sls}}_state_not_allowed: + test.fail_without_changes: + - name: {{sls}}_state_not_allowed + +{% endif %} diff --git a/salt/suricata/enabled.sls b/salt/suricata/enabled.sls new file mode 100644 index 000000000..efc5f0251 --- /dev/null +++ b/salt/suricata/enabled.sls @@ -0,0 +1,62 @@ +# 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 %} + +include: + - suricata.config + - suricata.sostatus + +so-suricata: + docker_container.running: + - image: {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-suricata:{{ GLOBALS.so_version }} + - privileged: True + - environment: + - INTERFACE={{ GLOBALS.sensor.interface }} + - binds: + - /opt/so/conf/suricata/suricata.yaml:/etc/suricata/suricata.yaml:ro + - /opt/so/conf/suricata/threshold.conf:/etc/suricata/threshold.conf:ro + - /opt/so/conf/suricata/rules:/etc/suricata/rules:ro + - /opt/so/log/suricata/:/var/log/suricata/:rw + - /nsm/suricata/:/nsm/:rw + - /nsm/suricata/extracted:/var/log/suricata//filestore:rw + - /opt/so/conf/suricata/bpf:/etc/suricata/bpf:ro + - network_mode: host + - watch: + - file: suriconfig + - file: surithresholding + - file: /opt/so/conf/suricata/rules/ + - file: /opt/so/conf/suricata/bpf + - require: + - file: suriconfig + - file: surithresholding + - file: suribpf + +delete_so-kibana_so-status.disabled: + file.uncomment: + - name: /opt/so/conf/so-status/so-status.conf + - regex: ^so-suricata$ + +# Add eve clean cron +clean_suricata_eve_files: + cron.present: + - name: /usr/sbin/so-suricata-eve-clean > /dev/null 2>&1 + - identifier: clean_suricata_eve_files + - user: root + - minute: '*/5' + - hour: '*' + - daymonth: '*' + - month: '*' + - dayweek: '*' + +{% else %} + +{{sls}}_state_not_allowed: + test.fail_without_changes: + - name: {{sls}}_state_not_allowed + +{% endif %} diff --git a/salt/suricata/files/threshold.conf.jinja b/salt/suricata/files/threshold.conf.jinja index 45642404a..a439dad96 100644 --- a/salt/suricata/files/threshold.conf.jinja +++ b/salt/suricata/files/threshold.conf.jinja @@ -1,9 +1,8 @@ -{% set THRESHOLDING = salt['pillar.get']('thresholding', {}) -%} - +{% import_yaml 'suricata/thresholding/sids.yaml' as THRESHOLDING %} {% if THRESHOLDING -%} - {% for EACH_SID in THRESHOLDING.sids -%} - {% for ACTIONS_LIST in THRESHOLDING.sids[EACH_SID] -%} + {% for EACH_SID in THRESHOLDING -%} + {% for ACTIONS_LIST in THRESHOLDING[EACH_SID] -%} {% for EACH_ACTION in ACTIONS_LIST -%} {%- if EACH_ACTION == 'threshold' %} @@ -31,6 +30,6 @@ {%- endfor %} {%- else %} -##### The thresholding pillar has not been defined +##### Navigate to suricata > thresholding > SIDS in SOC to define thresholding {%- endif %} diff --git a/salt/suricata/init.sls b/salt/suricata/init.sls index 7788fa94a..34e1cdcdf 100644 --- a/salt/suricata/init.sls +++ b/salt/suricata/init.sls @@ -3,228 +3,11 @@ # 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 in allowed_states and grains.role not in ['so-manager', 'so-managersearch'] %} - -{% from 'vars/globals.map.jinja' import GLOBALS %} -{% from "suricata/map.jinja" import SURICATAOPTIONS with context %} - -{% from 'bpf/suricata.map.jinja' import SURICATABPF %} -{% set BPF_STATUS = 0 %} - -{% from 'suricata/suricata_config.map.jinja' import suricata_defaults as suricata_config with context %} -{% from "suricata/map.jinja" import START with context %} - -# Suricata - -# Add Suricata Group -suricatagroup: - group.present: - - name: suricata - - gid: 940 - -# Add Suricata user -suricata: - user.present: - - uid: 940 - - gid: 940 - - home: /nsm/suricata - - createhome: False - -socoregroupwithsuricata: - group.present: - - name: socore - - gid: 939 - - addusers: - - suricata - -suricata_sbin: - file.recurse: - - name: /usr/sbin - - source: salt://suricata/tools/sbin - - user: 939 - - group: 939 - - file_mode: 755 - -suricata_sbin_jinja: - file.recurse: - - name: /usr/sbin - - source: salt://suricata/tools/sbin_jinja - - user: 939 - - group: 939 - - file_mode: 755 - - template: jinja - -suridir: - file.directory: - - name: /opt/so/conf/suricata - - user: 940 - - group: 940 - -suriruledir: - file.directory: - - name: /opt/so/conf/suricata/rules - - user: 940 - - group: 940 - - makedirs: True - -surilogdir: - file.directory: - - name: /opt/so/log/suricata - - user: 940 - - group: 939 - -suridatadir: - file.directory: - - name: /nsm/suricata/extracted - - user: 940 - - group: 939 - - mode: 770 - - makedirs: True - -surirulesync: - file.recurse: - - name: /opt/so/conf/suricata/rules/ - - source: salt://suricata/rules/ - - user: 940 - - group: 940 - - show_changes: False - -surilogscript: - file.managed: - - name: /usr/local/bin/surilogcompress - - source: salt://suricata/cron/surilogcompress - - mode: 755 - -surilogcompress: - cron.present: - - name: /usr/local/bin/surilogcompress - - identifier: surilogcompress - - user: suricata - - minute: '17' - - hour: '*' - - daymonth: '*' - - month: '*' - - dayweek: '*' - -suriconfig: - file.managed: - - name: /opt/so/conf/suricata/suricata.yaml - - source: salt://suricata/files/suricata.yaml.jinja - - context: - suricata_config: {{ suricata_config.suricata.config }} - - user: 940 - - group: 940 - - template: jinja - -surithresholding: - file.managed: - - name: /opt/so/conf/suricata/threshold.conf - - source: salt://suricata/files/threshold.conf.jinja - - user: 940 - - group: 940 - - template: jinja - -# BPF compilation and configuration -{% if SURICATABPF %} - {% set BPF_CALC = salt['cmd.script']('/usr/sbin/so-bpf-compile', GLOBALS.sensor.interface + ' ' + SURICATABPF|join(" "),cwd='/root') %} - {% if BPF_CALC['stderr'] == "" %} - {% set BPF_STATUS = 1 %} - {% else %} -suribpfcompilationfailure: - test.configurable_test_state: - - changes: False - - result: False - - comment: "BPF Syntax Error - Discarding Specified BPF" - {% endif %} -{% endif %} - -suribpf: - file.managed: - - name: /opt/so/conf/suricata/bpf - - user: 940 - - group: 940 - {% if BPF_STATUS %} - - contents: {{ SURICATABPF }} - {% else %} - - contents: - - "" - {% endif %} - -so-suricata: - docker_container.{{ SURICATAOPTIONS.status }}: - {% if SURICATAOPTIONS.status == 'running' %} - - image: {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-suricata:{{ GLOBALS.so_version }} - - start: {{ SURICATAOPTIONS.start }} - - privileged: True - - environment: - - INTERFACE={{ GLOBALS.sensor.interface }} - - binds: - - /opt/so/conf/suricata/suricata.yaml:/etc/suricata/suricata.yaml:ro - - /opt/so/conf/suricata/threshold.conf:/etc/suricata/threshold.conf:ro - - /opt/so/conf/suricata/rules:/etc/suricata/rules:ro - - /opt/so/log/suricata/:/var/log/suricata/:rw - - /nsm/suricata/:/nsm/:rw - - /nsm/suricata/extracted:/var/log/suricata//filestore:rw - - /opt/so/conf/suricata/bpf:/etc/suricata/bpf:ro - - network_mode: host - - watch: - - file: suriconfig - - file: surithresholding - - file: /opt/so/conf/suricata/rules/ - - file: /opt/so/conf/suricata/bpf - - require: - - file: suriconfig - - file: surithresholding - - file: suribpf - - {% else %} {# if Suricata isn't enabled, then stop and remove the container #} - - force: True - {% endif %} - -append_so-suricata_so-status.conf: - file.append: - - name: /opt/so/conf/so-status/so-status.conf - - text: so-suricata - - unless: grep -q so-suricata /opt/so/conf/so-status/so-status.conf - - {% if not SURICATAOPTIONS.start %} -so-suricata_so-status.disabled: - file.comment: - - name: /opt/so/conf/so-status/so-status.conf - - regex: ^so-suricata$ - {% else %} -delete_so-suricata_so-status.disabled: - file.uncomment: - - name: /opt/so/conf/so-status/so-status.conf - - regex: ^so-suricata$ - {% endif %} - -so-suricata-eve-clean: - file.managed: - - name: /usr/sbin/so-suricata-eve-clean - - user: root - - group: root - - mode: 755 - - template: jinja - - source: salt://suricata/cron/so-suricata-eve-clean - -# Add eve clean cron -clean_suricata_eve_files: - cron.present: - - name: /usr/sbin/so-suricata-eve-clean > /dev/null 2>&1 - - identifier: clean_suricata_eve_files - - user: root - - minute: '*/5' - - hour: '*' - - daymonth: '*' - - month: '*' - - dayweek: '*' +{% from 'suricata/map.jinja' import SURICATAMERGED %} +include: +{% if SURICATAMERGED.enabled %} + - suricata.enabled {% else %} - -{{sls}}_state_not_allowed: - test.fail_without_changes: - - name: {{sls}}_state_not_allowed - + - suricata.disabled {% endif %} diff --git a/salt/suricata/map.jinja b/salt/suricata/map.jinja index 550781436..b238405c8 100644 --- a/salt/suricata/map.jinja +++ b/salt/suricata/map.jinja @@ -1,11 +1,61 @@ -{% set SURICATAOPTIONS = {} %} -{% set ENABLED = salt['pillar.get']('suricata:enabled', 'True') %} +{% from 'vars/globals.map.jinja' import GLOBALS %} +{% import_yaml 'suricata/defaults.yaml' as SURICATADEFAULTS %} +{% set SURICATAMERGED = salt['pillar.get']('suricata', SURICATADEFAULTS.suricata, merge=True) %} +{% import_yaml 'suricata/suricata_mdengine.yaml' as suricata_mdengine %} -# don't start the docker container if it is an import node or disabled via pillar -{% if grains.id.split('_')|last == 'import' or ENABLED is sameas false %} - {% do SURICATAOPTIONS.update({'start': False}) %} - {% do SURICATAOPTIONS.update({'status': 'absent'}) %} -{% else %} - {% do SURICATAOPTIONS.update({'start': True}) %} - {% do SURICATAOPTIONS.update({'status': 'running'}) %} +{% set default_evelog_index = [] %} +{% set default_filestore_index = [] %} +{% set surimeta_evelog_index = [] %} +{% set surimeta_filestore_index = [] %} + +{# suricata.config.af-packet has to be rewritten here since we cant display '- interface' in the ui #} +{# we are limited to only one iterface #} +{% load_yaml as afpacket %} +- interface: {{ SURICATAMERGED.config['af-packet'].interface }} + cluster-id: {{ SURICATAMERGED.config['af-packet']['cluster-id'] }} + cluster-type: {{ SURICATAMERGED.config['af-packet']['cluster-type'] }} + defrag: {{ SURICATAMERGED.config['af-packet'].defrag }} + use-mmap: {{ SURICATAMERGED.config['af-packet']['use-mmap'] }} + threads: {{ SURICATAMERGED.config['af-packet'].threads }} + tpacket-v3: {{ SURICATAMERGED.config['af-packet']['tpacket-v3'] }} + ring-size: {{ SURICATAMERGED.config['af-packet']['ring-size'] }} +{% endload %} +{% do SURICATAMERGED.config.pop('af-packet') %} +{% do SURICATAMERGED.config.update({'af-packet': afpacket}) %} + +{% load_yaml as outputs %} +{% for le, ld in SURICATAMERGED.config.outputs.items() %} + - {{ le }}: {{ ld }} +{% endfor %} +{% endload %} +{% do SURICATAMERGED.config.pop('outputs') %} +{% do SURICATAMERGED.config.update({'outputs': outputs}) %} + +{# Find the index of eve-log so it can be updated later #} +{% for li in SURICATAMERGED.config.outputs %} + {% if 'eve-log' in li.keys() %} + {% do default_evelog_index.append(loop.index0) %} + {% endif %} + {% if 'file-store' in li.keys() %} + {% do default_filestore_index.append(loop.index0) %} + {% endif %} +{% endfor %} +{% set default_evelog_index = default_evelog_index[0] %} +{% set default_filestore_index = default_filestore_index[0] %} + +{# Find the index of eve-log so it can be grabbed later #} +{% for li in suricata_mdengine.suricata.config.outputs %} + {% if 'eve-log' in li.keys() %} + {% do surimeta_evelog_index.append(loop.index0) %} + {% endif %} + {% if 'file-store' in li.keys() %} + {% do surimeta_filestore_index.append(loop.index0) %} + {% endif %} +{% endfor %} +{% set surimeta_evelog_index = surimeta_evelog_index[0] %} +{% set surimeta_filestore_index = surimeta_filestore_index[0] %} + +{% if GLOBALS.md_engine == 'SURICATA' %} + {% do SURICATAMERGED.config.outputs[default_evelog_index]['eve-log'].types.extend(suricata_mdengine.suricata.config.outputs[surimeta_evelog_index]['eve-log'].types) %} + {% do SURICATAMERGED.config.outputs[default_filestore_index]['file-store'].update({'enabled':suricata_mdengine.suricata.config.outputs[surimeta_filestore_index]['file-store']['enabled']}) %} {% endif %} diff --git a/salt/suricata/soc_suricata.yaml b/salt/suricata/soc_suricata.yaml index ea98b7650..f1971f17f 100644 --- a/salt/suricata/soc_suricata.yaml +++ b/salt/suricata/soc_suricata.yaml @@ -1,9 +1,14 @@ suricata: + enabled: + description: You can enable or disable Suricata. + helpLink: suricata.html thresholding: sids__yaml: description: Threshold SIDS List - file: True syntax: yaml + file: True + global: True + multiline: True title: SIDS helpLink: suricata.html config: diff --git a/salt/suricata/sostatus.sls b/salt/suricata/sostatus.sls new file mode 100644 index 000000000..fc22e1aac --- /dev/null +++ b/salt/suricata/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-kibana_so-status.conf: + file.append: + - name: /opt/so/conf/so-status/so-status.conf + - text: so-suricata + - unless: grep -q so-suricata /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/suricata/suricata_config.map.jinja b/salt/suricata/suricata_config.map.jinja deleted file mode 100644 index fb4c22af3..000000000 --- a/salt/suricata/suricata_config.map.jinja +++ /dev/null @@ -1,56 +0,0 @@ -{% import_yaml 'suricata/defaults.yaml' as suricata_defaults with context %} -{% import_yaml 'suricata/suricata_meta.yaml' as suricata_meta with context %} -{% set suricata_pillar = pillar.suricata %} -{% set surimerge = salt['defaults.merge'](suricata_defaults, suricata_pillar, in_place=False) %} -{% set default_evelog_index = [] %} -{% set default_filestore_index = [] %} -{% set surimeta_evelog_index = [] %} -{% set surimeta_filestore_index = [] %} - -{% load_yaml as afpacket %} -- interface: {{ surimerge.suricata.config['af-packet'].interface }} - cluster-id: {{ surimerge.suricata.config['af-packet']['cluster-id'] }} - cluster-type: {{ surimerge.suricata.config['af-packet']['cluster-type'] }} - defrag: {{ surimerge.suricata.config['af-packet'].defrag }} - use-mmap: {{ surimerge.suricata.config['af-packet']['use-mmap'] }} - threads: {{ surimerge.suricata.config['af-packet'].threads }} - tpacket-v3: {{ surimerge.suricata.config['af-packet']['tpacket-v3'] }} - ring-size: {{ surimerge.suricata.config['af-packet']['ring-size'] }} -{% endload %} -{% do suricata_defaults.suricata.config.update({'af-packet': afpacket}) %} - -{% load_yaml as outputs %} -{% for le, ld in surimerge.suricata.config.outputs.items() %} - - {{ le }}: {{ ld }} -{% endfor %} -{% endload %} -{% do suricata_defaults.suricata.config.update({'outputs': outputs}) %} - -{# Find the index of eve-log so it can be updated later #} -{% for li in suricata_defaults.suricata.config.outputs %} - {% if 'eve-log' in li.keys() %} - {% do default_evelog_index.append(loop.index0) %} - {% endif %} - {% if 'file-store' in li.keys() %} - {% do default_filestore_index.append(loop.index0) %} - {% endif %} -{% endfor %} -{% set default_evelog_index = default_evelog_index[0] %} -{% set default_filestore_index = default_filestore_index[0] %} - -{# Find the index of eve-log so it can be grabbed later #} -{% for li in suricata_meta.suricata.config.outputs %} - {% if 'eve-log' in li.keys() %} - {% do surimeta_evelog_index.append(loop.index0) %} - {% endif %} - {% if 'file-store' in li.keys() %} - {% do surimeta_filestore_index.append(loop.index0) %} - {% endif %} -{% endfor %} -{% set surimeta_evelog_index = surimeta_evelog_index[0] %} -{% set surimeta_filestore_index = surimeta_filestore_index[0] %} - -{% if salt['pillar.get']('global:mdengine', 'ZEEK') == 'SURICATA' %} - {% do suricata_defaults.suricata.config.outputs[default_evelog_index]['eve-log'].types.extend(suricata_meta.suricata.config.outputs[surimeta_evelog_index]['eve-log'].types) %} - {% do suricata_defaults.suricata.config.outputs[default_filestore_index]['file-store'].update({'enabled':suricata_meta.suricata.config.outputs[surimeta_filestore_index]['file-store']['enabled']}) %} -{% endif %} diff --git a/salt/suricata/suricata_meta.yaml b/salt/suricata/suricata_mdengine.yaml similarity index 100% rename from salt/suricata/suricata_meta.yaml rename to salt/suricata/suricata_mdengine.yaml diff --git a/salt/suricata/thresholding/sids.yaml b/salt/suricata/thresholding/sids.yaml index e9dc04e25..e69de29bb 100644 --- a/salt/suricata/thresholding/sids.yaml +++ b/salt/suricata/thresholding/sids.yaml @@ -1,44 +0,0 @@ -thresholding: - sids: - 99999999999999999: - - threshold: - gen_id: 1 - type: threshold - track: by_src - count: 10 - seconds: 10 - - threshold: - gen_id: 1 - type: limit - track: by_dst - count: 100 - seconds: 30 - - rate_filter: - gen_id: 1 - track: by_rule - count: 50 - seconds: 30 - new_action: alert - timeout: 30 - - suppress: - gen_id: 1 - track: by_either - ip: 10.10.3.7 - 99999999999999998: - - threshold: - gen_id: 1 - type: limit - track: by_dst - count: 10 - seconds: 10 - - rate_filter: - gen_id: 1 - track: by_src - count: 50 - seconds: 20 - new_action: pass - timeout: 60 - - suppress: - gen_id: 1 - track: by_src - ip: 10.10.3.0/24 \ No newline at end of file diff --git a/salt/telegraf/scripts/redis.sh b/salt/telegraf/scripts/redis.sh index c730885d4..dba893c87 100644 --- a/salt/telegraf/scripts/redis.sh +++ b/salt/telegraf/scripts/redis.sh @@ -11,8 +11,9 @@ if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then UNPARSED=$(redis-cli llen logstash:unparsed | awk '{print $1}') PARSED=$(redis-cli llen logstash:parsed | awk '{print $1}') - - echo "redisqueue unparsed=$UNPARSED,parsed=$PARSED" + MEM_USED=$(redis-cli info memory | grep used_memory_peak_perc | cut -d ":" -f2 | sed "s/%//") + + echo "redisqueue unparsed=$UNPARSED,parsed=$PARSED,mem_used=$MEM_USED" fi