Skip to content

Commit

Permalink
add: ability to do integrity check in mssp mode
Browse files Browse the repository at this point in the history
  • Loading branch information
0xFustang committed Sep 23, 2024
1 parent 66d9469 commit 397e6e1
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/droid/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,10 @@ def convert_rules(parameters, droid_config, base_config, logger_param):
platform = ElasticPlatform(droid_config, logger_param, "esql", raw=False)
elif "eql" in platform_name:
platform = ElasticPlatform(droid_config, logger_param, "eql", raw=False)
elif "microsoft_sentinel" in platform_name:
platform = SentinelPlatform(droid_config, logger_param)
elif "microsoft_sentinel" in platform_name and parameters.mssp:
platform = SentinelPlatform(droid_config, logger_param, export_mssp=True)
elif "microsoft_sentinel" in platform_name:
platform = SentinelPlatform(droid_config, logger_param, export_mssp=False)
elif "microsoft_xdr" in platform_name and parameters.sentinel_xdr:
platform = SentinelPlatform(droid_config, logger_param)
elif "microsoft_xdr" in platform_name:
Expand Down
67 changes: 57 additions & 10 deletions src/droid/integrity.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,63 @@ def integrity_rule_splunk(rule_converted, rule_content, platform: SplunkPlatform
if error:
return error

def integrity_rule_sentinel(rule_converted, rule_content, platform: SentinelPlatform, rule_file, parameters, logger, error):
def integrity_rule_sentinel_mssp(rule_converted, rule_content, platform: SentinelPlatform, rule_file, parameters, logger, error):

try:
saved_search: dict = platform.get_rule(rule_content, rule_file)
# Mapping rule_content with a MS Sentinel saved search properties
mapping = {
"id": "name",
"detection": "query",
"description": "description"
}
export_list = platform.get_integrity_export_mssp()
except Exception as e:
logger.error(f"Couldn't get the export list for the designated customers - error {e}")
return error

logger.info("Integrity check for designated customers")

error_occured = False

for group, info in export_list.items():

tenant_id = info['tenant_id']
subscription_id = info['subscription_id']
resource_group_name = info['resource_group_name']
workspace_name = info['workspace_name']

logger.debug(f"Processing rule on {workspace_name} from group id {group}")
try:
saved_search: dict = platform.get_rule_mssp(
rule_content, rule_file, tenant_id,
subscription_id, resource_group_name,
workspace_name
)
except Exception as e:
logger.error(f"Couldn't check the integrity for the rule {rule_file} on workspace {workspace_name} from {group} - error {e}")
return error

error = integrity_rule_sentinel(rule_converted, rule_content, platform, rule_file, parameters, logger, error, saved_search=saved_search)

if error:
error_occured = True

if error_occured:
return error

def integrity_rule_sentinel(
rule_converted, rule_content, platform: SentinelPlatform,
rule_file, parameters, logger,
error, saved_search=None
):

try:
if not saved_search:
saved_search: dict = platform.get_rule(rule_content, rule_file)
except Exception as e:
logger.error(f"Couldn't check the integrity for the rule {rule_file} - error {e}")
return error

mapping = {
"id": "name",
"detection": "query",
"description": "description"
}

if saved_search:
logger.info(f"Successfully retrieved the rule {rule_file}")
else:
Expand Down Expand Up @@ -223,7 +266,6 @@ def integrity_rule_elastic(rule_converted, rule_content, platform: ElasticPlatfo
rule_content["detection"] = rule_converted

mapping = {
#"id": "name", # Not sure why this is here?
"detection": "query",
"description": "description"
}
Expand Down Expand Up @@ -275,6 +317,9 @@ def integrity_rule(parameters, rule_converted, rule_content, platform, rule_file
elif parameters.platform == "microsoft_xdr":
error = integrity_rule_ms_xdr(rule_converted, rule_content, platform, rule_file, parameters, logger, error)
return error
elif "microsoft_sentinel" in parameters.platform and parameters.mssp:
error = integrity_rule_sentinel_mssp(rule_converted, rule_content, platform, rule_file, parameters, logger, error)
return error
elif "microsoft_sentinel" in parameters.platform:
error = integrity_rule_sentinel(rule_converted, rule_content, platform, rule_file, parameters, logger, error)
return error
Expand All @@ -287,8 +332,10 @@ def integrity_rule_raw(parameters: dict, export_config: dict, logger_param: dict

if parameters.platform == "splunk":
platform = SplunkPlatform(export_config, logger_param)
elif parameters.platform == "microsoft_sentinel" and parameters.mssp:
platform = SentinelPlatform(export_config, logger_param, export_mssp=True)
elif parameters.platform == "microsoft_sentinel":
platform = SentinelPlatform(export_config, logger_param)
platform = SentinelPlatform(export_config, logger_param, export_mssp=False)
elif parameters.platform == "microsoft_xdr":
platform = MicrosoftXDRPlatform(export_config, logger_param)
elif parameters.platform == "esql" or parameters.platform == "eql":
Expand Down
45 changes: 43 additions & 2 deletions src/droid/platforms/sentinel.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,16 @@ def get_workspaces(self, credential, export_mode=False):

return workspace_list

def get_integrity_export_mssp(self) -> list:

if self._export_list_mssp:
self.logger.info("Integrity check for designated customers")
return self._export_list_mssp
else:
self.logger.error("No export_list_mssp found")
raise
# TODO: Integrity check to all customers


def mssp_run_sentinel_search(self,
client,
Expand Down Expand Up @@ -314,9 +324,40 @@ def run_sentinel_search(self, rule_converted, rule_file, mssp_mode):
except Exception as e:
self.logger.error(f"Rule {rule_file} error: {e}")

def get_rule_mssp(self, rule_content, rule_file,
tenant_id, subscription_id, resource_group_name,
workspace_name):
"""Retrieve a scheduled alert rule in Sentinel in MSSP mode
"""

self._tenant_id = tenant_id
credential = self.get_credentials()

client = SecurityInsights(credential, subscription_id)

try:
rule = client.alert_rules.get(
resource_group_name=resource_group_name,
workspace_name=workspace_name,
rule_id=rule_content['id']
)
self.logger.info(f"Successfully retrieved the rule {rule_file} for {workspace_name}")

if rule:
return rule
else:
return None

except ResourceNotFoundError:
self.logger.error(f"Rule not found {rule_file} in {workspace_name}")
return None

except Exception as e:
self.logger.error(f"Could not retrieve the rule {rule_file} in {workspace_name}")
raise

def get_rule(self, rule_content, rule_file):
"""Retrieve a scheduled alert rule in Sentinel
Remove a scheduled alert rule in Sentinel
"""
credential = self.get_credentials()

Expand Down Expand Up @@ -437,7 +478,7 @@ def create_rule(self, rule_content, rule_converted, rule_file):

if self._export_mssp:
if self._export_list_mssp:
self.logger.info("Exporting to restricted customers")
self.logger.info("Exporting to designated customers")
for group, info in self._export_list_mssp.items():

workspace_name = info['workspace_name']
Expand Down

0 comments on commit 397e6e1

Please sign in to comment.