mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2026-06-25 03:38:14 +02:00
Move global.push config to salt.auto_apply
The active-push tunables (enabled, highstate_interval_hours, debounce_seconds,
drain_interval, batch, batch_wait) described how Salt auto-applies changes, not
general grid config, so relocate them from the global namespace to a new
salt.auto_apply settings module.
- Add salt/salt/{defaults.yaml,auto_apply.map.jinja,soc_salt.yaml,adv_salt.yaml}.
auto_apply.map.jinja is a dedicated, side-effect-free merge map (the existing
salt/salt/map.jinja dereferences pillar.host.mainint at import time).
- Remove the push blocks from salt/global/{defaults,soc_global}.yaml.
- Register salt.soc_salt/salt.adv_salt in pillar/top.sls; seed the local pillar
stubs for fresh installs (make_some_dirs) and upgrades (ensure_salt_local_pillar
in soup, wired into up_to_3.2.0).
- Repoint all consumers: GLOBALMERGED.push.* -> AUTOAPPLY.* (schedule, salt
master, manager beacons, beacons_pushstate, orch.push_batch) and
pillar.get('global:push...') -> 'salt:auto_apply...' (push reactors,
so-push-drainer).
- Add a salt: fleetwide-highstate entry to pillar_push_map.yaml so edits keep
applying immediately, matching the prior global-namespace behavior.
This commit is contained in:
@@ -3,6 +3,8 @@ base:
|
||||
- ca
|
||||
- global.soc_global
|
||||
- global.adv_global
|
||||
- salt.soc_salt
|
||||
- salt.adv_salt
|
||||
- docker.soc_docker
|
||||
- docker.adv_docker
|
||||
- influxdb.token
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
global:
|
||||
pcapengine: SURICATA
|
||||
pipeline: REDIS
|
||||
push:
|
||||
enabled: true
|
||||
highstate_interval_hours: 2
|
||||
debounce_seconds: 30
|
||||
drain_interval: 15
|
||||
batch: '25%'
|
||||
batch_wait: 15
|
||||
|
||||
@@ -59,41 +59,4 @@ global:
|
||||
description: Allows use of Endgame with Security Onion. This feature requires a license from Endgame.
|
||||
global: True
|
||||
advanced: True
|
||||
push:
|
||||
enabled:
|
||||
description: Master kill-switch for the active push feature. When disabled, rule and pillar changes are picked up at the next scheduled highstate instead of being pushed immediately.
|
||||
forcedType: bool
|
||||
helpLink: push
|
||||
global: True
|
||||
highstate_interval_hours:
|
||||
description: How often every minion in the grid runs a scheduled state.highstate, in hours. Lower values keep minions closer in sync at the cost of more load; higher values reduce load but increase worst-case latency for non-pushed changes. The salt-minion health check restarts a minion if its last highstate is older than this value plus one hour.
|
||||
forcedType: int
|
||||
helpLink: push
|
||||
global: True
|
||||
advanced: True
|
||||
debounce_seconds:
|
||||
description: Trailing-edge debounce window in seconds. A push intent must be quiet for this long before the drainer dispatches. Rapid bursts of edits within this window coalesce into one dispatch.
|
||||
forcedType: int
|
||||
helpLink: push
|
||||
global: True
|
||||
advanced: True
|
||||
drain_interval:
|
||||
description: How often the push drainer checks for ready intents, in seconds. Small values lower dispatch latency at the cost of more background work on the manager.
|
||||
forcedType: int
|
||||
helpLink: push
|
||||
global: True
|
||||
advanced: True
|
||||
batch:
|
||||
description: "Host batch size for push orchestrations. A number (e.g. '10') or a percentage (e.g. '25%'). Limits how many minions run the push state at once so large fleets don't thundering-herd."
|
||||
helpLink: push
|
||||
global: True
|
||||
advanced: True
|
||||
regex: '^([0-9]+%?)$'
|
||||
regexFailureMessage: Enter a whole number or a whole-number percentage (e.g. 10 or 25%).
|
||||
batch_wait:
|
||||
description: Seconds to wait between host batches in a push orchestration. Gives the fleet time to breathe between waves.
|
||||
forcedType: int
|
||||
helpLink: push
|
||||
global: True
|
||||
advanced: True
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
||||
{% from 'global/map.jinja' import GLOBALMERGED %}
|
||||
{% from 'salt/auto_apply.map.jinja' import AUTOAPPLY %}
|
||||
|
||||
include:
|
||||
- salt.minion
|
||||
|
||||
{% if GLOBALS.is_manager and GLOBALMERGED.push.enabled %}
|
||||
{% if GLOBALS.is_manager and AUTOAPPLY.enabled %}
|
||||
salt_beacons_pushstate:
|
||||
file.managed:
|
||||
- name: /etc/salt/minion.d/beacons_pushstate.conf
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% from 'global/map.jinja' import GLOBALMERGED %}
|
||||
{% from 'salt/auto_apply.map.jinja' import AUTOAPPLY %}
|
||||
beacons:
|
||||
pillar_db:
|
||||
- interval: {{ GLOBALMERGED.push.drain_interval }}
|
||||
- interval: {{ AUTOAPPLY.drain_interval }}
|
||||
- disable_during_state_run: True
|
||||
inotify:
|
||||
- disable_during_state_run: True
|
||||
|
||||
@@ -60,9 +60,9 @@ def _make_logger():
|
||||
|
||||
|
||||
def _load_push_cfg():
|
||||
"""Read the global:push pillar subtree via salt-call. Returns a dict."""
|
||||
"""Read the salt:auto_apply pillar subtree via salt-call. Returns a dict."""
|
||||
caller = salt.client.Caller()
|
||||
cfg = caller.cmd('pillar.get', 'global:push', {})
|
||||
cfg = caller.cmd('pillar.get', 'salt:auto_apply', {})
|
||||
return cfg if isinstance(cfg, dict) else {}
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ def main():
|
||||
try:
|
||||
push = _load_push_cfg()
|
||||
except Exception:
|
||||
log.exception('failed to read global:push pillar; aborting drain pass')
|
||||
log.exception('failed to read salt:auto_apply pillar; aborting drain pass')
|
||||
return 1
|
||||
|
||||
if not push.get('enabled', True):
|
||||
|
||||
@@ -690,6 +690,21 @@ ensure_postgres_local_pillar() {
|
||||
chown -R socore:socore "$dir"
|
||||
}
|
||||
|
||||
ensure_salt_local_pillar() {
|
||||
# The salt.auto_apply settings (moved from global.push) are a new SOC settings
|
||||
# module, so the new pillar/top.sls references salt.soc_salt / salt.adv_salt
|
||||
# unconditionally. Managers upgrading from before this change have no
|
||||
# /opt/so/saltstack/local/pillar/salt/ (make_some_dirs only runs at install
|
||||
# time), so the stubs must be created here before salt-master restarts against
|
||||
# the new top.sls.
|
||||
echo "Ensuring salt local pillar stubs exist."
|
||||
local dir=/opt/so/saltstack/local/pillar/salt
|
||||
mkdir -p "$dir"
|
||||
[[ -f "$dir/soc_salt.sls" ]] || touch "$dir/soc_salt.sls"
|
||||
[[ -f "$dir/adv_salt.sls" ]] || touch "$dir/adv_salt.sls"
|
||||
chown -R socore:socore "$dir"
|
||||
}
|
||||
|
||||
ensure_postgres_secret() {
|
||||
# On a fresh install, generate_passwords + secrets_pillar seed
|
||||
# secrets:postgres_pass in /opt/so/saltstack/local/pillar/secrets.sls. That
|
||||
@@ -851,6 +866,8 @@ kibana_backport_streams_index_template() {
|
||||
}
|
||||
|
||||
up_to_3.2.0() {
|
||||
ensure_salt_local_pillar
|
||||
|
||||
fix_logstash_0013_lumberjack_pipeline_name
|
||||
|
||||
pin_elasticsearch_data_retention_method
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% from 'global/map.jinja' import GLOBALMERGED %}
|
||||
{% from 'salt/auto_apply.map.jinja' import AUTOAPPLY %}
|
||||
{% set actions = salt['pillar.get']('actions', []) %}
|
||||
{% set BATCH = GLOBALMERGED.push.batch %}
|
||||
{% set BATCH_WAIT = GLOBALMERGED.push.batch_wait %}
|
||||
{% set BATCH = AUTOAPPLY.batch %}
|
||||
{% set BATCH_WAIT = AUTOAPPLY.batch_wait %}
|
||||
|
||||
{% for action in actions %}
|
||||
{% if action.get('highstate') %}
|
||||
|
||||
@@ -185,6 +185,17 @@ registry:
|
||||
- state: registry
|
||||
tgt: 'G@role:so-eval or G@role:so-import or G@role:so-manager or G@role:so-managerhype or G@role:so-managersearch or G@role:so-standalone'
|
||||
|
||||
# salt: fanout to a fleetwide highstate. The salt.auto_apply settings tune the
|
||||
# push pipeline itself (enabled, debounce/drain intervals, batch sizing) and the
|
||||
# per-minion highstate schedule; they are consumed by the manager's schedule,
|
||||
# beacons, and master reactor config as well as every minion's highstate
|
||||
# schedule, so a targeted re-apply isn't meaningful. A salt audit row only fires
|
||||
# for SOC-driven salt.auto_apply edits -- salt version bumps go through soup, not
|
||||
# SOC, so they never reach this map.
|
||||
salt:
|
||||
- highstate: True
|
||||
tgt: '*'
|
||||
|
||||
# sensoroni: universal.
|
||||
sensoroni:
|
||||
- state: sensoroni
|
||||
|
||||
@@ -59,9 +59,9 @@ def _load_push_map():
|
||||
def _push_enabled():
|
||||
try:
|
||||
caller = Caller()
|
||||
return bool(caller.cmd('pillar.get', 'global:push:enabled', True))
|
||||
return bool(caller.cmd('pillar.get', 'salt:auto_apply:enabled', True))
|
||||
except Exception:
|
||||
LOG.exception('push_pillar: pillar.get global:push:enabled failed, assuming enabled')
|
||||
LOG.exception('push_pillar: pillar.get salt:auto_apply:enabled failed, assuming enabled')
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -35,9 +35,9 @@ def _sensor_compound():
|
||||
def _push_enabled():
|
||||
try:
|
||||
caller = Caller()
|
||||
return bool(caller.cmd('pillar.get', 'global:push:enabled', True))
|
||||
return bool(caller.cmd('pillar.get', 'salt:auto_apply:enabled', True))
|
||||
except Exception:
|
||||
LOG.exception('push_strelka: pillar.get global:push:enabled failed, assuming enabled')
|
||||
LOG.exception('push_strelka: pillar.get salt:auto_apply:enabled failed, assuming enabled')
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ def _sensor_compound_plus_import():
|
||||
def _push_enabled():
|
||||
try:
|
||||
caller = Caller()
|
||||
return bool(caller.cmd('pillar.get', 'global:push:enabled', True))
|
||||
return bool(caller.cmd('pillar.get', 'salt:auto_apply:enabled', True))
|
||||
except Exception:
|
||||
LOG.exception('push_suricata: pillar.get global:push:enabled failed, assuming enabled')
|
||||
LOG.exception('push_suricata: pillar.get salt:auto_apply:enabled failed, assuming enabled')
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
{% import_yaml 'salt/defaults.yaml' as SALT_DEFAULTS %}
|
||||
{% set AUTOAPPLY = salt['pillar.get']('salt:auto_apply', SALT_DEFAULTS.salt.auto_apply, merge=True) %}
|
||||
@@ -0,0 +1,8 @@
|
||||
salt:
|
||||
auto_apply:
|
||||
enabled: true
|
||||
highstate_interval_hours: 2
|
||||
debounce_seconds: 30
|
||||
drain_interval: 15
|
||||
batch: '25%'
|
||||
batch_wait: 15
|
||||
@@ -10,7 +10,7 @@
|
||||
# software that is protected by the license key."
|
||||
|
||||
{% from 'allowed_states.map.jinja' import allowed_states %}
|
||||
{% from 'global/map.jinja' import GLOBALMERGED %}
|
||||
{% from 'salt/auto_apply.map.jinja' import AUTOAPPLY %}
|
||||
{% if sls in allowed_states %}
|
||||
|
||||
include:
|
||||
@@ -65,7 +65,7 @@ engines_config:
|
||||
- name: /etc/salt/master.d/engines.conf
|
||||
- source: salt://salt/files/engines.conf
|
||||
|
||||
{% if GLOBALMERGED.push.enabled %}
|
||||
{% if AUTOAPPLY.enabled %}
|
||||
reactor_pushstate_config:
|
||||
file.managed:
|
||||
- name: /etc/salt/master.d/reactor_pushstate.conf
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
salt:
|
||||
auto_apply:
|
||||
enabled:
|
||||
description: Master kill-switch for the active push feature. When disabled, rule and pillar changes are picked up at the next scheduled highstate instead of being pushed immediately.
|
||||
forcedType: bool
|
||||
helpLink: push
|
||||
global: True
|
||||
highstate_interval_hours:
|
||||
description: How often every minion in the grid runs a scheduled state.highstate, in hours. Lower values keep minions closer in sync at the cost of more load; higher values reduce load but increase worst-case latency for non-pushed changes. The salt-minion health check restarts a minion if its last highstate is older than this value plus one hour.
|
||||
forcedType: int
|
||||
helpLink: push
|
||||
global: True
|
||||
advanced: True
|
||||
debounce_seconds:
|
||||
description: Trailing-edge debounce window in seconds. A push intent must be quiet for this long before the drainer dispatches. Rapid bursts of edits within this window coalesce into one dispatch.
|
||||
forcedType: int
|
||||
helpLink: push
|
||||
global: True
|
||||
advanced: True
|
||||
drain_interval:
|
||||
description: How often the push drainer checks for ready intents, in seconds. Small values lower dispatch latency at the cost of more background work on the manager.
|
||||
forcedType: int
|
||||
helpLink: push
|
||||
global: True
|
||||
advanced: True
|
||||
batch:
|
||||
description: "Host batch size for push orchestrations. A number (e.g. '10') or a percentage (e.g. '25%'). Limits how many minions run the push state at once so large fleets don't thundering-herd."
|
||||
helpLink: push
|
||||
global: True
|
||||
advanced: True
|
||||
regex: '^([0-9]+%?)$'
|
||||
regexFailureMessage: Enter a whole number or a whole-number percentage (e.g. 10 or 25%).
|
||||
batch_wait:
|
||||
description: Seconds to wait between host batches in a push orchestration. Gives the fleet time to breathe between waves.
|
||||
forcedType: int
|
||||
helpLink: push
|
||||
global: True
|
||||
advanced: True
|
||||
+4
-4
@@ -1,22 +1,22 @@
|
||||
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
||||
{% from 'global/map.jinja' import GLOBALMERGED %}
|
||||
{% from 'salt/auto_apply.map.jinja' import AUTOAPPLY %}
|
||||
|
||||
highstate_schedule:
|
||||
schedule.present:
|
||||
- function: state.highstate
|
||||
- hours: {{ GLOBALMERGED.push.highstate_interval_hours }}
|
||||
- hours: {{ AUTOAPPLY.highstate_interval_hours }}
|
||||
- maxrunning: 1
|
||||
{% if not GLOBALS.is_manager %}
|
||||
- splay: 1800
|
||||
{% endif %}
|
||||
|
||||
{% if GLOBALS.is_manager and GLOBALMERGED.push.enabled %}
|
||||
{% if GLOBALS.is_manager and AUTOAPPLY.enabled %}
|
||||
push_drain_schedule:
|
||||
schedule.present:
|
||||
- function: cmd.run
|
||||
- job_args:
|
||||
- /usr/sbin/so-push-drainer
|
||||
- seconds: {{ GLOBALMERGED.push.drain_interval }}
|
||||
- seconds: {{ AUTOAPPLY.drain_interval }}
|
||||
- maxrunning: 1
|
||||
- return_job: False
|
||||
{% elif GLOBALS.is_manager %}
|
||||
|
||||
+1
-1
@@ -1432,7 +1432,7 @@ make_some_dirs() {
|
||||
mkdir -p $local_salt_dir/salt/firewall/portgroups
|
||||
mkdir -p $local_salt_dir/salt/firewall/ports
|
||||
|
||||
for THEDIR in bpf elasticsearch ntp firewall redis backup influxdb postgres strelka sensoroni soc docker zeek suricata nginx telegraf logstash soc manager kratos hydra idh elastalert stig global kafka versionlock hypervisor vm; do
|
||||
for THEDIR in bpf elasticsearch ntp firewall redis backup influxdb postgres strelka sensoroni soc docker zeek suricata nginx telegraf logstash soc manager kratos hydra idh elastalert stig global salt kafka versionlock hypervisor vm; do
|
||||
mkdir -p $local_salt_dir/pillar/$THEDIR
|
||||
touch $local_salt_dir/pillar/$THEDIR/adv_$THEDIR.sls
|
||||
touch $local_salt_dir/pillar/$THEDIR/soc_$THEDIR.sls
|
||||
|
||||
Reference in New Issue
Block a user