From c4994a208b9f0746cc7b3867f8623faba41d718a Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Mon, 15 Apr 2024 11:37:21 -0400 Subject: [PATCH 1/7] restart salt minion if a manager and signing policies change --- salt/salt/minion.sls | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/salt/salt/minion.sls b/salt/salt/minion.sls index 2cc032745..8c6f7f019 100644 --- a/salt/salt/minion.sls +++ b/salt/salt/minion.sls @@ -13,6 +13,9 @@ include: - systemd.reload - repo.client - salt.mine_functions +{% if GLOBALS.role in GLOBALS.manager_roles %} + - ca +{% endif %} {% if INSTALLEDSALTVERSION|string != SALTVERSION|string %} @@ -98,5 +101,8 @@ salt_minion_service: - file: mine_functions {% if INSTALLEDSALTVERSION|string == SALTVERSION|string %} - file: set_log_levels +{% endif %} +{% if GLOBALS.role in GLOBALS.manager_roles %} + - file: /etc/salt/minion.d/signing_policies.conf {% endif %} - order: last From 4b79623ce31edfbf59763d41747ddb7a79fe7220 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 16 Apr 2024 16:51:35 -0400 Subject: [PATCH 2/7] watch pillar files for changes and do something --- salt/salt/engines/master/pillarWatch.py | 72 +++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 salt/salt/engines/master/pillarWatch.py diff --git a/salt/salt/engines/master/pillarWatch.py b/salt/salt/engines/master/pillarWatch.py new file mode 100644 index 000000000..c45e2383d --- /dev/null +++ b/salt/salt/engines/master/pillarWatch.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- + +import logging +from time import sleep +import os +import salt.client +import re + +log = logging.getLogger(__name__) +local = salt.client.LocalClient() + +def start(fpa, interval=10): + log.info("##### PILLARWATCH STARTED #####") + + try: + # maybe change this location + dataFile = open("/opt/so/state/pillarWatch.txt", "r+") + df = dataFile.read() + log.info("df: %s" % str(df)) + except FileNotFoundError: + log.info("No previous pillarWatch data saved") + + currentValues = [] + + log.info("FPA: %s" % str(fpa)) + for i in fpa: + log.trace("files: %s" % i['files']) + log.trace("pillar: %s" % i['pillar']) + log.trace("action: %s" % i['action']) + pillarFiles = i['files'] + pillar = i['pillar'] + action = i['action'] + + patterns = pillar.split(".") + log.trace("pillar: %s" % pillar) + log.trace("patterns: %s" % patterns) + log.trace("patterns length: %i" % len(patterns)) + # this var is used to track how many times the pattern has been found in the pillar file so that we can access the proper index later + patternFound = 0 + for pillarFile in pillarFiles: + with open(pillarFile, "r") as file: + log.info("checking file: %s" % pillarFile) + for line in file: + log.trace("line: %s" % line) + log.trace("pillarWatch engine: looking for: %s" % patterns[patternFound]) + # since we are looping line by line through a pillar file, the next line will check if each line matches the progression of keys through the pillar + # ex. if we are looking for the value of global.pipeline, then this will loop through the pillar file until 'global' is found, then it will look + # for pipeline. once pipeline is found, it will record the value + if re.search(patterns[patternFound], line): + log.trace("PILLARWATCH FOUND: %s" % patterns[patternFound]) + patternFound += 1 + # we have found the final key in the pillar that we are looking for, get the value + if patternFound == len(patterns): + for l in df.splitlines(): + if pillar in l: + previousPillarValue = l.split(":")[1] + log.info("%s previousPillarValue:%s" % (pillar, str(previousPillarValue))) + currentPillarValue = str(line.split(":")[1]).strip() + log.info("%s currentPillarValue: %s" % (pillar,currentPillarValue)) + if pillar in df: + df = re.sub(r"\b{}\b.*".format(pillar), pillar + ': ' + currentPillarValue, df) + #df = df.replace(pillar, pillar + ': ' + currentPillarValue) + else: + df = pillar + ': ' + currentPillarValue + log.info("df: %s" % df) + #currentValues.append(pillar + ":" + currentPillarValue) + # we have found the pillar so we dont need to loop throught the file anymore + break + dataFile.seek(0) + dataFile.write(df) + dataFile.truncate() + dataFile.close() From 4caa6a10b586d733f02df376e715e9f4338fbe8e Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Wed, 17 Apr 2024 18:09:04 -0400 Subject: [PATCH 3/7] watch a pillar in files and take action --- salt/salt/engines/master/pillarWatch.py | 47 +++++++++++++++++++------ salt/salt/files/engines.conf | 30 ++++++++++++++++ 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/salt/salt/engines/master/pillarWatch.py b/salt/salt/engines/master/pillarWatch.py index c45e2383d..c6f343dc8 100644 --- a/salt/salt/engines/master/pillarWatch.py +++ b/salt/salt/engines/master/pillarWatch.py @@ -5,6 +5,7 @@ from time import sleep import os import salt.client import re +from ast import literal_eval log = logging.getLogger(__name__) local = salt.client.LocalClient() @@ -12,24 +13,26 @@ local = salt.client.LocalClient() def start(fpa, interval=10): log.info("##### PILLARWATCH STARTED #####") + # try to open the file that stores the previous runs data + # if the file doesn't exist, create a blank one try: # maybe change this location dataFile = open("/opt/so/state/pillarWatch.txt", "r+") - df = dataFile.read() - log.info("df: %s" % str(df)) except FileNotFoundError: log.info("No previous pillarWatch data saved") + dataFile = open("/opt/so/state/pillarWatch.txt", "w+") - currentValues = [] + df = dataFile.read() + log.info("df: %s" % str(df)) log.info("FPA: %s" % str(fpa)) for i in fpa: log.trace("files: %s" % i['files']) log.trace("pillar: %s" % i['pillar']) - log.trace("action: %s" % i['action']) + log.trace("action: %s" % i['actions']) pillarFiles = i['files'] pillar = i['pillar'] - action = i['action'] + actions = i['actions'] patterns = pillar.split(".") log.trace("pillar: %s" % pillar) @@ -49,23 +52,45 @@ def start(fpa, interval=10): if re.search(patterns[patternFound], line): log.trace("PILLARWATCH FOUND: %s" % patterns[patternFound]) patternFound += 1 - # we have found the final key in the pillar that we are looking for, get the value + # we have found the final key in the pillar that we are looking for, get the previous value then the current value if patternFound == len(patterns): + # at this point, df is equal to the contents of the pillarWatch file that is used to tract the previous values of the pillars + previousPillarValue = 'PREVIOUSPILLARVALUENOTSAVEDINDATAFILE' for l in df.splitlines(): if pillar in l: - previousPillarValue = l.split(":")[1] - log.info("%s previousPillarValue:%s" % (pillar, str(previousPillarValue))) + previousPillarValue = l.split(":")[1].strip() + log.info("%s previousPillarValue: %s" % (pillar, str(previousPillarValue))) currentPillarValue = str(line.split(":")[1]).strip() log.info("%s currentPillarValue: %s" % (pillar,currentPillarValue)) if pillar in df: df = re.sub(r"\b{}\b.*".format(pillar), pillar + ': ' + currentPillarValue, df) - #df = df.replace(pillar, pillar + ': ' + currentPillarValue) else: - df = pillar + ': ' + currentPillarValue + df += pillar + ': ' + currentPillarValue + '\n' log.info("df: %s" % df) - #currentValues.append(pillar + ":" + currentPillarValue) # we have found the pillar so we dont need to loop throught the file anymore break + if currentPillarValue != previousPillarValue: + log.info("cPV != pPV: %s != %s" % (currentPillarValue,previousPillarValue)) + if previousPillarValue in actions['from']: + ACTIONS=actions['from'][previousPillarValue]['to'][currentPillarValue] + elif '*' in actions['from']: + # need more logic here for to and from + ACTIONS=actions['from']['*']['to']['*'] + else: + ACTIONS='FROM TO NOT DEFINED' + #for f in actions: + log.info("actions: %s" % actions['from']) + log.info("ACTIONS: %s" % ACTIONS) + for action in ACTIONS: + log.info(action) + for saltModule, args in action.items(): + log.info(saltModule) + log.info(args) + # args=list(action.values())[0] + # log.info(args) + whatHappened = __salt__[saltModule](**args) + log.info("whatHappened: %s" % whatHappened) + dataFile.seek(0) dataFile.write(df) dataFile.truncate() diff --git a/salt/salt/files/engines.conf b/salt/salt/files/engines.conf index 7c43e99e1..26be7bf37 100644 --- a/salt/salt/files/engines.conf +++ b/salt/salt/files/engines.conf @@ -4,3 +4,33 @@ engines_dirs: engines: - checkmine: interval: 60 + - pillarWatch: + fpa: + - files: + - /opt/so/saltstack/local/pillar/global/soc_global.sls + - /opt/so/saltstack/local/pillar/global/adv_global.sls + pillar: global.pipeline + actions: + from: + REDIS: + to: + KAFKA: + - cmd.run: + cmd: /usr/sbin/so-yaml.py replace /opt/so/saltstack/local/pillar/kafka/soc_kafka.sls kafka.enabled True + KAFKA: + to: + REDIS: + - cmd.run: + cmd: /usr/sbin/so-yaml.py replace /opt/so/saltstack/local/pillar/kafka/soc_kafka.sls kafka.enabled False + - files: + - /opt/so/saltstack/local/pillar/idstools/soc_idstools.sls + - /opt/so/saltstack/local/pillar/idstools/adv_idstools.sls + pillar: idstools.config.ruleset + actions: + from: + '*': + to: + '*': + - cmd.run: + cmd: /usr/sbin/so-rule-update + interval: 10 From 506bbd314df0eff9fbd6a24f60135991e5270818 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Thu, 18 Apr 2024 10:26:10 -0400 Subject: [PATCH 4/7] more comments, better logging --- salt/salt/engines/master/pillarWatch.py | 96 +++++++++++++++---------- salt/salt/files/engines.conf | 4 +- 2 files changed, 60 insertions(+), 40 deletions(-) diff --git a/salt/salt/engines/master/pillarWatch.py b/salt/salt/engines/master/pillarWatch.py index c6f343dc8..b19a6d709 100644 --- a/salt/salt/engines/master/pillarWatch.py +++ b/salt/salt/engines/master/pillarWatch.py @@ -1,17 +1,19 @@ +# 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. + # -*- coding: utf-8 -*- import logging -from time import sleep -import os -import salt.client import re -from ast import literal_eval +import salt.client log = logging.getLogger(__name__) local = salt.client.LocalClient() def start(fpa, interval=10): - log.info("##### PILLARWATCH STARTED #####") + log.info("pillarWatch engine: started") # try to open the file that stores the previous runs data # if the file doesn't exist, create a blank one @@ -19,77 +21,95 @@ def start(fpa, interval=10): # maybe change this location dataFile = open("/opt/so/state/pillarWatch.txt", "r+") except FileNotFoundError: - log.info("No previous pillarWatch data saved") + log.warn("pillarWatch engine: No previous pillarWatch data saved") dataFile = open("/opt/so/state/pillarWatch.txt", "w+") df = dataFile.read() - log.info("df: %s" % str(df)) - - log.info("FPA: %s" % str(fpa)) for i in fpa: - log.trace("files: %s" % i['files']) - log.trace("pillar: %s" % i['pillar']) - log.trace("action: %s" % i['actions']) + log.trace("pillarWatch engine: files: %s" % i['files']) + log.trace("pillarWatch engine: pillar: %s" % i['pillar']) + log.trace("pillarWatch engine: actions: %s" % i['actions']) pillarFiles = i['files'] pillar = i['pillar'] actions = i['actions'] - + # these are the keys that we are going to look for as we traverse the pillarFiles patterns = pillar.split(".") - log.trace("pillar: %s" % pillar) - log.trace("patterns: %s" % patterns) - log.trace("patterns length: %i" % len(patterns)) # this var is used to track how many times the pattern has been found in the pillar file so that we can access the proper index later patternFound = 0 for pillarFile in pillarFiles: with open(pillarFile, "r") as file: - log.info("checking file: %s" % pillarFile) + log.info("pillarWatch engine: checking file: %s" % pillarFile) for line in file: - log.trace("line: %s" % line) + log.trace("pillarWatch engine: inspecting line: %s in file: %s" % (line, file)) log.trace("pillarWatch engine: looking for: %s" % patterns[patternFound]) # since we are looping line by line through a pillar file, the next line will check if each line matches the progression of keys through the pillar # ex. if we are looking for the value of global.pipeline, then this will loop through the pillar file until 'global' is found, then it will look # for pipeline. once pipeline is found, it will record the value - if re.search(patterns[patternFound], line): - log.trace("PILLARWATCH FOUND: %s" % patterns[patternFound]) + if re.search(patterns[patternFound] + ':', line): + # strip the newline because it makes the logs u-g-l-y + log.info("pillarWatch engine: found: %s" % line.strip('\n')) patternFound += 1 # we have found the final key in the pillar that we are looking for, get the previous value then the current value if patternFound == len(patterns): # at this point, df is equal to the contents of the pillarWatch file that is used to tract the previous values of the pillars previousPillarValue = 'PREVIOUSPILLARVALUENOTSAVEDINDATAFILE' + # check the contents of the dataFile that stores the previousPillarValue(s). + # find if the pillar we are checking for changes has previously been saved. if so, grab it's prior value for l in df.splitlines(): if pillar in l: - previousPillarValue = l.split(":")[1].strip() - log.info("%s previousPillarValue: %s" % (pillar, str(previousPillarValue))) + previousPillarValue = str(l.split(":")[1].strip()) + log.info("pillarWatch engine: %s previousPillarValue: %s" % (pillar, previousPillarValue)) currentPillarValue = str(line.split(":")[1]).strip() - log.info("%s currentPillarValue: %s" % (pillar,currentPillarValue)) + log.info("pillarWatch engine: %s currentPillarValue: %s" % (pillar, currentPillarValue)) + # if the pillar we are checking for changes has been defined in the dataFile, + # replace the previousPillarValue with the currentPillarValue. if it isn't in there, append it. if pillar in df: df = re.sub(r"\b{}\b.*".format(pillar), pillar + ': ' + currentPillarValue, df) else: df += pillar + ': ' + currentPillarValue + '\n' - log.info("df: %s" % df) + log.trace("pillarWatch engine: df: %s" % df) # we have found the pillar so we dont need to loop throught the file anymore break + # if the pillar value changed, then we find what actions we should take + log.info("pillarWatch engine: checking if currentPillarValue != previousPillarValue") + log.info("pillarWatch engine: %s currentPillarValue: %s" % (pillar, currentPillarValue)) + log.info("pillarWatch engine: %s previousPillarValue: %s" % (pillar, previousPillarValue)) if currentPillarValue != previousPillarValue: - log.info("cPV != pPV: %s != %s" % (currentPillarValue,previousPillarValue)) + log.info("pillarWatch engine: currentPillarValue != previousPillarValue: %s != %s" % (currentPillarValue, previousPillarValue)) + # check if the previous pillar value is defined in the pillar from -> to actions if previousPillarValue in actions['from']: - ACTIONS=actions['from'][previousPillarValue]['to'][currentPillarValue] + # check if the new / current pillar value is defined under to + if currentPillarValue in actions['from'][previousPillarValue]['to']: + ACTIONS=actions['from'][previousPillarValue]['to'][currentPillarValue] + # if the new / current pillar value isn't defined under to, is there a wildcard defined + elif '*' in actions['from'][previousPillarValue]['to']: + ACTIONS=actions['from'][previousPillarValue]['to']['*'] + # no action was defined for us to take when we see the pillar change + else: + ACTIONS='NO DEFINED ACTION FOR US TO TAKE' + # if the previous pillar wasn't defined in the actions from, is there a wildcard defined for the pillar that we are changing from elif '*' in actions['from']: + # is the new pillar value defined for the wildcard match + if currentPillarValue in actions['from']['*']['to']: + ACTIONS=actions['from']['*']['to'][currentPillarValue] + # if the new pillar doesn't have an action, was a wildcard defined + elif '*' in actions['from']['*']['to']: # need more logic here for to and from - ACTIONS=actions['from']['*']['to']['*'] + ACTIONS=actions['from']['*']['to']['*'] + else: + ACTIONS='NO DEFINED ACTION FOR US TO TAKE' + # a match for the previous pillar wasn't defined in the action in either the form of a direct match or wildcard else: - ACTIONS='FROM TO NOT DEFINED' - #for f in actions: - log.info("actions: %s" % actions['from']) - log.info("ACTIONS: %s" % ACTIONS) + ACTIONS='NO DEFINED ACTION FOR US TO TAKE' + log.info("pillarWatch engine: actions: %s" % actions['from']) + log.info("pillarWatch engine: ACTIONS: %s" % ACTIONS) for action in ACTIONS: - log.info(action) + log.info("pillarWatch engine: action: %s" % action) for saltModule, args in action.items(): - log.info(saltModule) - log.info(args) - # args=list(action.values())[0] - # log.info(args) - whatHappened = __salt__[saltModule](**args) - log.info("whatHappened: %s" % whatHappened) + log.info("pillarWatch engine: saltModule: %s" % saltModule) + log.info("pillarWatch engine: args: %s" % args) + actionReturn = __salt__[saltModule](**args) + log.info("pillarWatch engine: actionReturn: %s" % actionReturn) dataFile.seek(0) dataFile.write(df) diff --git a/salt/salt/files/engines.conf b/salt/salt/files/engines.conf index 26be7bf37..de5c1e43a 100644 --- a/salt/salt/files/engines.conf +++ b/salt/salt/files/engines.conf @@ -12,14 +12,14 @@ engines: pillar: global.pipeline actions: from: - REDIS: + '*': to: KAFKA: - cmd.run: cmd: /usr/sbin/so-yaml.py replace /opt/so/saltstack/local/pillar/kafka/soc_kafka.sls kafka.enabled True KAFKA: to: - REDIS: + '*': - cmd.run: cmd: /usr/sbin/so-yaml.py replace /opt/so/saltstack/local/pillar/kafka/soc_kafka.sls kafka.enabled False - files: From 610dd2c08d3907eac18b2a1841f7fc4d5d6665d1 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Thu, 18 Apr 2024 11:11:14 -0400 Subject: [PATCH 5/7] improve it --- salt/salt/engines/master/pillarWatch.py | 27 ++++++++++++++----------- salt/salt/files/engines.conf | 8 ++++++++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/salt/salt/engines/master/pillarWatch.py b/salt/salt/engines/master/pillarWatch.py index b19a6d709..abbb632f8 100644 --- a/salt/salt/engines/master/pillarWatch.py +++ b/salt/salt/engines/master/pillarWatch.py @@ -13,7 +13,7 @@ log = logging.getLogger(__name__) local = salt.client.LocalClient() def start(fpa, interval=10): - log.info("pillarWatch engine: started") + log.info("pillarWatch engine: checking watched pillars for changes") # try to open the file that stores the previous runs data # if the file doesn't exist, create a blank one @@ -26,6 +26,8 @@ def start(fpa, interval=10): df = dataFile.read() for i in fpa: + currentPillarValue = '' + previousPillarValue = '' log.trace("pillarWatch engine: files: %s" % i['files']) log.trace("pillarWatch engine: pillar: %s" % i['pillar']) log.trace("pillarWatch engine: actions: %s" % i['actions']) @@ -58,9 +60,9 @@ def start(fpa, interval=10): for l in df.splitlines(): if pillar in l: previousPillarValue = str(l.split(":")[1].strip()) - log.info("pillarWatch engine: %s previousPillarValue: %s" % (pillar, previousPillarValue)) currentPillarValue = str(line.split(":")[1]).strip() log.info("pillarWatch engine: %s currentPillarValue: %s" % (pillar, currentPillarValue)) + log.info("pillarWatch engine: %s previousPillarValue: %s" % (pillar, previousPillarValue)) # if the pillar we are checking for changes has been defined in the dataFile, # replace the previousPillarValue with the currentPillarValue. if it isn't in there, append it. if pillar in df: @@ -86,7 +88,7 @@ def start(fpa, interval=10): ACTIONS=actions['from'][previousPillarValue]['to']['*'] # no action was defined for us to take when we see the pillar change else: - ACTIONS='NO DEFINED ACTION FOR US TO TAKE' + ACTIONS=['NO DEFINED ACTION FOR US TO TAKE'] # if the previous pillar wasn't defined in the actions from, is there a wildcard defined for the pillar that we are changing from elif '*' in actions['from']: # is the new pillar value defined for the wildcard match @@ -97,19 +99,20 @@ def start(fpa, interval=10): # need more logic here for to and from ACTIONS=actions['from']['*']['to']['*'] else: - ACTIONS='NO DEFINED ACTION FOR US TO TAKE' + ACTIONS=['NO DEFINED ACTION FOR US TO TAKE'] # a match for the previous pillar wasn't defined in the action in either the form of a direct match or wildcard else: - ACTIONS='NO DEFINED ACTION FOR US TO TAKE' - log.info("pillarWatch engine: actions: %s" % actions['from']) - log.info("pillarWatch engine: ACTIONS: %s" % ACTIONS) + ACTIONS=['NO DEFINED ACTION FOR US TO TAKE'] + log.info("pillarWatch engine: all defined actions: %s" % actions['from']) + log.info("pillarWatch engine: ACTIONS: %s chosen based on previousPillarValue: %s switching to currentPillarValue: %s" % (ACTIONS, previousPillarValue, currentPillarValue)) for action in ACTIONS: log.info("pillarWatch engine: action: %s" % action) - for saltModule, args in action.items(): - log.info("pillarWatch engine: saltModule: %s" % saltModule) - log.info("pillarWatch engine: args: %s" % args) - actionReturn = __salt__[saltModule](**args) - log.info("pillarWatch engine: actionReturn: %s" % actionReturn) + if action != 'NO DEFINED ACTION FOR US TO TAKE': + for saltModule, args in action.items(): + log.info("pillarWatch engine: saltModule: %s" % saltModule) + log.info("pillarWatch engine: args: %s" % args) + actionReturn = __salt__[saltModule](**args) + log.info("pillarWatch engine: actionReturn: %s" % actionReturn) dataFile.seek(0) dataFile.write(df) diff --git a/salt/salt/files/engines.conf b/salt/salt/files/engines.conf index de5c1e43a..c15194eaf 100644 --- a/salt/salt/files/engines.conf +++ b/salt/salt/files/engines.conf @@ -17,11 +17,19 @@ engines: KAFKA: - cmd.run: cmd: /usr/sbin/so-yaml.py replace /opt/so/saltstack/local/pillar/kafka/soc_kafka.sls kafka.enabled True + - cmd.run: + cmd: salt-call saltutil.kill_all_jobs + - cmd.run: + cmd: salt-call state.highstate & KAFKA: to: '*': - cmd.run: cmd: /usr/sbin/so-yaml.py replace /opt/so/saltstack/local/pillar/kafka/soc_kafka.sls kafka.enabled False + - cmd.run: + cmd: salt-call saltutil.kill_all_jobs + - cmd.run: + cmd: salt-call state.highstate & - files: - /opt/so/saltstack/local/pillar/idstools/soc_idstools.sls - /opt/so/saltstack/local/pillar/idstools/adv_idstools.sls From 1f6eb9cdc34e496979c25223c32721fb9ad838b6 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Thu, 18 Apr 2024 13:50:37 -0400 Subject: [PATCH 6/7] match keys better. go through files reverse first found is prio --- salt/salt/engines/master/pillarWatch.py | 24 +++++++++++++++--------- salt/salt/files/engines.conf | 1 + 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/salt/salt/engines/master/pillarWatch.py b/salt/salt/engines/master/pillarWatch.py index abbb632f8..9f85a07c4 100644 --- a/salt/salt/engines/master/pillarWatch.py +++ b/salt/salt/engines/master/pillarWatch.py @@ -26,8 +26,6 @@ def start(fpa, interval=10): df = dataFile.read() for i in fpa: - currentPillarValue = '' - previousPillarValue = '' log.trace("pillarWatch engine: files: %s" % i['files']) log.trace("pillarWatch engine: pillar: %s" % i['pillar']) log.trace("pillarWatch engine: actions: %s" % i['actions']) @@ -36,9 +34,12 @@ def start(fpa, interval=10): actions = i['actions'] # these are the keys that we are going to look for as we traverse the pillarFiles patterns = pillar.split(".") - # this var is used to track how many times the pattern has been found in the pillar file so that we can access the proper index later - patternFound = 0 - for pillarFile in pillarFiles: + # check the pillar files in reveresed order to replicate the same hierarchy as the pillar top file + for pillarFile in reversed(pillarFiles): + currentPillarValue = '' + previousPillarValue = '' + # this var is used to track how many times the pattern has been found in the pillar file so that we can access the proper index later + patternFound = 0 with open(pillarFile, "r") as file: log.info("pillarWatch engine: checking file: %s" % pillarFile) for line in file: @@ -47,7 +48,7 @@ def start(fpa, interval=10): # since we are looping line by line through a pillar file, the next line will check if each line matches the progression of keys through the pillar # ex. if we are looking for the value of global.pipeline, then this will loop through the pillar file until 'global' is found, then it will look # for pipeline. once pipeline is found, it will record the value - if re.search(patterns[patternFound] + ':', line): + if re.search('^' + patterns[patternFound] + ':', line.strip()): # strip the newline because it makes the logs u-g-l-y log.info("pillarWatch engine: found: %s" % line.strip('\n')) patternFound += 1 @@ -70,8 +71,12 @@ def start(fpa, interval=10): else: df += pillar + ': ' + currentPillarValue + '\n' log.trace("pillarWatch engine: df: %s" % df) - # we have found the pillar so we dont need to loop throught the file anymore + # we have found the pillar so we dont need to loop through the file anymore break + # if key and value was found in the first file, then we don't want to look in + # any more files since we use the first file as the source of truth. + if patternFound == len(patterns): + break # if the pillar value changed, then we find what actions we should take log.info("pillarWatch engine: checking if currentPillarValue != previousPillarValue") log.info("pillarWatch engine: %s currentPillarValue: %s" % (pillar, currentPillarValue)) @@ -111,8 +116,9 @@ def start(fpa, interval=10): for saltModule, args in action.items(): log.info("pillarWatch engine: saltModule: %s" % saltModule) log.info("pillarWatch engine: args: %s" % args) - actionReturn = __salt__[saltModule](**args) - log.info("pillarWatch engine: actionReturn: %s" % actionReturn) + __salt__[saltModule](**args) + #actionReturn = __salt__[saltModule](**args) + #log.info("pillarWatch engine: actionReturn: %s" % actionReturn) dataFile.seek(0) dataFile.write(df) diff --git a/salt/salt/files/engines.conf b/salt/salt/files/engines.conf index c15194eaf..3066f588c 100644 --- a/salt/salt/files/engines.conf +++ b/salt/salt/files/engines.conf @@ -6,6 +6,7 @@ engines: interval: 60 - pillarWatch: fpa: + # these files will be checked in reversed order to replicate the same hierarchy as the pillar top file - files: - /opt/so/saltstack/local/pillar/global/soc_global.sls - /opt/so/saltstack/local/pillar/global/adv_global.sls From 6c5e0579cf01a106ff16347e7817b40407e46744 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Fri, 19 Apr 2024 09:32:32 -0400 Subject: [PATCH 7/7] logging changes. ensure salt master has pillarWatch engine --- salt/salt/engines/master/pillarWatch.py | 35 ++++++++++++------------- salt/salt/files/engines.conf | 16 +++++------ salt/salt/master.sls | 5 ++++ 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/salt/salt/engines/master/pillarWatch.py b/salt/salt/engines/master/pillarWatch.py index 9f85a07c4..0f6f0ba6a 100644 --- a/salt/salt/engines/master/pillarWatch.py +++ b/salt/salt/engines/master/pillarWatch.py @@ -7,13 +7,14 @@ import logging import re -import salt.client - log = logging.getLogger(__name__) -local = salt.client.LocalClient() + +# will need this in future versions of this engine +#import salt.client +#local = salt.client.LocalClient() def start(fpa, interval=10): - log.info("pillarWatch engine: checking watched pillars for changes") + log.info("pillarWatch engine: ##### checking watched pillars for changes #####") # try to open the file that stores the previous runs data # if the file doesn't exist, create a blank one @@ -41,7 +42,7 @@ def start(fpa, interval=10): # this var is used to track how many times the pattern has been found in the pillar file so that we can access the proper index later patternFound = 0 with open(pillarFile, "r") as file: - log.info("pillarWatch engine: checking file: %s" % pillarFile) + log.debug("pillarWatch engine: checking file: %s" % pillarFile) for line in file: log.trace("pillarWatch engine: inspecting line: %s in file: %s" % (line, file)) log.trace("pillarWatch engine: looking for: %s" % patterns[patternFound]) @@ -50,7 +51,7 @@ def start(fpa, interval=10): # for pipeline. once pipeline is found, it will record the value if re.search('^' + patterns[patternFound] + ':', line.strip()): # strip the newline because it makes the logs u-g-l-y - log.info("pillarWatch engine: found: %s" % line.strip('\n')) + log.debug("pillarWatch engine: found: %s" % line.strip('\n')) patternFound += 1 # we have found the final key in the pillar that we are looking for, get the previous value then the current value if patternFound == len(patterns): @@ -62,8 +63,8 @@ def start(fpa, interval=10): if pillar in l: previousPillarValue = str(l.split(":")[1].strip()) currentPillarValue = str(line.split(":")[1]).strip() - log.info("pillarWatch engine: %s currentPillarValue: %s" % (pillar, currentPillarValue)) - log.info("pillarWatch engine: %s previousPillarValue: %s" % (pillar, previousPillarValue)) + log.debug("pillarWatch engine: %s currentPillarValue: %s" % (pillar, currentPillarValue)) + log.debug("pillarWatch engine: %s previousPillarValue: %s" % (pillar, previousPillarValue)) # if the pillar we are checking for changes has been defined in the dataFile, # replace the previousPillarValue with the currentPillarValue. if it isn't in there, append it. if pillar in df: @@ -78,9 +79,7 @@ def start(fpa, interval=10): if patternFound == len(patterns): break # if the pillar value changed, then we find what actions we should take - log.info("pillarWatch engine: checking if currentPillarValue != previousPillarValue") - log.info("pillarWatch engine: %s currentPillarValue: %s" % (pillar, currentPillarValue)) - log.info("pillarWatch engine: %s previousPillarValue: %s" % (pillar, previousPillarValue)) + log.debug("pillarWatch engine: checking if currentPillarValue != previousPillarValue") if currentPillarValue != previousPillarValue: log.info("pillarWatch engine: currentPillarValue != previousPillarValue: %s != %s" % (currentPillarValue, previousPillarValue)) # check if the previous pillar value is defined in the pillar from -> to actions @@ -108,17 +107,17 @@ def start(fpa, interval=10): # a match for the previous pillar wasn't defined in the action in either the form of a direct match or wildcard else: ACTIONS=['NO DEFINED ACTION FOR US TO TAKE'] - log.info("pillarWatch engine: all defined actions: %s" % actions['from']) - log.info("pillarWatch engine: ACTIONS: %s chosen based on previousPillarValue: %s switching to currentPillarValue: %s" % (ACTIONS, previousPillarValue, currentPillarValue)) + log.debug("pillarWatch engine: all defined actions: %s" % actions['from']) + log.debug("pillarWatch engine: ACTIONS: %s chosen based on previousPillarValue: %s switching to currentPillarValue: %s" % (ACTIONS, previousPillarValue, currentPillarValue)) for action in ACTIONS: log.info("pillarWatch engine: action: %s" % action) if action != 'NO DEFINED ACTION FOR US TO TAKE': for saltModule, args in action.items(): - log.info("pillarWatch engine: saltModule: %s" % saltModule) - log.info("pillarWatch engine: args: %s" % args) - __salt__[saltModule](**args) - #actionReturn = __salt__[saltModule](**args) - #log.info("pillarWatch engine: actionReturn: %s" % actionReturn) + log.debug("pillarWatch engine: saltModule: %s" % saltModule) + log.debug("pillarWatch engine: args: %s" % args) + #__salt__[saltModule](**args) + actionReturn = __salt__[saltModule](**args) + log.info("pillarWatch engine: actionReturn: %s" % actionReturn) dataFile.seek(0) dataFile.write(df) diff --git a/salt/salt/files/engines.conf b/salt/salt/files/engines.conf index 3066f588c..bee9493ee 100644 --- a/salt/salt/files/engines.conf +++ b/salt/salt/files/engines.conf @@ -18,19 +18,19 @@ engines: KAFKA: - cmd.run: cmd: /usr/sbin/so-yaml.py replace /opt/so/saltstack/local/pillar/kafka/soc_kafka.sls kafka.enabled True - - cmd.run: - cmd: salt-call saltutil.kill_all_jobs - - cmd.run: - cmd: salt-call state.highstate & +# - cmd.run: +# cmd: salt-call saltutil.kill_all_jobs +# - cmd.run: +# cmd: salt-call state.highstate & KAFKA: to: '*': - cmd.run: cmd: /usr/sbin/so-yaml.py replace /opt/so/saltstack/local/pillar/kafka/soc_kafka.sls kafka.enabled False - - cmd.run: - cmd: salt-call saltutil.kill_all_jobs - - cmd.run: - cmd: salt-call state.highstate & +# - cmd.run: +# cmd: salt-call saltutil.kill_all_jobs +# - cmd.run: +# cmd: salt-call state.highstate & - files: - /opt/so/saltstack/local/pillar/idstools/soc_idstools.sls - /opt/so/saltstack/local/pillar/idstools/adv_idstools.sls diff --git a/salt/salt/master.sls b/salt/salt/master.sls index 0a65f3e01..51acca61d 100644 --- a/salt/salt/master.sls +++ b/salt/salt/master.sls @@ -27,6 +27,11 @@ checkmine_engine: - source: salt://salt/engines/master/checkmine.py - makedirs: True +pillarWatch_engine: + file.managed: + - name: /etc/salt/engines/pillarWatch.py + - source: salt://salt/engines/master/pillarWatch.py + engines_config: file.managed: - name: /etc/salt/master.d/engines.conf