mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2026-05-10 21:30:30 +02:00
Fan postgres telegraf cred for manager on every auth run
The empty-pillar case produced a telegraf.conf with `user= password=`
which libpq misparses ("password=" gets consumed as the user value),
yielding `password authentication failed for user "password="` on
every manager without a prior fan-out (fresh install, not the salt-key
path the reactor handles).
Two fixes:
- salt/postgres/auth.sls: always fan for grains.id in addition to any
postgres_fanout_minion from the reactor, so the manager's own pillar
is populated on every postgres.auth run. The existing `unless` guard
keeps re-runs idempotent.
- salt/telegraf/etc/telegraf.conf: gate the [[outputs.postgresql]]
block on PG_USER and PG_PASS being non-empty. If a minion hasn't
received its pillar yet the output block simply isn't rendered — the
next highstate picks up the creds once the fan-out completes, and in
the meantime telegraf keeps running the other outputs instead of
erroring with a malformed connection string.
This commit is contained in:
+23
-10
@@ -50,14 +50,27 @@ postgres_auth_pillar:
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
- show_changes: False
|
- show_changes: False
|
||||||
|
|
||||||
{# Fan a specific minion's telegraf cred out to its own pillar file. Only
|
{# Fan a specific minion's telegraf cred out to its own pillar file.
|
||||||
runs when postgres_fanout_minion pillar is provided — otherwise this state
|
Two triggers populate the target list:
|
||||||
is a no-op. That keeps manager highstates from doing N so-yaml.py forks
|
- grains.id (always) so the manager's own pillar is populated on every
|
||||||
when nothing changed. The reactor passes postgres_fanout_minion through
|
postgres.auth run — otherwise the manager's telegraf has no cred on
|
||||||
the orch on salt-key accept; soup handles bulk backfill separately. #}
|
a fresh install and can't write to its own postgres.
|
||||||
|
- pillar postgres_fanout_minion (when the reactor fires on a new
|
||||||
|
minion's salt-key accept).
|
||||||
|
The `unless` guard keeps re-runs idempotent, so this is one so-yaml.py
|
||||||
|
check per target, not per minion in the grid. Bulk backfill for
|
||||||
|
already-accepted minions lives in soup. #}
|
||||||
|
{% set fanout_targets = [] %}
|
||||||
|
{% if grains.id %}
|
||||||
|
{%- do fanout_targets.append(grains.id) %}
|
||||||
|
{% endif %}
|
||||||
{% set fanout_mid = salt['pillar.get']('postgres_fanout_minion') %}
|
{% set fanout_mid = salt['pillar.get']('postgres_fanout_minion') %}
|
||||||
{% if fanout_mid %}
|
{% if fanout_mid and fanout_mid not in fanout_targets %}
|
||||||
{%- set safe = fanout_mid | replace('.','_') | replace('-','_') | lower %}
|
{%- do fanout_targets.append(fanout_mid) %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for mid in fanout_targets %}
|
||||||
|
{%- set safe = mid | replace('.','_') | replace('-','_') | lower %}
|
||||||
{%- set key = 'telegraf_' ~ safe %}
|
{%- set key = 'telegraf_' ~ safe %}
|
||||||
{%- set entry = telegraf_users.get(key) %}
|
{%- set entry = telegraf_users.get(key) %}
|
||||||
{%- if entry %}
|
{%- if entry %}
|
||||||
@@ -66,7 +79,7 @@ postgres_telegraf_minion_pillar_{{ safe }}:
|
|||||||
cmd.run:
|
cmd.run:
|
||||||
- name: |
|
- name: |
|
||||||
set -e
|
set -e
|
||||||
PILLAR_FILE=/opt/so/saltstack/local/pillar/minions/{{ fanout_mid }}.sls
|
PILLAR_FILE=/opt/so/saltstack/local/pillar/minions/{{ mid }}.sls
|
||||||
if [ ! -f "$PILLAR_FILE" ]; then
|
if [ ! -f "$PILLAR_FILE" ]; then
|
||||||
echo '{}' > "$PILLAR_FILE"
|
echo '{}' > "$PILLAR_FILE"
|
||||||
chown socore:socore "$PILLAR_FILE" 2>/dev/null || true
|
chown socore:socore "$PILLAR_FILE" 2>/dev/null || true
|
||||||
@@ -75,12 +88,12 @@ postgres_telegraf_minion_pillar_{{ safe }}:
|
|||||||
/usr/sbin/so-yaml.py replace "$PILLAR_FILE" postgres.telegraf.user '{{ entry.user }}'
|
/usr/sbin/so-yaml.py replace "$PILLAR_FILE" postgres.telegraf.user '{{ entry.user }}'
|
||||||
/usr/sbin/so-yaml.py replace "$PILLAR_FILE" postgres.telegraf.pass '{{ entry.pass }}'
|
/usr/sbin/so-yaml.py replace "$PILLAR_FILE" postgres.telegraf.pass '{{ entry.pass }}'
|
||||||
- unless: |
|
- unless: |
|
||||||
[ "$(/usr/sbin/so-yaml.py get -r /opt/so/saltstack/local/pillar/minions/{{ fanout_mid }}.sls postgres.telegraf.user 2>/dev/null)" = '{{ entry.user }}' ]
|
[ "$(/usr/sbin/so-yaml.py get -r /opt/so/saltstack/local/pillar/minions/{{ mid }}.sls postgres.telegraf.user 2>/dev/null)" = '{{ entry.user }}' ]
|
||||||
- require:
|
- require:
|
||||||
- file: postgres_auth_pillar
|
- file: postgres_auth_pillar
|
||||||
|
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{% endif %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
{{sls}}_state_not_allowed:
|
{{sls}}_state_not_allowed:
|
||||||
|
|||||||
@@ -96,7 +96,7 @@
|
|||||||
# insecure_skip_verify = false
|
# insecure_skip_verify = false
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{%- if TG_OUT in ['POSTGRES', 'BOTH'] %}
|
{%- if TG_OUT in ['POSTGRES', 'BOTH'] and PG_USER and PG_PASS %}
|
||||||
# Configuration for sending metrics to PostgreSQL.
|
# Configuration for sending metrics to PostgreSQL.
|
||||||
# options='-c role=so_telegraf' makes every connection SET ROLE to the shared
|
# options='-c role=so_telegraf' makes every connection SET ROLE to the shared
|
||||||
# group role so tables created on first write are owned by so_telegraf, and
|
# group role so tables created on first write are owned by so_telegraf, and
|
||||||
|
|||||||
Reference in New Issue
Block a user