Skip to content

Commit

Permalink
XDR integrations - adding terminate commands (#35226)
Browse files Browse the repository at this point in the history
* adding command

* Ciac 10544 rasterize handle regression regarding integration option parameter (#34695)

* Added external last updated time incident field to the commontypes (#35004)

* Added external last updated time incident field to the commontypes

* RN

* fomated the incident field

* RN modified

* changed from verison

* RN

* commit

* unsearchable true

* HPE switch marketplace (#35201)

* Updated the MP to support only the right one

* Update rn

* Revert "Revert "[Marketplace Contribution] FTP"" (#35200)

* Revert "Revert "[Marketplace Contribution] FTP (#34659) (#35177)" (#35199)"

This reverts commit c34a2a4.

* added noqa

---------

Co-authored-by: RotemAmit <ramit@paloaltonetworks.com>

* Update PaloAltoNetworks_Cortex_XDR_Incident_Sync_README.md (#35181)

* Update PaloAltoNetworks_Cortex_XDR_Incident_Sync_README.md

* Update Packs/CortexXDR/Playbooks/PaloAltoNetworks_Cortex_XDR_Incident_Sync_README.md

Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com>

---------

Co-authored-by: Mai Morag <81917647+maimorag@users.noreply.github.com>

* [SplunkPy] Update the README Troubleshooting (#35208)

* [SplunkPy] Update the Troubleshooting

* Update Packs/SplunkPy/Integrations/SplunkPy/README.md

Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com>

* Update Packs/SplunkPy/Integrations/SplunkPy/README.md

Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com>

---------

Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com>

* Align dbot output context path and IN124 problematic packs (#35136)

* import problematic packs

* update

* changes

* import problematic packs

* update dockers

* update dockers

* added rns

* reverts

* update dockers

* cr fixes

* fix ComonServerPython docstring (#35197)

* fix ComonServerPython docstring

* RN

* Prevent changing infra files (#35209)

* demisto class for all (#35211)

* New pack for CVE-2024-6387 (#35220)

* New pack for CVE-2024-6387

* exclude-known-url

* adjust the playbook and pack readme

* adjust the playbook and pack readme

---------

Co-authored-by: Chanan Welt <cwelt@paloaltonetworks.com>

* Fix roles in common playbooks data collection task (#35133)

* Fixed an issue with the data collection tasks to send emails to the corresponding roles in XSIAM (Investigator) and XSOAR (Analyst).

* RN

* Removed administrator role from the data collection tasks

* udpated RN

* Recorded Future Intelligence Cloud CIAC - 10390 (#35030)

* Creating modeling rules

* Updating schema

* Removing url portal link

* Adding release notes and test data

* fixed test pb (#35221)

* Switch netutils (#34874)

* update image

* bump image

* Update Packs/ProofpointEmailSecurity/ReleaseNotes/1_0_2.md

* Update Packs/ProofpointEmailSecurity/Integrations/ProofpointEmailSecurityEventCollector/ProofpointEmailSecurityEventCollector.yml

* updated the classifier and layout of the qradar integration (#35222)

* updated the classifier and layout of the qradar integration

* added the release notes

* commit

* RN

* improved implementation of IsIncidentPartOfCampaign (#33954)

* improved implementation of IsIncidentPartOfCampaign

* was found

* docker update

* skip none string

* Zerofox/add cac data (#35227)

* Zerofox/add cac data (#35183)

* add compromised credentials command (#138)

* fix mypy check and tests

* Fix yml file format

* Add period to yaml description

* Include PR comments

- fix release notes comment
- add unit test
- format code

* update docker

* update RN

---------

Co-authored-by: Diego Ramirez R <dramirez@zerofox.com>
Co-authored-by: ipolishuk <ipolishuk@paloaltonetworks.com>

* Fixed CortexCoreIR http_request (#35206)

* fixed xpanse

* add RN

* fixed

* adding rn

* fix test

* fix test

* fix testcommonserver pyton

* fix unit tests and revert changes in demistomock

* add xplanatory docstring

* Bump pack from version Base to 1.34.24.

* adding memory threshold to incident enrichment

---------

Co-authored-by: sapirshuker <sshuker@paloaltonetworks.com>
Co-authored-by: Content Bot <bot@demisto.com>

* Azure SQL Management - Client Credentials  (#35175)

* added client credentials flow - working

* updated readme and description

* changed to default value for token_retrieval_url

* created release notes and run pre commit

* changed redme and description after code review

* updated docker image

* changed some mistakes in readme

* changed some mistakes in discription

---------

Co-authored-by: noy <nodavidi.paloaltonetworks.com>

* Azure waf client credentials (#35182)

* changed yml file

* added client credentials to py

* added client credentials to py

* added release note

* changed readme and description for client credentials

* run pre commit

* updated docker image

* changed some mistakes in readme

* changed some mistakes in discription

---------

Co-authored-by: noy <nodavidi.paloaltonetworks.com>

* Update integration logo (#35112) (#35225)

updated integration logo to align with Prisma Cloud V2

Co-authored-by: epartington <epartington@users.noreply.github.com>
Co-authored-by: Danny Fried <dfried@paloaltonetworks.com>

* Azure devops client credentials (#35034)

* changed the py file to match client credentials

* changed the yml file to match client cre4dentials

* changed the scope for client credentails

* changed the scope

* py

* getting 203 error from api

* made the final changes for client credentials

* changed description

* changed some description and added client credentials for README

* ran precommit and created release nores

* added global var for scope

* fixed pre commit

* made changes in readme and in description after doc review

* removed in description and in readme 'using cortex xsoar azure app'

* changed to default value for token_retrieval_url

* changed condition for scope

* changed test test_generate_login_urlplaybook to match the new scope

* changes cope global name

* updated docker image

* deleted the word Demisto - not relevant

* changed docker image and removed demisto word from description

---------

Co-authored-by: noy <nodavidi.paloaltonetworks.com>

* SplunkPy:get drilldown search in correct format (#35162)

* fix + RN + test

* RN

* fix ruff

* CR changes

* fix pre commit

* CR changes

* [MicrosoftAzureStorageApiModule] fixed token to start with '?' (#35223)

* fixed token to be with ?

* RN

* pre commit and docker

* fixed test AzureStorageTable_test.py

* fixed test AzureStorageQueue_test.py

* fixed test AzureStorageFileShare_test.py

* fixed test AzureStorageContainer_test.py

---------

Co-authored-by: okarkkatz <okarkkatz@paloaltonetworks.com>

* check

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix unit test

* pre-commit

* fix

* removing arg

* adding failed on status

* adding RN and docs

* unit test

* unit tests

* fix

* fix

* fix

* fix

* pre-commit

* Update Packs/ApiModules/Scripts/CoreIRApiModule/CoreIRApiModule.py

Co-authored-by: EyalPintzov <91007713+eyalpalo@users.noreply.github.com>

* Update Packs/ApiModules/Scripts/CoreIRApiModule/CoreIRApiModule.py

Co-authored-by: EyalPintzov <91007713+eyalpalo@users.noreply.github.com>

* add unit tests

* cr

* fix

* fix

* fixes

* fixes

* fix unit tests

* fix unit tests

* fix

* Apply suggestions from code review

Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com>

* fix

* fix

* fix

---------

Co-authored-by: ilaredo <166304750+ilaredo@users.noreply.github.com>
Co-authored-by: omerKarkKatz <95565843+omerKarkKatz@users.noreply.github.com>
Co-authored-by: Shelly Tzohar <45915502+Shellyber@users.noreply.github.com>
Co-authored-by: Dan Tavori <38749041+dantavori@users.noreply.github.com>
Co-authored-by: RotemAmit <ramit@paloaltonetworks.com>
Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com>
Co-authored-by: Menachem Weinfeld <90556466+mmhw@users.noreply.github.com>
Co-authored-by: Yuval Hayun <70104171+YuvHayun@users.noreply.github.com>
Co-authored-by: Moshe Eichler <78307768+MosheEichler@users.noreply.github.com>
Co-authored-by: dorschw <81086590+dorschw@users.noreply.github.com>
Co-authored-by: Ben Melamed <bmelamed@paloaltonetworks.com>
Co-authored-by: Chanan Welt <cwelt@paloaltonetworks.com>
Co-authored-by: Sasha Sokolovich <88268646+ssokolovich@users.noreply.github.com>
Co-authored-by: ellopez777 <159898322+ellopez777@users.noreply.github.com>
Co-authored-by: Judah Schwartz <JudahSchwartz@users.noreply.github.com>
Co-authored-by: content-bot <55035720+content-bot@users.noreply.github.com>
Co-authored-by: Diego Ramirez R <dramirez@zerofox.com>
Co-authored-by: ipolishuk <ipolishuk@paloaltonetworks.com>
Co-authored-by: sapirshuker <sshuker@paloaltonetworks.com>
Co-authored-by: Content Bot <bot@demisto.com>
Co-authored-by: noydavidi <77931201+noydavidi@users.noreply.github.com>
Co-authored-by: epartington <epartington@users.noreply.github.com>
Co-authored-by: Danny Fried <dfried@paloaltonetworks.com>
Co-authored-by: Israel Lappe <79846863+ilappe@users.noreply.github.com>
Co-authored-by: Binat Ziser <89336697+bziser@users.noreply.github.com>
Co-authored-by: okarkkatz <okarkkatz@paloaltonetworks.com>
Co-authored-by: EyalPintzov <91007713+eyalpalo@users.noreply.github.com>
  • Loading branch information
1 parent 276838d commit 0ca66e1
Show file tree
Hide file tree
Showing 12 changed files with 473 additions and 6 deletions.
137 changes: 134 additions & 3 deletions Packs/ApiModules/Scripts/CoreIRApiModule/CoreIRApiModule.py
Original file line number Diff line number Diff line change
Expand Up @@ -1572,6 +1572,52 @@ def remove_user_role(self, user_emails: list[str]) -> dict[str, dict[str, str]]:
}},
)

def terminate_on_agent(self,
url_suffix_endpoint: str,
id_key: str,
id_value: str,
agent_id: str,
process_name: Optional[str],
incident_id: Optional[str]) -> dict[str, dict[str, str]]:
"""
Terminate a specific process or a the causality on an agent.
:type url_suffix_endpoint: ``str``
:param agent_id: The endpoint of the command(terminate_causality or terminate_process).
:type agent_id: ``str``
:param agent_id: The ID of the agent.
:type id_key: ``str``
:param id_key: The key name ID- causality_id or process_id.
:type id_key: ``str``
:param id_key: The ID data- causality_id or process_id.
:type process_name: ``Optional[str]``
:param process_name: The name of the process. Optional.
:type incident_id: ``Optional[str]``
:param incident_id: The ID of the incident. Optional.
:return: The response from the API.
:rtype: ``dict[str, dict[str, str]]``
"""
request_data: Dict[str, Any] = {
"agent_id": agent_id,
id_key: id_value,
}
if process_name:
request_data["process_name"] = process_name
if incident_id:
request_data["incident_id"] = incident_id
response = self._http_request(
method='POST',
url_suffix=f'/endpoints/{url_suffix_endpoint}/',
json_data={"request_data": request_data},
)
return response.get('reply')


class AlertFilterArg:
def __init__(self, search_field: str, search_type: Optional[str], arg_type: str, option_mapper: dict = None):
Expand Down Expand Up @@ -1651,7 +1697,8 @@ def run_polling_command(client: CoreClient,
results_function: Callable,
polling_field: str,
polling_value: List,
stop_polling: bool = False) -> CommandResults:
stop_polling: bool = False,
values_raise_error: List = []) -> CommandResults:
"""
Arguments:
args: args
Expand All @@ -1664,6 +1711,7 @@ def run_polling_command(client: CoreClient,
polling_value: list of values of the polling_field we want to check. The list can contain values to stop or
continue polling on, not both.
stop_polling: True - polling_value stops the polling. False - polling_value does not stop the polling.
values_raise_error: list of polling values that require raising an error.
Return:
command_results(CommandResults)
Expand Down Expand Up @@ -1708,6 +1756,8 @@ def run_polling_command(client: CoreClient,
result = outputs_result_func.get(polling_field) if isinstance(outputs_result_func, dict) else \
outputs_result_func[0].get(polling_field)
cond = result not in polling_value if stop_polling else result in polling_value
if values_raise_error and result in values_raise_error:
raise DemistoException(f"The command {cmd} failed. Received status {result}")
if cond:
# schedule next poll
polling_args = {
Expand Down Expand Up @@ -1906,7 +1956,7 @@ def endpoint_scan_command(client: CoreClient, args) -> CommandResults:
def action_status_get_command(client: CoreClient, args) -> CommandResults:
action_id_list = argToList(args.get('action_id', ''))
action_id_list = [arg_to_int(arg=item, arg_name=str(item)) for item in action_id_list]

demisto.debug(f'action_status_get_command {action_id_list=}')
result = []
for action_id in action_id_list:
data = client.action_status_get(action_id)
Expand All @@ -1915,7 +1965,7 @@ def action_status_get_command(client: CoreClient, args) -> CommandResults:
result.append({
'action_id': action_id,
'endpoint_id': endpoint_id,
'status': status
'status': status,
})

return CommandResults(
Expand Down Expand Up @@ -4403,3 +4453,84 @@ def get_incidents_command(client, args):
},
raw_incidents
)


def terminate_process_command(client, args) -> CommandResults:
"""
AVAILABLE ONLY TO XDR3.12 / XSIAM2.4
Terminate the process command for a specific agent and instance IDs.
:type client: ``Client``
:param client: The client to use for making API calls.
:type args: ``Dict[str, Any]``
:param args: The arguments for the command.
:return: The results of the command.
:rtype: ``CommandResults``
"""
agent_id = args.get('agent_id')
instance_ids = argToList(args.get('instance_id'))
process_name = args.get('process_name')
incident_id = args.get('incident_id')
replies: List[Dict[str, Any]] = []
for instance_id in instance_ids:
reply_per_instance_id = client.terminate_on_agent(
url_suffix_endpoint='terminate_process',
id_key='instance_id',
id_value=instance_id,
agent_id=agent_id,
process_name=process_name,
incident_id=incident_id
)
action_id = reply_per_instance_id.get("group_action_id")
demisto.debug(f'Action terminate process succeeded with action_id={action_id}')
replies.append({"action_id": action_id})

return CommandResults(
readable_output=tableToMarkdown(f'Action terminate process created on instance ids: {", ".join(instance_ids)}', replies),
outputs={
f'{args.get("integration_context_brand", "CoreApiModule")}'
f'.TerminateProcess(val.actionId && val.actionId == obj.actionId)': replies},
raw_response=replies
)


def terminate_causality_command(client, args) -> CommandResults:
"""
AVAILABLE ONLY TO XDR3.12 / XSIAM2.4
Terminate the causality command for a specific agent and causality IDs.
:type client: ``Client``
:param client: The client to use for making API calls.
:type args: ``Dict[str, Any]``
:param args: The arguments for the command.
:return: The results of the command.
:rtype: ``CommandResults``
"""
agent_id = args.get('agent_id')
causality_ids = argToList(args.get('causality_id'))
process_name = args.get('process_name')
incident_id = args.get('incident_id')
replies: List[Dict[str, Any]] = []
for causality_id in causality_ids:
reply_per_instance_id = client.terminate_on_agent(
url_suffix_endpoint='terminate_causality',
id_key='causality_id',
id_value=causality_id,
agent_id=agent_id,
process_name=process_name,
incident_id=incident_id
)
action_id = reply_per_instance_id.get("group_action_id")
demisto.debug(f'Action terminate process succeeded with action_id={action_id}')
replies.append({"action_id": action_id})

return CommandResults(
readable_output=tableToMarkdown(f'Action terminate causality created on {",".join(causality_ids)}', replies),
outputs={f'{args.get("integration_context_brand", "CoreApiModule")}.TerminateProcess(val.actionId == obj.actionId)':
replies},
raw_response=replies
)
113 changes: 113 additions & 0 deletions Packs/ApiModules/Scripts/CoreIRApiModule/CoreIRApiModule_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4228,3 +4228,116 @@ def test_request_for_bin_file_via_demisto_call(mocker, allow_bin_response):
assert res == test_bin_data
except DemistoException as e:
assert f'{ALLOW_BIN_CONTENT_RESPONSE_SERVER_VERSION}-{ALLOW_BIN_CONTENT_RESPONSE_BUILD_NUM}' in str(e)


def test_terminate_process_command(mocker):
"""
Given:
- An XSIAM machine with a build version that supports demisto._apiCall() with RBAC validations.
- instance_id_1
- instance_id_2
- agent_id
When:
- Calling the terminate_process_command method.
Then:
- case 1 - Make sure the response are as expected (action_id).
"""
from CoreIRApiModule import CoreClient, terminate_process_command
client = CoreClient(
base_url=f'{Core_URL}/public_api/v1', headers={},
)

mocker.patch("CoreIRApiModule.FORWARD_USER_RUN_RBAC", new=True)
mocker.patch.object(demisto, "_apiCall", side_effect=[
{'name': '/api/webapp/public_api/v1/endpoints/terminate_process',
'status': 200,
'data': json.dumps({'reply': {'group_action_id': 1}})},
{'name': '/api/webapp/public_api/v1/endpoints/terminate_process',
'status': 200,
'data': json.dumps({'reply': {'group_action_id': 2}})}
]
)

result = terminate_process_command(client=client, args={'agent_id': '1', 'instance_id': ['instance_id_1', 'instance_id_2']})
assert result.readable_output == ('### Action terminate process created on instance ids:'
' instance_id_1, instance_id_2\n|action_id|\n|---|\n| 1 |\n| 2 |\n')
assert result.raw_response == [{'action_id': 1}, {'action_id': 2}]


def test_terminate_causality_command(mocker):
"""
Given:
- An XSIAM machine with a build version that supports demisto._apiCall() with RBAC validations.
- causality_id
- agent_id
When:
- Calling the terminate_causality_command method.
Then:
- case 1 - Make sure the response are as expected (action_id).
"""
from CoreIRApiModule import CoreClient, terminate_causality_command
client = CoreClient(
base_url=f'{Core_URL}/public_api/v1', headers={},
)

mocker.patch("CoreIRApiModule.FORWARD_USER_RUN_RBAC", new=True)
mocker.patch.object(demisto, "_apiCall", side_effect=[
{'name': '/api/webapp/public_api/v1/endpoints/terminate_causality',
'status': 200,
'data': json.dumps({'reply': {'group_action_id': 1}})},
{'name': '/api/webapp/public_api/v1/endpoints/terminate_causality',
'status': 200,
'data': json.dumps({'reply': {'group_action_id': 2}})}
]
)

result = terminate_causality_command(client=client, args={'agent_id': '1', 'causality_id': [
'causality_id_1', 'causality_id_2']})
assert result.readable_output == ('### Action terminate causality created on causality_id_1,'
'causality_id_2\n|action_id|\n|---|\n| 1 |\n| 2 |\n')
assert result.raw_response == [{'action_id': 1}, {'action_id': 2}]


def test_run_polling_command_values_raise_error(mocker):
"""
Given -
- run_polling_command arguments.
-
When -
- Running the run_polling_command
Then
- Make sure that an error is raised with the correct output.
"""
from CoreIRApiModule import run_polling_command
from CommonServerPython import DemistoException, ScheduledCommand
from unittest.mock import Mock

polling_args = {
'endpoint_ids': '1', 'command_decision_field': 'action_id', 'action_id': '1', 'hide_polling_output': True
}
mocker.patch.object(ScheduledCommand, 'raise_error_if_not_supported', return_value=None)
client = Mock()
mock_command_results = Mock()
mock_command_results.raw_response = {"status": "TIMEOUT"}
mock_command_results.return_value = mock_command_results
client.get_command_results.return_value = mock_command_results

with pytest.raises(DemistoException) as e:
run_polling_command(client=client,
args=polling_args,
cmd="core-terminate-causality",
command_function=Mock(),
command_decision_field="action_id",
results_function=mock_command_results,
polling_field="status",
polling_value=["PENDING",
"IN_PROGRESS",
"PENDING_ABORT"],
values_raise_error=["FAILED",
"TIMEOUT",
"ABORTED",
"CANCELED"]
)
assert str(e.value) == 'The command core-terminate-causality failed. Received status TIMEOUT'
41 changes: 41 additions & 0 deletions Packs/Core/Integrations/CortexCoreIR/CortexCoreIR.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
'core-get-cmd-analytics-prevalence': 'cmd',
}

TERMINATE_BUILD_NUM = '1398786'
TERMINATE_SERVER_VERSION = '8.9.0'


class Client(CoreClient):

Expand Down Expand Up @@ -471,6 +474,44 @@ def main(): # pragma: no cover
elif command == 'core-get-incidents':
return_outputs(*get_incidents_command(client, args))

elif command == 'core-terminate-process':
if not is_demisto_version_ge(version=TERMINATE_SERVER_VERSION,
build_number=TERMINATE_BUILD_NUM):
raise DemistoException('This command is only available for XSIAM 2.4')
return_results(run_polling_command(client=client,
args=args,
cmd="core-terminate-process",
command_function=terminate_process_command,
command_decision_field="action_id",
results_function=action_status_get_command,
polling_field="status",
polling_value=["PENDING",
"IN_PROGRESS",
"PENDING_ABORT"
],
values_raise_error=["FAILED",
"TIMEOUT",
"ABORTED",
"CANCELED"]))

elif command == 'core-terminate-causality':
if not is_demisto_version_ge(version=TERMINATE_BUILD_NUM, build_number=TERMINATE_BUILD_NUM):
raise DemistoException("This command is only available for XSIAM 2.4")
return_results(run_polling_command(client=client,
args=args,
cmd="core-terminate-causality",
command_function=terminate_causality_command,
command_decision_field="action_id",
results_function=action_status_get_command,
polling_field="status",
polling_value=["PENDING",
"IN_PROGRESS",
"PENDING_ABORT"],
values_raise_error=["FAILED",
"TIMEOUT",
"ABORTED",
"CANCELED"]
))
elif command in PREVALENCE_COMMANDS:
return_results(handle_prevalence_command(client, command, args))

Expand Down
Loading

0 comments on commit 0ca66e1

Please sign in to comment.