mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2026-07-01 22:58:37 +02:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a6cc58306 | |||
| 9217670bab | |||
| 576c7bfedd | |||
| b3b7ecdded | |||
| 0af020b6c3 | |||
| 339a5af4a3 | |||
| 7952c274c4 | |||
| 67a9abadf2 | |||
| 94f31e1356 | |||
| 435e2b4182 | |||
| 13ebde61bd | |||
| b0b022c3ad | |||
| 27c1c35e62 | |||
| f45631af3a | |||
| 8e2753aeb8 | |||
| 698a746d6d |
@@ -291,6 +291,20 @@ download_and_verify() {
|
||||
fi
|
||||
}
|
||||
|
||||
# check if container with name is running and optionally stop it
|
||||
docker_check_running() {
|
||||
# show running containers, only names
|
||||
if docker ps --format '{{.Names}}' | grep -q "^so-${1}$"; then
|
||||
if [[ "$2" == "--stop" ]]; then
|
||||
docker stop "so-${1}"
|
||||
fi
|
||||
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
elastic_license() {
|
||||
|
||||
read -r -d '' message <<- EOM
|
||||
|
||||
Executable
+57
@@ -0,0 +1,57 @@
|
||||
#!/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.
|
||||
#
|
||||
# so-kernel-upgrade — switch the boot default to the installed UEK8 (6.x) kernel.
|
||||
#
|
||||
# Security Onion is moving off the EL9 stock kernel / UEK7 (5.x) onto UEK8 (6.x).
|
||||
# Installing the kernel-uek-core package adds a UEK8 boot entry but does NOT make it the
|
||||
# default: kernel-install/grubby only auto-promote a new kernel within the running
|
||||
# kernel's flavor lineage, and we're crossing from a 5.x kernel to the new 6.x UEK flavor.
|
||||
# So even with UPDATEDEFAULT=yes and DEFAULTKERNEL=kernel-uek-core the box keeps booting
|
||||
# the old kernel. This tool finds the newest installed 6.x UEK kernel and makes it the
|
||||
# GRUB default via grubby so the next boot comes up on UEK8.
|
||||
#
|
||||
# Idempotent: if the UEK8 kernel is already the default it does nothing. It only sets the
|
||||
# boot default; it does NOT reboot — the admin reboots the node on their own schedule.
|
||||
|
||||
log() { echo "[so-kernel-upgrade] $*"; }
|
||||
|
||||
[ "$(id -u)" -eq 0 ] || { log "must run as root"; exit 1; }
|
||||
command -v grubby >/dev/null 2>&1 || { log "grubby not found"; exit 1; }
|
||||
|
||||
# Newest installed UEK8 (6.x) kernel known to the bootloader. UEK8 vmlinuz paths look like
|
||||
# /boot/vmlinuz-6.12.0-203.76.7.5.el9uek.x86_64; the 5.x UEK7 and 5.14 RHCK won't match.
|
||||
target="$(grubby --info=ALL 2>/dev/null \
|
||||
| sed -n 's/^kernel="\(.*\)"$/\1/p' \
|
||||
| grep -E '/vmlinuz-6\.[0-9]+.*uek' \
|
||||
| sort -V | tail -1)"
|
||||
|
||||
if [ -z "$target" ]; then
|
||||
log "no installed 6.x UEK (UEK8) kernel found — confirm the kernel repo is assigned and"
|
||||
log "'dnf update' has installed kernel-uek-core. Nothing to do."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
current="$(grubby --default-kernel 2>/dev/null)"
|
||||
if [ "$current" = "$target" ]; then
|
||||
log "UEK8 kernel is already the boot default: $target"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log "current default kernel: ${current:-unknown}"
|
||||
log "switching boot default to UEK8 kernel: $target"
|
||||
grubby --set-default="$target" || { log "ERROR: grubby --set-default failed for $target"; exit 1; }
|
||||
|
||||
# Verify the change actually took before claiming success.
|
||||
now="$(grubby --default-kernel 2>/dev/null)"
|
||||
if [ "$now" != "$target" ]; then
|
||||
log "ERROR: default kernel is still '${now:-unknown}' after set-default"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "boot default is now $target"
|
||||
log "REBOOT REQUIRED to start using the UEK8 kernel (currently running $(uname -r))."
|
||||
@@ -5,27 +5,41 @@
|
||||
# https://securityonion.net/license; you may not use this file except in compliance with the
|
||||
# Elastic License 2.0.
|
||||
|
||||
|
||||
|
||||
# Usage: so-restart kibana | playbook
|
||||
|
||||
. /usr/sbin/so-common
|
||||
|
||||
if [ $# -ge 1 ]; then
|
||||
usage() {
|
||||
echo "Usage: $0 <component> [args]"
|
||||
echo ""
|
||||
echo "Supported args:"
|
||||
echo " --force | -f Force stop all Salt jobs before starting component."
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 kibana Restart Kibana"
|
||||
echo " $0 kibana --force Force stop all Salt jobs before restarting Kibana"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo $banner
|
||||
printf "Restarting $1...\n\nThis could take a while if another Salt job is running. \nRun this command with --force to stop all Salt jobs before proceeding.\n"
|
||||
echo $banner
|
||||
|
||||
if [ "$2" = "--force" ]; then
|
||||
printf "\nForce-stopping all Salt jobs before proceeding\n\n"
|
||||
salt-call saltutil.kill_all_jobs
|
||||
fi
|
||||
|
||||
case $1 in
|
||||
"elastic-fleet") docker stop so-elastic-fleet && docker rm so-elastic-fleet && salt-call state.apply elasticfleet queue=True;;
|
||||
*) docker stop so-$1 ; docker rm so-$1 ; salt-call state.apply $1 queue=True;;
|
||||
esac
|
||||
else
|
||||
echo -e "\nPlease provide an argument by running like so-restart $component, or by using the component-specific script.\nEx. so-restart logstash, or so-logstash-restart\n"
|
||||
if [[ $# -lt 1 ]]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
#shellcheck disable=SC2154
|
||||
echo "$banner"
|
||||
printf "Restarting %s...\n\nThis could take a while if another Salt job is running. \nRun this command with --force to stop all Salt jobs before proceeding.\n" "$1"
|
||||
echo "$banner"
|
||||
if [[ "$2" = "--force" ]] || [[ "$2" = "-f" ]]; then
|
||||
printf "\nForce-stopping all Salt jobs before proceeding\n\n"
|
||||
salt-call saltutil.kill_all_jobs
|
||||
fi
|
||||
case $1 in
|
||||
"elastic-fleet"|"elasticfleet")
|
||||
docker_check_running "elastic-fleet" "--stop"
|
||||
docker rm "so-elastic-fleet" 2> /dev/null
|
||||
salt-call state.apply elasticfleet queue=True
|
||||
;;
|
||||
*)
|
||||
docker_check_running "$1" "--stop"
|
||||
docker rm "so-${1}" 2> /dev/null
|
||||
salt-call state.apply "$1" queue=True
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -5,27 +5,54 @@
|
||||
# https://securityonion.net/license; you may not use this file except in compliance with the
|
||||
# Elastic License 2.0.
|
||||
|
||||
|
||||
|
||||
# Usage: so-start all | kibana | playbook
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. /usr/sbin/so-common
|
||||
|
||||
if [ $# -ge 1 ]; then
|
||||
echo $banner
|
||||
printf "Starting $1...\n\nThis could take a while if another Salt job is running. \nRun this command with --force to stop all Salt jobs before proceeding.\n"
|
||||
echo $banner
|
||||
usage() {
|
||||
echo "Usage: $0 <component> [args]"
|
||||
echo ""
|
||||
echo "Supported args:"
|
||||
echo " --force | -f Force stop all Salt jobs before starting component."
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 kibana Start Kibana"
|
||||
echo " $0 kibana --force Force stop all Salt jobs before starting Kibana"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ "$2" = "--force" ]; then
|
||||
printf "\nForce-stopping all Salt jobs before proceeding\n\n"
|
||||
salt-call saltutil.kill_all_jobs
|
||||
fi
|
||||
|
||||
case $1 in
|
||||
"all") salt-call state.highstate queue=True;;
|
||||
"elastic-fleet") if docker ps | grep -q so-$1; then printf "\n$1 is already running!\n\n"; else docker rm so-$1 >/dev/null 2>&1 ; salt-call state.apply elasticfleet queue=True; fi ;;
|
||||
*) if docker ps | grep -E -q '^so-$1$'; then printf "\n$1 is already running\n\n"; else docker rm so-$1 >/dev/null 2>&1 ; salt-call state.apply $1 queue=True; fi ;;
|
||||
esac
|
||||
else
|
||||
echo -e "\nPlease provide an argument by running like so-start $component, or by using the component-specific script.\nEx. so-start logstash, or so-logstash-start\n"
|
||||
if [[ $# -lt 1 ]]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
#shellcheck disable=SC2154
|
||||
echo "$banner"
|
||||
printf "Starting %s...\n\nThis could take a while if another Salt job is running. \nRun this command with --force to stop all Salt jobs before proceeding.\n" "$1"
|
||||
echo "$banner"
|
||||
if [[ "$2" = "--force" ]] || [[ "$2" == "-f" ]]; then
|
||||
printf "\nForce-stopping all Salt jobs before proceeding\n\n"
|
||||
salt-call saltutil.kill_all_jobs
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
"all")
|
||||
salt-call state.highstate queue=True
|
||||
;;
|
||||
"elastic-fleet"|"elasticfleet")
|
||||
if docker_check_running "elastic-fleet"; then
|
||||
printf "\nso-%s is already running!\n\n" "elastic-fleet"
|
||||
/usr/sbin/so-status
|
||||
else
|
||||
docker rm "so-elastic-fleet" 2> /dev/null
|
||||
salt-call state.apply elasticfleet queue=True
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if docker_check_running "$1"; then
|
||||
printf "\nso-%s is already running\n\n" "$1"
|
||||
/usr/sbin/so-status
|
||||
else
|
||||
docker rm "so-${1}" 2> /dev/null
|
||||
salt-call state.apply "$1" queue=True
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -5,21 +5,33 @@
|
||||
# https://securityonion.net/license; you may not use this file except in compliance with the
|
||||
# Elastic License 2.0.
|
||||
|
||||
|
||||
|
||||
# Usage: so-stop kibana | playbook | thehive
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. /usr/sbin/so-common
|
||||
|
||||
if [ $# -ge 1 ]; then
|
||||
echo $banner
|
||||
printf "Stopping $1...\n"
|
||||
echo $banner
|
||||
usage() {
|
||||
echo "Usage: $0 <component>"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 kibana Stop Kibana"
|
||||
exit 1
|
||||
}
|
||||
|
||||
case $1 in
|
||||
*) docker stop so-$1 ; docker rm so-$1 ;;
|
||||
esac
|
||||
else
|
||||
echo -e "\nPlease provide an argument by running like so-stop $component, or by using the component-specific script.\nEx. so-stop logstash, or so-logstash-stop\n"
|
||||
if [[ $# -lt 1 ]]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
|
||||
#shellcheck disable=SC2154
|
||||
echo "$banner"
|
||||
printf "Stopping %s...\n" "$1"
|
||||
echo "$banner"
|
||||
case $1 in
|
||||
"elasticfleet"|"elastic-fleet")
|
||||
docker_check_running "elastic-fleet" "--stop"
|
||||
docker rm "so-elastic-fleet" 2> /dev/null
|
||||
;;
|
||||
*)
|
||||
docker_check_running "$1" "--stop"
|
||||
docker rm "so-${1}" 2> /dev/null
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
https://repo.securityonion.net/file/so-repo/prod/3/oracle/9-uek8
|
||||
https://repo-alt.securityonion.net/prod/3/oracle/9-uek8
|
||||
@@ -10,4 +10,9 @@ keepcache=0
|
||||
name=Security Onion Repo repo
|
||||
mirrorlist=file:///opt/so/conf/reposync/mirror.txt
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
gpgcheck=1
|
||||
[securityonionkernel]
|
||||
name=Security Onion Repo repo
|
||||
mirrorlist=file:///opt/so/conf/reposync/mirror-kernel.txt
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
|
||||
@@ -86,6 +86,28 @@ repo_dir:
|
||||
- group
|
||||
- show_changes: False
|
||||
|
||||
kernelrepo_dir:
|
||||
file.directory:
|
||||
- name: /nsm/kernelrepo
|
||||
- user: socore
|
||||
- group: socore
|
||||
- recurse:
|
||||
- user
|
||||
- group
|
||||
- show_changes: False
|
||||
|
||||
# Ensure /nsm/kernelrepo is always a valid (if empty) repo before it is ever assigned to
|
||||
# a client. Without repodata/repomd.xml an enabled file:///nsm/kernelrepo repo makes every
|
||||
# dnf operation fail; so-repo-sync only populates it after the highstate, so seed an empty
|
||||
# repo here. Only runs when repodata is missing, so it won't clobber a synced repo.
|
||||
kernelrepo_init_empty:
|
||||
cmd.run:
|
||||
- name: createrepo /nsm/kernelrepo
|
||||
- unless: 'test -e /nsm/kernelrepo/repodata/repomd.xml'
|
||||
- require:
|
||||
- file: kernelrepo_dir
|
||||
- pkg: install_createrepo
|
||||
|
||||
manager_sbin:
|
||||
file.recurse:
|
||||
- name: /usr/sbin
|
||||
@@ -122,6 +144,13 @@ so-repo-mirrorlist:
|
||||
- user: socore
|
||||
- group: socore
|
||||
|
||||
so-repo-kernel-mirrorlist:
|
||||
file.managed:
|
||||
- name: /opt/so/conf/reposync/mirror-kernel.txt
|
||||
- source: salt://manager/files/mirror-kernel.txt
|
||||
- user: socore
|
||||
- group: socore
|
||||
|
||||
so-repo-sync:
|
||||
{% if MANAGERMERGED.reposync.enabled %}
|
||||
cron.present:
|
||||
|
||||
@@ -10,5 +10,16 @@ NOROOT=1
|
||||
set -e
|
||||
|
||||
curl --retry 5 --retry-delay 60 -A "reposync/$(sync_options)" https://sigs.securityonion.net/checkup --output /tmp/checkup
|
||||
|
||||
dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionsync --download-metadata -p /nsm/repo/
|
||||
createrepo /nsm/repo
|
||||
|
||||
# The kernel repo section is deployed to repodownload.conf by the manager highstate, which
|
||||
# runs AFTER this script during soup. On the first upgrade to a kernel-aware version the
|
||||
# on-disk config still predates the section, so guard on its presence to avoid dnf's
|
||||
# "Unknown repo: 'securityonionkernel'" aborting the sync (set -e). The next sync after the
|
||||
# highstate deploys the section will pick it up.
|
||||
if grep -q '^\[securityonionkernel\]' /opt/so/conf/reposync/repodownload.conf; then
|
||||
dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionkernel --download-metadata -p /nsm/kernelrepo/
|
||||
createrepo /nsm/kernelrepo
|
||||
fi
|
||||
|
||||
@@ -59,6 +59,7 @@ so-nginx:
|
||||
- /opt/so/conf/navigator/layers/:/opt/socore/html/navigator/assets/so:ro
|
||||
- /opt/so/conf/navigator/config.json:/opt/socore/html/navigator/assets/config.json:ro
|
||||
- /nsm/repo:/opt/socore/html/repo:ro
|
||||
- /nsm/kernelrepo:/opt/socore/html/kernelrepo:ro
|
||||
- /nsm/rules:/nsm/rules:ro
|
||||
{% if NGINXMERGED.external_suricata %}
|
||||
- /opt/so/rules/nids/suri:/surirules:ro
|
||||
|
||||
@@ -323,6 +323,16 @@ http {
|
||||
autoindex_localtime on;
|
||||
}
|
||||
|
||||
location /kernelrepo/ {
|
||||
allow all;
|
||||
sendfile on;
|
||||
sendfile_max_chunk 1m;
|
||||
autoindex on;
|
||||
autoindex_exact_size off;
|
||||
autoindex_format html;
|
||||
autoindex_localtime on;
|
||||
}
|
||||
|
||||
location /influxdb/ {
|
||||
auth_request /auth/sessions/whoami;
|
||||
rewrite /influxdb/api/(.*) /api/$1 break;
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
{% from 'repo/client/map.jinja' import REPOPATH with context %}
|
||||
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
||||
|
||||
{% import_yaml 'salt/minion.defaults.yaml' as saltversion %}
|
||||
{% set saltversion = saltversion.salt.minion.version %}
|
||||
{% set INSTALLEDSALTVERSION = grains.saltversion %}
|
||||
|
||||
{% set role = grains.id.split('_') | last %}
|
||||
{% set MANAGER = salt['grains.get']('master') %}
|
||||
{% if grains['os'] == 'OEL' %}
|
||||
@@ -57,6 +61,32 @@ so_repo:
|
||||
- enabled: 1
|
||||
- gpgcheck: 1
|
||||
|
||||
# Only assign the kernel repo once this node's running salt matches the version this
|
||||
# SO release ships. During a soup the grid is mid-salt-upgrade; gating here keeps the
|
||||
# UEK8 kernel repo (and the kernel update it enables) from activating until the node is
|
||||
# fully on the target salt, the same way other states defer across the upgrade window.
|
||||
{% if saltversion | string == INSTALLEDSALTVERSION | string %}
|
||||
so_kernel_repo:
|
||||
pkgrepo.managed:
|
||||
- name: securityonionkernel
|
||||
- humanname: Security Onion Kernel Repo
|
||||
{% if GLOBALS.is_manager %}
|
||||
- baseurl: file:///nsm/kernelrepo/
|
||||
{% else %}
|
||||
- baseurl: https://{{ GLOBALS.repo_host }}/kernelrepo
|
||||
{% endif %}
|
||||
- enabled: 1
|
||||
- gpgcheck: 1
|
||||
# Supplementary kernel repo: tolerate it being empty/unreachable (e.g. before the
|
||||
# manager has populated /nsm/kernelrepo) so a missing repomd.xml can't make every
|
||||
# dnf/pkg operation on the grid fail.
|
||||
- skip_if_unavailable: 1
|
||||
# Only assign the kernel repo once physical NIC names are pinned by MAC, so the
|
||||
# UEK8 kernel update can't renumber interfaces SO binds by name (see pin_nic_names
|
||||
# in salt/common/init.sls, which drops this marker via /usr/sbin/so-nic-pin).
|
||||
- onlyif: 'test -e /opt/so/state/nic_names_pinned'
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
# TODO: Add a pillar entry for custom repos
|
||||
|
||||
@@ -134,6 +134,30 @@ socsigmasopipeline:
|
||||
- group: 939
|
||||
- mode: 600
|
||||
|
||||
socsigmaplaybookpipeline:
|
||||
file.managed:
|
||||
- name: /opt/so/conf/soc/sigma_playbook_pipeline.yaml
|
||||
- source: salt://soc/files/soc/sigma_playbook_pipeline.yaml
|
||||
- user: 939
|
||||
- group: 939
|
||||
- mode: 600
|
||||
|
||||
socplaybookplaceholdermap:
|
||||
file.managed:
|
||||
- name: /opt/so/conf/soc/playbook_placeholder_map.yaml
|
||||
- source: salt://soc/files/soc/playbook_placeholder_map.yaml
|
||||
- user: 939
|
||||
- group: 939
|
||||
- mode: 600
|
||||
|
||||
socplaybookplaceholdermapcustom:
|
||||
file.managed:
|
||||
- name: /opt/so/conf/soc/playbook_placeholder_map_custom.yaml
|
||||
- source: salt://soc/files/soc/playbook_placeholder_map_custom.yaml
|
||||
- user: 939
|
||||
- group: 939
|
||||
- mode: 600
|
||||
|
||||
socbanner:
|
||||
file.managed:
|
||||
- name: /opt/so/conf/soc/banner.md
|
||||
|
||||
@@ -1499,9 +1499,9 @@ soc:
|
||||
playbookRepoPath: /opt/sensoroni/playbooks/
|
||||
playbookRepos:
|
||||
default:
|
||||
- repo: https://github.com/Security-Onion-Solutions/securityonion-resources-playbooks
|
||||
- repo: https://github.com/defensivedepth/HCIP-Sigma
|
||||
branch: main
|
||||
folder: securityonion-normalized
|
||||
folder: playbooks
|
||||
airgap:
|
||||
- repo: file:///nsm/airgap-resources/playbooks/securityonion-resources-playbooks
|
||||
branch: main
|
||||
|
||||
@@ -45,7 +45,10 @@ so-soc:
|
||||
- /opt/so/conf/soc/motd.md:/opt/sensoroni/html/motd.md:ro
|
||||
- /opt/so/conf/soc/banner.md:/opt/sensoroni/html/login/banner.md:ro
|
||||
- /opt/so/conf/soc/sigma_so_pipeline.yaml:/opt/sensoroni/sigma_so_pipeline.yaml:ro
|
||||
- /opt/so/conf/soc/sigma_playbook_pipeline.yaml:/opt/sensoroni/sigma_playbook_pipeline.yaml:ro
|
||||
- /opt/so/conf/soc/sigma_final_pipeline.yaml:/opt/sensoroni/sigma_final_pipeline.yaml:rw
|
||||
- /opt/so/conf/soc/playbook_placeholder_map.yaml:/opt/sensoroni/playbook_placeholder_map.yaml:ro
|
||||
- /opt/so/conf/soc/playbook_placeholder_map_custom.yaml:/opt/sensoroni/playbook_placeholder_map_custom.yaml:rw
|
||||
- /opt/so/conf/soc/custom.js:/opt/sensoroni/html/js/custom.js:ro
|
||||
- /opt/so/conf/soc/custom_roles:/opt/sensoroni/rbac/custom_roles:ro
|
||||
- /opt/so/conf/soc/soc_users_roles:/opt/sensoroni/rbac/users_roles:rw
|
||||
@@ -99,6 +102,8 @@ so-soc:
|
||||
- file: soccustomroles
|
||||
- file: socusersroles
|
||||
- file: socclientsroles
|
||||
- file: socplaybookplaceholdermap
|
||||
- file: socplaybookplaceholdermapcustom
|
||||
|
||||
delete_so-soc_so-status.disabled:
|
||||
file.uncomment:
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# Global Playbook placeholder map: %token% -> event field path.
|
||||
#
|
||||
# Loaded by the SOC Playbook module and used to resolve `field|expand:%placeholder%` values
|
||||
# from an alert when converting playbook questions to OQL.
|
||||
# Left: the %token% used in a question
|
||||
# Right: the event field its value is read from (event_data.-nested or bare; the module
|
||||
# tries both).
|
||||
#
|
||||
# Example: with `src_ip: source.ip` (below), a question that writes
|
||||
# `source.ip|expand: '%src_ip%'` resolves %src_ip% to the alert's source.ip at convert time.
|
||||
#
|
||||
# This is the global base layer. To add or override tokens edit playbook_placeholder_map_custom.yaml.
|
||||
# those entries overlay this map and win on conflict.
|
||||
|
||||
CommandLine: process.command_line
|
||||
CurrentDirectory: process.working_directory
|
||||
Image: process.executable
|
||||
ImageLoaded: dll.name
|
||||
ParentImage: process.parent.executable
|
||||
ParentName: process.parent.name
|
||||
ParentProcessGuid: process.parent.entity_id
|
||||
ProcessGuid: process.entity_id
|
||||
TargetFilename: file.name
|
||||
TargetObject: registry.path
|
||||
TargetUserName: user.target.name
|
||||
User: user.name
|
||||
community_id: network.community_id
|
||||
dns_resolved_ip: dns.resolved_ip
|
||||
document_id: soc_id
|
||||
dst_ip: destination.ip
|
||||
dst_port: destination.port
|
||||
event_data_source_ip: source.ip
|
||||
file_path: file.path
|
||||
file_dirs: process.file_dirs
|
||||
file_name: process.name
|
||||
file_paths: process.file_paths
|
||||
hostname: host.name
|
||||
private_ip: network.private_ip
|
||||
public_ip: network.public_ip
|
||||
related_hosts: related.hosts
|
||||
related_ip: related.ip
|
||||
src_ip: source.ip
|
||||
dns_query_name: dns.query_name
|
||||
flow_id: log.id.uid
|
||||
payload: network.data.decoded
|
||||
rule_category: rule.category
|
||||
rule_name: rule.name
|
||||
rule_uuid: rule.uuid
|
||||
src_port: source.port
|
||||
@@ -0,0 +1,14 @@
|
||||
# Custom Playbook placeholder map: %token% -> event field path.
|
||||
#
|
||||
#
|
||||
# Left: the %token% used in a playbook question.
|
||||
# Right: the event field its value is read from (event_data.-nested or bare; the module tries
|
||||
# both). Note: a token that is simply named after a flat event field resolves automatically
|
||||
# without an entry here - only add a mapping when the token name differs from the field name.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# account_id: cloudflare.account_id
|
||||
#
|
||||
# A question that writes
|
||||
# `account_id|expand: '%account_id%'` resolves %account_id% from the alert at convert time.
|
||||
@@ -0,0 +1,12 @@
|
||||
name: Security Onion - Playbook Pipeline
|
||||
priority: 97
|
||||
transformations:
|
||||
# Route string fields to their lowercase-normalized .caseless subfield so wildcard
|
||||
# matches are case-insensitive.
|
||||
- id: case_insensitive_string_fields
|
||||
type: field_name_mapping
|
||||
mapping:
|
||||
process.executable: process.executable.caseless
|
||||
process.parent.executable: process.parent.executable.caseless
|
||||
process.command_line: process.command_line.caseless
|
||||
process.parent.command_line: process.parent.command_line.caseless
|
||||
@@ -63,6 +63,14 @@ transformations:
|
||||
rule_conditions:
|
||||
- type: logsource
|
||||
category: antivirus
|
||||
# OS-agnostic process_creation scoping for product-less (NIDS/host-pivot) rules.
|
||||
- id: process_creation_os_agnostic
|
||||
type: add_condition
|
||||
conditions:
|
||||
event.category: process
|
||||
rule_conditions:
|
||||
- type: logsource
|
||||
category: process_creation
|
||||
# Transforms the `Hashes` field to ECS fields
|
||||
# ECS fields are used by the hash fields emitted by Elastic Defend
|
||||
# If shipped with Elastic Agent, sysmon logs will also have hashes mapped to ECS fields
|
||||
@@ -108,6 +116,40 @@ transformations:
|
||||
- type: logsource
|
||||
product: windows
|
||||
category: driver_load
|
||||
- id: ecs_fix_process_creation
|
||||
type: field_name_mapping
|
||||
mapping:
|
||||
# bare `Hashes` (the combined-string case is broken out above)
|
||||
winlog.event_data.Hashes: process.hash.sha256
|
||||
winlog.event_data.IntegrityLevel: process.Ext.token.integrity_level_name
|
||||
winlog.event_data.ParentName: process.parent.name
|
||||
rule_conditions:
|
||||
- type: logsource
|
||||
product: windows
|
||||
category: process_creation
|
||||
- id: ecs_fix_registry_set
|
||||
type: field_name_mapping
|
||||
mapping:
|
||||
winlog.event_data.Details: registry.data.strings
|
||||
# field rename only; EventType values (SetValue/CreateKey) still differ from
|
||||
# event.action values (modification/creation)
|
||||
winlog.event_data.EventType: event.action
|
||||
rule_conditions:
|
||||
- type: logsource
|
||||
product: windows
|
||||
category: registry_set
|
||||
- id: ecs_fix_image_load
|
||||
type: field_name_mapping
|
||||
mapping:
|
||||
file.path: dll.path
|
||||
file.code_signature.signed: dll.code_signature.exists
|
||||
winlog.event_data.Signature: dll.code_signature.subject_name
|
||||
file.code_signature.status: dll.code_signature.status
|
||||
winlog.event_data.Hashes: dll.hash.sha256
|
||||
rule_conditions:
|
||||
- type: logsource
|
||||
product: windows
|
||||
category: image_load
|
||||
- id: linux_security_add-fields
|
||||
type: add_condition
|
||||
conditions:
|
||||
@@ -281,6 +323,15 @@ transformations:
|
||||
rule_conditions:
|
||||
- type: logsource
|
||||
category: file_event
|
||||
# Scope image_load rules to Elastic Endpoint library events (event.category:library, dll.*
|
||||
# populated).
|
||||
- id: endpoint_image_load_add-fields
|
||||
type: add_condition
|
||||
conditions:
|
||||
event.category: 'library'
|
||||
rule_conditions:
|
||||
- type: logsource
|
||||
category: image_load
|
||||
# Maps network rules to all network logs
|
||||
# This targets all network logs, all services, generated from endpoints and network
|
||||
- id: network_add-fields
|
||||
|
||||
@@ -46,7 +46,15 @@ soc:
|
||||
syntax: yaml
|
||||
file: True
|
||||
global: True
|
||||
advanced: True
|
||||
advanced: False
|
||||
helpLink: security-onion-console-customization
|
||||
playbook_placeholder_map_custom__yaml:
|
||||
title: Playbook Placeholder Map
|
||||
description: Custom mappings of Playbook %placeholder% tokens to event fields.
|
||||
syntax: yaml
|
||||
file: True
|
||||
global: True
|
||||
advanced: False
|
||||
helpLink: security-onion-console-customization
|
||||
config:
|
||||
licenseKey:
|
||||
|
||||
@@ -886,6 +886,7 @@ create_repo() {
|
||||
title "Create the repo directory"
|
||||
logCmd "dnf -y install yum-utils createrepo_c"
|
||||
logCmd "createrepo /nsm/repo"
|
||||
logCmd "createrepo /nsm/kernelrepo"
|
||||
}
|
||||
|
||||
|
||||
@@ -1812,6 +1813,16 @@ securityonion_repo() {
|
||||
echo "mirrorlist=file:///etc/yum/mirror.txt" >> /etc/yum.repos.d/securityonion.repo
|
||||
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
|
||||
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
|
||||
echo "https://repo.securityonion.net/file/so-repo/prod/3/oracle/9-uek8" > /etc/yum/mirror-kernel.txt
|
||||
echo "https://so-repo-east.s3.us-east-005.backblazeb2.com/prod/3/oracle/9-uek8" >> /etc/yum/mirror-kernel.txt
|
||||
echo "[securityonionkernel]" > /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "name=Security Onion Kernel Repo repo" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "mirrorlist=file:///etc/yum/mirror-kernel.txt" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "enabled=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
# Supplementary kernel repo: tolerate it being empty/unreachable so a missing
|
||||
# repomd.xml can't make every dnf operation fail before the repo is populated.
|
||||
echo "skip_if_unavailable=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
logCmd "dnf repolist"
|
||||
else
|
||||
echo "[securityonion]" > /etc/yum.repos.d/securityonion.repo
|
||||
@@ -1820,6 +1831,13 @@ securityonion_repo() {
|
||||
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
|
||||
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
|
||||
echo "sslverify=0" >> /etc/yum.repos.d/securityonion.repo
|
||||
echo "[securityonionkernel]" > /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "name=Security Onion Kernel Repo" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "baseurl=https://$MSRV/kernelrepo" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "enabled=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "sslverify=0" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "skip_if_unavailable=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
logCmd "dnf repolist"
|
||||
fi
|
||||
elif [[ ! $waitforstate ]]; then
|
||||
@@ -1829,12 +1847,25 @@ securityonion_repo() {
|
||||
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
|
||||
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
|
||||
echo "sslverify=0" >> /etc/yum.repos.d/securityonion.repo
|
||||
echo "[securityonionkernel]" > /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "name=Security Onion Kernel Repo" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "baseurl=https://$MSRV/kernelrepo" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "enabled=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "sslverify=0" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "skip_if_unavailable=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
elif [[ $waitforstate ]]; then
|
||||
echo "[securityonion]" > /etc/yum.repos.d/securityonion.repo
|
||||
echo "name=Security Onion Repo" >> /etc/yum.repos.d/securityonion.repo
|
||||
echo "baseurl=file:///nsm/repo/" >> /etc/yum.repos.d/securityonion.repo
|
||||
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
|
||||
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
|
||||
echo "[securityonionkernel]" > /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "name=Security Onion Kernel Repo" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "baseurl=file:///nsm/kernelrepo/" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "enabled=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
echo "skip_if_unavailable=1" >> /etc/yum.repos.d/securityonionkernel.repo
|
||||
fi
|
||||
logCmd "dnf repolist all"
|
||||
if [[ $waitforstate ]]; then
|
||||
@@ -1850,9 +1881,12 @@ repo_sync_local() {
|
||||
# Sync the repo from the SO repo locally.
|
||||
info "Adding Repo Download Configuration"
|
||||
mkdir -p /nsm/repo
|
||||
mkdir -p /nsm/kernelrepo
|
||||
mkdir -p /opt/so/conf/reposync/cache
|
||||
echo "https://repo.securityonion.net/file/so-repo/prod/3/oracle/9" > /opt/so/conf/reposync/mirror.txt
|
||||
echo "https://repo-alt.securityonion.net/prod/3/oracle/9" >> /opt/so/conf/reposync/mirror.txt
|
||||
echo "https://repo.securityonion.net/file/so-repo/prod/3/oracle/9-uek8" > /opt/so/conf/reposync/mirror-kernel.txt
|
||||
echo "https://repo-alt.securityonion.net/prod/3/oracle/9-uek8" >> /opt/so/conf/reposync/mirror-kernel.txt
|
||||
echo "[main]" > /opt/so/conf/reposync/repodownload.conf
|
||||
echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf
|
||||
echo "installonly_limit=3" >> /opt/so/conf/reposync/repodownload.conf
|
||||
@@ -1866,12 +1900,18 @@ repo_sync_local() {
|
||||
echo "mirrorlist=file:///opt/so/conf/reposync/mirror.txt" >> /opt/so/conf/reposync/repodownload.conf
|
||||
echo "enabled=1" >> /opt/so/conf/reposync/repodownload.conf
|
||||
echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf
|
||||
echo "[securityonionkernel]" >> /opt/so/conf/reposync/repodownload.conf
|
||||
echo "name=Security Onion Kernel Repo repo" >> /opt/so/conf/reposync/repodownload.conf
|
||||
echo "mirrorlist=file:///opt/so/conf/reposync/mirror-kernel.txt" >> /opt/so/conf/reposync/repodownload.conf
|
||||
echo "enabled=1" >> /opt/so/conf/reposync/repodownload.conf
|
||||
echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf
|
||||
|
||||
logCmd "dnf repolist"
|
||||
|
||||
if [[ ! $is_airgap ]]; then
|
||||
curl --retry 5 --retry-delay 60 -A "netinstall/$SOVERSION/$OS/$(uname -r)/1" https://sigs.securityonion.net/checkup --output /tmp/install
|
||||
retry 5 60 "dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionsync --download-metadata -p /nsm/repo/" >> "$setup_log" 2>&1 || fail_setup
|
||||
retry 5 60 "dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionkernel --download-metadata -p /nsm/kernelrepo/" >> "$setup_log" 2>&1 || fail_setup
|
||||
# After the download is complete run createrepo
|
||||
create_repo
|
||||
fi
|
||||
@@ -2228,6 +2268,13 @@ update_sudoers_for_testing() {
|
||||
}
|
||||
|
||||
update_packages() {
|
||||
# Pin physical NIC names by MAC BEFORE pulling packages, so the UEK8 kernel that
|
||||
# the update below installs can't renumber the interfaces SO binds by name. Doing
|
||||
# it here (instead of waiting for the common highstate) also drops the
|
||||
# /opt/so/state/nic_names_pinned marker that gates the kernel repo, so the kernel
|
||||
# repo is assigned on the very first highstate and the kernel isn't downgraded and
|
||||
# then re-upgraded. Run-once: so-nic-pin no-ops if the marker already exists.
|
||||
logCmd "bash ../salt/common/tools/sbin/so-nic-pin"
|
||||
logCmd "dnf repolist"
|
||||
logCmd "dnf -y update --allowerasing --exclude=salt*,docker*,containerd*"
|
||||
RMREPOFILES=("oracle-linux-ol9.repo" "uek-ol9.repo" "virt-ol9.repo")
|
||||
|
||||
Reference in New Issue
Block a user