Skip to content

Commit

Permalink
Add polling mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
TOUFIKIzakarya committed Jun 16, 2024
1 parent ffaa3cb commit 6cc884b
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 68 deletions.
132 changes: 72 additions & 60 deletions Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.py
Original file line number Diff line number Diff line change
Expand Up @@ -950,8 +950,6 @@ def search_events_command(client: Client, args: Dict[str, Any]) -> CommandResult
term = args["query"]
max_last_events = args.get("max_last_events")
exclude_info_arg = args.get("exclude_info")
timeout_in_seconds = int(args["timeout_in_seconds"])
exclude_info_arg = args.get("exclude_info")
exclude_info_param = demisto.params().get("exclude_info_events")
replace_symbol = demisto.params().get("replace_dots_event")

Expand All @@ -963,66 +961,45 @@ def search_events_command(client: Client, args: Dict[str, Any]) -> CommandResult
)
search_job_uuid = search["uuid"]

start_time = time.time()
bool_flag = True
while bool_flag:
# Break when the time of the query is bigger than the timeout
if time.time() - start_time > timeout_in_seconds:
demisto.debug(
"The query of the events have timeout without a valid status result."
)
break
query_status = client.query_events_status(event_search_job_uuid=search_job_uuid)
status = query_status["status"]

if status == 2:
events = client.retrieve_events(event_search_job_uuid=search_job_uuid)
total = max_last_events or events["total"]

if len(events["items"]) > 0:
if exclude_info_arg:
headers = exclude_info_events(
event_info=events, exclude_info=exclude_info_arg
)
headers = [
header.replace(".", replace_symbol) for header in headers
]
events_undot = undot(json_data=events)
readable_output = tableToMarkdown(
f"{total} events out of {str(events['total'])} retrieved for the {term}",
events_undot,
headers=headers,
)
elif exclude_info_param:
headers = exclude_info_events(
event_info=events, exclude_info=",".join(exclude_info_param)
)
headers = [
header.replace(".", replace_symbol) for header in headers
]
events_undot = undot(json_data=events)
readable_output = tableToMarkdown(
f"{total} events out of {events['total']} retrieved for the {term}",
events_undot,
headers=headers,
)
else:
events_undot = undot(json_data=events)
readable_output = tableToMarkdown(
f"{total} events out of {events['total']} retrieved for the {term}",
events_undot,
)
else:
readable_output = tableToMarkdown(
f"{total} events out of {events['total']} retrieved for the {term}",
events["items"],
)
bool_flag = False
await_alert_status_command(args={"uuid": search_job_uuid}, client=client)

else:
demisto.debug(f"The query is still running with the status {status}")
events = client.retrieve_events(event_search_job_uuid=search_job_uuid)
total = max_last_events or events["total"]

time.sleep(int(args["interval_in_seconds"]))
if len(events["items"]) > 0:
if exclude_info_arg:
headers = exclude_info_events(
event_info=events, exclude_info=exclude_info_arg
)
headers = [header.replace(".", replace_symbol) for header in headers]
events_undot = undot(json_data=events)
readable_output = tableToMarkdown(
f"{total} events out of {str(events['total'])} retrieved for the {term}",
events_undot,
headers=headers,
)
elif exclude_info_param:
headers = exclude_info_events(
event_info=events, exclude_info=",".join(exclude_info_param)
)
headers = [header.replace(".", replace_symbol) for header in headers]
events_undot = undot(json_data=events)
readable_output = tableToMarkdown(
f"{total} events out of {events['total']} retrieved for the {term}",
events_undot,
headers=headers,
)
else:
events_undot = undot(json_data=events)
readable_output = tableToMarkdown(
f"{total} events out of {events['total']} retrieved for the {term}",
events_undot,
)
else:
readable_output = tableToMarkdown(
f"{total} events out of {events['total']} retrieved for the {term}",
events["items"],
)

return CommandResults(
readable_output=readable_output,
Expand All @@ -1032,6 +1009,39 @@ def search_events_command(client: Client, args: Dict[str, Any]) -> CommandResult
)


@polling_function(
name="await-alert-status",
poll_message="Polling for alert status",
)
def await_alert_status_command(args: Dict[str, Any], client: Client) -> PollResult:
"""
Polls for the status of an alert search job.
Args:
args (Dict[str, Any]): The command arguments.
- uuid (str): The UUID of the alert search job.
client (Client): The SekoiaXDR client.
Returns:
PollResult: The result of the polling.
- continue_to_poll (bool): Whether to continue polling.
- response (Any): The response from the query.
"""
search_job_uuid = args["uuid"]
query_status = client.query_events_status(event_search_job_uuid=search_job_uuid)

finished_status = query_status["status"] == 2

if finished_status:
return PollResult(
continue_to_poll=False,
response=query_status["status"],
)

return PollResult(continue_to_poll=True, response=query_status["status"])


def update_status_alert_command(client: Client, args: Dict[str, Any]) -> CommandResults:
"""Parameters"""
alert_uuid, updated_status, comment = (
Expand Down Expand Up @@ -1422,6 +1432,8 @@ def main() -> None:
return_results(retrieve_events_command(client, args))
elif command == "sekoia-xdr-search-events":
return_results(search_events_command(client, args))
elif command == "sekoia-xdr-await_alert_status":
return_results(await_alert_status_command(args, client))
elif command == "sekoia-xdr-update-status-alert":
return_results(update_status_alert_command(client, args))
elif command == "sekoia-xdr-post-comment-alert":
Expand Down
16 changes: 8 additions & 8 deletions Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -653,13 +653,6 @@ script:
- user_agent.original
description: "Indicate if there is any information you want to exclude from the results of the events. i.e: original.message, message, agent.name, etc. These are the names of the headers presented in the table. If the header you want to exclude is not in the list write it and press enter."
isArray: true
- name: interval_in_seconds
default: true
description: Interval in seconds between each poll.
defaultValue: "2"
- name: timeout_in_seconds
description: Polling timeout in seconds.
defaultValue: "60"
outputs:
- contextPath: SekoiaXDR.Events.Results
description: The outputs are different for each event, they will be output inside SekoiaXDR.Events.Results.
Expand All @@ -681,6 +674,13 @@ script:
- name: comment
description: A comment to describe why the alert status has changed.
description: Command to update the status of a specific Alert by uuid or short_id.
- name: sekoia-xdr-await_alert_status
polling: true
arguments:
- name: uuid
required: true
description: The UUID of the alert search job
description: Polling command to await for query to finish.
- name: sekoia-xdr-post-comment-alert
arguments:
- name: id
Expand Down Expand Up @@ -1178,7 +1178,7 @@ script:
description: Query parameters, i.e. limit -> 10 , match['status_name'] -> Ongoing.
type: keyValue
description: Command that performs a HTTP request to Sekoia using the integration authentication configured.
dockerimage: demisto/python3:3.10.14.97374
dockerimage: demisto/python3:3.10.14.94490
isfetch: true
runonce: false
subtype: python3
Expand Down

0 comments on commit 6cc884b

Please sign in to comment.