fix round of Cisco changes to the script

This commit is contained in:
Noam Landress 2023-05-10 17:13:31 +03:00
Родитель 4aa2921476
Коммит 03c53be33b
1 изменённых файлов: 47 добавлений и 33 удалений

Просмотреть файл

@ -20,13 +20,15 @@ AGENT_CONF_FILE = "/etc/opt/microsoft/azuremonitoragent/config-cache/mdsd.hr.jso
FAILED_TESTS_COUNT = 0
WARNING_TESTS_COUNT = 0
NOT_RUN_TESTS_COUNT = 0
SCRIPT_HELP_MESSAGE = "Usage: python cef_AMA_troubleshoot.py [OPTION]\n" \
SCRIPT_HELP_MESSAGE = "Usage: python AMA_troubleshoot.py [STREAM_NAME] [OPTION]\n" \
"Runs CEF validation tests on the collector machine and generates a log file here- /tmp/cef_troubleshooter_output_file.log\n\n" \
" --cef/--CEF run the troubleshooting script for the CEF scenario." \
" --ASA/--CISCO run the troubleshooting script for the Cisco scenario." \
" collect, runs the script in collect mode. Useful in case you want to open a ticket. Generates an output file here- /tmp/cef_troubleshooter_collection_output.log\n" \
" -h, --help display the help and exit\n\n" \
"Example:\n" \
" python cef_AMA_troubleshoot.py\n" \
" python cef_AMA_troubleshoot.py collect\n\n" \
" python cef_AMA_troubleshoot.py --cef\n" \
" python cef_AMA_troubleshoot.py --cisco collect\n\n" \
"This script verifies the installation of the CEF connector on the collector machine. It returns a status for each test and action items to fix detected issues."
DELIMITER = "\n" + "-" * 20 + "\n"
@ -318,17 +320,20 @@ class DCRConfigurationVerifications:
This class is for data collection rules verifications
"""
# CONSTANTS
global STREAM_SCENARIO
DCR_DOC = "https://docs.microsoft.com/azure/azure-monitor/agents/data-collection-rule-overview"
DCRA_DOC = "https://docs.microsoft.com/rest/api/monitor/data-collection-rule-associations"
CEF_STREAM_NAME = "SECURITY_CEF_BLOB"
CISCO_STREAM_NAME = "SECURITY_CISCO_ASA_BLOB"
STREAM_NAME = {"cef": CEF_STREAM_NAME, "asa": CISCO_STREAM_NAME}
DCR_MISSING_ERR = "Could not detect any data collection rule on the machine. The data reaching this server will not be forwarded to any workspace." \
" For explanation on how to install a Data collection rule please browse- {} \n " \
"In order to read about how to associate a DCR to a machine please review- {}".format(DCR_DOC,
DCRA_DOC)
DCR_MISSING_CEF_STREAM_ERR = "Could not detect any data collection rule for CEF data. No CEF events will " \
"be collected from this machine to any workspace. Please create a CEF DCR using the following documentation- " \
DCR_MISSING_CEF_STREAM_ERR = "Could not detect any data collection rule for the provided datatype. No such events will " \
"be collected from this machine to any workspace. Please create a DCR using the following documentation- " \
"{} and run again".format(DCR_DOC)
CEF_MULTI_HOMING_MESSAGE = "Detected multiple collection rules sending the CEF stream. This scenario is called multi-homing and might have effect on the agent's performance"
CEF_MULTI_HOMING_MESSAGE = "Detected multiple collection rules sending the same stream. This scenario is called multi-homing and might have effect on the agent's performance"
def verify_dcr_exists(self):
"""
@ -344,14 +349,14 @@ class DCRConfigurationVerifications:
return False
return True
def verify_dcr_content_has_cef_stream(self):
def verify_dcr_content_has_stream(self):
"""
Verifying there is a DCR on the machine for forwarding cef data
"""
command_name = "verify_DCR_content_has_CEF_stream"
command_to_run = "sudo grep -ri \"{}\" /etc/opt/microsoft/azuremonitoragent/config-cache/configchunks/".format(
self.CEF_STREAM_NAME)
result_keywords_array = [self.CEF_STREAM_NAME]
self.STREAM_NAME[STREAM_SCENARIO])
result_keywords_array = [self.STREAM_NAME[STREAM_SCENARIO]]
command_object = CommandVerification(command_name, command_to_run, result_keywords_array)
command_object.run_full_test()
if not command_object.is_successful:
@ -365,7 +370,7 @@ class DCRConfigurationVerifications:
"""
command_name = "verify_CEF_dcr_has_valid_content"
command_to_run = "sudo grep -ri \"{}\" /etc/opt/microsoft/azuremonitoragent/config-cache/configchunks/".format(
self.CEF_STREAM_NAME)
self.STREAM_NAME[STREAM_SCENARIO])
result_keywords_array = ["stream", "kind", "syslog", "dataSources", "configuration", "facilityNames",
"logLevels", "SecurityInsights", "endpoint", "channels", "sendToChannels", "ods-",
"opinsights.azure", "id"]
@ -383,13 +388,13 @@ class DCRConfigurationVerifications:
return False
command_object.run_full_verification()
def check_cef_multi_homing(self):
def check_multi_homing(self):
"""
Counting the amount of DCRs forwarding CEF data in order to alert from multi-homing scenarios.
"""
command_name = "check_cef_multi_homing"
command_to_run = "sudo grep -ri \"{}\" /etc/opt/microsoft/azuremonitoragent/config-cache/configchunks/ | wc -l".format(
self.CEF_STREAM_NAME)
self.STREAM_NAME[STREAM_SCENARIO])
command_object = CommandVerification(command_name, command_to_run)
command_object.run_command()
try:
@ -409,10 +414,10 @@ class DCRConfigurationVerifications:
"""
if not self.verify_dcr_exists():
return False
if not self.verify_dcr_content_has_cef_stream():
if not self.verify_dcr_content_has_stream():
return False
self.verify_dcr_has_valid_content()
self.check_cef_multi_homing()
self.check_multi_homing()
class SyslogDaemonVerifications:
@ -577,28 +582,29 @@ class IncomingEventsVerifications:
This class is for sending and capturing CEF events in the incoming stream of events to the syslog daemon port
"""
# CONSTANTS
global STREAM_SCENARIO
FIXED_CEF_MESSAGE = "0|TestCommonEventFormat|MOCK|common=event-format-test|end|TRAFFIC|1|rt=$common=event-formatted-receive_time deviceExternalId=0002D01655 src=1.1.1.1 dst=2.2.2.2 sourceTranslatedAddress=1.1.1.1 destinationTranslatedAddress=3.3.3.3 cs1Label=Rule cs1=CEF_TEST_InternetDNS"
CISCO_FIXED_MESSAGE = "Deny inbound TCP src inet:1.1.1.1 dst inet:2.2.2.2"
STREAM_MESSAGE = {"cef": FIXED_CEF_MESSAGE, "asa": CISCO_FIXED_MESSAGE}
IDENT_NAME = {"cef": "CEF:", "asa": "%ASA-7-106010:"}
TCPDUMP_NOT_INSTALLED_ERROR_MESSAGE = "Notice that \'tcpdump\' is not installed in your Linux machine.\nWe cannot monitor traffic without it.\nPlease install \'tcpdump\'."
LOGGER_NOT_INSTALLED_ERROR_MESSAGE = "Warning: Could not execute \'logger\' command. This means that no mock message was sent to your workspace."
CEF_EVENTS_FOUND_MESSAGE = "Found CEF events in stream. Please verify CEF events arrived at your workspace"
CEF_EVENTS_NOT_FOUND_ERROR_MESSAGE = "Could not locate \"CEF\" message in tcpdump. Please verify CEF events can be sent to the machine and there is not firewall blocking incoming traffic"
@staticmethod
def handle_tcpdump_line(line):
def handle_tcpdump_line(self, line):
"""
Validate there are incoming CEF events.
Validate there are incoming events for the relevant stream.
:param line: a text line from the tcpdump stream
:return: True if CEF exists in the line. Otherwise, false.
:return: True if the stream exists in the line. Otherwise, false.
"""
if "CEF" in line:
if self.IDENT_NAME[STREAM_SCENARIO] in line:
return True
return False
def incoming_logs_validations(self, mock_message=False):
"""
Validate that there is incoming traffic of CEF messages
Validate that there is incoming traffic of the stream type
:param mock_message: Tells if to generate mock messages
:return: True if successfully captured CEF events.
:return: True if successfully captured events of the relevant stream.
"""
tcpdump_time_restriction = 10
start_seconds = int(round(time.time()))
@ -606,9 +612,9 @@ class IncomingEventsVerifications:
mock_message_counter = 0
command_name = "listen_to_incoming_cef_events"
command_to_run = "sudo tcpdump -A -ni any port 514 -vv"
result_keywords_array = ["CEF"]
result_keywords_array = [self.IDENT_NAME[STREAM_SCENARIO]]
command_object = CommandVerification(command_name, command_to_run, result_keywords_array)
print("Attempting to capture CEF events using tcpdump. This could take up to " + str(
print("Attempting to capture events using tcpdump. This could take up to " + str(
tcpdump_time_restriction) + " seconds.")
tcp_dump = subprocess.Popen(command_object.command_to_run, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
@ -632,10 +638,11 @@ class IncomingEventsVerifications:
if self.handle_tcpdump_line(line):
command_object.command_result = line
command_object.run_full_verification()
print_ok(self.CEF_EVENTS_FOUND_MESSAGE)
print_ok("Found {0} events in stream. Please verify {0} events arrived at your workspace".format(STREAM_SCENARIO))
return True
end_seconds = int(round(time.time()))
print_error(self.CEF_EVENTS_NOT_FOUND_ERROR_MESSAGE)
print_error("Could not locate {0} message in tcpdump. Please verify {0} events can be sent to the machine and"
" there is not firewall blocking incoming traffic".format(STREAM_SCENARIO))
command_object.command_result = str(line)
command_object.run_full_verification()
return False
@ -648,13 +655,12 @@ class IncomingEventsVerifications:
"""
try:
for index in range(0, amount):
command_tokens = ["logger", "-p", "local4.warn", "-t", "CEF:", self.FIXED_CEF_MESSAGE, "-P", str(port),
"-n",
"127.0.0.1"]
command_tokens = ["logger", "-p", "local4.warn", "-t", self.IDENT_NAME[STREAM_SCENARIO],
self.STREAM_MESSAGE[STREAM_SCENARIO], "-P", str(port), "-n", "127.0.0.1"]
logger = subprocess.Popen(command_tokens, stdout=subprocess.PIPE)
o, e = logger.communicate()
if e is not None:
print("Error could not send cef mock message")
print("Error could not send mock message")
except OSError:
print(self.LOGGER_NOT_INSTALLED_ERROR_MESSAGE)
@ -770,8 +776,8 @@ def getargs(should_print=True):
"""
parser = argparse.ArgumentParser(description=SCRIPT_HELP_MESSAGE)
parser.add_argument('collect', nargs='?', help='Collect syslog message samples to file')
# parser.add_argument('--CEF', '--cef', action='store_true', default=False, help='Validate CEF DCR and events')
# parser.add_argument('--ASA', '--asa', action='store_true', default=False, help='Validate Cisco ASA DCR and events')
parser.add_argument('--CEF', '--cef', action='store_true', default=False, help='Validate CEF DCR and events')
parser.add_argument('--ASA', '--asa', action='store_true', default=False, help='Validate Cisco ASA DCR and events')
args = parser.parse_args()
if should_print:
for arg in vars(args):
@ -782,8 +788,16 @@ def getargs(should_print=True):
def main():
global STREAM_SCENARIO
args = getargs()
verify_root_privileges()
if args.CEF:
STREAM_SCENARIO = "cef"
elif args.ASA:
STREAM_SCENARIO = "asa"
else:
print_error("Invalid stream name provided. The supported streams are either \'--CEF\' or \'--ASA\'. Please try again.")
sys.exit()
if args.collect:
print_notice("Starting to collect data. This may take a couple of seconds")
machine_env = find_dcr_cloud_environment()