Multi OS Support

This commit is contained in:
Mike Reeves
2023-07-13 15:05:51 -04:00
45 changed files with 3361 additions and 1351 deletions

View File

@@ -1,18 +1,18 @@
### 2.4.2-20230531 ISO image built on 2023/05/31 ### 2.4.3-20230711 ISO image built on 2023/07/11
### Download and Verify ### Download and Verify
2.4.2-20230531 ISO image: 2.4.3-20230711 ISO image:
https://download.securityonion.net/file/securityonion/securityonion-2.4.2-20230531.iso https://download.securityonion.net/file/securityonion/securityonion-2.4.3-20230711.iso
MD5: EB861EFB7F7DA6FB418075B4C452E4EB MD5: F481ED39E02A5AF05EB50D319D97A6C7
SHA1: 479A72DBB0633CB23608122F7200A24E2C3C3128 SHA1: 20F9BAA8F73A44C21A8DFE81F36247BCF33CEDA6
SHA256: B69C1AE4C576BBBC37F4B87C2A8379903421E65B2C4F24C90FABB0EAD6F0471B SHA256: D805522E02CD4941641385F6FF86FAAC240DA6C5FD98F78460348632C7C631B0
Signature for ISO image: Signature for ISO image:
https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.2-20230531.iso.sig https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.3-20230711.iso.sig
Signing key: Signing key:
https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/2.4/main/KEYS https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/2.4/main/KEYS
@@ -26,22 +26,22 @@ wget https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/2.
Download the signature file for the ISO: Download the signature file for the ISO:
``` ```
wget https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.2-20230531.iso.sig wget https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.3-20230711.iso.sig
``` ```
Download the ISO image: Download the ISO image:
``` ```
wget https://download.securityonion.net/file/securityonion/securityonion-2.4.2-20230531.iso wget https://download.securityonion.net/file/securityonion/securityonion-2.4.3-20230711.iso
``` ```
Verify the downloaded ISO image using the signature file: Verify the downloaded ISO image using the signature file:
``` ```
gpg --verify securityonion-2.4.2-20230531.iso.sig securityonion-2.4.2-20230531.iso gpg --verify securityonion-2.4.3-20230711.iso.sig securityonion-2.4.3-20230711.iso
``` ```
The output should show "Good signature" and the Primary key fingerprint should match what's shown below: The output should show "Good signature" and the Primary key fingerprint should match what's shown below:
``` ```
gpg: Signature made Wed 31 May 2023 05:01:41 PM EDT using RSA key ID FE507013 gpg: Signature made Tue 11 Jul 2023 06:23:37 PM EDT using RSA key ID FE507013
gpg: Good signature from "Security Onion Solutions, LLC <info@securityonionsolutions.com>" gpg: Good signature from "Security Onion Solutions, LLC <info@securityonionsolutions.com>"
gpg: WARNING: This key is not certified with a trusted signature! gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner. gpg: There is no indication that the signature belongs to the owner.

View File

@@ -1,6 +1,6 @@
## Security Onion 2.4 Release Candidate 1 (RC1) ## Security Onion 2.4 Beta 4
Security Onion 2.4 Release Candidate 1 (RC1) is here! Security Onion 2.4 Beta 4 is here!
## Screenshots ## Screenshots

View File

@@ -1 +1 @@
2.4.3 2.4.4

View File

@@ -2,7 +2,7 @@
{% set cached_grains = salt.saltutil.runner('cache.grains', tgt='*') %} {% set cached_grains = salt.saltutil.runner('cache.grains', tgt='*') %}
{% for minionid, ip in salt.saltutil.runner( {% for minionid, ip in salt.saltutil.runner(
'mine.get', 'mine.get',
tgt='G@role:so-manager or G@role:so-managersearch or G@role:so-standalone or G@role:so-searchnode or G@role:so-heavynode or G@role:so-receiver or G@role:so-helix ', tgt='G@role:so-manager or G@role:so-managersearch or G@role:so-standalone or G@role:so-searchnode or G@role:so-heavynode or G@role:so-receiver or G@role:so-fleet ',
fun='network.ip_addrs', fun='network.ip_addrs',
tgt_type='compound') | dictsort() tgt_type='compound') | dictsort()
%} %}

14
pillar/soc/license.sls Normal file
View File

@@ -0,0 +1,14 @@
# Copyright Jason Ertel (github.com/jertel).
# 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.
# Note: Per the Elastic License 2.0, the second limitation states:
#
# "You may not move, change, disable, or circumvent the license key functionality
# in the software, and you may not remove or obscure any functionality in the
# software that is protected by the license key."
# This file is generated by Security Onion and contains a list of license-enabled features.
features: []

View File

@@ -40,6 +40,7 @@ base:
- logstash.adv_logstash - logstash.adv_logstash
- soc.soc_soc - soc.soc_soc
- soc.adv_soc - soc.adv_soc
- soc.license
- soctopus.soc_soctopus - soctopus.soc_soctopus
- soctopus.adv_soctopus - soctopus.adv_soctopus
- kibana.soc_kibana - kibana.soc_kibana
@@ -103,6 +104,7 @@ base:
- idstools.adv_idstools - idstools.adv_idstools
- soc.soc_soc - soc.soc_soc
- soc.adv_soc - soc.adv_soc
- soc.license
- soctopus.soc_soctopus - soctopus.soc_soctopus
- soctopus.adv_soctopus - soctopus.adv_soctopus
- kibana.soc_kibana - kibana.soc_kibana
@@ -161,6 +163,7 @@ base:
- manager.adv_manager - manager.adv_manager
- soc.soc_soc - soc.soc_soc
- soc.adv_soc - soc.adv_soc
- soc.license
- soctopus.soc_soctopus - soctopus.soc_soctopus
- soctopus.adv_soctopus - soctopus.adv_soctopus
- kibana.soc_kibana - kibana.soc_kibana
@@ -258,6 +261,7 @@ base:
- manager.adv_manager - manager.adv_manager
- soc.soc_soc - soc.soc_soc
- soc.adv_soc - soc.adv_soc
- soc.license
- soctopus.soc_soctopus - soctopus.soc_soctopus
- soctopus.adv_soctopus - soctopus.adv_soctopus
- kibana.soc_kibana - kibana.soc_kibana

View File

@@ -20,7 +20,6 @@ pki_private_key:
- name: /etc/pki/ca.key - name: /etc/pki/ca.key
- keysize: 4096 - keysize: 4096
- passphrase: - passphrase:
- cipher: aes_256_cbc
- backup: True - backup: True
{% if salt['file.file_exists']('/etc/pki/ca.key') -%} {% if salt['file.file_exists']('/etc/pki/ca.key') -%}
- prereq: - prereq:

View File

@@ -303,6 +303,17 @@ lookup_role() {
echo ${pieces[1]} echo ${pieces[1]}
} }
is_feature_enabled() {
feature=$1
enabled=$(lookup_salt_value features)
for cur in $enabled; do
if [[ "$feature" == "$cur" ]]; then
return 0
fi
done
return 1
}
require_manager() { require_manager() {
if is_manager_node; then if is_manager_node; then
echo "This is a manager, so we can proceed." echo "This is a manager, so we can proceed."

View File

@@ -30,7 +30,7 @@ class PlaybookESAlerter(Alerter):
if 'es_username' in self.rule and 'es_password' in self.rule: if 'es_username' in self.rule and 'es_password' in self.rule:
creds = (self.rule['es_username'], self.rule['es_password']) 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} payload = {"tags":"alert","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']}/logs-playbook.alerts-so/_doc/" url = f"https://{self.rule['es_host']}:{self.rule['es_port']}/logs-playbook.alerts-so/_doc/"
requests.post(url, data=json.dumps(payload), headers=headers, verify=False, auth=creds) requests.post(url, data=json.dumps(payload), headers=headers, verify=False, auth=creds)

View File

@@ -2,10 +2,11 @@ elasticfleet:
enabled: False enabled: False
config: config:
server: server:
custom_fqdn: ''
enable_auto_configuration: True
endpoints_enrollment: '' endpoints_enrollment: ''
es_token: '' es_token: ''
grid_enrollment: '' grid_enrollment: ''
url: ''
logging: logging:
zeek: zeek:
excluded: excluded:

View File

@@ -7,6 +7,8 @@
{% if sls.split('.')[0] in allowed_states %} {% if sls.split('.')[0] in allowed_states %}
{% from 'vars/globals.map.jinja' import GLOBALS %} {% from 'vars/globals.map.jinja' import GLOBALS %}
{% from 'docker/docker.map.jinja' import DOCKER %} {% from 'docker/docker.map.jinja' import DOCKER %}
{% from 'elasticfleet/map.jinja' import ELASTICFLEETMERGED %}
{# This value is generated during node install and stored in minion pillar #} {# This value is generated during node install and stored in minion pillar #}
{% set SERVICETOKEN = salt['pillar.get']('elasticfleet:config:server:es_token','') %} {% set SERVICETOKEN = salt['pillar.get']('elasticfleet:config:server:es_token','') %}
@@ -14,6 +16,16 @@ include:
- elasticfleet.config - elasticfleet.config
- elasticfleet.sostatus - elasticfleet.sostatus
{% if ELASTICFLEETMERGED.config.server.enable_auto_configuration and grains.role not in ['so-import', 'so-eval'] %}
so-elastic-fleet-auto-configure-logstash-outputs:
cmd.run:
- name: /usr/sbin/so-elastic-fleet-outputs-update
#so-elastic-fleet-auto-configure-server-urls:
# cmd.run:
# - name: /usr/sbin/so-elastic-fleet-urls-update
{% endif %}
{% if SERVICETOKEN != '' %} {% if SERVICETOKEN != '' %}
so-elastic-fleet: so-elastic-fleet:
docker_container.running: docker_container.running:

View File

@@ -13,9 +13,14 @@
"system.auth": { "system.auth": {
"enabled": true, "enabled": true,
"vars": { "vars": {
"ignore_older": "72h",
"paths": [ "paths": [
"/var/log/auth.log*", "/var/log/auth.log*",
"/var/log/secure*" "/var/log/secure*"
],
"preserve_original_event": false,
"tags": [
"system-auth"
] ]
} }
}, },
@@ -24,27 +29,42 @@
"vars": { "vars": {
"paths": [ "paths": [
"/var/log/messages*", "/var/log/messages*",
"/var/log/syslog*" "/var/log/syslog*",
] "/var/log/system*"
],
"tags": [],
"ignore_older": "72h"
} }
} }
} }
}, },
"system-winlog": { "system-winlog": {
"enabled": true, "enabled": true,
"vars": {
"preserve_original_event": false
},
"streams": { "streams": {
"system.application": { "system.application": {
"enabled": true, "enabled": true,
"vars": { "vars": {
"preserve_original_event": false,
"ignore_older": "72h",
"language": 0,
"tags": [] "tags": []
} }
}, },
"system.security": { "system.security": {
"enabled": true, "enabled": true,
"vars": { "vars": {
"preserve_original_event": false,
"ignore_older": "72h",
"language": 0,
"tags": []
}
},
"system.system": {
"enabled": true,
"vars": {
"preserve_original_event": false,
"ignore_older": "72h",
"language": 0,
"tags": [] "tags": []
} }
} }

View File

@@ -11,6 +11,16 @@ elasticfleet:
helpLink: zeek.html helpLink: zeek.html
config: config:
server: server:
custom_fqdn:
description: Custom FQDN for Agents to connect to.
global: True
helpLink: elastic-fleet.html
advanced: True
enable_auto_configuration:
description: Enable auto-configuration of Logstash Outputs & Fleet Host URLs.
global: True
helpLink: elastic-fleet.html
advanced: True
endpoints_enrollment: endpoints_enrollment:
description: Endpoint enrollment key. description: Endpoint enrollment key.
global: True global: True
@@ -29,8 +39,3 @@ elasticfleet:
helpLink: elastic-fleet.html helpLink: elastic-fleet.html
sensitive: True sensitive: True
advanced: True advanced: True
url:
description: Agent connection URL.
global: True
helpLink: elastic-fleet.html
advanced: True

View File

@@ -35,10 +35,8 @@ if [ ! -f /opt/so/state/eaintegrations.txt ]; then
elastic_fleet_integration_update "$INTEGRATION_ID" "@$INTEGRATION" elastic_fleet_integration_update "$INTEGRATION_ID" "@$INTEGRATION"
else else
printf "\n\nIntegration does not exist - Creating integration\n" printf "\n\nIntegration does not exist - Creating integration\n"
if [ "$NAME" != "elasticsearch-logs" ]; then
elastic_fleet_integration_create "@$INTEGRATION" elastic_fleet_integration_create "@$INTEGRATION"
fi fi
fi
done done
if [[ "$RETURN_CODE" != "1" ]]; then if [[ "$RETURN_CODE" != "1" ]]; then
touch /opt/so/state/eaintegrations.txt touch /opt/so/state/eaintegrations.txt

View File

@@ -0,0 +1,75 @@
# 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 'vars/globals.map.jinja' import GLOBALS %}
{% set CUSTOMFQDN = salt['pillar.get']('elasticfleet:config:server:custom_fqdn') %}
function update_logstash_outputs() {
# Generate updated JSON payload
JSON_STRING=$(jq -n --arg UPDATEDLIST $NEW_LIST_JSON '{"name":"grid-logstash","type":"logstash","hosts": $UPDATEDLIST,"is_default":true,"is_default_monitoring":true,"config_yaml":""}')
# Update Logstash Outputs
curl -K /opt/so/conf/elasticsearch/curl.config -L -X PUT "localhost:5601/api/fleet/outputs/so-manager_logstash" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d "$JSON_STRING" | jq
}
# Get current list of Logstash Outputs
RAW_JSON=$(curl -K /opt/so/conf/elasticsearch/curl.config 'http://localhost:5601/api/fleet/outputs/so-manager_logstash')
# Check to make sure that the server responded with good data - else, bail from script
CHECKSUM=$(jq -r '.item.id' <<< "$RAW_JSON")
if [ "$CHECKSUM" != "so-manager_logstash" ]; then
printf "Failed to query for current Logstash Outputs..."
exit 1
fi
# Get the current list of Logstash outputs & hash them
CURRENT_LIST=$(jq -c -r '.item.hosts' <<< "$RAW_JSON")
CURRENT_HASH=$(sha1sum <<< "$CURRENT_LIST" | awk '{print $1}')
# Create array & add initial elements
if [ "{{ GLOBALS.manager_ip }}" = "{{ GLOBALS.url_base }}" ]; then
NEW_LIST=("{{ GLOBALS.url_base }}:5055")
else
NEW_LIST=("{{ GLOBALS.url_base }}:5055" "{{ GLOBALS.manager_ip }}:5055")
fi
{% if CUSTOMFQDN != "" %}
# Add Custom Hostname to list
NEW_LIST+=("{{ CUSTOMFQDN }}:5055")
{% endif %}
# Query for the current Grid Nodes that are running Logstash
LOGSTASHNODES=$(salt-call --out=json pillar.get logstash:nodes | jq '.local')
# Query for Receiver Nodes & add them to the list
if grep -q "receiver" <<< $LOGSTASHNODES; then
readarray -t RECEIVERNODES < <(jq -r ' .receiver | keys_unsorted[]' <<< $LOGSTASHNODES)
for NODE in "${RECEIVERNODES[@]}"
do
NEW_LIST+=("$NODE:5055")
done
fi
# Query for Fleet Nodes & add them to the list
if grep -q "fleet" <<< $LOGSTASHNODES; then
readarray -t FLEETNODES < <(jq -r ' .fleet | keys_unsorted[]' <<< $LOGSTASHNODES)
for NODE in "${FLEETNODES[@]}"
do
NEW_LIST+=("$NODE:5055")
done
fi
# Sort & hash the new list of Logstash Outputs
NEW_LIST_JSON=$(jq --compact-output --null-input '$ARGS.positional' --args -- "${NEW_LIST[@]}")
NEW_HASH=$(sha1sum <<< "$NEW_LIST_JSON" | awk '{print $1}')
# Compare the current & new list of outputs - if different, update the Logstash outputs
if [ "$NEW_HASH" = "$CURRENT_HASH" ]; then
printf "\nHashes match - no update needed.\n"
printf "Current List: $CURRENT_LIST\nNew List: $NEW_LIST_JSON\n"
exit 0
else
printf "\nHashes don't match - update needed.\n"
printf "Current List: $CURRENT_LIST\nNew List: $NEW_LIST_JSON\n"
update_logstash_outputs
fi

View File

@@ -26,7 +26,7 @@ JSON_STRING=$( jq -n \
curl -K /opt/so/conf/elasticsearch/curl.config -L -X POST "localhost:5601/api/fleet/outputs" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d "$JSON_STRING" curl -K /opt/so/conf/elasticsearch/curl.config -L -X POST "localhost:5601/api/fleet/outputs" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d "$JSON_STRING"
printf "\n\n" printf "\n\n"
printf "\nCreate Logstash Output if node is not an Import or Eval install\n" printf "\nCreate Logstash Output Config if node is not an Import or Eval install\n"
{% if grains.role not in ['so-import', 'so-eval'] %} {% if grains.role not in ['so-import', 'so-eval'] %}
LOGSTASHCRT=$(openssl x509 -in /etc/pki/elasticfleet-logstash.crt) LOGSTASHCRT=$(openssl x509 -in /etc/pki/elasticfleet-logstash.crt)
LOGSTASHKEY=$(openssl rsa -in /etc/pki/elasticfleet-logstash.key) LOGSTASHKEY=$(openssl rsa -in /etc/pki/elasticfleet-logstash.key)

View File

@@ -3,11 +3,11 @@
{% set HIGHLANDER = salt['pillar.get']('global:highlander', False) %} {% set HIGHLANDER = salt['pillar.get']('global:highlander', False) %}
{# ES_LOGSTASH_NODES is the same as LOGSTASH_NODES from logstash/map.jinja but heavynodes are removed #} {# ES_LOGSTASH_NODES is the same as LOGSTASH_NODES from logstash/map.jinja but heavynodes and fleet nodes are removed #}
{% set ES_LOGSTASH_NODES = [] %} {% set ES_LOGSTASH_NODES = [] %}
{% set node_data = salt['pillar.get']('logstash:nodes', {GLOBALS.role.split('-')[1]: {GLOBALS.hostname: {'ip': GLOBALS.node_ip}}}) %} {% set node_data = salt['pillar.get']('logstash:nodes', {GLOBALS.role.split('-')[1]: {GLOBALS.hostname: {'ip': GLOBALS.node_ip}}}) %}
{% for node_type, node_details in node_data.items() | sort %} {% for node_type, node_details in node_data.items() | sort %}
{% if node_type != 'heavynode' %} {% if node_type not in ['heavynode', 'fleet'] %}
{% for hostname in node_data[node_type].keys() %} {% for hostname in node_data[node_type].keys() %}
{% do ES_LOGSTASH_NODES.append({hostname:node_details[hostname].ip}) %} {% do ES_LOGSTASH_NODES.append({hostname:node_details[hostname].ip}) %}
{% endfor %} {% endfor %}

View File

@@ -1,5 +1,5 @@
{ {
"description" : "strelka", "description" : "Strelka logs",
"processors" : [ "processors" : [
{ "set": { "field": "event.dataset", "value": "file" } }, { "set": { "field": "event.dataset", "value": "file" } },
{ "json": { "field": "message", "target_field": "message2", "ignore_failure": true } }, { "json": { "field": "message", "target_field": "message2", "ignore_failure": true } },
@@ -54,8 +54,8 @@
{ "set": { "if": "ctx.exiftool?.FileInodeChangeDate != null", "field": "file.ctime", "value": "{{exiftool.FileInodeChangeDate}}", "ignore_failure": true }}, { "set": { "if": "ctx.exiftool?.FileInodeChangeDate != null", "field": "file.ctime", "value": "{{exiftool.FileInodeChangeDate}}", "ignore_failure": true }},
{ "set": { "if": "ctx.exiftool?.FileDirectory != null", "field": "file.directory", "value": "{{exiftool.FileDirectory}}", "ignore_failure": true }}, { "set": { "if": "ctx.exiftool?.FileDirectory != null", "field": "file.directory", "value": "{{exiftool.FileDirectory}}", "ignore_failure": true }},
{ "set": { "if": "ctx.exiftool?.Subsystem != null", "field": "host.subsystem", "value": "{{exiftool.Subsystem}}", "ignore_failure": true }}, { "set": { "if": "ctx.exiftool?.Subsystem != null", "field": "host.subsystem", "value": "{{exiftool.Subsystem}}", "ignore_failure": true }},
{ "set": { "if": "ctx.scan?.yara?.matches != null", "field": "rule.name", "value": "{{scan.yara.matches.0}}" }}, { "set": { "if": "ctx.scan?.yara?.matches instanceof List", "field": "rule.name", "value": "{{scan.yara.matches.0}}" }},
{ "set": { "if": "ctx.scan?.yara?.matches != null", "field": "dataset", "value": "alert", "override": true }}, { "set": { "if": "ctx.rule?.name != null", "field": "event.dataset", "value": "alert", "override": true }},
{ "rename": { "field": "file.flavors.mime", "target_field": "file.mime_type", "ignore_missing": true }}, { "rename": { "field": "file.flavors.mime", "target_field": "file.mime_type", "ignore_missing": true }},
{ "set": { "if": "ctx.rule?.name != null && ctx.rule?.score == null", "field": "event.severity", "value": 3, "override": true } }, { "set": { "if": "ctx.rule?.name != null && ctx.rule?.score == null", "field": "event.severity", "value": 3, "override": true } },
{ "convert" : { "if": "ctx.rule?.score != null", "field" : "rule.score","type": "integer"}}, { "convert" : { "if": "ctx.rule?.score != null", "field" : "rule.score","type": "integer"}},
@@ -63,6 +63,8 @@
{ "set": { "if": "ctx.rule?.score != null && ctx.rule?.score >= 50 && ctx.rule?.score <=69", "field": "event.severity", "value": 2, "override": true } }, { "set": { "if": "ctx.rule?.score != null && ctx.rule?.score >= 50 && ctx.rule?.score <=69", "field": "event.severity", "value": 2, "override": true } },
{ "set": { "if": "ctx.rule?.score != null && ctx.rule?.score >= 70 && ctx.rule?.score <=89", "field": "event.severity", "value": 3, "override": true } }, { "set": { "if": "ctx.rule?.score != null && ctx.rule?.score >= 70 && ctx.rule?.score <=89", "field": "event.severity", "value": 3, "override": true } },
{ "set": { "if": "ctx.rule?.score != null && ctx.rule?.score >= 90", "field": "event.severity", "value": 4, "override": true } }, { "set": { "if": "ctx.rule?.score != null && ctx.rule?.score >= 90", "field": "event.severity", "value": 4, "override": true } },
{ "set": { "if": "ctx.scan?.entropy?.entropy == 0", "field": "scan.entropy.entropy", "value": "0.0", "override": true } },
{ "set": { "if": "ctx.scan?.pe?.image_version == 0", "field": "scan.pe.image_version", "value": "0.0", "override": true } },
{ "set": { "field": "observer.name", "value": "{{agent.name}}" }}, { "set": { "field": "observer.name", "value": "{{agent.name}}" }},
{ "convert" : { "field" : "scan.exiftool","type": "string", "ignore_missing":true }}, { "convert" : { "field" : "scan.exiftool","type": "string", "ignore_missing":true }},
{ "remove": { "field": ["host", "path", "message", "exiftool", "scan.yara.meta"], "ignore_missing": true } }, { "remove": { "field": ["host", "path", "message", "exiftool", "scan.yara.meta"], "ignore_missing": true } },

View File

@@ -4,18 +4,26 @@
# https://securityonion.net/license; you may not use this file except in compliance with the # https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0. # Elastic License 2.0.
{%- import_yaml 'elasticfleet/defaults.yaml' as ELASTICFLEETDEFAULTS %} {%- import_yaml 'elasticfleet/defaults.yaml' as ELASTICFLEETDEFAULTS %}
{% from 'vars/globals.map.jinja' import GLOBALS %}
{%- set SUPPORTED_PACKAGES = salt['pillar.get']('elasticfleet:packages', default=ELASTICFLEETDEFAULTS.elasticfleet.packages, merge=True) %} {%- set SUPPORTED_PACKAGES = salt['pillar.get']('elasticfleet:packages', default=ELASTICFLEETDEFAULTS.elasticfleet.packages, merge=True) %}
. /usr/sbin/so-common . /usr/sbin/so-common
{% if GLOBALS.role != 'so-heavynode' %}
. /usr/sbin/so-elastic-fleet-common . /usr/sbin/so-elastic-fleet-common
{% endif %}
default_conf_dir=/opt/so/conf default_conf_dir=/opt/so/conf
# Define a default directory to load pipelines from # Define a default directory to load pipelines from
ELASTICSEARCH_TEMPLATES="$default_conf_dir/elasticsearch/templates/" ELASTICSEARCH_TEMPLATES="$default_conf_dir/elasticsearch/templates/"
if [ -f /usr/sbin/so-elastic-fleet-common ]; then {% if GLOBALS.role == 'so-heavynode' %}
file="/opt/so/conf/elasticsearch/templates/index/so-common-template.json"
{% else %}
file="/usr/sbin/so-elastic-fleet-common"
{% endif %}
if [ -f "$file" ]; then
# Wait for ElasticSearch to initialize # Wait for ElasticSearch to initialize
echo -n "Waiting for ElasticSearch..." echo -n "Waiting for ElasticSearch..."
COUNT=0 COUNT=0
@@ -39,6 +47,7 @@ if [ -f /usr/sbin/so-elastic-fleet-common ]; then
exit 1 exit 1
fi fi
{% if GLOBALS.role != 'so-heavynode' %}
SESSIONCOOKIE=$(curl -s -K /opt/so/conf/elasticsearch/curl.config -c - -X GET http://localhost:5601/ | grep sid | awk '{print $7}') SESSIONCOOKIE=$(curl -s -K /opt/so/conf/elasticsearch/curl.config -c - -X GET http://localhost:5601/ | grep sid | awk '{print $7}')
INSTALLED=$(elastic_fleet_package_is_installed {{ SUPPORTED_PACKAGES[0] }} ) INSTALLED=$(elastic_fleet_package_is_installed {{ SUPPORTED_PACKAGES[0] }} )
if [ "$INSTALLED" != "installed" ]; then if [ "$INSTALLED" != "installed" ]; then
@@ -47,7 +56,7 @@ if [ -f /usr/sbin/so-elastic-fleet-common ]; then
echo echo
exit 0 exit 0
fi fi
{% endif %}
set -e set -e
cd ${ELASTICSEARCH_TEMPLATES}/component/ecs cd ${ELASTICSEARCH_TEMPLATES}/component/ecs
@@ -58,7 +67,12 @@ if [ -f /usr/sbin/so-elastic-fleet-common ]; then
cd ${ELASTICSEARCH_TEMPLATES}/component/elastic-agent cd ${ELASTICSEARCH_TEMPLATES}/component/elastic-agent
echo "Loading Elastic Agent component templates..." echo "Loading Elastic Agent component templates..."
for i in *; do TEMPLATE=${i::-5}; echo "$TEMPLATE"; so-elasticsearch-query _component_template/$TEMPLATE -d@$i -XPUT 2>/dev/null; echo; done {% if GLOBALS.role == 'so-heavynode' %}
component_pattern="so-*"
{% else %}
component_pattern="*"
{% endif %}
for i in $component_pattern; do TEMPLATE=${i::-5}; echo "$TEMPLATE"; so-elasticsearch-query _component_template/$TEMPLATE -d@$i -XPUT 2>/dev/null; echo; done
# Load SO-specific component templates # Load SO-specific component templates
cd ${ELASTICSEARCH_TEMPLATES}/component/so cd ${ELASTICSEARCH_TEMPLATES}/component/so
@@ -71,10 +85,25 @@ if [ -f /usr/sbin/so-elastic-fleet-common ]; then
cd ${ELASTICSEARCH_TEMPLATES}/index cd ${ELASTICSEARCH_TEMPLATES}/index
echo "Loading Security Onion index templates..." echo "Loading Security Onion index templates..."
for i in *; do TEMPLATE=${i::-14}; echo "$TEMPLATE"; so-elasticsearch-query _index_template/$TEMPLATE -d@$i -XPUT 2>/dev/null; echo; done shopt -s extglob
{% if GLOBALS.role == 'so-heavynode' %}
pattern="!(*1password*|*aws*|*azure*|*cloudflare*|*elastic_agent*|*fim*|*github*|*google*|*osquery*|*system*|*windows*)"
{% else %}
pattern="*"
{% endif %}
for i in $pattern; do
TEMPLATE=${i::-14};
echo "$TEMPLATE";
so-elasticsearch-query _index_template/$TEMPLATE -d@$i -XPUT 2>/dev/null;
echo;
done
echo echo
else else
{% if GLOBALS.role == 'so-heavynode' %}
echo "Common template does not exist. Exiting..."
{% else %}
echo "Elastic Fleet not configured. Exiting..." echo "Elastic Fleet not configured. Exiting..."
{% endif %}
exit 0 exit 0
fi fi
cd - >/dev/null cd - >/dev/null

View File

@@ -731,7 +731,6 @@ firewall:
- yum - yum
- beats_5044 - beats_5044
- beats_5644 - beats_5644
- beats_5056
- elastic_agent_control - elastic_agent_control
- elastic_agent_data - elastic_agent_data
- elastic_agent_update - elastic_agent_update
@@ -1159,6 +1158,9 @@ firewall:
chain: chain:
DOCKER-USER: DOCKER-USER:
hostgroups: hostgroups:
fleet:
portgroups:
- beats_5056
sensor: sensor:
portgroups: portgroups:
- beats_5044 - beats_5044

File diff suppressed because one or more lines are too long

View File

@@ -22,15 +22,16 @@ logstash:
defined_pipelines: defined_pipelines:
fleet: fleet:
- so/0012_input_elastic_agent.conf - so/0012_input_elastic_agent.conf
- so/9806_output_http_fleet.conf.jinja - so/9806_output_lumberjack_fleet.conf.jinja
manager: manager:
- so/0011_input_endgame.conf - so/0011_input_endgame.conf
- so/0012_input_elastic_agent.conf - so/0012_input_elastic_agent.conf
- so/0013_input_http_fleet.conf - so/0013_input_lumberjack_fleet.conf
- so/9999_output_redis.conf.jinja - so/9999_output_redis.conf.jinja
receiver: receiver:
- so/0011_input_endgame.conf - so/0011_input_endgame.conf
- so/0012_input_elastic_agent.conf - so/0012_input_elastic_agent.conf
- so/0013_input_lumberjack_fleet.conf
- so/9999_output_redis.conf.jinja - so/9999_output_redis.conf.jinja
search: search:
- so/0900_input_redis.conf.jinja - so/0900_input_redis.conf.jinja

View File

@@ -59,8 +59,10 @@ so-logstash:
- /etc/pki/filebeat.p8:/usr/share/logstash/filebeat.key:ro - /etc/pki/filebeat.p8:/usr/share/logstash/filebeat.key:ro
{% endif %} {% endif %}
{% if GLOBALS.role in ['so-manager', 'so-managersearch', 'so-standalone', 'so-import', 'so-eval','so-fleet', 'so-heavynode', 'so-receiver'] %} {% if GLOBALS.role in ['so-manager', 'so-managersearch', 'so-standalone', 'so-import', 'so-eval','so-fleet', 'so-heavynode', 'so-receiver'] %}
- /opt/so/conf/elastic-fleet/certs/elasticfleet-logstash.crt:/usr/share/logstash/elasticfleet-logstash.crt:ro - /etc/pki/elasticfleet-logstash.crt:/usr/share/logstash/elasticfleet-logstash.crt:ro
- /opt/so/conf/elastic-fleet/certs/elasticfleet-logstash.p8:/usr/share/logstash/elasticfleet-logstash.key:ro - /etc/pki/elasticfleet-logstash.key:/usr/share/logstash/elasticfleet-logstash.key:ro
- /etc/pki/elasticfleet-lumberjack.crt:/usr/share/logstash/elasticfleet-lumberjack.crt:ro
- /etc/pki/elasticfleet-lumberjack.key:/usr/share/logstash/elasticfleet-lumberjack.key:ro
{% endif %} {% endif %}
{% if GLOBALS.role in ['so-manager', 'so-managersearch', 'so-standalone', 'so-import'] %} {% if GLOBALS.role in ['so-manager', 'so-managersearch', 'so-standalone', 'so-import'] %}
- /etc/pki/ca.crt:/usr/share/filebeat/ca.crt:ro - /etc/pki/ca.crt:/usr/share/filebeat/ca.crt:ro

View File

@@ -1,21 +0,0 @@
input {
http {
additional_codecs => { "application/json" => "json_lines" }
port => 5056
tags => [ "elastic-agent" ]
ssl => true
ssl_certificate_authorities => ["/usr/share/filebeat/ca.crt"]
ssl_certificate => "/usr/share/logstash/filebeat.crt"
ssl_key => "/usr/share/logstash/filebeat.key"
ssl_verify_mode => "peer"
ecs_compatibility => v8
}
}
filter {
if "elastic-agent" in [tags] {
mutate {
remove_field => ["http","[metadata][input]","url","user_agent"]
}
}
}

View File

@@ -0,0 +1,22 @@
input {
elastic_agent {
port => 5056
tags => [ "elastic-agent", "fleet-lumberjack-input" ]
ssl => true
ssl_certificate => "/usr/share/logstash/elasticfleet-lumberjack.crt"
ssl_key => "/usr/share/logstash/elasticfleet-lumberjack.key"
ecs_compatibility => v8
id => "fleet-lumberjack-in"
codec => "json"
}
}
filter {
if "fleet-lumberjack-input" in [tags] {
mutate {
rename => {"@metadata" => "metadata"}
}
}
}

View File

@@ -1,11 +0,0 @@
output {
http {
url => 'https://{{ GLOBALS.manager }}:5056'
cacert => ["/usr/share/filebeat/ca.crt"]
http_method => post
retry_non_idempotent => true
format => json_batch
http_compression => true
ecs_compatibility => v8
}
}

View File

@@ -0,0 +1,25 @@
{% set FAILOVER_LOGSTASH_NODES = [] %}
{% set node_data = salt['pillar.get']('logstash:nodes', {GLOBALS.role.split('-')[1]: {GLOBALS.hostname: {'ip': GLOBALS.node_ip}}}) %}
{% for node_type, node_details in node_data.items() | sort %}
{% if node_type not in ['heavynode', 'fleet', 'searchnode'] %}
{% for hostname in node_data[node_type].keys() %}
{% do FAILOVER_LOGSTASH_NODES.append(node_details[hostname].ip) %}
{% endfor %}
{% endif %}
{% endfor %}
filter {
mutate {
add_tag => "fleet-lumberjack-{{ GLOBALS.hostname }}"
}
}
output {
lumberjack {
codec => json
hosts => {{ FAILOVER_LOGSTASH_NODES }}
ssl_certificate => "/usr/share/filebeat/ca.crt"
port => 5056
id => "fleet-lumberjack-{{ GLOBALS.hostname }}"
}
}

View File

@@ -1,12 +0,0 @@
#!/bin/bash
# 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.
. /usr/sbin/so-common
docker exec -it so-redis redis-cli llen logstash:unparsed

View File

@@ -1,99 +0,0 @@
#!/bin/bash
# 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.
echo "Starting to check for yara rule updates at $(date)..."
output_dir="/opt/so/saltstack/local/salt/strelka/rules"
mkdir -p $output_dir
repos="/opt/so/conf/strelka/repos.txt"
newcounter=0
excludedcounter=0
excluded_rules=({{ EXCLUDEDRULES | join(' ') }})
{% if ISAIRGAP is sameas true %}
echo "Airgap mode enabled."
clone_dir="/nsm/repo/rules/strelka"
repo_name="signature-base"
[ -d $output_dir/$repo_name ] && rm -rf $output_dir/$repo_name
mkdir -p mkdir -p $output_dir/$repo_name
# Ensure a copy of the license is available for the rules
[ -f $clone_dir/LICENSE ] && cp $clone_dir/$repo_name/LICENSE $output_dir/$repo_name
# Copy over rules
for i in $(find $clone_dir/yara -name "*.yar*"); do
rule_name=$(echo $i | awk -F '/' '{print $NF}')
if [[ ! "${excluded_rules}" =~ ${rule_name} ]]; then
echo "Adding rule: $rule_name..."
cp $i $output_dir/$repo_name
((newcounter++))
else
echo "Excluding rule: $rule_name..."
((excludedcounter++))
fi
done
echo "Done!"
if [ "$newcounter" -gt 0 ] || [ "$excludedcounter" -gt 0 ];then
echo "$newcounter rules added."
echo "$excludedcounter rule(s) excluded."
fi
{% else %}
gh_status=$(curl -s -o /dev/null -w "%{http_code}" https://github.com)
clone_dir="/tmp"
if [ "$gh_status" == "200" ] || [ "$gh_status" == "301" ]; then
while IFS= read -r repo; do
if ! $(echo "$repo" | grep -qE '^#'); then
# Remove old repo if existing bc of previous error condition or unexpected disruption
repo_name=`echo $repo | awk -F '/' '{print $NF}'`
[ -d $output_dir/$repo_name ] && rm -rf $output_dir/$repo_name
# Clone repo and make appropriate directories for rules
git clone $repo $clone_dir/$repo_name
echo "Analyzing rules from $clone_dir/$repo_name..."
mkdir -p $output_dir/$repo_name
# Ensure a copy of the license is available for the rules
[ -f $clone_dir/$repo_name/LICENSE ] && cp $clone_dir/$repo_name/LICENSE $output_dir/$repo_name
# Copy over rules
for i in $(find $clone_dir/$repo_name -name "*.yar*"); do
rule_name=$(echo $i | awk -F '/' '{print $NF}')
if [[ ! "${excluded_rules}" =~ ${rule_name} ]]; then
echo "Adding rule: $rule_name..."
cp $i $output_dir/$repo_name
((newcounter++))
else
echo "Excluding rule: $rule_name..."
((excludedcounter++))
fi
done
rm -rf $clone_dir/$repo_name
fi
done < $repos
echo "Done!"
if [ "$newcounter" -gt 0 ] || [ "$excludedcounter" -gt 0 ];then
echo "$newcounter rule(s) added."
echo "$excludedcounter rule(s) excluded."
fi
else
echo "Server returned $gh_status status code."
echo "No connectivity to Github...exiting..."
exit 1
fi
{% endif %}
echo "Finished rule updates at $(date)..."

View File

@@ -93,26 +93,65 @@ strelkarepos:
- makedirs: True - makedirs: True
{% endif %} {% endif %}
yara_update_script: yara_update_scripts:
file.managed: file.recurse:
- name: /usr/sbin/so-yara-update - name: /usr/sbin/
- source: salt://manager/files/so-yara-update.jinja - source: salt://manager/tools/sbin_jinja/
- user: root - user: socore
- group: root - group: socore
- mode: 755 - file_mode: 755
- template: jinja - template: jinja
- defaults: - defaults:
ISAIRGAP: {{ GLOBALS.airgap }}
EXCLUDEDRULES: {{ STRELKAMERGED.rules.excluded }} EXCLUDEDRULES: {{ STRELKAMERGED.rules.excluded }}
rules_dir:
file.directory:
- name: /nsm/rules/yara
- user: socore
- group: socore
- makedirs: True
{% if GLOBALS.airgap %}
remove_strelka-yara-download:
cron.absent:
- user: socore
- identifier: strelka-yara-download
strelka-yara-update: strelka-yara-update:
cron.present: cron.present:
- user: root - user: socore
- name: '/usr/sbin/so-yara-update >> /nsm/strelka/log/yara-update.log 2>&1' - name: '/usr/sbin/so-yara-update >> /nsm/strelka/log/yara-update.log 2>&1'
- identifier: strelka-yara-update - identifier: strelka-yara-update
- hour: '7' - hour: '7'
- minute: '1' - minute: '1'
update_yara_rules:
cmd.run:
- name: /usr/sbin/so-yara-update
- onchanges:
- file: yara_update_scripts
{% else %}
remove_strelka-yara-update:
cron.absent:
- user: socore
- identifier: strelka-yara-update
strelka-yara-download:
cron.present:
- user: socore
- name: '/usr/sbin/so-yara-download >> /nsm/strelka/log/yara-download.log 2>&1'
- identifier: strelka-yara-download
- hour: '7'
- minute: '1'
download_yara_rules:
cmd.run:
- name: /usr/sbin/so-yara-download
- onchanges:
- file: yara_update_scripts
{% endif %}
{% else %} {% else %}
{{sls}}_state_not_allowed: {{sls}}_state_not_allowed:

View File

@@ -515,7 +515,7 @@ function createFLEET() {
add_logstash_to_minion add_logstash_to_minion
create_fleet_policy create_fleet_policy
update_fleet_host_urls update_fleet_host_urls
update_logstash_outputs #update_logstash_outputs
add_telegraf_to_minion add_telegraf_to_minion
add_nginx_to_minion add_nginx_to_minion
} }

View File

@@ -0,0 +1,50 @@
#!/bin/bash
NOROOT=1
. /usr/sbin/so-common
{%- set proxy = salt['pillar.get']('manager:proxy') %}
# Download the rules from the internet
{%- if proxy %}
export http_proxy={{ proxy }}
export https_proxy={{ proxy }}
export no_proxy= salt['pillar.get']('manager:no_proxy')
{%- endif %}
repos="/opt/so/conf/strelka/repos.txt"
output_dir=/nsm/rules/yara
gh_status=$(curl -s -o /dev/null -w "%{http_code}" https://github.com)
clone_dir="/tmp"
if [ "$gh_status" == "200" ] || [ "$gh_status" == "301" ]; then
while IFS= read -r repo; do
if ! $(echo "$repo" | grep -qE '^#'); then
# Remove old repo if existing bc of previous error condition or unexpected disruption
repo_name=`echo $repo | awk -F '/' '{print $NF}'`
[ -d $output_dir/$repo_name ] && rm -rf $output_dir/$repo_name
# Clone repo and make appropriate directories for rules
git clone $repo $clone_dir/$repo_name
echo "Analyzing rules from $clone_dir/$repo_name..."
mkdir -p $output_dir/$repo_name
# Ensure a copy of the license is available for the rules
[ -f $clone_dir/$repo_name/LICENSE ] && cp $clone_dir/$repo_name/LICENSE $output_dir/$repo_name
# Copy over rules
for i in $(find $clone_dir/$repo_name -name "*.yar*"); do
rule_name=$(echo $i | awk -F '/' '{print $NF}')
cp $i $output_dir/$repo_name
done
rm -rf $clone_dir/$repo_name
fi
done < $repos
echo "Done!"
/usr/sbin/so-yara-update
else
echo "Server returned $gh_status status code."
echo "No connectivity to Github...exiting..."
exit 1
fi

View File

@@ -0,0 +1,41 @@
#!/bin/bash
# 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.
NOROOT=1
. /usr/sbin/so-common
echo "Starting to check for yara rule updates at $(date)..."
newcounter=0
excludedcounter=0
excluded_rules=({{ EXCLUDEDRULES | join(' ') }})
# Pull down the SO Rules
SORULEDIR=/nsm/rules/yara
OUTPUTDIR=/opt/so/saltstack/local/salt/strelka/rules
mkdir -p $OUTPUTDIR
# remove all rules prior to copy so we can clear out old rules
rm -f $OUTPUTDIR/*
for i in $(find $SORULEDIR -name "*.yar" -o -name "*.yara"); do
rule_name=$(echo $i | awk -F '/' '{print $NF}')
if [[ ! "${excluded_rules[*]}" =~ ${rule_name} ]]; then
echo "Adding rule: $rule_name..."
cp $i $OUTPUTDIR/$rule_name
((newcounter++))
else
echo "Excluding rule: $rule_name..."
((excludedcounter++))
fi
done
if [ "$newcounter" -gt 0 ] || [ "$excludedcounter" -gt 0 ];then
echo "$newcounter rules added."
echo "$excludedcounter rule(s) excluded."
fi
echo "Finished rule updates at $(date)..."

View File

@@ -160,7 +160,7 @@ http {
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
} }
location ~ ^/auth/.*?(whoami|logout|settings|webauthn.js) { location ~ ^/auth/.*?(whoami|logout|settings|errors|webauthn.js) {
rewrite /auth/(.*) /$1 break; rewrite /auth/(.*) /$1 break;
proxy_pass http://{{ GLOBALS.manager }}:4433; proxy_pass http://{{ GLOBALS.manager }}:4433;
proxy_read_timeout 90; proxy_read_timeout 90;

View File

@@ -33,11 +33,6 @@ so-soc:
- /opt/so/conf/soc/soc_users_roles:/opt/sensoroni/rbac/users_roles:rw - /opt/so/conf/soc/soc_users_roles:/opt/sensoroni/rbac/users_roles:rw
- /opt/so/conf/soc/queue:/opt/sensoroni/queue:rw - /opt/so/conf/soc/queue:/opt/sensoroni/queue:rw
- /opt/so/saltstack:/opt/so/saltstack:rw - /opt/so/saltstack:/opt/so/saltstack:rw
{% if DOCKER.containers['so-soc'].custom_bind_mounts %}
{% for BIND in DOCKER.containers['so-soc'].custom_bind_mounts %}
- {{ BIND }}
{% endfor %}
{% endif %}
- extra_hosts: {{ DOCKER_EXTRA_HOSTS }} - extra_hosts: {{ DOCKER_EXTRA_HOSTS }}
{% if DOCKER.containers['so-soc'].extra_hosts %} {% if DOCKER.containers['so-soc'].extra_hosts %}
{% for XTRAHOST in DOCKER.containers['so-soc'].extra_hosts %} {% for XTRAHOST in DOCKER.containers['so-soc'].extra_hosts %}

View File

@@ -7,6 +7,7 @@
{% if sls in allowed_states %} {% if sls in allowed_states %}
{% from 'vars/globals.map.jinja' import GLOBALS %} {% from 'vars/globals.map.jinja' import GLOBALS %}
{% set CUSTOMFQDN = salt['pillar.get']('elasticfleet:config:server:custom_fqdn') %}
{% set global_ca_text = [] %} {% set global_ca_text = [] %}
{% set global_ca_server = [] %} {% set global_ca_server = [] %}
@@ -76,12 +77,6 @@ influxdb_crt:
- days_remaining: 0 - days_remaining: 0
- days_valid: 820 - days_valid: 820
- backup: True - backup: True
{% if grains.role not in ['so-heavynode'] %}
- unless:
# https://github.com/saltstack/salt/issues/52167
# Will trigger 5 days (432000 sec) from cert expiration
- 'enddate=$(date -d "$(openssl x509 -in /etc/pki/influxdb.crt -enddate -noout | cut -d= -f2)" +%s) ; now=$(date +%s) ; expire_date=$(( now + 432000)); [ $enddate -gt $expire_date ]'
{% endif %}
- timeout: 30 - timeout: 30
- retry: - retry:
attempts: 5 attempts: 5
@@ -121,12 +116,6 @@ redis_crt:
- days_remaining: 0 - days_remaining: 0
- days_valid: 820 - days_valid: 820
- backup: True - backup: True
{% if grains.role not in ['so-heavynode'] %}
- unless:
# https://github.com/saltstack/salt/issues/52167
# Will trigger 5 days (432000 sec) from cert expiration
- 'enddate=$(date -d "$(openssl x509 -in /etc/pki/redis.crt -enddate -noout | cut -d= -f2)" +%s) ; now=$(date +%s) ; expire_date=$(( now + 432000)); [ $enddate -gt $expire_date ]'
{% endif %}
- timeout: 30 - timeout: 30
- retry: - retry:
attempts: 5 attempts: 5
@@ -141,15 +130,16 @@ rediskeyperms:
{% endif %} {% endif %}
{% if grains['role'] in ['so-manager', 'so-eval', 'so-managersearch', 'so-standalone', 'so-import', 'so-heavynode', 'so-fleet', 'so-receiver'] %} {% if grains['role'] in ['so-manager', 'so-eval', 'so-managersearch', 'so-standalone', 'so-import', 'so-heavynode', 'so-fleet', 'so-receiver'] %}
# Create cert for Elastic Fleet Host
{% if grains['role'] not in [ 'so-heavynode', 'so-receiver'] %}
# Start -- Elastic Fleet Host Cert
etc_elasticfleet_key: etc_elasticfleet_key:
x509.private_key_managed: x509.private_key_managed:
- name: /etc/pki/elasticfleet.key - name: /etc/pki/elasticfleet-server.key
- keysize: 4096 - keysize: 4096
- backup: True - backup: True
- new: True - new: True
{% if salt['file.file_exists']('/etc/pki/elasticfleet.key') -%} {% if salt['file.file_exists']('/etc/pki/elasticfleet-server.key') -%}
- prereq: - prereq:
- x509: etc_elasticfleet_crt - x509: etc_elasticfleet_crt
{%- endif %} {%- endif %}
@@ -157,44 +147,33 @@ etc_elasticfleet_key:
attempts: 5 attempts: 5
interval: 30 interval: 30
# Request a cert and drop it where it needs to go to be distributed
etc_elasticfleet_crt: etc_elasticfleet_crt:
x509.certificate_managed: x509.certificate_managed:
- name: /etc/pki/elasticfleet.crt - name: /etc/pki/elasticfleet-server.crt
- ca_server: {{ ca_server }} - ca_server: {{ ca_server }}
- signing_policy: elasticfleet - signing_policy: elasticfleet
- private_key: /etc/pki/elasticfleet.key - private_key: /etc/pki/elasticfleet-server.key
- CN: {{ GLOBALS.hostname }} - CN: {{ GLOBALS.url_base }}
- subjectAltName: DNS:{{ GLOBALS.hostname }}, IP:{{ GLOBALS.node_ip }} - subjectAltName: DNS:{{ GLOBALS.hostname }},IP:{{ GLOBALS.node_ip }} {% if CUSTOMFQDN != "" %},DNS:{{ CUSTOMFQDN }}{% endif %}
- days_remaining: 0 - days_remaining: 0
- days_valid: 820 - days_valid: 820
- backup: True - backup: True
{% if grains.role not in ['so-heavynode'] %}
- unless:
# https://github.com/saltstack/salt/issues/52167
# Will trigger 5 days (432000 sec) from cert expiration
- 'enddate=$(date -d "$(openssl x509 -in /etc/pki/elasticfleet.crt -enddate -noout | cut -d= -f2)" +%s) ; now=$(date +%s) ; expire_date=$(( now + 432000)); [ $enddate -gt $expire_date ]'
{% endif %}
- timeout: 30 - timeout: 30
- retry: - retry:
attempts: 5 attempts: 5
interval: 30 interval: 30
cmd.run:
- name: "/usr/bin/openssl pkcs8 -in /etc/pki/elasticfleet.key -topk8 -out /etc/pki/elasticfleet.p8 -nocrypt"
- onchanges:
- x509: etc_elasticfleet_key
efperms: efperms:
file.managed: file.managed:
- replace: False - replace: False
- name: /etc/pki/elasticfleet.key - name: /etc/pki/elasticfleet-server.key
- mode: 640 - mode: 640
- group: 939 - group: 939
chownelasticfleetcrt: chownelasticfleetcrt:
file.managed: file.managed:
- replace: False - replace: False
- name: /etc/pki/elasticfleet.crt - name: /etc/pki/elasticfleet-server.crt
- mode: 640 - mode: 640
- user: 947 - user: 947
- group: 939 - group: 939
@@ -202,32 +181,19 @@ chownelasticfleetcrt:
chownelasticfleetkey: chownelasticfleetkey:
file.managed: file.managed:
- replace: False - replace: False
- name: /etc/pki/elasticfleet.key - name: /etc/pki/elasticfleet-server.key
- mode: 640 - mode: 640
- user: 947 - user: 947
- group: 939 - group: 939
# End -- Elastic Fleet Host Cert
{% endif %} # endif is for not including HeavyNodes & Receivers
# Create Symlinks to the keys to distribute it to all the things {% if grains['role'] not in [ 'so-heavynode'] %}
elasticfleetdircerts: # Start -- Elastic Fleet Logstash Input Cert
file.directory: etc_elasticfleet_logstash_key:
- name: /opt/so/saltstack/local/salt/elasticfleet/files/certs
- makedirs: True
efcrtlink:
file.symlink:
- name: /opt/so/saltstack/local/salt/elasticfleet/files/certs/elasticfleet.crt
- target: /etc/pki/elasticfleet.crt
- user: socore
- group: socore
{% if grains.role not in ['so-fleet'] %}
# Create Cert for Elastic Fleet Logstash Input (Same cert used across all Fleet nodes)
etc_elasticfleetlogstash_key:
x509.private_key_managed: x509.private_key_managed:
- name: /etc/pki/elasticfleet-logstash.key - name: /etc/pki/elasticfleet-logstash.key
- bits: 4096 - keysize: 4096
- backup: True - backup: True
- new: True - new: True
{% if salt['file.file_exists']('/etc/pki/elasticfleet-logstash.key') -%} {% if salt['file.file_exists']('/etc/pki/elasticfleet-logstash.key') -%}
@@ -238,24 +204,17 @@ etc_elasticfleetlogstash_key:
attempts: 5 attempts: 5
interval: 30 interval: 30
# Request a cert and drop it where it needs to go to be distributed etc_elasticfleet_logstash_crt:
etc_elasticfleetlogstash_crt:
x509.certificate_managed: x509.certificate_managed:
- name: /etc/pki/elasticfleet-logstash.crt - name: /etc/pki/elasticfleet-logstash.crt
- ca_server: {{ ca_server }} - ca_server: {{ ca_server }}
- signing_policy: elasticfleet - signing_policy: elasticfleet
- private_key: /etc/pki/elasticfleet-logstash.key - private_key: /etc/pki/elasticfleet-logstash.key
- CN: {{ GLOBALS.hostname }} - CN: {{ GLOBALS.url_base }}
- subjectAltName: DNS:{{ GLOBALS.hostname }}, IP:{{ GLOBALS.node_ip }} - subjectAltName: DNS:{{ GLOBALS.hostname }},IP:{{ GLOBALS.node_ip }} {% if CUSTOMFQDN != "" %},DNS:{{ CUSTOMFQDN }}{% endif %}
- days_remaining: 0 - days_remaining: 0
- days_valid: 820 - days_valid: 820
- backup: True - backup: True
{% if grains.role not in ['so-heavynode'] %}
- unless:
# https://github.com/saltstack/salt/issues/52167
# Will trigger 5 days (432000 sec) from cert expiration
- 'enddate=$(date -d "$(openssl x509 -in /etc/pki/elasticfleet-logstash.crt -enddate -noout | cut -d= -f2)" +%s) ; now=$(date +%s) ; expire_date=$(( now + 432000)); [ $enddate -gt $expire_date ]'
{% endif %}
- timeout: 30 - timeout: 30
- retry: - retry:
attempts: 5 attempts: 5
@@ -263,7 +222,7 @@ etc_elasticfleetlogstash_crt:
cmd.run: cmd.run:
- name: "/usr/bin/openssl pkcs8 -in /etc/pki/elasticfleet-logstash.key -topk8 -out /etc/pki/elasticfleet-logstash.p8 -nocrypt" - name: "/usr/bin/openssl pkcs8 -in /etc/pki/elasticfleet-logstash.key -topk8 -out /etc/pki/elasticfleet-logstash.p8 -nocrypt"
- onchanges: - onchanges:
- x509: etc_elasticfleet_key - x509: etc_elasticfleet_logstash_key
eflogstashperms: eflogstashperms:
file.managed: file.managed:
@@ -272,63 +231,150 @@ eflogstashperms:
- mode: 640 - mode: 640
- group: 939 - group: 939
chownilogstashelasticfleetp8: chownelasticfleetlogstashcrt:
file.managed:
- replace: False
- name: /etc/pki/elasticfleet-logstash.p8
- mode: 640
- user: 947
- group: 939
chownilogstashelasticfleetlogstashcrt:
file.managed: file.managed:
- replace: False - replace: False
- name: /etc/pki/elasticfleet-logstash.crt - name: /etc/pki/elasticfleet-logstash.crt
- mode: 640 - mode: 640
- user: 947 - user: 931
- group: 939 - group: 939
chownilogstashelasticfleetlogstashkey: chownelasticfleetlogstashkey:
file.managed: file.managed:
- replace: False - replace: False
- name: /etc/pki/elasticfleet-logstash.key - name: /etc/pki/elasticfleet-logstash.key
- mode: 640 - mode: 640
- user: 931
- group: 939
# End -- Elastic Fleet Logstash Input Cert
{% endif %} # endif is for not including HeavyNodes
# Start -- Elastic Fleet Node - Logstash Lumberjack Input / Output
# Cert needed on: Managers, Receivers
etc_elasticfleetlumberjack_key:
x509.private_key_managed:
- name: /etc/pki/elasticfleet-lumberjack.key
- bits: 4096
- backup: True
- new: True
{% if salt['file.file_exists']('/etc/pki/elasticfleet-lumberjack.key') -%}
- prereq:
- x509: etc_elasticfleet_crt
{%- endif %}
- retry:
attempts: 5
interval: 30
etc_elasticfleetlumberjack_crt:
x509.certificate_managed:
- name: /etc/pki/elasticfleet-lumberjack.crt
- ca_server: {{ ca_server }}
- signing_policy: elasticfleet
- private_key: /etc/pki/elasticfleet-lumberjack.key
- CN: {{ GLOBALS.node_ip }}
- subjectAltName: DNS:{{ GLOBALS.hostname }}
- days_remaining: 0
- days_valid: 820
- backup: True
- timeout: 30
- retry:
attempts: 5
interval: 30
cmd.run:
- name: "/usr/bin/openssl pkcs8 -in /etc/pki/elasticfleet-lumberjack.key -topk8 -out /etc/pki/elasticfleet-lumberjack.p8 -nocrypt"
- onchanges:
- x509: etc_elasticfleet_key
eflogstashlumberjackperms:
file.managed:
- replace: False
- name: /etc/pki/elasticfleet-lumberjack.key
- mode: 640
- group: 939
chownilogstashelasticfleetlumberjackp8:
file.managed:
- replace: False
- name: /etc/pki/elasticfleet-lumberjack.p8
- mode: 640
- user: 931
- group: 939
chownilogstashelasticfleetlogstashlumberjackcrt:
file.managed:
- replace: False
- name: /etc/pki/elasticfleet-lumberjack.crt
- mode: 640
- user: 931
- group: 939
chownilogstashelasticfleetlogstashlumberjackkey:
file.managed:
- replace: False
- name: /etc/pki/elasticfleet-lumberjack.key
- mode: 640
- user: 931
- group: 939
# End -- Elastic Fleet Node - Logstash Lumberjack Input / Output
# Start -- Elastic Fleet Client Cert for Agent (Mutual Auth with Logstash Output)
etc_elasticfleet_agent_key:
x509.private_key_managed:
- name: /etc/pki/elasticfleet-agent.key
- keysize: 4096
- backup: True
- new: True
{% if salt['file.file_exists']('/etc/pki/elasticfleet-agent.key') -%}
- prereq:
- x509: etc_elasticfleet_crt
{%- endif %}
- retry:
attempts: 5
interval: 30
etc_elasticfleet_agent_crt:
x509.certificate_managed:
- name: /etc/pki/elasticfleet-agent.crt
- ca_server: {{ ca_server }}
- signing_policy: elasticfleet
- private_key: /etc/pki/elasticfleet-agent.key
- CN: {{ GLOBALS.hostname }}
- days_remaining: 0
- days_valid: 820
- backup: True
- timeout: 30
- retry:
attempts: 5
interval: 30
cmd.run:
- name: "/usr/bin/openssl pkcs8 -in /etc/pki/elasticfleet-agent.key -topk8 -out /etc/pki/elasticfleet-agent.p8 -nocrypt"
- onchanges:
- x509: etc_elasticfleet_key
efagentperms:
file.managed:
- replace: False
- name: /etc/pki/elasticfleet-agent.key
- mode: 640
- group: 939
chownelasticfleetagentcrt:
file.managed:
- replace: False
- name: /etc/pki/elasticfleet-agent.crt
- mode: 640
- user: 947 - user: 947
- group: 939 - group: 939
eflogstashkeylink: chownelasticfleetagentkey:
file.symlink:
- name: /opt/so/saltstack/local/salt/elasticfleet/files/certs/elasticfleet-logstash.p8
- target: /etc/pki/elasticfleet.p8
- user: socore
- group: socore
eflogstashcrtlink:
file.symlink:
- name: /opt/so/saltstack/local/salt/elasticfleet/files/certs/elasticfleet-logstash.crt
- target: /etc/pki/elasticfleet.crt
- user: socore
- group: socore
{% endif %}
/opt/so/conf/elastic-fleet/certs/elasticfleet-logstash.p8:
file.managed: file.managed:
- replace: True - replace: False
- source: salt://elasticfleet/files/certs/elasticfleet-logstash.p8 - name: /etc/pki/elasticfleet-agent.key
- makedirs: True
- mode: 640 - mode: 640
- user: 931 - user: 947
- group: 939
/opt/so/conf/elastic-fleet/certs/elasticfleet-logstash.crt:
file.managed:
- replace: True
- source: salt://elasticfleet/files/certs/elasticfleet-logstash.crt
- makedirs: True
- mode: 640
- user: 931
- group: 939 - group: 939
# End -- Elastic Fleet Client Cert for Agent (Mutual Auth with Logstash Output)
{% endif %} {% endif %}
@@ -359,12 +405,6 @@ etc_filebeat_crt:
- days_remaining: 0 - days_remaining: 0
- days_valid: 820 - days_valid: 820
- backup: True - backup: True
{% if grains.role not in ['so-heavynode'] %}
- unless:
# https://github.com/saltstack/salt/issues/52167
# Will trigger 5 days (432000 sec) from cert expiration
- 'enddate=$(date -d "$(openssl x509 -in /etc/pki/filebeat.crt -enddate -noout | cut -d= -f2)" +%s) ; now=$(date +%s) ; expire_date=$(( now + 432000)); [ $enddate -gt $expire_date ]'
{% endif %}
- timeout: 30 - timeout: 30
- retry: - retry:
attempts: 5 attempts: 5
@@ -436,10 +476,6 @@ registry_crt:
- days_remaining: 0 - days_remaining: 0
- days_valid: 820 - days_valid: 820
- backup: True - backup: True
- unless:
# https://github.com/saltstack/salt/issues/52167
# Will trigger 5 days (432000 sec) from cert expiration
- 'enddate=$(date -d "$(openssl x509 -in /etc/pki/registry.crt -enddate -noout | cut -d= -f2)" +%s) ; now=$(date +%s) ; expire_date=$(( now + 432000)); [ $enddate -gt $expire_date ]'
- timeout: 30 - timeout: 30
- retry: - retry:
attempts: 5 attempts: 5
@@ -478,12 +514,6 @@ regkeyperms:
- days_remaining: 0 - days_remaining: 0
- days_valid: 820 - days_valid: 820
- backup: True - backup: True
{% if grains.role not in ['so-heavynode'] %}
- unless:
# https://github.com/saltstack/salt/issues/52167
# Will trigger 5 days (432000 sec) from cert expiration
- 'enddate=$(date -d "$(openssl x509 -in /etc/pki/elasticsearch.crt -enddate -noout | cut -d= -f2)" +%s) ; now=$(date +%s) ; expire_date=$(( now + 432000)); [ $enddate -gt $expire_date ]'
{% endif %}
- timeout: 30 - timeout: 30
- retry: - retry:
attempts: 5 attempts: 5
@@ -545,12 +575,6 @@ conf_filebeat_crt:
- days_remaining: 0 - days_remaining: 0
- days_valid: 820 - days_valid: 820
- backup: True - backup: True
{% if grains.role not in ['so-heavynode'] %}
- unless:
# https://github.com/saltstack/salt/issues/52167
# Will trigger 5 days (432000 sec) from cert expiration
- 'enddate=$(date -d "$(openssl x509 -in /opt/so/conf/filebeat/etc/pki/filebeat.crt -enddate -noout | cut -d= -f2)" +%s) ; now=$(date +%s) ; expire_date=$(( now + 432000)); [ $enddate -gt $expire_date ]'
{% endif %}
- timeout: 30 - timeout: 30
- retry: - retry:
attempts: 5 attempts: 5
@@ -605,10 +629,6 @@ chownfilebeatp8:
- days_remaining: 0 - days_remaining: 0
- days_valid: 820 - days_valid: 820
- backup: True - backup: True
- unless:
# https://github.com/saltstack/salt/issues/52167
# Will trigger 5 days (432000 sec) from cert expiration
- 'enddate=$(date -d "$(openssl x509 -in /etc/pki/elasticsearch.crt -enddate -noout | cut -d= -f2)" +%s) ; now=$(date +%s) ; expire_date=$(( now + 432000)); [ $enddate -gt $expire_date ]'
- timeout: 30 - timeout: 30
- retry: - retry:
attempts: 5 attempts: 5

View File

@@ -42,6 +42,8 @@ strelka_backend:
{% endfor %} {% endfor %}
{% endif %} {% endif %}
- restart_policy: on-failure - restart_policy: on-failure
- watch:
- file: strelkarules
delete_so-strelka-backend_so-status.disabled: delete_so-strelka-backend_so-status.disabled:
file.uncomment: file.uncomment:

View File

@@ -43,15 +43,6 @@ strelka_sbin:
- group: 939 - group: 939
- file_mode: 755 - file_mode: 755
strelka_sbin_jinja:
file.recurse:
- name: /usr/sbin
- source: salt://strelka/tools/sbin_jinja
- user: 939
- group: 939
- file_mode: 755
- template: jinja
{% else %} {% else %}
{{sls}}_state_not_allowed: {{sls}}_state_not_allowed:

View File

@@ -542,7 +542,8 @@ strelka:
enabled: False enabled: False
rules: rules:
enabled: True enabled: True
repos: [] repos:
- https://github.com/Security-Onion-Solutions/securityonion-yara.git
excluded: excluded:
- apt_flame2_orchestrator.yar - apt_flame2_orchestrator.yar
- apt_tetris.yar - apt_tetris.yar

View File

@@ -579,7 +579,7 @@ strelka:
helpLink: strelka.html helpLink: strelka.html
advanced: False advanced: False
repos: repos:
description: List of repos for so-yara-update to use to download rules. description: List of repos for so-yara-download to use to download rules.
readonly: False readonly: False
global: False global: False
helpLink: strelka.html helpLink: strelka.html

View File

@@ -1,21 +0,0 @@
#!/bin/bash
NOROOT=1
. /usr/sbin/so-common
{%- set proxy = salt['pillar.get']('manager:proxy') %}
# Download the rules from the internet
{%- if proxy %}
export http_proxy={{ proxy }}
export https_proxy={{ proxy }}
export no_proxy= salt['pillar.get']('manager:no_proxy')
{%- endif %}
mkdir -p /tmp/yara
cd /tmp/yara
git clone https://github.com/Security-Onion-Solutions/securityonion-yara.git
mkdir -p /nsm/rules/yara
rsync -shav --progress /tmp/yara/securityonion-yara/yara /nsm/rules/
cd /tmp
rm -rf /tmp/yara

File diff suppressed because it is too large Load Diff

View File

@@ -1534,18 +1534,6 @@ create_sensoroni_pillar() {
} }
create_strelka_pillar() {
title "Create the Strelka pillar file"
touch $adv_strelka_pillar_file
printf '%s\n'\
"strelka:"\
" enabled: $STRELKA"\
" rules: 1" > "$strelka_pillar_file"
printf '%s\n'\
" repos:"\
" - 'https://$HOSTNAME:7788/yara'" >> "$strelka_pillar_file"
}
backup_pillar() { backup_pillar() {
title "Create the backup pillar file" title "Create the backup pillar file"
touch $adv_backup_pillar_file touch $adv_backup_pillar_file
@@ -2134,6 +2122,12 @@ saltify() {
logCmd "salt-pip install docker --no-index --only-binary=:all: --find-links files/salt_module_deps/docker/" logCmd "salt-pip install docker --no-index --only-binary=:all: --find-links files/salt_module_deps/docker/"
logCmd "salt-pip install pymysql --no-index --only-binary=:all: --find-links files/salt_module_deps/pymysql/" logCmd "salt-pip install pymysql --no-index --only-binary=:all: --find-links files/salt_module_deps/pymysql/"
# this can be removed when https://github.com/saltstack/salt/issues/64195 is resolved
if [ $SALTVERSION == "3006.1" ]; then
info "Salt version 3006.1 found. Patching /opt/saltstack/salt/lib/python3.10/site-packages/salt/states/x509_v2.py"
\cp -v ./files/patch/states/x509_v2.py /opt/saltstack/salt/lib/python3.10/site-packages/salt/states/x509_v2.py
fi
} }

View File

@@ -660,13 +660,14 @@ if ! [[ -f $install_opt_file ]]; then
logCmd "salt-call state.apply -l info manager" logCmd "salt-call state.apply -l info manager"
logCmd "salt-call state.apply influxdb -l info" logCmd "salt-call state.apply influxdb -l info"
logCmd "salt-call state.highstate -l info" logCmd "salt-call state.highstate -l info"
logCmd "salt-call schedule.disable -linfo --local"
if [[ ! $is_airgap ]]; then if [[ ! $is_airgap ]]; then
title "Downloading IDS Rules" title "Downloading IDS Rules"
logCmd "so-rule-update" logCmd "so-rule-update"
title "Restarting Suricata to pick up the new rules" title "Restarting Suricata to pick up the new rules"
logCmd "so-suricata-restart" logCmd "so-suricata-restart"
title "Downloading YARA rules" title "Downloading YARA rules"
logCmd "runuser -l socore 'so-yara-update'" logCmd "su socore -c '/usr/sbin/so-yara-download'"
title "Restarting Strelka to use new rules" title "Restarting Strelka to use new rules"
logCmd "so-strelka-restart" logCmd "so-strelka-restart"
fi fi
@@ -684,6 +685,7 @@ if ! [[ -f $install_opt_file ]]; then
fi fi
checkin_at_boot checkin_at_boot
set_initial_firewall_access set_initial_firewall_access
logCmd "salt-call schedule.enable -linfo --local"
systemctl restart salt-master systemctl restart salt-master
systemctl restart salt-minion systemctl restart salt-minion
verify_setup verify_setup

BIN
sigs

Binary file not shown.