diff --git a/salt/allowed_states.map.jinja b/salt/allowed_states.map.jinja index e7a9a0491..206c2fad6 100644 --- a/salt/allowed_states.map.jinja +++ b/salt/allowed_states.map.jinja @@ -46,6 +46,7 @@ 'pcap', 'suricata', 'healthcheck', + 'elasticagent', 'schedule', 'tcpreplay', 'docker_clean' diff --git a/salt/elasticagent/config.sls b/salt/elasticagent/config.sls new file mode 100644 index 000000000..18d0e482e --- /dev/null +++ b/salt/elasticagent/config.sls @@ -0,0 +1,47 @@ +# 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 %} +{% from 'vars/globals.map.jinja' import GLOBALS %} +{% if sls.split('.')[0] in allowed_states %} + +# Add EA Group +elasticagentgroup: + group.present: + - name: elastic-agent + - gid: 949 + +# Add EA user +elastic-agent: + user.present: + - uid: 949 + - gid: 949 + - home: /opt/so/conf/elastic-agent + - createhome: False + +elasticagentconfdir: + file.directory: + - name: /opt/so/conf/elastic-agent + - user: 949 + - group: 939 + - makedirs: True + +# Create config +create-elastic-agent-config: + file.managed: + - name: /opt/so/conf/elastic-agent/elastic-agent.yml + - source: salt://elasticagent/files/elastic-agent.yml.jinja + - user: 949 + - group: 939 + - template: jinja + + +{% else %} + +{{sls}}_state_not_allowed: + test.fail_without_changes: + - name: {{sls}}_state_not_allowed + +{% endif %} diff --git a/salt/elasticagent/defaults.yaml b/salt/elasticagent/defaults.yaml new file mode 100644 index 000000000..f9b1bd67a --- /dev/null +++ b/salt/elasticagent/defaults.yaml @@ -0,0 +1,2 @@ +elasticagent: + enabled: False \ No newline at end of file diff --git a/salt/elasticagent/disabled.sls b/salt/elasticagent/disabled.sls new file mode 100644 index 000000000..a6d72b193 --- /dev/null +++ b/salt/elasticagent/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: + - elasticagent.sostatus + +so-elastic-agent: + docker_container.absent: + - force: True + +so-elastic-agent_so-status.disabled: + file.comment: + - name: /opt/so/conf/so-status/so-status.conf + - regex: ^so-elastic-agent$ + +{% else %} + +{{sls}}_state_not_allowed: + test.fail_without_changes: + - name: {{sls}}_state_not_allowed + +{% endif %} diff --git a/salt/elasticagent/enabled.sls b/salt/elasticagent/enabled.sls new file mode 100644 index 000000000..52467a54e --- /dev/null +++ b/salt/elasticagent/enabled.sls @@ -0,0 +1,65 @@ +# 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: + - elasticagent.config + - elasticagent.sostatus + +so-elastic-agent: + docker_container.running: + - image: {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-elastic-agent:{{ GLOBALS.so_version }} + - name: so-elastic-agent + - hostname: {{ GLOBALS.hostname }} + - detach: True + - user: 949 + - networks: + - sobridge: + - ipv4_address: {{ DOCKER.containers['so-elastic-agent'].ip }} + - extra_hosts: + - {{ GLOBALS.manager }}:{{ GLOBALS.manager_ip }} + - {{ GLOBALS.hostname }}:{{ GLOBALS.node_ip }} + {% if DOCKER.containers['so-elastic-agent'].extra_hosts %} + {% for XTRAHOST in DOCKER.containers['so-elastic-agent'].extra_hosts %} + - {{ XTRAHOST }} + {% endfor %} + {% endif %} + - port_bindings: + {% for BINDING in DOCKER.containers['so-elastic-agent'].port_bindings %} + - {{ BINDING }} + {% endfor %} + - binds: + - /opt/so/conf/elastic-agent/elastic-agent.yml:/usr/share/elastic-agent/elastic-agent.yml:ro + {% if DOCKER.containers['so-elastic-agent'].custom_bind_mounts %} + {% for BIND in DOCKER.containers['so-elastic-agent'].custom_bind_mounts %} + - {{ BIND }} + {% endfor %} + {% endif %} + - environment: + {% if DOCKER.containers['so-elastic-agent'].extra_env %} + {% for XTRAENV in DOCKER.containers['so-elastic-agent'].extra_env %} + - {{ XTRAENV }} + {% endfor %} + {% endif %} + + +delete_so-elastic-agent_so-status.disabled: + file.uncomment: + - name: /opt/so/conf/so-status/so-status.conf + - regex: ^so-elastic-agent$ + + +{% else %} + +{{sls}}_state_not_allowed: + test.fail_without_changes: + - name: {{sls}}_state_not_allowed + +{% endif %} diff --git a/salt/elasticagent/files/elastic-agent.yml.jinja b/salt/elasticagent/files/elastic-agent.yml.jinja new file mode 100644 index 000000000..3eb63962b --- /dev/null +++ b/salt/elasticagent/files/elastic-agent.yml.jinja @@ -0,0 +1,118 @@ +{% from 'vars/globals.map.jinja' import GLOBALS %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %} + +id: aea1ba80-1065-11ee-a369-97538913b6a9 +revision: 2 +outputs: + default: + type: elasticsearch + hosts: + - 'https://{{ GLOBALS.hostname }}:9200' + username: '{{ ES_USER }}' + password: '{{ ES_PASS }}' +output_permissions: {} +agent: + download: + sourceURI: 'http://{{ GLOBALS.manager }}:8443/artifacts/' + monitoring: + enabled: false + logs: false + metrics: false + features: {} +inputs: + - id: logfile-logs-80ffa884-2cfc-459a-964a-34df25714d85 + name: suricata-logs + revision: 1 + type: logfile + use_output: default + meta: + package: + name: log + version: 1.1.2 + data_stream: + namespace: so + package_policy_id: 80ffa884-2cfc-459a-964a-34df25714d85 + streams: + - id: logfile-log.log-80ffa884-2cfc-459a-964a-34df25714d85 + data_stream: + dataset: suricata + paths: + - /nsm/suricata/eve*.json + processors: + - add_fields: + target: event + fields: + category: network + module: suricata + pipeline: suricata.common + - id: logfile-logs-90103ac4-f6bd-4a4a-b596-952c332390fc + name: strelka-logs + revision: 1 + type: logfile + use_output: default + meta: + package: + name: log + version: 1.1.2 + data_stream: + namespace: so + package_policy_id: 90103ac4-f6bd-4a4a-b596-952c332390fc + streams: + - id: logfile-log.log-90103ac4-f6bd-4a4a-b596-952c332390fc + data_stream: + dataset: strelka + paths: + - /nsm/strelka/log/strelka.log + processors: + - add_fields: + target: event + fields: + category: file + module: strelka + pipeline: strelka.file + - id: logfile-logs-6197fe84-9b58-4d9b-8464-3d517f28808d + name: zeek-logs + revision: 1 + type: logfile + use_output: default + meta: + package: + name: log + version: 1.1.2 + data_stream: + namespace: so + package_policy_id: 6197fe84-9b58-4d9b-8464-3d517f28808d + streams: + - id: logfile-log.log-6197fe84-9b58-4d9b-8464-3d517f28808d + data_stream: + dataset: zeek + paths: + - /nsm/zeek/logs/current/*.log + processors: + - dissect: + tokenizer: '/nsm/zeek/logs/current/%{pipeline}.log' + field: log.file.path + trim_chars: .log + target_prefix: '' + - script: + lang: javascript + source: | + function process(event) { + var pl = event.Get("pipeline"); + event.Put("@metadata.pipeline", "zeek." + pl); + } + - add_fields: + target: event + fields: + category: network + module: zeek + - add_tags: + tags: ics + when: + regexp: + pipeline: >- + ^bacnet*|^bsap*|^cip*|^cotp*|^dnp3*|^ecat*|^enip*|^modbus*|^opcua*|^profinet*|^s7comm* + exclude_files: + - >- + broker|capture_loss|cluster|ecat_arp_info|known_hosts|known_services|loaded_scripts|ntp|ocsp|packet_filter|reporter|stats|stderr|stdout.log$ diff --git a/salt/elasticagent/init.sls b/salt/elasticagent/init.sls new file mode 100644 index 000000000..3ea474026 --- /dev/null +++ b/salt/elasticagent/init.sls @@ -0,0 +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 as shown at +# https://securityonion.net/license; you may not use this file except in compliance with the +# Elastic License 2.0. + +{% from 'elasticagent/map.jinja' import ELASTICAGENTMERGED %} + +include: +{% if ELASTICAGENTMERGED.enabled %} + - elasticagent.enabled +{% else %} + - elasticagent.disabled +{% endif %} diff --git a/salt/elasticagent/map.jinja b/salt/elasticagent/map.jinja new file mode 100644 index 000000000..f48172502 --- /dev/null +++ b/salt/elasticagent/map.jinja @@ -0,0 +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 'elasticagent/defaults.yaml' as ELASTICAGENTDEFAULTS %} +{% set ELASTICAGENTMERGED = salt['pillar.get']('elasticagent', ELASTICAGENTDEFAULTS.elasticagent, merge=True) %} diff --git a/salt/elasticagent/sostatus.sls b/salt/elasticagent/sostatus.sls new file mode 100644 index 000000000..e2cbc9b8e --- /dev/null +++ b/salt/elasticagent/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-elastic-agent_so-status.conf: + file.append: + - name: /opt/so/conf/so-status/so-status.conf + - text: so-elastic-agent + - unless: grep -q so-elastic-agent$ /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/elasticfleet/config.sls b/salt/elasticfleet/config.sls index cc3b0675f..9bfb6e34d 100644 --- a/salt/elasticfleet/config.sls +++ b/salt/elasticfleet/config.sls @@ -8,13 +8,13 @@ {% if sls.split('.')[0] in allowed_states %} # Add EA Group -elasticsagentgroup: +elasticfleetgroup: group.present: - - name: elastic-agent + - name: elastic-fleet - gid: 947 # Add EA user -elastic-agent: +elastic-fleet: user.present: - uid: 947 - gid: 947 diff --git a/salt/top.sls b/salt/top.sls index 229557575..11a594f29 100644 --- a/salt/top.sls +++ b/salt/top.sls @@ -209,6 +209,7 @@ base: - suricata - zeek - elasticfleet.install_agent_grid + - elasticagent - docker_clean '*_import and G@saltversion:{{saltversion}}':