Switch to using single-row summaries for all the Defender alerts. Move the extra into into the details section.

This commit is contained in:
Marsell Kukuljevic 2024-12-06 13:05:14 +01:00
parent 1dca9e4a65
commit 6d39ee351b
3 changed files with 54 additions and 26 deletions

Binary file not shown.

View File

@ -25,8 +25,8 @@ def check_state_above(alert_percentages, measured_percent):
# Convert JSON entries into dictionaries indexed by name. We're assuming here
# that the name is unique across AZs and resource groups. If not, add the
# 'location' and 'resource_group' fields in each object to the name.
# that the name is unique across AZs. If not, add the 'location' field in each
# object to the name.
def parse(string_table):
lookup = {}
@ -39,12 +39,25 @@ def parse(string_table):
return lookup
# Produce a list of Azure objects for discovery.
# Produce a list of Azure objects for discovery. This applies for KeyVault and
# Firewall.
def discover(section):
for name, details in sorted(section.items()):
yield Service(item=name)
# Produce a list of Azure resource group objects for discovery. This applies to
# Defender. We also assume each section comes entirely from the same resource
# group (this should be true given our special agent).
def discover_defender(section):
items = list(section.values())
if items != []:
yield Service(item=items[0]["resource_group"])
else:
yield Service(item=None)
# Given a specific keyvault metric, look it up in the parsed output, and produce
# results on that service based upon the metric's range.
def check_keyvault(item, params, section):
@ -200,34 +213,49 @@ def check_firewall(item, params, section):
)
def check_defender(item, params, section):
alert = section.get(item)
if alert is None:
return
num_high = 0
num_med = 0
num_low = 0
num_info = 0
details = alert["alert"]
status = details["status"]
final_state = State.OK
region_details = []
if status != "Active" and status != "InProgress":
return
for name, alert in sorted(section.items()):
details = alert["alert"]
status = details["status"]
severity = details["severity"]
url = details["url"]
info = details["info"]
if status != "Active" and status != "InProgress":
continue
if severity == "High":
state = State(params.get("severity_high", State.CRIT))
elif severity == "Medium":
state = State(params.get("severity_medium", State.WARN))
elif severity == "Low":
state = State(params.get("severity_low", State.WARN))
elif severity == "Informational":
state = State(params.get("severity_informational", State.OK))
else:
state = State.UNKNOWN
severity = details["severity"]
url = details["url"]
info = details["info"]
if severity == "High":
num_high += 1
state = State(params.get("severity_high", State.CRIT))
elif severity == "Medium":
num_med += 1
state = State(params.get("severity_medium", State.WARN))
elif severity == "Low":
num_low += 1
state = State(params.get("severity_low", State.WARN))
elif severity == "Informational":
num_info += 1
state = State(params.get("severity_informational", State.OK))
else:
state = State.UNKNOWN
final_state = State(max(final_state.value, state.value))
if state.value > State.OK.value:
region_details.append(f"{severity}: {info}: {url}")
yield Result(
state=state,
summary=f"{severity}: {status}: {info}: {url}"
state=final_state,
summary=f"High: {num_high}, Medium: {num_med}, Low: {num_low}, Informational: {num_info}",
details="\n".join(region_details)
)
@ -276,5 +304,5 @@ register.check_plugin(
check_default_parameters={},
check_ruleset_name="azure_defender",
discovery_function=discover,
discovery_function=discover_defender,
)