Trend Micro Vision One V3

TrendAI Vision One™ is a purpose-built threat defense platform that provides added value and new benefits beyond XDR solutions, allowing you to see more and respond faster. Providing deep and broad extended detection and response (XDR) capabilities that collect and automatically correlate data across multiple security layers—email, endpoints, servers, cloud workloads, and networks—TrendAI Vision One™ prevents the majority of attacks with automated protection.

Data Enrichment & Threat Intelligence · TrendAI Vision One™

Details

IDTrend Micro Vision One V3
ProviderTrendAI™
CategoryData Enrichment & Threat Intelligence
From Version6.5.0
Docker Imagedemisto/pytmv1:0.11.0.10133006
Supported ModulesAgentix XSIAM

README

TrendAI Vision One™ is a purpose-built threat defense platform that provides added value and new benefits beyond XDR solutions, allowing you to see more and respond faster. Providing deep and broad extended detection and response (XDR) capabilities that collect and automatically correlate data across multiple security layers—email, endpoints, servers, cloud workloads, and networks—TrendAI Vision One™ prevents the majority of attacks with automated protection. V3 version of the app includes everything that the previous app had and adds more capabilities. It leverages V3 of TrendAI™ APIs and introduces further ability to manage domain accounts with addition of 4 domain account actions for enabling/disabling user account, forcing sign-out and password resets for compromised accounts. This app is in active development. We previously added 4 actions, one to fetch email activity data with count, one to fetch endpoint activity data with count and an action to restore a quarantined email message. In this release we have added 6 new custom script actions allowing the user to fetch a list of available custom scripts in XDR portal, ability to run a custom script on a specified endpoint, capacity to add, download, update and delete a custom script from XDR portal.
This integration was integrated and tested with version 3 API of TrendAI Vision One™.

Configure TrendAI Vision One™ v3 in Cortex

Parameter Description Required
API URL (e.g. https://api.xdr.trendmicro.com) The base url for the TrendAI Vision One™ API True
API Key The API token to access data True
Fetch incidents   False
Incidents Fetch Interval   False
Incident type   False
Sync On First Run (days)   False
Use system proxy settings   False
Trust any certificate (not secure)   False
Source Reliability Reliability of the source providing the intelligence data. False
Severity Severity of the incident being fetched. False
Incident Mirroring Direction Choose the direction to mirror incidents. Outgoing mirrors XSOAR changes to Vision One alerts. Cortex XSOAR only parameter. False

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

trendmicro-visionone-enable-user-account


Allows the user to sign in to new application and browser sessions. Supported IAM systems -> Azure AD and Active Directory (on-premises).

Base Command

trendmicro-visionone-enable-user-account

Input

Argument Name Description Required
account_identifiers List of object(s) containing account_name and optional description. e.g. [{“account_name”:”some-account”,”description”:”enable”}]. Required

Context Output

Path Type Description
VisionOne.User_Account.status number Status of request to enable user account.
VisionOne.User_Account.task_id string Task ID generated after enabling user account.

trendmicro-visionone-disable-user-account


Signs the user out of all active application and browser sessions, and prevents the user from signing in any new session. Supported IAM systems -> Azure AD and Active Directory (on-premises).

Base Command

trendmicro-visionone-disable-user-account

Input

Argument Name Description Required
account_identifiers List of object(s) containing account_name and optional description. e.g. [{“account_name”:”some-account”,”description”:”disable”}]. Required

Context Output

Path Type Description
VisionOne.User_Account.status number Status of request to disable user account.
VisionOne.User_Account.task_id string Task ID generated after disabling user account.

trendmicro-visionone-force-signout


Signs the user out of all active application and browser sessions. Supported IAM systems -> Azure AD.

Base Command

trendmicro-visionone-force-signout

Input

Argument Name Description Required
account_identifiers List of object(s) containing account_name and optional description. e.g. [{“account_name”:”some-account”,”description”:”sign-out”}]. Required

Context Output

Path Type Description
VisionOne.Force_Sign_Out.status number Status of request to sign out user.
VisionOne.Force_Sign_Out.task_id string Task ID generated after signing out user.

trendmicro-visionone-force-password-reset


Signs the user out of all active application and browser sessions, and forces the user to create a new password during the next sign-in attempt. Supported IAM systems -> Azure AD and Active Directory (on-premises).

Base Command

trendmicro-visionone-force-password-reset

Input

Argument Name Description Required
account_identifiers List of object(s) containing account_name and optional description. e.g. [{“account_name”:”some-account”,”description”:”reset”}]. Required

Context Output

Path Type Description
VisionOne.Force_Password_Reset.status number Status of request to reset user password.
VisionOne.Force_Password_Reset.task_id string Task ID generated after resetting user password.

trendmicro-visionone-add-to-block-list


Adds a domain, ip, file_sha1, url, sender_mail_address to the User-Defined Suspicious Objects List, which blocks the objects on subsequent detections.

Base Command

trendmicro-visionone-add-to-block-list

Input

Argument Name Description Required
block_objects List of object(s) made up of object_type (domain,ip,file_sha1,url,sender_mail_address), object_value and optional description. e.g. [{“object_type”:”domain”,”object_value”:”www.yahoo.com”}]. Required

Context Output

Path Type Description
VisionOne.BlockList.status number Status of adding domain, ip, file_sha1, url, sender_mail_address to the User-Defined Suspicious Objects List.
VisionOne.BlockList.task_id string Task ID generated after adding domain, ip, file_sha1, url, sender_mail_address to the User-Defined Suspicious Objects List.

trendmicro-visionone-remove-from-block-list


Removes a domain, ip, file_sha1, url, sender_mail_address from the User-Defined Suspicious Objects List.

Base Command

trendmicro-visionone-remove-from-block-list

Input

Argument Name Description Required
block_objects List of object(s) made up of object_type (domain,ip,file_sha1,url,sender_mail_address), object_value and optional description. e.g. [{“object_type”:”domain”,”object_value”:”www.yahoo.com”}]. Required

Context Output

Path Type Description
VisionOne.BlockList.status number Status of removing domain, ip, file_sha1, url, sender_mail_address that was added to the User-Defined Suspicious Objects List from block list.
VisionOne.BlockList.task_id string Task ID generated after removing domain, ip, file_sha1, url, sender_mail_address from the User-Defined Suspicious Objects List.

trendmicro-visionone-quarantine-email-message


Moves a message from a mailbox to the quarantine folder.

Base Command

trendmicro-visionone-quarantine-email-message

Input

Argument Name Description Required
email_identifiers List of object(s) containing message_id (<mailMsgId>), mailbox (mailbox ID) and description or unique_id (msgUuid) and optional description from TrendAI Vision One™ message activity data. e.g. [{“message_id”:”xasbjAgs72912-asdjnaj”,”mailbox”:”mailbox-name”,”description”:”quarantine”}]. Required

Context Output

Path Type Description
VisionOne.Email.status number Status of moving a message from a mailbox to the quarantine folder.
VisionOne.Email.task_id string Task ID generated after moving a message from a mailbox to the quarantine folder.

trendmicro-visionone-delete-email-message


Deletes a message from a mailbox.

Base Command

trendmicro-visionone-delete-email-message

Input

Argument Name Description Required
email_identifiers List of object(s) containing message_id (<mailMsgId>), mailbox (mailbox ID) and description or unique_id (msgUuid) and optional description from TrendAI Vision One™ message activity data. e.g. [{“message_id”:”xasbjAgs72912-asdjnaj”,”mailbox”:”mailbox-name”,”description”:”disable”:”delete”}]. Required

Context Output

Path Type Description
VisionOne.Email.status number Status of deleting a message from a mailbox.
VisionOne.Email.task_id string Task ID generated after deleting a message from a mailbox.

trendmicro-visionone-restore-email-message


Restores a quarantined message. Deleted messages cannot be restored.

Base Command

trendmicro-visionone-restore-email-message

Input

Argument Name Description Required
email_identifiers List of object(s) containing message_id (<mailMsgId>), mailbox (mailbox ID) and description or unique_id (msgUuid) and optional description from TrendAI Vision One™ message activity data. e.g. [{“message_id”:”xasbjAgs72912-asdjnaj”,”mailbox”:”mailbox-name”}]. Required

Context Output

Path Type Description
VisionOne.Email.status number Status of restoring a message.
VisionOne.Email.task_id string Task ID generated after restoring a message.

trendmicro-visionone-isolate-endpoint


Disconnects an endpoint from the network (but allows communication with the managing TrendAI™ product).

Base Command

trendmicro-visionone-isolate-endpoint

Input

Argument Name Description Required
endpoint_identifiers List of object(s) containing endpoint (hostname) and description or agent_guid and description. e.g. [{“endpoint”:”test-endpoint”,”description”:”isolate endpoint”}]. Required

Context Output

Path Type Description
VisionOne.Endpoint_Connection.status number Status of isolating endpoint(s).
VisionOne.Endpoint_Connection.task_id string Task ID generated after isolating endpoint(s).

trendmicro-visionone-restore-endpoint-connection


Restores network connectivity to an endpoint that applied the “isolate endpoint” action.

Base Command

trendmicro-visionone-restore-endpoint-connection

Input

Argument Name Description Required
endpoint_identifiers List of object(s) containing endpoint (hostname) and description or agent_guid and description. e.g. [{“endpoint”:”test-endpoint”,”description”:”restore endpoint”}]. Required

Context Output

Path Type Description
VisionOne.Endpoint_Connection.status number Status of restoring endpoint(s).
VisionOne.Endpoint_Connection.task_id string Task ID generated after restoring endpoint(s).

trendmicro-visionone-add-objects-to-exception-list


Adds domain, ip, url, file_sha1, file_sha256, sender_mail_address to the Exception List and prevents these objects from being added to the Suspicious Object List.

Base Command

trendmicro-visionone-add-objects-to-exception-list

Input

Argument Name Description Required
block_objects List of object(s) consisting of object_type (domain,ip,url,file_sha1,file_sha256,sender_mail_address), object_value and description. e.g. [{“object_type”:”ip”,”object_value”:”5.5.5.5”}, {“object_type”:”domain”,”object_value”:”www.yahoo.com”}]. Required

Context Output

Path Type Description
VisionOne.Exception_List.message string Success or fail response message.
VisionOne.Exception_List.multi_response.status number Status of adding item(s) to exception list.
VisionOne.Exception_List.multi_response.task_id string Task ID generated after adding item(s) to exception list.
VisionOne.Exception_List.total_items number Count of total items present in exception list.

trendmicro-visionone-delete-objects-from-exception-list


Deletes domain, ip, url, file_sha1, file_sha256, sender_mail_address from the Exception List.

Base Command

trendmicro-visionone-delete-objects-from-exception-list

Input

Argument Name Description Required
block_objects List of object(s) consisting of object_type (domain,ip,url,file_sha1,file_sha256,sender_mail_address), object_value and description. e.g. [{“object_type”:”ip”,”object_value”:”5.5.5.5”,”description”:”exception list”}]. Required

Context Output

Path Type Description
VisionOne.Exception_List.message string Success or fail response message.
VisionOne.Exception_List.multi_response.status number status code of response.
VisionOne.Exception_List.multi_response.task_id string Task ID generated after removing item(s) from exception list.
VisionOne.Exception_List.total_items number count of item present in exception list.

trendmicro-visionone-add-objects-to-suspicious-list


Adds domain, ip, url, file_sha1, file_sha256, sender_mail_address to the Suspicious Object List.

Base Command

trendmicro-visionone-add-objects-to-suspicious-list

Input

Argument Name Description Required
block_objects List of object(s) consisting of object_type (domain,ip,url,file_sha1,file_sha256,sender_mail_address), object_value, scan_action, risk_level, expiry_days and description. e.g. [{“object_type”:”ip”,”object_value”:”5.5.5.5”,”scan_action”:”block”,”risk_level”:”medium”,”expiry_days”:7}]. Required

Context Output

Path Type Description
VisionOne.Suspicious_List.message string Success or fail response message.
VisionOne.Suspicious_List.multi_response.status number Status of request to add item(s) to suspicious list.
VisionOne.Suspicious_List.multi_response.task_id string Task ID generated after adding item(s) to suspicious list.
VisionOne.Suspicious_List.total_items number Count of total items present in suspicious object list.

trendmicro-visionone-delete-objects-from-suspicious-list


Deletes domain, ip, url, file_sha1, file_sha256, sender_mail_address from the Suspicious Object List.

Base Command

trendmicro-visionone-delete-objects-from-suspicious-list

Input

Argument Name Description Required
block_objects List of object(s) consisting of object_type (domain,ip,url,file_sha1,file_sha256,sender_mail_address) and object_value. e.g. [{“object_type”:”ip”,”object_value”:”5.5.5.5”}]. Required

Context Output

Path Type Description
VisionOne.Suspicious_List.message string Success or fail response message.
VisionOne.Suspicious_List.multi_response.status number Status of request to remove item(s) from suspicious object list.
VisionOne.Suspicious_List.multi_response.task_id string Task ID generated after removing item(s) from suspicious object list.
VisionOne.Suspicious_List.total_items number Count of total items present in suspicious object list.

trendmicro-visionone-get-endpoint-info


Retrieves information about a specific endpoint.

Base Command

trendmicro-visionone-get-endpoint-info

Input

Argument Name Description Required
endpoint Filter (A dictionary object with key/value used to create a query string) for retrieving a subset of endpoint information e.g. endpoint={“endpointName”:”test-endpoint1”, “ip”:”52.72.139.96”}. Multiple endpoints can be queried but unique keys need to be supplied (e.g. endpointName, ip, etc.). For complete list of keys check (https://automation.trendmicro.com/xdr/api-v3#tag/Search/paths/~1v3.0~1eiqs~1endpoints/get). Required
query_op Conditional operator used to build request that allows user to retrieve a subset of collected endpoint(s). Possible values: and/or. Ex. or: the results retrieved will contain information for endpoint(s) matching endpointName OR ip. and: results retrieved will contain endpoint information for endpoint matching endpointName AND ip. Required

Context Output

Path Type Description
VisionOne.Endpoint_Info.agent_guid string Agent Guid of the endpoint.
VisionOne.Endpoint_Info.login_account.value string Account currently logged on to the endpoint.
VisionOne.Endpoint_Info.endpoint_name.value string Hostname of the endpoint queried.
VisionOne.Endpoint_Info.mac_address.value string MAC address of the endpoint queried.
VisionOne.Endpoint_Info.ip.value string IP address of the endpoint queried.
VisionOne.Endpoint_Info.os_name string Operating System name of the endpoint queried.
VisionOne.Endpoint_Info.os_version string Operating System version of the endpoint queried.
VisionOne.Endpoint_Info.os_description string Description of the Operating System of the endpoint queried.
VisionOne.Endpoint_Info.product_code string Product code of the TrendAI™ product running on the endpoint.
VisionOne.Endpoint_Info.installed_product_codes string Product code of the TrendAI™ product installed on the endpoint.
VisionOne.Endpoint_Info.component_update_policy string The update policy for the module/pattern of the agent installed on the endpoint.
VisionOne.Endpoint_Info.component_update_status string The status of the module/pattern updates of the agent installed on the endpoint.
VisionOne.Endpoint_Info.component_version string The agent component version.
VisionOne.Endpoint_Info.policy_name string The name of a policy for an event.
VisionOne.Endpoint_Info.protection_manager string The name of your protection manager.

trendmicro-visionone-get-endpoint-activity-data


Displays search results from the Endpoint Activity Data source that match the parameters provided.

Base Command

trendmicro-visionone-get-endpoint-activity-data

Input

Argument Name Description Required
fields Filter (A dictionary object with key/value used to create a query string) for retrieving a subset of endpoint activity data e.g. {“endpointName”:”sample-host”,”dpt”: 443}. Complete list of supported fields (https://automation.trendmicro.com/xdr/api-v3#tag/Search/paths/~1v3.0~1search~1endpointActivities/get). Required
query_op Conditional operator used to build request that allows user to retrieve a subset of collected endpoint activity data. Possible values: and/or. Ex. or: the results retrieved will contain activity data for endpoint(s) matching endpointName OR dpt. and: will contain activity data for endpoint matching endpointName AND dpt. Defaults to and. Optional
start Timestamp in ISO 8601 format that indicates the start of the data retrieval range. If no value is specified, start defaults to 24 hours before the request is made. e.g. start=”2023-10-01T08:00:00Z”. Optional
end Timestamp in ISO 8601 format that indicates the end of the data retrieval time range. If no value is specified, end defaults to the time the request is made. e.g. end=”2023-12-01T08:00:00Z”. Optional
top Number of records displayed on a page. e.g. top=5. Optional
select List of fields to include in the search results. If no fields are specified, the query returns all supported fields. e.g. select=”dpt,dst,endpointHostName”. Optional
fetch_max_count Max results to be fetched by call. Optional
fetch_all Do you want to fetch all matching records or only records matching the top value. Optional

Context Output

Path Type Description
VisionOne.Endpoint_Activity_Data.dpt string Destination port.
VisionOne.Endpoint_Activity_Data.dst string Destination IP address.
VisionOne.Endpoint_Activity_Data.endpoint_guid string endpoint GUID for identity.
VisionOne.Endpoint_Activity_Data.endpoint_host_name string Hostname of the endpoint on which the event was generated.
VisionOne.Endpoint_Activity_Data.endpoint_ip string Endpoint IP address list.
VisionOne.Endpoint_Activity_Data.event_id string ID corresponding to data field mapping.
VisionOne.Endpoint_Activity_Data.event_sub_id string ID corresponding to data field mapping.
VisionOne.Endpoint_Activity_Data.object_integrity_level string ID corresponding to data field mapping.
VisionOne.Endpoint_Activity_Data.object_true_type string ID corresponding to data field mapping.
VisionOne.Endpoint_Activity_Data.object_sub_true_type string ID corresponding to data field mapping.
VisionOne.Endpoint_Activity_Data.win_event_id string ID corresponding to data field mapping.
VisionOne.Endpoint_Activity_Data.event_time string Log collect time utc format.
VisionOne.Endpoint_Activity_Data.event_time_d_t string Log collect time.
VisionOne.Endpoint_Activity_Data.host_name string Hostname of the endpoint on which the event was generated.
VisionOne.Endpoint_Activity_Data.logon_user string Logon user name.
VisionOne.Endpoint_Activity_Data.object_cmd string Command line entry of target process.
VisionOne.Endpoint_Activity_Data.object_file_hash_sha1 string The SHA1 hash of target process image or target file.
VisionOne.Endpoint_Activity_Data.object_file_path string File path location of target process image or target file.
VisionOne.Endpoint_Activity_Data.object_host_name string Server name where Internet event was detected.
VisionOne.Endpoint_Activity_Data.object_ip string IP address of internet event.
VisionOne.Endpoint_Activity_Data.object_ips string IP address list of internet event.
VisionOne.Endpoint_Activity_Data.object_port string The port number used by internet event.
VisionOne.Endpoint_Activity_Data.object_registry_data string The registry value data.
VisionOne.Endpoint_Activity_Data.object_registry_key_handle string The registry key.
VisionOne.Endpoint_Activity_Data.object_registry_value string Registry value name.
VisionOne.Endpoint_Activity_Data.object_signer string Certificate signer of object process or file.
VisionOne.Endpoint_Activity_Data.object_signer_valid string Validity of certificate signer.
VisionOne.Endpoint_Activity_Data.object_user string The owner name of target process / The logon user name.
VisionOne.Endpoint_Activity_Data.os string System.
VisionOne.Endpoint_Activity_Data.parent_cmd string The command line that parent process.
VisionOne.Endpoint_Activity_Data.parent_file_hash_sha1 string The SHA1 hash of parent process.
VisionOne.Endpoint_Activity_Data.parent_file_path string The file path location of parent process.
VisionOne.Endpoint_Activity_Data.process_cmd string The command line used to launch this process.
VisionOne.Endpoint_Activity_Data.process_file_hash_sha1 string The process file sha1.
VisionOne.Endpoint_Activity_Data.process_file_path string The process file path.
VisionOne.Endpoint_Activity_Data.request string Request URL (normally detected by Web Reputation Services).
VisionOne.Endpoint_Activity_Data.search_d_l string Search data lake.
VisionOne.Endpoint_Activity_Data.spt string Source port.
VisionOne.Endpoint_Activity_Data.src string Source IP address.
VisionOne.Endpoint_Activity_Data.src_file_hash_sha1 string Source file sha1.
VisionOne.Endpoint_Activity_Data.src_file_path string Source file path.
VisionOne.Endpoint_Activity_Data.tags string Detected by Security Analytics Engine filters.
VisionOne.Endpoint_Activity_Data.uuid string Log unique identity.

trendmicro-visionone-get-endpoint-activity-data-count


Displays total count of search results from the Endpoint Activity Data source that match the parameters provided.

Base Command

trendmicro-visionone-get-endpoint-activity-data-count

Input

Argument Name Description Required
fields Filter (A dictionary object with key/value used to create a query string) for retrieving endpoint activity data count e.g. {“endpointName”:”sample-host”,”dpt”:443}. Complete list of supported fields (https://automation.trendmicro.com/xdr/api-v3#tag/Search/paths/~1v3.0~1search~1endpointActivities/get). Required
query_op Conditional operator used to build request that allows user to retrieve a count of collected endpoint activity. Possible values: and/or. Ex. or: the results retrieved will contain activity count for endpoint(s) matching endpointName OR dpt. and: the results retrieved will contain activity count for endpoint matching endpointName AND dpt. Defaults to and. Optional
start Timestamp in ISO 8601 format that indicates the start of the data retrieval range. If no value is specified, start defaults to 24 hours before the request is made. e.g. start=”2023-10-01T08:00:00Z”. Optional
end Timestamp in ISO 8601 format that indicates the end of the data retrieval time range. If no value is specified, end defaults to the time the request is made. e.g. end=”2023-12-01T08:00:00Z”. Optional
select List of fields to include in the search results. If no fields are specified, the query returns all supported fields. e.g. select=”dpt,dst,endpointHostName”. Optional

Context Output

Path Type Description
VisionOne.Endpoint_Activity_Data_Count.endpoint_activity_count string Total count for endpoint activity queried.

trendmicro-visionone-get-email-activity-data


Displays search results from the Email Activity Data source that match the parameters provided.

Base Command

trendmicro-visionone-get-email-activity-data

Input

Argument Name Description Required
fields Filter (A dictionary object with key/value used to create a query string) for retrieving a subset of email activity data e.g. {“mailMsgSubject”:”spam”,”mailSenderIp”:”192.169.1.1”}. Complete list of supported fields (https://automation.trendmicro.com/xdr/api-v3#tag/Search/paths/~1v3.0~1search~1emailActivities/get). Required
query_op Conditional operator used to build request that allows user to retrieve a subset of email activity data. Possible values: and/or. Ex. or: the results retrieved will contain activity data for email(s) matching mailMsgSubject OR mailSenderIp. and: the results retrieved will contain activity data for email matching mailMsgSubject AND mailSenderIp. Defaults to and. Optional
start Timestamp in ISO 8601 format that indicates the start of the data retrieval range. If no value is specified, start defaults to 24 hours before the request is made. e.g. start=”2023-10-01T08:00:00Z”. Optional
end Timestamp in ISO 8601 format that indicates the end of the data retrieval time range. If no value is specified, end defaults to the time the request is made. e.g. end=”2023-12-01T08:00:00Z”. Optional
top Number of records displayed on a page. e.g. top=5. Optional
select List of fields to include in the search results. If no fields are specified, the query returns all supported fields. e.g. select=”mailMsgSubject,mailFromAddresses,mailToAddresses”. Optional
fetch_max_count Max results to be fetched by call. Optional
fetch_all Do you want to fetch all matching records or only records matching the top value. Optional

Context Output

Path Type Description
VisionOne.Email_Activity_Data.mail_msg_subject string Subject of the email message.
VisionOne.Email_Activity_Data.mail_msg_id string Internet message ID of the email message.
VisionOne.Email_Activity_Data.msg_uuid string Unique ID of the email message.
VisionOne.Email_Activity_Data.mailbox string Mailbox where the email message is.
VisionOne.Email_Activity_Data.mail_sender_ip string Source IP address of the email message.
VisionOne.Email_Activity_Data.mail_from_addresses string Sender email address of the email message.
VisionOne.Email_Activity_Data.mail_whole_header string Information about the header of the email message.
VisionOne.Email_Activity_Data.mail_to_addresses string A list of recipient email addresses of the email message.
VisionOne.Email_Activity_Data.mail_source_domain string Source domain of the email message.
VisionOne.Email_Activity_Data.search_d_l string Search data lake.
VisionOne.Email_Activity_Data.scan_type string Email activity scan type.
VisionOne.Email_Activity_Data.event_time string Date and time UTC.
VisionOne.Email_Activity_Data.org_id string Unique ID used to identify an organization.
VisionOne.Email_Activity_Data.mail_urls_visible_link string Visible link in email message.
VisionOne.Email_Activity_Data.mail_urls_real_link string Real link in email message.

trendmicro-visionone-get-email-activity-data-count


Displays search results from the Email Activity Data source that match the parameters provided.

Base Command

trendmicro-visionone-get-email-activity-data-count

Input

Argument Name Description Required
fields Filter (A dictionary object with key/value used to create a query string) for retrieving email activity data count e.g. {“mailMsgSubject”:”spam”,”mailSenderIp”:”192.169.1.1”}. Complete list of supported fields (https://automation.trendmicro.com/xdr/api-v3#tag/Search/paths/~1v3.0~1search~1emailActivities/get). Required
query_op Conditional operator used to build request that allows user to retrieve a count of collected email activity. Possible values: and/or. Ex. or: the results retrieved will contain activity count for email(s) matching mailMsgSubject OR mailSenderIp. and: the results retrieved will contain activity count for email matching mailMsgSubject AND mailSenderIp. Defaults to and. Optional
start Timestamp in ISO 8601 format that indicates the start of the data retrieval range. If no value is specified, start defaults to 24 hours before the request is made. e.g. start=”2023-10-01T08:00:00Z”. Optional
end Timestamp in ISO 8601 format that indicates the end of the data retrieval time range. If no value is specified, end defaults to the time the request is made. e.g. end=”2023-12-01T08:00:00Z”. Optional
select List of fields to include in the search results. If no fields are specified, the query returns all supported fields. e.g. select=”mailMsgSubject,mailFromAddresses,mailToAddresses”. Optional

Context Output

Path Type Description
VisionOne.Email_Activity_Data_Count.email_activity_count string Total count of email activity.

trendmicro-visionone-terminate-process


Terminates a process that is running on an endpoint.

Base Command

trendmicro-visionone-terminate-process

Input

Argument Name Description Required
process_identifiers List of object(s) consisting of endpoint (hostname) or agent_guid, file_sha1, filename and description. e.g. [{“endpoint”:”test-endpoint”,”file_sha1”:”fb5608fa03de204a12fe1e9e5275e4a682107471”,”filename”:”test.txt”,”description”:”terminate process”}]. Required

Context Output

Path Type Description
VisionOne.Terminate_Process.status number Status of request to terminate process.
VisionOne.Terminate_Process.task_id string Task Id generated after terminating a process.

trendmicro-visionone-get-file-analysis-status


Retrieves the status of a sandbox analysis submission.

Base Command

trendmicro-visionone-get-file-analysis-status

Input

Argument Name Description Required
task_id task_id from the trendmicro-visionone-submit-file-to-sandbox command output. e.g. task_id=”012e4eac-9bd9-4e89-95db-77e02f75a611”. Required

Context Output

Path Type Description
VisionOne.File_Analysis_Status.id string Submission ID of the file submitted for sandbox analysis.
VisionOne.File_Analysis_Status.status string Response code for the action call.
VisionOne.File_Analysis_Status.action string Action performed on the submitted file.
VisionOne.File_Analysis_Status.error string Error code and message for the submission.
VisionOne.File_Analysis_Status.digest string The hash values of file analyzed.
VisionOne.File_Analysis_Status.created_date_time string Create date time for the sandbox analysis.
VisionOne.File_Analysis_Status.last_action_date_time string Date and time for last action performed on the submission.
VisionOne.File_Analysis_Status.resource_location string Location of the submitted file.
VisionOne.File_Analysis_Status.is_cached string Is the file cached or not (True or False).
VisionOne.File_Analysis_Status.arguments string Arguments for the file submitted.

trendmicro-visionone-get-file-analysis-result


Retrieves the sandbox submission analysis result.

Base Command

trendmicro-visionone-get-file-analysis-result

Input

Argument Name Description Required
report_id report_id of the sandbox submission retrieved from the trendmicro-visionone-get-file-analysis-status command. e.g. report_id=”012e4eac-9bd9-4e89-95db-77e02f75a611”. Required
poll If script should wait until the task is finished before returning the result, enabled by default. poll=true. Possible values are: true, false. Optional
poll_time_sec Maximum time to wait for the result to be available. e.g. poll_time_sec=45. Optional

Context Output

Path Type Description
VisionOne.File_Analysis_Result.id string Report ID for the submission.
VisionOne.File_Analysis_Result.type string Type of object.
VisionOne.File_Analysis_Result.digest string The hash values of file analyzed.
VisionOne.File_Analysis_Result.risk_level string Risk Level of suspicious object.
VisionOne.File_Analysis_Result.analysis_completion_date_time string Analyze time of suspicious object.
VisionOne.File_Analysis_Result.arguments string Arguments for the suspicious object.
VisionOne.File_Analysis_Result.detection_names string Detection name for the suspicious object.
VisionOne.File_Analysis_Result.threat_types string Threat type of the suspicious object.
VisionOne.File_Analysis_Result.true_file_type string File type for the suspicious object.
VisionOne.File_Analysis_Result.DBotScore.Score number The DBot score.
VisionOne.File_Analysis_Result.DBotScore.Vendor string The Vendor name.
VisionOne.File_Analysis_Result.DBotScore.Reliability string The reliability of an intelligence-data source.

trendmicro-visionone-collect-forensic-file


Compresses a file on an endpoint in a password-protected archive and then sends the archive to the XDR service platform.

Base Command

trendmicro-visionone-collect-forensic-file

Input

Argument Name Description Required
collect_files List of object(s) containing endpoint (hostname) or agent_guid, file_path and description. e.g. [{“endpoint”:”test-endpoint”,”file_path”:”C:/test_dir/test.txt”,”filename”:”test.txt”,”description”:”collect file”}]. Required

Context Output

Path Type Description
VisionOne.Collect_Forensic_File.status number Status of request to collect file from endpoint.
VisionOne.Collect_Forensic_File.task_id string Task ID generated after collecting file for forensic analysis.

trendmicro-visionone-download-information-for-collected-forensic-file


Retrieves a URL and other information required to download a collected file via the trendmicro-visionone-collect-forensic-file command.

Base Command

trendmicro-visionone-download-information-for-collected-forensic-file

Input

Argument Name Description Required
task_id taskId output from the collect forensic file command. e.g. task_id=”00000012”. Required
poll If script should wait until the task is finished before returning the result, enabled by default. e.g. poll=true. Possible values are: true, false. Optional
poll_time_sec Maximum time to wait for the result to be available. e.g. poll_time_sec=45. Optional

Context Output

Path Type Description
VisionOne.Download_Information_For_Collected_Forensic_File.status string Status of action performed (succeeded, running or failed).
VisionOne.Download_Information_For_Collected_Forensic_File.created_date_time string The create date time for the file.
VisionOne.Download_Information_For_Collected_Forensic_File.id string Task ID used to query for forensic file information.
VisionOne.Download_Information_For_Collected_Forensic_File.last_action_date_time string Time and date of last action on file.
VisionOne.Download_Information_For_Collected_Forensic_File.description string Task description.
VisionOne.Download_Information_For_Collected_Forensic_File.action string Action performed on file.
VisionOne.Download_Information_For_Collected_Forensic_File.account string The account associated with the request.
VisionOne.Download_Information_For_Collected_Forensic_File.agent_guid string AgentGuid of the endpoint used to collect file.
VisionOne.Download_Information_For_Collected_Forensic_File.endpoint_name string hostname of the endpoint used to collect file.
VisionOne.Download_Information_For_Collected_Forensic_File.file_path string File path for the file that was collected.
VisionOne.Download_Information_For_Collected_Forensic_File.file_sha1 string The fileSha1 for the collected file.
VisionOne.Download_Information_For_Collected_Forensic_File.file_sha256 string The fileSha256 for the collected file.
VisionOne.Download_Information_For_Collected_Forensic_File.file_size number The file size of the file collected.
VisionOne.Download_Information_For_Collected_Forensic_File.resource_location string URL location of the file collected that can be used to download.
VisionOne.Download_Information_For_Collected_Forensic_File.expired_date_time string The expiration date and time of the file.
VisionOne.Download_Information_For_Collected_Forensic_File.password string The password for the file collected.
VisionOne.Download_Information_For_Collected_Forensic_File.error string Error response generated for the request.

trendmicro-visionone-download-investigation-package


Downloads the investigation package based on submission ID.

Base Command

trendmicro-visionone-download-investigation-package

Input

Argument Name Description Required
submission_id The submission ID for the object submitted to sandbox for analysis. e.g. submission_id=”012e4eac-9bd9-4e89-95db-77e02f75a611”. Required
poll If script should wait until the task is finished before returning the result, enabled by default. e.g. poll=true. Possible values are: true, false. Optional
poll_time_sec Maximum time to wait for the result to be available. e.g. poll_time_sec=45. Optional

Context Output

Path Type Description
VisionOne.Download_Investigation_Package.submission_id string The submission for the file.
VisionOne.Download_Investigation_Package.result_code number Result code of making a request to download investigation package.
VisionOne.Download_Investigation_Package.message number Message notifying user that investigation package is ready for download.

trendmicro-visionone-download-suspicious-object-list


Downloads the suspicious object list associated to the specified object. Note ~ Suspicious Object Lists are only available for objects with a high risk level.

Base Command

trendmicro-visionone-download-suspicious-object-list

Input

Argument Name Description Required
submission_id The submission ID for the object submitted to sandbox for analysis. e.g. submission_id=”012e4eac-9bd9-4e89-95db-77e02f75a611”. Required
poll If script should wait until the task is finished before returning the result, enabled by default. e.g. poll=true. Possible values are: true, false. Optional
poll_time_sec Maximum time to wait for the result to be available. e.g. poll_time_sec=45. Optional

Context Output

Path Type Description
VisionOne.Download_Suspicious_Object_list.type string The type of suspicious object.
VisionOne.Download_Suspicious_Object_list.value string Value of the suspicious object.
VisionOne.Download_Suspicious_Object_list.risk_level string Risk level of the analyzed object.
VisionOne.Download_Suspicious_Object_list.root_sha1 string status code for the command.
VisionOne.Download_Suspicious_Object_list.analysis_completion_date_time string The analysis completion date and time.
VisionOne.Download_Suspicious_Object_list.expired_date_time string The expiration date and time for the suspicious object.

trendmicro-visionone-download-analysis-report


Downloads the analysis report for an object submitted to sandbox for analysis based on the submission ID.

Base Command

trendmicro-visionone-download-analysis-report

Input

Argument Name Description Required
submission_id The submission ID for the object submitted to sandbox for analysis. e.g. submission_id=”012e4eac-9bd9-4e89-95db-77e02f75a611”. Required
poll If script should wait until the task is finished before returning the result, enabled by default. e.g. poll=true. Possible values are: true, false. Optional
poll_time_sec Maximum time to wait for the result to be available. e.g. poll_time_sec=45. Optional

Context Output

Path Type Description
VisionOne.Download_Analysis_Report.submission_id string The submission ID for the sandbox object.
VisionOne.Download_Analysis_Report.result_code string Result code of making a request to download analysis report.
VisionOne.Download_Analysis_Report.message string Message notifying user that analysis report is ready for download.

trendmicro-visionone-submit-file-to-sandbox


Submits a file to the sandbox for analysis (Note. For more information about the supported file types, see the TrendAI Vision One™ Online Help. Submissions require credits. Does not require credits in regions where Sandbox Analysis has not been officially released.)

Base Command

trendmicro-visionone-submit-file-to-sandbox

Input

Argument Name Description Required
file_url URL pointing to the location of the file to be submitted. e.g. file_url=”https://someurl.com/test.txt”. Required
file_name Name of the file (including extension) to be analyzed. e.g. file_name=”some-file.txt”. Required
document_password The Base64 encoded password for decrypting the submitted document sample. e.g. document_password=”dGVzdA==”. Optional
archive_password The Base64 encoded password for decrypting the submitted archive. e.g. archive_password=”dGVzdA==”. Optional
arguments Parameter that allows you to specify Base64-encoded command line arguments to run the submitted file. e.g. arguments=”LS10ZXN0IA==”. Optional

Context Output

Path Type Description
VisionOne.Submit_File_to_Sandbox.message string Result code of submitting file to sandbox for analysis.
VisionOne.Submit_File_to_Sandbox.code string HTTP status code of the request made to submit file to sandbox.
VisionOne.Submit_File_to_Sandbox.task_id string ID generated for submitting file to sandbox for analysis.
VisionOne.Submit_File_to_Sandbox.digest string The hash value of the file.
VisionOne.Submit_File_to_Sandbox.arguments string Command line arguments to run the submitted file.

trendmicro-visionone-submit-file-entry-to-sandbox


Submits a file to the sandbox for analysis (Note. For more information about the supported file types, see the TrendAI Vision One™ Online Help. Submissions require credits. Does not require credits in regions where Sandbox Analysis has not been officially released.)

Base Command

trendmicro-visionone-submit-file-entry-to-sandbox

Input

Argument Name Description Required
entry_id Entry ID of the file to be submitted. e.g. entry_id=”104@49493d71”. Required
document_password The Base64 encoded password for decrypting the submitted document sample. e.g. document_password=”dGVzdA==”. Optional
archive_password The Base64 encoded password for decrypting the submitted archive. e.g. archive_password=”dGVzdA==”. Optional
arguments Parameter that allows you to specify Base64-encoded command line arguments to run the submitted file. e.g. arguments=”LS10ZXN0IA==”. Optional

Context Output

Path Type Description
VisionOne.Submit_File_Entry_to_Sandbox.message string Result code of submitting file entry to sandbox for analysis.
VisionOne.Submit_File_Entry_to_Sandbox.code string HTTP status code of the request made to submit file entry to sandbox.
VisionOne.Submit_File_Entry_to_Sandbox.task_id string ID of the submitted file.
VisionOne.Submit_File_Entry_to_Sandbox.digest string The hash value of the file.
VisionOne.Submit_File_Entry_to_Sandbox.filename string The name of the file submitted.
VisionOne.Submit_File_Entry_to_Sandbox.file_path string The path to the file associated to incident.
VisionOne.Submit_File_Entry_to_Sandbox.entry_id string The Entry ID for the file.
VisionOne.Submit_File_Entry_to_Sandbox.arguments string Command line arguments to run the submitted file.

trendmicro-visionone-submit-urls-to-sandbox


Sends URL(s) to sandbox for analysis.

Base Command

trendmicro-visionone-submit-urls-to-sandbox

Input

Argument Name Description Required
urls List of URLs to be sent for analysis. e.g. urls=”https://test.com,https://dummydomain.com”. Required

Context Output

Path Type Description
VisionOne.Submit_Urls_to_Sandbox.id string ID generated for the URL sent to sandbox for analysis.
VisionOne.Submit_Urls_to_Sandbox.url string URL sent to sandbox for analysis.
VisionOne.Submit_Urls_to_Sandbox.digest string Digest value generated for the URL sent to sandbox for analysis.
VisionOne.Submit_Urls_to_Sandbox.status string HTTPS status code of making the request.
VisionOne.Submit_Urls_to_Sandbox.task_id string Task ID generated for the URL sent to sandbox for analysis.

trendmicro-visionone-get-alert-details


Fetches details for a specific alert.

Base Command

trendmicro-visionone-get-alert-details

Input

Argument Name Description Required
workbench_id Workbench ID for the alert to query. e.g. workbench_id=”WB-14-20190709-00003”. Required

Context Output

Path Type Description
VisionOne.Alert_Details.etag string The ETag of the resource you want to update.
VisionOne.Alert_Details.alert.id string ID of the workbench alert.
VisionOne.Alert_Details.alert.model string Name of the detection model that triggered the alert.
VisionOne.Alert_Details.alert.score number Overall severity assigned to the alert based on the severity of the matched detection model and the impact scope.
VisionOne.Alert_Details.alert.severity string Workbench alert severity.
VisionOne.Alert_Details.alert.indicators string The indicators refer to those objects which are found by RCA or sweeping.
VisionOne.Alert_Details.alert.description string Description of the detection model that triggered the alert.
VisionOne.Alert_Details.alert.impact_scope string Affected entities information.
VisionOne.Alert_Details.alert.matched_rules string The rules are triggered.
VisionOne.Alert_Details.alert.alert_provider string Alert provider.
VisionOne.Alert_Details.alert.schema_version string The version of the JSON schema, not the version of alert trigger content.
VisionOne.Alert_Details.alert.workbench_link string Workbench URL.
VisionOne.Alert_Details.alert.created_date_time string Datetime in ISO 8601 format (yyyy-MM-ddThh:mm:ssZ in UTC) that indicates the created date time of the alert.
VisionOne.Alert_Details.alert.updated_date_time string Datetime in ISO 8601 format (yyyy-MM-ddThh:mm:ssZ in UTC) that indicates the last updated date time of the alert.
VisionOne.Alert_Details.alert.investigation_status string Workbench alert status.
VisionOne.Alert_Details.alert.first_investigated_date_time string The date and time the case status was changed to ‘In progress’ in ISO 8601 format (yyyy-MM-ddThh:mm:ssZ, UTC).
VisionOne.Alert_Details.alert.incident_id string The unique identifier of an incident.
VisionOne.Alert_Details.alert.case_id string The unique identifier of a case.
VisionOne.Alert_Details.alert.owner_ids string The owners of the Workbench alert.
VisionOne.Alert_Details.alert.model_id string ID of the detection model that triggered the alert.
VisionOne.Alert_Details.alert.model_type string Type of the detection model that triggered the alert.
VisionOne.Alert_Details.alert.status string The status of a case or investigation.
VisionOne.Alert_Details.alert.investigation_result string The findings of a case or investigation.

trendmicro-visionone-run-sandbox-submission-polling


Runs a polling command to retrieve the status of a sandbox analysis submission.

Base Command

trendmicro-visionone-run-sandbox-submission-polling

Input

Argument Name Description Required
polling polling the task for 30 seconds interval. e.g. polling=true. Default is true. Optional
task_id task_id from the trendmicro-visionone-submit-file-to-sandbox or trendmicro-visionone-submit-file-entry-to-sandbox command output. e.g. task_id=”012e4eac-9bd9-4e89-95db-77e02f75a611”. Required

Context Output

Path Type Description
VisionOne.Sandbox_Submission_Polling.message string Status of the sandbox analysis.
VisionOne.Sandbox_Submission_Polling.status_code string Status code of the request.
VisionOne.Sandbox_Submission_Polling.status string Status of action to analyze file in sandbox.
VisionOne.Sandbox_Submission_Polling.report_id string Report ID of the submission queried.
VisionOne.Sandbox_Submission_Polling.digest string The hash values of file analyzed.
VisionOne.Sandbox_Submission_Polling.analysis_completion_time string Sample analysis completed time.
VisionOne.Sandbox_Submission_Polling.risk_level string Risk Level of the analyzed file.
VisionOne.Sandbox_Submission_Polling.detection_name_list string Detection name of this sample, if applicable.
VisionOne.Sandbox_Submission_Polling.threat_type_list string Threat type of this sample.
VisionOne.Sandbox_Submission_Polling.file_type string File type of this sample.
VisionOne.Sandbox_Submission_Polling.type string Object type.
VisionOne.Sandbox_Submission_Polling.message string Error message for failed call.
VisionOne.Sandbox_Submission_Polling.code string Error code for failed call.
VisionOne.Sandbox_Submission_Polling.DBotScore.Score number The DBot score.
VisionOne.Sandbox_Submission_Polling.DBotScore.Vendor string The Vendor name.
VisionOne.Sandbox_Submission_Polling.DBotScore.Reliability string The reliability of an intelligence-data source.

trendmicro-visionone-check-task-status


Command gives the status of the running task based on the task id.

Base Command

trendmicro-visionone-check-task-status

Input

Argument Name Description Required
polling polling the task for 30 seconds interval. e.g. polling=true. Default is true. Optional
task_id Task id of the task you would like to check. e.g. task_id=”00000012”. Required

Context Output

Path Type Description
VisionOne.Task_Status.id string Task ID of the task queried.
VisionOne.Task_Status.status string Status of the task.
VisionOne.Task_Status.created_date_time string Timestamp in ISO 8601 format.
VisionOne.Task_Status.last_action_date_time string Timestamp in ISO 8601 format.
VisionOne.Task_Status.action string Action performed.
VisionOne.Task_Status.description string Description of the task.
VisionOne.Task_Status.account string Account that performed the task.
VisionOne.Task_Status.type string Value type.
VisionOne.Task_Status.value string Value that was submitted.
VisionOne.Task_Status.tasks string Task related information.
VisionOne.Task_Status.agent_guid string Agent guid of the endpoint.
VisionOne.Task_Status.endpoint_name string Endpoint name.

trendmicro-visionone-add-note


Attaches a note to a workbench alert.

Base Command

trendmicro-visionone-add-note

Input

Argument Name Description Required
workbench_id ID of the workbench you would like to attach the note to. e.g. workbench_id=”WB-14-20190709-00003”. Required
content Contents of the note to be attached. e.g. content=”Some details for the workbench alert.”. Required

Context Output

Path Type Description
VisionOne.Add_Note.code string HTTPS status code of making the request.
VisionOne.Add_Note.message string Message notifying the user of note added to workbench.
VisionOne.Add_Note.note_id string ID of the note added to workbench.

trendmicro-visionone-update-status


Updates the status of a workbench alert.

Base Command

trendmicro-visionone-update-status

Input

Argument Name Description Required
workbench_id ID of the workbench you would like to update the status for. e.g. workbench_id=”WB-14-20190709-00003”. Required
if_match Target resource will be updated only if it matches ETag of the target one. Etag is one of the outputs from get_alert_details. e.g. if_match=”d41d8cd98f00b204e9800998ecf8427e”. Required
status Status to assign to the workbench alert. e.g. status=”closed”. Possible values are: open, in_progress, closed. Optional
inv_status The status of an investigation. NOTE: THIS FIELD IS DEPRECATED! e.g. inv_status=”true_positive”. Possible values are: new, in_progress, true_positive, false_positive, benign_true_positive, closed. Optional
inv_result The findings of a case or investigation. e.g. status=”noteworthy”. Possible values are: noteworthy, true_positive, false_positive, benign_true_positive, no_findings. Optional

Context Output

Path Type Description
VisionOne.Update_Status.Workbench_Id string The ID of the workbench that had the status updated.
VisionOne.Update_Status.code string HTTP status code of updating workbench alert status.
VisionOne.Update_Status.message string Message notifying user that the alert status has been updated to user defined status.

trendmicro-visionone-run-custom-script


Runs a custom script on the specified endpoint or agentGuid.

Base Command

trendmicro-visionone-run-custom-script

Input

Argument Name Description Required
block_objects List of object(s) made up of filename, endpoint or agent_guid and optional description and optional parameter. e.g. [{“filename”:”test.ps1”,”endpoint”:”test-endpoint1”,”description”:”Run custom script”,”parameter”:”some-string”}]. Required

Context Output

Path Type Description
VisionOne.Run_Custom_Script.status number Status of running custom script.
VisionOne.Run_Custom_Script.task_id string Task ID generated after running custom script.

trendmicro-visionone-get-custom-script-list


Fetches a list of all available custom scripts in V1 XDR Portal.

Base Command

trendmicro-visionone-get-custom-script-list

Input

Argument Name Description Required
filename Name of the custom script. e.g. filename=”hello.sh”. Optional
filetype Type of script, either bash or powershell. e.g. filetype=”bash”. Optional
query_op Conditional operator used to build request that allows user to retrieve a subset of custom scripts. Possible values: and/or. Ex. or: the results retrieved will contain custom script(s) matching FileName OR FileType. and: the result retrieved will contain custom script matching FileName AND FileType. Defaults to and. Optional

Context Output

Path Type Description
VisionOne.Get_Custom_Script_List.id string The id for custom script.
VisionOne.Get_Custom_Script_List.description string The script description.
VisionOne.Get_Custom_Script_List.filename string Name of the script.
VisionOne.Get_Custom_Script_List.filetype string File type for the script.

trendmicro-visionone-add-custom-script


Adds a custom script to V1 portal in Response management under custom scripts.

Base Command

trendmicro-visionone-add-custom-script

Input

Argument Name Description Required
filename Name of the custom script. e.g. filename=”hello.sh”. Required
filetype File type of custom script. e.g. filetype=”bash”. Required
script_contents The contents of custom script to be added. script_contents=”#!/bin/sh echo ‘Custom script to do something’”. Required
description Description of the custom script. e.g. description=”This script does something.”. Optional

Context Output

Path Type Description
VisionOne.Add_Custom_Script.id string ID generated for the added custom script.

trendmicro-visionone-download-custom-script


Downloads the contents of a custom script based on script ID.

Base Command

trendmicro-visionone-download-custom-script

Input

Argument Name Description Required
script_id ID for the custom script to download. e.g. script_id=”44c99cb0-8c5f-4182-af55-62135dbe32f1”. Required

Context Output

Path Type Description
VisionOne.Download_Custom_Script.text string Contents of the custom script.

trendmicro-visionone-delete-custom-script


Delete a custom script based on script ID.

Base Command

trendmicro-visionone-delete-custom-script

Input

Argument Name Description Required
script_id ID of custom script to be deleted. e.g. script_id=”44c99cb0-8c5f-4182-af55-62135dbe32f1”. Required

Context Output

Path Type Description
VisionOne.Delete_Custom_Script.status string Success or Failure status code.

trendmicro-visionone-update-custom-script


Updates the contents of a custom script based on script ID.

Base Command

trendmicro-visionone-update-custom-script

Input

Argument Name Description Required
filename Name of the custom script. e.g. filename=”hello.sh”. Required
filetype The filetype of custom script. e.g. filetype=”bash”. Required
script_id ID of custom script to be updated. e.g. script_id=”44c99cb0-8c5f-4182-af55-62135dbe32f1”. Required
script_contents The updated contents of custom script. e.g. script_contents=”#!/bin/sh echo ‘Hello World’”. Required
description Description of the custom script. e.g. description=”Updating script to print Hello World.”. Optional

Context Output

Path Type Description
VisionOne.Update_Custom_Script.status string The Success or Error status.

trendmicro-visionone-get-observed-attack-techniques


Displays a list of Observed Attack Techniques events that match the specified criteria.

Base Command

trendmicro-visionone-get-observed-attack-techniques

Input

Argument Name Description Required
fields Filter (A dictionary object with key/value used to create a query string) for retrieving a subset of the collected Observed Attack Techniques events e.g. {“endpointName”:”sample-host”,”riskLevel”:”low”}. Complete list of supported fields (https://automation.trendmicro.com/xdr/api-v3#tag/Observed-Attack-Techniques/paths/~1v3.0~1oat~1detections/get). Required
query_op Conditional operator used to build request that allows user to retrieve a subset of the collected Observed Attack Techniques events. Possible values: and/or. Ex. or: the results retrieved will contain OAT events for endpoint(s) matching endpointName OR riskLevel. and: will contain OAT events data for endpoint matching endpointName AND riskLevel. Defaults to and. Possible values are: and, or. Optional
detected_start The start of the event detection data retrieval time range in ISO 8601 format. Default: 1 hour before the time you make the request. e.g. detected_start=”2023-10-01T08:00:00Z”. Optional
detected_end The end of the event detection data retrieval time range in ISO 8601 format. Default: The time you make the request. e.g. detected_end=”2023-12-01T08:00:00Z”. Optional
ingested_start The beginning of the data ingestion time range in ISO 8601 format. e.g. ingested_start=”2023-12-01T08:00:00Z”. Optional
ingested_end The end of the data ingestion time range in ISO 8601 format. e.g. ingested_end=”2023-12-01T08:00:00Z”. Optional
top Number of records displayed on a page. e.g. top=5. Optional

Context Output

Path Type Description
VisionOne.Get_Observed_Attack_Techniques.id string Unique alphanumeric string that identifies an Observed Attack Techniques event.
VisionOne.Get_Observed_Attack_Techniques.source string The data sources associated with log types.
VisionOne.Get_Observed_Attack_Techniques.detail string Object that contains detailed information about an Observed Attack Technique event. Object may vary depending on the products purchased by the customer and the products supported in their respective regions.
VisionOne.Get_Observed_Attack_Techniques.filters string List of filters and associated information.
VisionOne.Get_Observed_Attack_Techniques.endpoint string Object that contains information about an endpoint. This field is displayed only when the detection event is related to endpoints.
VisionOne.Get_Observed_Attack_Techniques.entity_name string Name associated with an entity.
VisionOne.Get_Observed_Attack_Techniques.entity_type string Entity type associated with an event is determined by the products purchased by the customer and the products supported in their regions.
VisionOne.Get_Observed_Attack_Techniques.detected_date_time string Timestamp in ISO 8601 format that indicates when an Observed Attack Techniques event was detected.
VisionOne.Get_Observed_Attack_Techniques.ingested_date_time string Timestamp in ISO 8601 format that indicates when the pipeline ingested data related to an Observed Attack Techniques event. This field is displayed only when ingestedStartDateTime and ingestedEndDateTime are used to define the data retrieval time range.

Configuration parameters

  • url — API URL (e.g. https://api.xdr.trendmicro.com) (required)
  • apikey — (required)
  • isFetch — Fetch incidents
  • incidentFetchInterval — Incidents Fetch Interval
  • incidentType — Incident type
  • first_fetch — Sync On First Run (days)
  • max_fetch — Max Incidents
  • proxy — Use system proxy settings
  • insecure — Trust any certificate (not secure)
  • integrationReliability — Source Reliability
  • incident_severity — Severity
  • mirror_direction — Incident Mirroring Direction

Commands (47)

  • get-mapping-fields

    Returns the list of fields for an incident type. This command is used for incident mirroring.

  • get-modified-remote-data

    Gets the list of Vision One alerts that were modified since the last update time. This command is used for incoming mirroring.

  • get-remote-data

    Gets remote data from Vision One for a specific alert. This method is used for incoming mirroring and debugging purposes.

  • trendmicro-visionone-add-custom-script

    Adds a custom script to V1 portal in Response management under custom scripts.

  • trendmicro-visionone-add-note

    Attaches a note to a workbench alert.

  • trendmicro-visionone-add-objects-to-exception-list

    Adds domain, ip, url, file_sha1, file_sha256, sender_mail_address to the Exception List and prevents these objects from being added to the Suspicious Object List.

  • trendmicro-visionone-add-objects-to-suspicious-list

    Adds domain, ip, url, file_sha1, file_sha256, sender_mail_address to the Suspicious Object List.

  • trendmicro-visionone-add-to-block-list

    Adds a domain, ip, file_sha1, url, sender_mail_address to the User-Defined Suspicious Objects List, which blocks the objects on subsequent detections.

  • trendmicro-visionone-check-task-status

    Command gives the status of the running task based on the task id.

  • trendmicro-visionone-collect-forensic-file

    Compresses a file on an endpoint in a password-protected archive and then sends the archive to the XDR service platform.

  • trendmicro-visionone-delete-custom-script

    Delete a custom script based on script ID.

  • trendmicro-visionone-delete-email-message

    Deletes a message from a mailbox.

  • trendmicro-visionone-delete-objects-from-exception-list

    Deletes domain, ip, url, file_sha1, file_sha256, sender_mail_address from the Exception List.

  • trendmicro-visionone-delete-objects-from-suspicious-list

    Deletes domain, ip, url, file_sha1, file_sha256, sender_mail_address from the Suspicious Object List.

  • trendmicro-visionone-disable-user-account

    Signs the user out of all active application and browser sessions, and prevents the user from signing in any new session. Supported IAM systems -> Azure AD and Active Directory (on-premises).

  • trendmicro-visionone-download-analysis-report

    Downloads the analysis report for an object submitted to sandbox for analysis based on the submission ID.

  • trendmicro-visionone-download-custom-script

    Downloads the contents of a custom script based on script ID.

  • trendmicro-visionone-download-information-for-collected-forensic-file

    Retrieves a URL and other information required to download a collected file via the trendmicro-visionone-collect-forensic-file command.

  • trendmicro-visionone-download-investigation-package

    Downloads the investigation package based on submission ID.

  • trendmicro-visionone-download-suspicious-object-list

    Downloads the suspicious object list associated to the specified object. Note ~ Suspicious Object Lists are only available for objects with a high risk level.

  • trendmicro-visionone-enable-user-account

    Allows the user to sign in to new application and browser sessions. Supported IAM systems -> Azure AD and Active Directory (on-premises).

  • trendmicro-visionone-force-password-reset

    Signs the user out of all active application and browser sessions, and forces the user to create a new password during the next sign-in attempt. Supported IAM systems -> Azure AD and Active Directory (on-premises).

  • trendmicro-visionone-force-signout

    Signs the user out of all active application and browser sessions. Supported IAM systems -> Azure AD.

  • trendmicro-visionone-get-alert-details

    Fetches details for a specific alert.

  • trendmicro-visionone-get-custom-script-list

    Fetches a list of all available custom scripts in V1 XDR Portal.

  • trendmicro-visionone-get-email-activity-data

    Displays search results from the Email Activity Data source that match the parameters provided.

  • trendmicro-visionone-get-email-activity-data-count

    Displays search results from the Email Activity Data source that match the parameters provided.

  • trendmicro-visionone-get-endpoint-activity-data

    Displays search results from the Endpoint Activity Data source that match the parameters provided.

  • trendmicro-visionone-get-endpoint-activity-data-count

    Displays total count of search results from the Endpoint Activity Data source that match the parameters provided.

  • trendmicro-visionone-get-endpoint-info

    Retrieves information about a specific endpoint.

  • trendmicro-visionone-get-file-analysis-result

    Retrieves the sandbox submission analysis result.

  • trendmicro-visionone-get-file-analysis-status

    Retrieves the status of a sandbox analysis submission.

  • trendmicro-visionone-get-observed-attack-techniques

    Displays a list of Observed Attack Techniques events that match the specified criteria.

  • trendmicro-visionone-isolate-endpoint

    Disconnects an endpoint from the network (but allows communication with the managing TrendAI™ product).

  • trendmicro-visionone-quarantine-email-message

    Moves a message from a mailbox to the quarantine folder.

  • trendmicro-visionone-remove-from-block-list

    Removes a domain, ip, file_sha1, url, sender_mail_address from the User-Defined Suspicious Objects List.

  • trendmicro-visionone-restore-email-message

    Restores a quarantined message. Deleted messages cannot be restored.

  • trendmicro-visionone-restore-endpoint-connection

    Restores network connectivity to an endpoint that applied the "isolate endpoint" action.

  • trendmicro-visionone-run-custom-script

    Runs a custom script on the specified endpoint or agentGuid.

  • trendmicro-visionone-run-sandbox-submission-polling

    Runs a polling command to retrieve the status of a sandbox analysis submission.

  • trendmicro-visionone-submit-file-entry-to-sandbox

    Submits a file to the sandbox for analysis (Note. For more information about the supported file types, see [the TrendAI Vision One™Online Help](https://docs.trendmicro.com/en-us/enterprise/trend-micro-vision-one/threat-intelligence-/sandbox-analysis/sandbox-supported-fi.aspx). Submissions require credits. Does not require credits in regions where Sandbox Analysis has not been officially released.)

  • trendmicro-visionone-submit-file-to-sandbox

    Submits a file to the sandbox for analysis (Note. For more information about the supported file types, see [the TrendAI Vision One™ Online Help](https://docs.trendmicro.com/en-us/enterprise/trend-micro-vision-one/threat-intelligence-/sandbox-analysis/sandbox-supported-fi.aspx). Submissions require credits. Does not require credits in regions where Sandbox Analysis has not been officially released.)

  • trendmicro-visionone-submit-urls-to-sandbox

    Sends URL(s) to sandbox for analysis.

  • trendmicro-visionone-terminate-process

    Terminates a process that is running on an endpoint.

  • trendmicro-visionone-update-custom-script

    Updates the contents of a custom script based on script ID.

  • trendmicro-visionone-update-status

    Updates the status of a workbench alert.

  • update-remote-system

    Pushes local XSOAR incident changes to the remote Vision One alert system. This command is used for outgoing mirroring.

import json
from typing import Any

# import unittest
from unittest.mock import Mock

import demistomock as demisto
import TrendMicroVisionOneV3
from pytmv1 import (
    Account,
    AccountTaskResp,
    AddAlertNoteResp,
    AddCustomScriptResp,
    BaseTaskResp,
    BytesResp,
    CollectFileTaskResp,
    Digest,
    EmailActivity,
    Endpoint,
    EndpointActivity,
    GetAlertResp,
    GetEmailActivitiesCountResp,
    Iam,
    ListCustomScriptsResp,
    ListEmailActivityResp,
    ListEndpointActivityResp,
    ListOatsResp,
    ListSandboxSuspiciousResp,
    MsData,
    MsDataUrl,
    MultiResp,
    MultiResult,
    MultiUrlResp,
    NoContentResp,
    OatEvent,
    ObjectType,
    OperatingSystem,
    ProductCode,
    QueryOp,
    Result,
    ResultCode,
    RiskLevel,
    SandboxAction,
    SandboxAnalysisResultResp,
    SandboxObjectType,
    SandboxSubmissionStatusResp,
    SandboxSuspiciousObject,
    ScriptType,
    Status,
    SubmitFileToSandboxResp,
    TaskAction,
    TextResp,
    Value,
    ValueList,
)
from pytmv1.model.common import Script
from TrendMicroVisionOneV3 import (
    add_custom_script,
    add_note,
    add_or_delete_from_exception_list,
    add_or_remove_from_block_list,
    add_to_suspicious_list,
    collect_file,
    delete_custom_script,
    delete_from_suspicious_list,
    download_analysis_report,
    download_custom_script,
    download_information_collected_file,
    download_investigation_package,
    download_suspicious_object_list,
    enable_or_disable_user_account,
    force_password_reset,
    force_sign_out,
    get_alert_details,
    get_custom_script_list,
    get_email_activity_data,
    get_email_activity_data_count,
    get_endpoint_activity_data,
    get_endpoint_activity_data_count,
    get_endpoint_info,
    get_file_analysis_result,
    get_file_analysis_status,
    get_mapping_fields_command,
    get_modified_remote_data_command,
    get_observed_attack_techniques,
    get_remote_data_command,
    get_sandbox_submission_status,
    get_task_status,
    isolate_or_restore_connection,
    quarantine_or_delete_email_message,
    restore_email_message,
    run_custom_script,
    submit_file_entry_to_sandbox,
    submit_file_to_sandbox,
    submit_urls_to_sandbox,
    terminate_process,
    update_custom_script,
    update_remote_system_command,
    update_status,
    vision_one_status_to_xsoar,
    xsoar_status_to_vision_one,
)

# Provide valid API KEY
api_key = "test api key"
proxy = True
verify = True


# Mock response for enabling or disabling user account
def enable_user_account_mock_response(*args, **kwargs) -> MultiResult[MultiResp]:
    with open("./test_data/enable_user_account.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


def test_enable_user_account(mocker):
    """Test enable user account success response."""
    client = Mock()
    client.account.enable = Mock(return_value=enable_user_account_mock_response())
    args = {
        "account_identifiers": json.dumps(
            [
                {
                    "account_name": "ghost@trendmicro.com",
                    "description": "Enable user account.",
                }
            ]
        )
    }
    result = TrendMicroVisionOneV3.enable_or_disable_user_account(client, "trendmicro-visionone-enable-user-account", args)
    assert result.outputs[0]["status"] == 202
    assert result.outputs[0]["task_id"] == "00000010"
    assert result.outputs_prefix == "VisionOne.User_Account"
    assert result.outputs_key_field == "task_id"


def disable_user_account_mock_response(*args, **kwargs):
    with open("./test_data/disable_user_account.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


def test_disable_user_account(mocker):
    """Test disable user account success response."""
    client = Mock()
    client.account.disable = Mock(return_value=disable_user_account_mock_response())
    args = {
        "account_identifiers": json.dumps(
            [
                {
                    "account_name": "ghost@trendmicro.com",
                    "description": "Disable user account.",
                }
            ]
        )
    }
    result = enable_or_disable_user_account(client, "trendmicro-visionone-disable-user-account", args)
    assert result.outputs[0]["status"] == 202
    assert result.outputs[0]["task_id"] == "00000009"
    assert result.outputs_prefix == "VisionOne.User_Account"
    assert result.outputs_key_field == "task_id"


# Mock response for force sign out
def force_signout_mock_response(*args, **kwargs):
    with open("./test_data/force_signout.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


def test_force_signout(mocker):
    """Test to force sign out user account with successful result."""
    client = Mock()
    client.account.sign_out = Mock(return_value=force_signout_mock_response())
    args = {
        "account_identifiers": json.dumps(
            [
                {
                    "account_name": "ghost@trendmicro.com",
                    "description": "Signing out user account.",
                }
            ]
        )
    }

    result = force_sign_out(client, args)
    assert result.outputs[0]["status"] == 202
    assert result.outputs[0]["task_id"] == "00000012"
    assert result.outputs_prefix == "VisionOne.Force_Sign_Out"
    assert result.outputs_key_field == "task_id"


# Mock response for force password reset
def force_password_reset_mock_response(*args, **kwargs):
    with open("./test_data/force_password_reset.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


def test_force_password_reset(mocker):
    """Test to force sign out user account with successful result."""
    client = Mock()
    client.account.reset = Mock(return_value=force_password_reset_mock_response())
    args = {
        "account_identifiers": json.dumps(
            [
                {
                    "account_name": "ghost@trendmicro.com",
                    "description": "Signing out user account.",
                }
            ]
        )
    }
    result = force_password_reset(client, args)
    assert result.outputs[0]["status"] == 202
    assert result.outputs[0]["task_id"] == "00000011"
    assert result.outputs_prefix == "VisionOne.Force_Password_Reset"
    assert result.outputs_key_field == "task_id"


# Mock function for add to block list
def add_blocklist_mock_response(*args, **kwargs):
    with open("./test_data/add_blocklist.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test cases for add to block list
def test_add_blocklist(mocker):
    """Test add to block list with positive scenario."""
    client = Mock()
    client.object.add_block = Mock(return_value=add_blocklist_mock_response())
    args = {
        "block_objects": json.dumps(
            [
                {
                    "object_type": "file_sha1",
                    "object_value": "2de5c1125d5f991842727ed8eca8b5fda0ffa249b",
                    "description": "Add to blocklist.",
                }
            ]
        )
    }
    result = add_or_remove_from_block_list(client, "trendmicro-visionone-add-to-block-list", args)
    assert result.outputs[0]["status"] == 202
    assert result.outputs[0]["task_id"] == "00000007"
    assert result.outputs_prefix == "VisionOne.BlockList"
    assert result.outputs_key_field == "task_id"


# Mock function for remove from block list
def remove_blocklist_mock_response(*args, **kwargs):
    with open("./test_data/remove_blocklist.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test cases for remove from block list
def test_remove_blocklist(mocker):
    """Test remove block list positive scenario."""
    client = Mock()
    client.object.delete_block = Mock(return_value=remove_blocklist_mock_response())
    args = {
        "block_objects": json.dumps(
            [
                {
                    "object_type": "domain",
                    "object_value": "www.test.com",
                    "description": "Remove from block list",
                }
            ]
        )
    }
    result = add_or_remove_from_block_list(client, "trendmicro-visionone-remove-from-block-list", args)
    assert result.outputs[0]["status"] == 202
    assert result.outputs[0]["task_id"] == "00000008"
    assert result.outputs_prefix == "VisionOne.BlockList"
    assert result.outputs_key_field == "task_id"


# Mock function for quarantine and delete email message
def quarantine_email_mock_response(*args, **kwargs):
    with open("./test_data/quarantine_email.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test cases for quarantine email message
def test_quarantine_email_message(mocker):
    """Test quarantine email message positive scenario."""
    client = Mock()
    client.email.quarantine = Mock(return_value=quarantine_email_mock_response())
    args = {
        "email_identifiers": json.dumps(
            [
                {
                    "message_id": ("<CANUJTKTjto9GAHTr9V=TFqMZhRXqVn=MfSqmTdAMyv9PDX3k+vQ0w@mail.gmail.com>"),
                    "mailbox": "kjshdfjksahd@trendenablement.com",
                    "description": "quarantine email",
                }
            ]
        )
    }
    result = quarantine_or_delete_email_message(client, "trendmicro-visionone-quarantine-email-message", args)
    assert result.outputs[0]["status"] == 202
    assert result.outputs[0]["task_id"] == "00000002"
    assert result.outputs_prefix == "VisionOne.Email"
    assert result.outputs_key_field == "task_id"


def delete_email_mock_response(*args, **kwargs):
    with open("./test_data/delete_email.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test cases for delete email message
def test_delete_email_message(mocker):
    """Test delete email message with positive scenario."""
    client = Mock()
    client.email.delete = Mock(return_value=delete_email_mock_response())
    args = {
        "email_identifiers": json.dumps(
            [
                {
                    "unique_id": ("CANUJTKTjto9GAHTr9V=TFqMZhRXqVn=MfSqmTdAMyv9PDX3k+vQ0w@mail.gmail.com"),
                    "description": "delete email",
                }
            ]
        )
    }
    result = quarantine_or_delete_email_message(client, "trendmicro-visionone-delete-email-message", args)
    assert result.outputs[0]["status"] == 202
    assert result.outputs[0]["task_id"] == "00000001"
    assert result.outputs_prefix == "VisionOne.Email"
    assert result.outputs_key_field == "task_id"


# Mock response for restore email message
def restore_email_mock_response(*args, **kwargs):
    with open("./test_data/restore_email_message.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test case for restore email
def test_restore_email_message(mocker):
    client = Mock()
    client.email.restore = Mock(return_value=restore_email_mock_response())
    args = {
        "email_identifiers": json.dumps(
            [
                {
                    "unique_id": "CANUJTKTjto9GAHTr9V=TFqMZhRXqVnMfSqmTdAMyv9PDX3k",
                    "description": "Restore email.",
                }
            ]
        )
    }
    result = restore_email_message(client, args)
    assert result.outputs[0]["status"] == 202
    assert result.outputs[0]["task_id"] == "00000003"
    assert result.outputs_prefix == "VisionOne.Email"
    assert result.outputs_key_field == "task_id"


# Mock response for isolate endpoint
def isolate_mock_response(*args, **kwargs):
    with open("./test_data/isolate_endpoint.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test cases for isolate endpoint
def test_isolate_endpoint(mocker):
    """Test isolate endpoint positive scenario."""
    client = Mock()
    client.endpoint.isolate = Mock(return_value=isolate_mock_response())
    args = {
        "endpoint_identifiers": json.dumps(
            [
                {
                    "endpoint": "client782",
                    "description": "Add to blocklist.",
                }
            ]
        )
    }
    result = isolate_or_restore_connection(client, "trendmicro-visionone-isolate-endpoint", args)
    assert result.outputs[0]["status"] == 202
    assert result.outputs[0]["task_id"] == "00000004"
    assert result.outputs_prefix == "VisionOne.Endpoint_Connection"
    assert result.outputs_key_field == "task_id"


# Mock response for restore endpoint
def restore_endpoint_mock_response(*args, **kwargs):
    with open("./test_data/restore_endpoint.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test cases for restore endpoint
def test_restore_endpoint(mocker):
    """Test restore endpoint positive scenario."""
    client = Mock()
    client.endpoint.restore = Mock(return_value=restore_endpoint_mock_response())
    args = {
        "endpoint_identifiers": json.dumps(
            [
                {
                    "agent_guid": "cb9c8412-1f64-4fa0-a36b-76bf41a07ede",
                    "description": "Remove from blocklist.",
                }
            ]
        )
    }
    result = isolate_or_restore_connection(client, "trendmicro-visionone-restore-endpoint-connection", args)
    assert result.outputs[0]["status"] == 202
    assert result.outputs[0]["task_id"] == "00000005"
    assert result.outputs_prefix == "VisionOne.Endpoint_Connection"
    assert result.outputs_key_field == "task_id"


# Mock response for terminate process
def terminate_process_mock_response(*args, **kwargs):
    with open("./test_data/terminate_process.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test cases for terminate process endpoint
def test_terminate_process(mocker):
    """Test terminate process positive scenario."""
    client = Mock()
    client.endpoint.terminate_process = Mock(return_value=terminate_process_mock_response())
    args = {
        "process_identifiers": json.dumps(
            [
                {
                    "endpoint": "035f6286-2414-4cb4-8d05-e67d2d32c944",
                    "file_sha1": "12a08b7a3c5a10b64700c0aca1a47941b50a4f8b",
                    "description": "terminate info",
                    "filename": "testfile.txt",
                }
            ]
        )
    }
    result = terminate_process(client, args)
    assert result.outputs[0]["status"] == 202
    assert result.outputs[0]["task_id"] == "00000006"
    assert result.outputs_prefix == "VisionOne.Terminate_Process"
    assert result.outputs_key_field == "task_id"


# Mock response for add to exception list
def add_exception_mock_response(*args, **kwargs):
    with open("./test_data/add_exception.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test cases for add exception list.
def test_add_object_to_exception_list(mocker):
    """Test add to exception list with positive scenario."""
    client = Mock()
    client.object.add_exception = Mock(return_value=add_exception_mock_response())
    args = {
        "block_objects": json.dumps(
            [
                {
                    "object_type": "domain",
                    "object_value": "1.alisiosanguera.com",
                    "description": "new key",
                }
            ]
        )
    }
    result = add_or_delete_from_exception_list(client, "trendmicro-visionone-add-objects-to-exception-list", args)
    assert result.outputs["message"] == "success"
    assert isinstance(result.outputs["total_items"], int)
    assert result.outputs_prefix == "VisionOne.Exception_List"
    assert result.outputs_key_field == "multi_response"


# Mock response for remove from exception list
def delete_exception_mock_response(*args, **kwargs):
    with open("./test_data/remove_exception.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test cases for delete exception list.
def test_delete_object_from_exception_list(mocker):
    """Test delete exception list positive scenario."""
    client = Mock()
    client.object.delete_exception = Mock(return_value=delete_exception_mock_response())
    args = {
        "block_objects": json.dumps(
            [
                {
                    "object_type": "ip",
                    "object_value": "7.7.7.7",
                    "description": "Remove IP from exception list",
                }
            ]
        )
    }
    result = add_or_delete_from_exception_list(client, "trendmicro-visionone-delete-objects-from-exception-list", args)
    assert result.outputs["message"] == "success"
    assert isinstance(result.outputs["total_items"], int)
    assert result.outputs_prefix == "VisionOne.Exception_List"
    assert result.outputs_key_field == "multi_response"


# Mock response for add to suspicious list
def add_suspicious_mock_response(*args, **kwargs):
    with open("./test_data/add_suspicious_list.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test cases for add suspicious object list
def test_add_object_to_suspicious_list(mocker):
    """Test add to suspicious list with poistive scenario."""
    client = Mock()
    client.object.add_suspicious = Mock(return_value=add_suspicious_mock_response())
    args = {
        "block_objects": json.dumps(
            [
                {
                    "object_type": "domain",
                    "object_value": "1.alisiosanguera.com.cn",
                    "description": "Example Suspicious Object.",
                    "scan_action": "log",
                    "risk_level": "high",
                    "expiry_days": 15,
                }
            ]
        )
    }
    result = add_to_suspicious_list(client, args)
    assert result.outputs["message"] == "success"
    assert isinstance(result.outputs["total_items"], int)
    assert result.outputs_prefix == "VisionOne.Suspicious_List"
    assert result.outputs_key_field == "multi_response"


# Mock response for delete from suspicious list
def delete_suspicious_mock_response(*args, **kwargs):
    with open("./test_data/delete_suspicious_list.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test cases for delete suspicious object list
def test_delete_object_from_suspicious_list(mocker):
    """Test delete object from suspicious list."""
    client = Mock()
    client.object.delete_suspicious = Mock(return_value=delete_suspicious_mock_response())
    args = {
        "block_objects": json.dumps(
            [
                {
                    "object_type": "domain",
                    "object_value": "1.alisiosanguera.com.cn",
                    "description": "Delete from suspicious list",
                }
            ]
        )
    }
    result = delete_from_suspicious_list(client, args)
    assert result.outputs["message"] == "success"
    assert isinstance(result.outputs["total_items"], int)
    assert result.outputs_prefix == "VisionOne.Suspicious_List"
    assert result.outputs_key_field == "multi_response"


# Mock response for Get file analysis status
def mock_file_analysis_status_response(*args, **kwargs):
    # with open("./test_data/get_file_analysis_status.json") as f:
    #     return_value: list[dict[str, Any]] = json.load(f)
    return Result(
        result_code=ResultCode.SUCCESS,
        response=SandboxSubmissionStatusResp(
            id="921674d0-9735-4f79-b7de-c852e00a003d",
            status=Status.SUCCEEDED,
            created_date_time="2021-11-17T12:00:00Z",
            last_action_date_time="2021-12-17T12:00:00Z",
            action=SandboxAction.ANALYZE_FILE,
            resource_location="https://api.xdr.trendmicro.com/...",
            is_cached=False,
            arguments="LS10ZXN0IA==",
            digest=Digest(
                md5="4ac174730d4143a119037d9fda81c7a9",
                sha1="fb5608fa03de204a12fe1e9e5275e4a682107471",
                sha256="65b0f656e79ab84ca17807158e3eac206bd58be6689ddeb95956a48748d138f9",
            ),
        ),
    )


# Test Cases for Get file analysis status
def test_get_file_analysis_status(mocker):
    """Test to get status of file"""
    client = Mock()
    client.sandbox.get_submission_status = Mock(return_value=mock_file_analysis_status_response())
    args = {"task_id": "921674d0-9735-4f79-b7de-c852e00a003d"}
    result = get_file_analysis_status(client, args)
    assert isinstance(result.outputs["is_cached"], bool)
    assert result.outputs["status"] == "succeeded"
    assert isinstance(result.outputs["action"], str)
    assert isinstance(result.outputs["arguments"], str)
    assert result.outputs["id"] == "921674d0-9735-4f79-b7de-c852e00a003d"
    assert isinstance(result.outputs["digest"], dict)
    assert isinstance(result.outputs["resource_location"], str)
    assert result.outputs_prefix == "VisionOne.File_Analysis_Status"
    assert result.outputs_key_field == "id"


# Mock response for Get file analysis report
def mock_file_result_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=SandboxAnalysisResultResp(
            id="800f908d-9578-4333-91e5-822794ed5483",
            type=SandboxObjectType.FILE,
            analysis_completion_date_time="2021-11-17T12:00:00Z",
            risk_level=RiskLevel.HIGH,
            true_file_type="exe",
            digest=Digest(
                md5="4ac174730d4143a119037d9fda81c7a9",
                sha1="fb5608fa03de204a12fe1e9e5275e4a682107471",
                sha256="65b0f656e79ab84ca17807158e3eac206bd58be6689ddeb95956a48748d138f9",
            ),
            arguments="LS10ZXN0IA==",
            detection_names=["VAN_DROPPER.UMXX"],
            threat_types=["Dropper"],
        ),
    )


# Test cases for get file analysis report
def test_get_file_analysis_result(mocker):
    """Test get file analysis report data."""
    client = Mock()
    client.sandbox.get_analysis_result = Mock(return_value=mock_file_result_response())
    args = {
        "report_id": "800f908d-9578-4333-91e5-822794ed5483",
        "poll": "true",
        "poll_time_sec": 30,
    }
    result = get_file_analysis_result(client, args)
    assert result.outputs["id"] == "800f908d-9578-4333-91e5-822794ed5483"
    assert isinstance(result.outputs["type"], str)
    assert isinstance(result.outputs["digest"], dict)
    assert isinstance(result.outputs["arguments"], str)
    assert isinstance(result.outputs["analysis_completion_date_time"], str)
    assert result.outputs["risk_level"] == "high"
    assert isinstance(result.outputs["detection_names"], list)
    assert isinstance(result.outputs["threat_types"], list)
    assert isinstance(result.outputs["true_file_type"], str)
    assert result.outputs_key_field == "id"


# Mock response for collect file
def mock_collect_file_response(*args, **kwargs):
    with open("./test_data/collect_forensic_file.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test cases for collect forensic file.
def test_collect_forensic_file(mocker):
    """Test collect file with positive scenario."""
    client = Mock()
    client.endpoint.collect_file = Mock(return_value=mock_collect_file_response())
    args = {
        "collect_files": json.dumps(
            [
                {
                    "endpoint": "client95c3",
                    "file_path": "C/file_path/sample.txt",
                    "description": "collect file",
                }
            ]
        )
    }
    result = collect_file(client, args)
    assert result.outputs[0]["status"] == 202
    assert result.outputs[0]["task_id"] == "00000003"
    assert result.outputs_prefix == "VisionOne.Collect_Forensic_File"
    assert result.outputs_key_field == "task_id"


# Mock for downloaded file information
def mock_download_collected_file_info_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=CollectFileTaskResp(
            id="00000003",
            status=Status.SUCCEEDED,
            action=TaskAction.COLLECT_FILE,
            created_date_time="2023-11-12T12:00:00Z",
            last_action_date_time="2023-11-16T12:00:00Z",
            description="Test",
            account="API",
            agent_guid="cb9c8412-1f64-4fa0-a36b-76bf41a07ede",
            endpoint_name="trend-host-1",
            file_path="string",
            file_sha1="12a08b7a3c5a10b64700c0aca1a47941b50a4f8b",
            file_sha256="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            file_size=102400,
            resource_location="htttps://api.xdr.trendmicro.com/...",
            expired_date_time="2023-11-17T12:00:00Z",
            password="LS10ZXN0IA==",
        ),
    )


# Test Cases for Collected downloaded file information.
def test_get_forensic_file_information(mocker):
    """Test endpoint to get collected file information based on task id"""
    client = Mock()
    client.task.get_result_class = Mock(return_value=mock_download_collected_file_info_response())
    args = {
        "task_id": "00000003",
        "poll": "true",
        "poll_time_sec": 30,
    }
    result = download_information_collected_file(client, args)
    assert result.outputs["id"] == "00000003"
    # assert result.outputs["action"] == "collectFile"
    assert result.outputs["status"] == "succeeded"
    assert result.outputs["agent_guid"] == "cb9c8412-1f64-4fa0-a36b-76bf41a07ede"
    assert result.outputs["endpoint_name"] == "trend-host-1"
    assert result.outputs["file_sha1"] == "12a08b7a3c5a10b64700c0aca1a47941b50a4f8b"
    assert result.outputs["file_size"] == 102400
    assert isinstance(result.outputs["file_path"], str)
    assert isinstance(result.outputs["resource_location"], str)
    assert isinstance(result.outputs["expired_date_time"], str)
    assert isinstance(result.outputs["created_date_time"], str)
    assert isinstance(result.outputs["password"], str)


# Mock response for Download analysis results
def mock_download_analysis_report_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=BytesResp(content=b"JVBERi0xLjQKJcCnN0cmVhbQp4nD2OywoCMQxF9=="),
    )


# Test Case for Download analysis report
def test_download_analysis_report(mocker):
    """
    Test to download analysis report (PDF) of file submitted
    to sandbox based on submission ID returned by get
    file analysis status.
    """
    client = Mock()
    client.sandbox.download_analysis_result = Mock(return_value=mock_download_analysis_report_response())
    args = {
        "submission_id": "8559a7ce-2b85-451b-8742-4b943ad76a22",
        "poll": "true",
        "poll_time_sec": 30,
    }
    result = download_analysis_report(client, args)
    assert result[1].outputs["result_code"] == "SUCCESS"
    assert result[1].outputs["submission_id"] == "8559a7ce-2b85-451b-8742-4b943ad76a22"
    assert result[1].outputs_prefix == "VisionOne.Download_Analysis_Report"
    assert result[1].outputs_key_field == "submission_id"


# Mock response for download investigation package
def mock_download_investigation_package_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=BytesResp(content=b"JVBERi0xLjQKJcCnN0cmVhbQp4nD2OywoCMQxF9=="),
    )


# Test case for Download analysis package
def test_download_investigation_package(mocker):
    """
    Test to download investigation package for file
    submitted to sandbox based on submission ID returned
    by get file analysis status.
    """
    client = Mock()
    client.sandbox.download_investigation_package = Mock(return_value=mock_download_investigation_package_response())
    args = {
        "submission_id": "8559a7ce-2b85-451b-8742-4b943ad76a22",
        "poll": "true",
        "poll_time_sec": 30,
    }
    result = download_investigation_package(client, args)
    assert result[1].outputs["result_code"] == "SUCCESS"
    assert result[1].outputs["submission_id"] == "8559a7ce-2b85-451b-8742-4b943ad76a22"
    assert result[1].outputs_prefix == "VisionOne.Download_Investigation_Package"
    assert result[1].outputs_key_field == "submission_id"


# Mock response for download suspicious object list
def mock_download_suspicious_object_list_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=ListSandboxSuspiciousResp(
            items=[
                SandboxSuspiciousObject(
                    risk_level=RiskLevel.HIGH,
                    analysis_completion_date_time="2021-11-17T12:00:00Z",
                    expired_date_time="2022-12-17T12:00:00Z",
                    root_sha1="12a08b7a3c5a10b64700c0aca1a47941b50a4f8b",
                    value="https://someurl.com",
                    type=ObjectType.URL,
                )
            ],
        ),
    )


# Test case for download suspicious object list
def test_download_suspicious_object_list(mocker):
    """
    Test to download suspicious object list
    based on submission ID returned by download
    file analysis report. Only items classified as
    High will be populated in the list. If no items
    exist, a 404 not found error will be returned.
    """
    client = Mock()
    client.sandbox.list_suspicious = Mock(return_value=mock_download_suspicious_object_list_response())
    args = {
        "submission_id": "8559a7ce-2b85-451b-8742-4b943ad76a22",
        "poll": "true",
        "poll_time_sec": 30,
    }
    result = download_suspicious_object_list(client, args)
    assert result.outputs[0]["risk_level"] == "high"
    assert isinstance(result.outputs[0]["analysis_completion_date_time"], str)
    assert isinstance(result.outputs[0]["expired_date_time"], str)
    assert isinstance(result.outputs[0]["root_sha1"], str)
    assert isinstance(result.outputs[0]["type"], str)
    assert isinstance(result.outputs[0]["value"], str)
    assert result.outputs_prefix == "VisionOne.Download_Suspicious_Object_list"
    assert result.outputs_key_field == "risk_level"


# Mock response for submit file to sandbox.
def mock_submit_file_to_sandbox_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=SubmitFileToSandboxResp(
            id="012e4eac-9bd9-4e89-95db-77e02f75a6f3",
            digest=Digest(
                md5="4ac174730d4143a119037d9fda81c7a9",
                sha1="fb5608fa03de204a12fe1e9e5275e4a682107471",
                sha256="65b0f656e79ab84ca17807158e3eac206bd58be6689ddeb95956a48748d138f9",
            ),
            arguments="LS10ZXN0IA==",
        ),
    )


# Mock response for submit file to sandbox.
def mocked_requests_get(*args, **kwargs):
    class MockResponse:
        def __init__(self, json_data, status_code, content):
            self.json_data = json_data
            self.status_code = status_code
            self.content = content

        def json(self):
            return self.json_data

    if args[0] == "http://someurl.com/test.json":
        return MockResponse({"key1": "value1"}, 200, "response")
    elif args[0] == "http://someotherurl.com/anothertest.json":
        return MockResponse({"key2": "value2"}, 200, "response")

    return MockResponse(None, 404, None)


# Mock response for submit file to sandbox.
def mocked_requests_post(*args, **kwargs):
    class MockResponse:
        def __init__(self, json_data, status_code, content):
            self.json_data = json_data
            self.status_code = status_code
            self.content = content

        def json(self):
            return {
                "id": "012e4eac-9bd9-4e89-95db-77e02f75a6f3",
                "digest": {
                    "md5": "4ac174730d4143a119037d9fda81c7a9",
                    "sha1": "fb5608fa03de204a12fe1e9e5275e4a682107471",
                    "sha256": "65b0f656e79ab84ca17807158e3eac206bd58be6689ddeb95956a48748d138f9",
                },
                "arguments": "LS10ZXN0IA==",
            }

        def raise_for_status(self):
            return True

    if args[0] == "http://someurl.com/test.json":
        return MockResponse({"key1": "value1"}, 200, "response")
    elif args[0] == "http://someotherurl.com/anothertest.json":
        return MockResponse({"key2": "value2"}, 200, "response")

    return MockResponse(None, 404, None)


def test_submit_file_to_sandbox(mocker):
    client = Mock()
    client.sandbox.submit_file = Mock(return_value=mock_submit_file_to_sandbox_response())
    args = {
        "file_path": "https://someurl.com/test.json",
        "filename": "dummy.pdf",
        "archive_password": "6hn467c8",
        "document_password": "",
        "arguments": "LS10ZXN0IA==",
    }
    mocker.patch("TrendMicroVisionOneV3.requests.get", mocked_requests_get)
    result = submit_file_to_sandbox(client, args)
    assert isinstance(result.outputs["task_id"], str)
    assert isinstance(result.outputs["digest"], dict)
    assert result.outputs["code"] == 202
    assert isinstance(result.outputs["arguments"], str)
    assert result.outputs["message"] == "SUCCESS"
    assert result.outputs_key_field == "task_id"


def test_submit_file_entry_to_sandbox(mocker):
    mocker.patch.object(
        demisto,
        "getFilePath",
        return_value={"id": id, "path": "README.md", "name": "test.txt"},
    )
    client = Mock()
    client.sandbox.submit_file = Mock(return_value=mock_submit_file_to_sandbox_response())
    mocker.patch("TrendMicroVisionOneV3.requests.get", mocked_requests_get)
    mocker.patch("TrendMicroVisionOneV3.requests.post", mocked_requests_post)
    args = {
        "entry_id": "12@1221",
        "archive_password": "6hn467c8",
        "document_password": "",
        "arguments": "LS10ZXN0IA==",
    }

    result = submit_file_entry_to_sandbox(client, args)
    assert result.outputs["entry_id"] == "12@1221"
    assert isinstance(result.outputs["task_id"], str)
    assert isinstance(result.outputs["digest"], dict)
    assert result.outputs_key_field == "entry_id"


# Mock response for submit urls to sandbox
def mock_urls_to_sandbox_response(*args, **kwargs):
    with open("./test_data/submit_urls_sandbox.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiUrlResp(items=[MsDataUrl(**data) for data in return_value]),
    )


# Test case for submit urls to sandbox
def test_submit_urls_to_sandbox(mocker):
    client = Mock()
    client.sandbox.submit_url = Mock(return_value=mock_urls_to_sandbox_response())
    args = {
        "urls": json.dumps(
            [
                "http://www.shadywebsite.com",
                "http://www.virus2.com",
                "https://testurl.com",
            ]
        )
    }
    result = submit_urls_to_sandbox(client, args)
    assert isinstance(result.outputs[0]["url"], str)
    assert isinstance(result.outputs[0]["id"], str)
    assert isinstance(result.outputs[0]["digest"], dict)
    assert result.outputs_key_field == "id"


def test_sandbox_submission_polling(mocker):
    """Test sandbox submission polling."""
    client = Mock()
    client.sandbox.get_submission_status = Mock(return_value=mock_file_analysis_status_response())
    client.sandbox.get_analysis_result = Mock(return_value=mock_file_result_response())
    mocker.patch.object(
        demisto,
        "demistoVersion",
        return_value={"version": "6.2.0", "buildNumber": "12345"},
    )
    mocker.patch("CommonServerPython.ScheduledCommand.raise_error_if_not_supported", lambda: None)

    args = {"task_id": "800f908d-9578-4333-91e5-822794ed5483"}
    result = get_sandbox_submission_status(args, client)
    assert result.outputs["report_id"] == "800f908d-9578-4333-91e5-822794ed5483"
    assert isinstance(result.outputs["type"], str)
    assert isinstance(result.outputs["digest"], dict)
    assert isinstance(result.outputs["arguments"], str)
    assert isinstance(result.outputs["analysis_completion_time"], str)
    assert isinstance(result.outputs["risk_level"], str)
    assert isinstance(result.outputs["detection_name_list"], list)
    assert isinstance(result.outputs["threat_type_list"], list)
    assert isinstance(result.outputs["file_type"], str)


# Mock function for check task status
def get_base_task_result_mock_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=BaseTaskResp(
            id="00000004",
            status=Status.SUCCEEDED,
            created_date_time="2021-11-17T12:00:00Z",
            last_action_date_time="2021-12-17T12:00:00Z",
            action=TaskAction.ENABLE_ACCOUNT,
            description="something",
            account="API",
        ),
    )


# Mock function for check task status
def check_task_status_mock_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=AccountTaskResp(
            id="00000004",
            status=Status.SUCCEEDED,
            created_date_time="2021-11-17T12:00:00Z",
            last_action_date_time="2021-12-17T12:00:00Z",
            action=TaskAction.ENABLE_ACCOUNT,
            description="something",
            account="API",
            tasks=[
                Account(
                    iam=Iam.AAD,
                    account_name="jdoe@trendenablement.com",
                    status=Status.SUCCEEDED,
                    last_action_date_time="2023-11-16T21:51:19Z",
                )
            ],
        ),
    )


def test_check_task_status(mocker):
    client = Mock()
    client.task.get_result = Mock(return_value=get_base_task_result_mock_response())
    client.task.get_result_class = Mock(return_value=check_task_status_mock_response())
    mocker.patch("CommonServerPython.ScheduledCommand.raise_error_if_not_supported", lambda: None)
    args = {
        "task_id": "00000004",
        "poll": "true",
        "poll_time_sec": 30,
    }
    result = get_task_status(args, client)
    assert result.outputs["id"] == "00000004"
    assert result.outputs["status"] == "succeeded"
    assert isinstance(result.outputs["action"], str)
    assert isinstance(result.outputs["created_date_time"], str)
    assert isinstance(result.outputs["description"], str)
    assert isinstance(result.outputs["last_action_date_time"], str)


# Mock for downloaded file information
def mock_get_endpoint_info_response(*args, **kwargs):
    return Endpoint(
        agent_guid="35fa11da-a24e-40cf-8b56-baf8828cc151",
        login_account=ValueList(
            value=["MSEDGEWIN10\\\\IEUser"],
            updated_date_time="2020-06-01T02:12:56Z",
        ),
        endpoint_name=Value(value="MSEDGEWIN10", updated_date_time="2020-06-01T02:12:56Z"),
        mac_address=ValueList(
            updated_date_time="2020-06-01T02:12:56Z",
            value=["00:1c:42:be:22:5f"],
        ),
        ip=ValueList(value=["10.211.55.36"], updated_date_time="2020-06-01T02:12:56Z"),
        os_name=OperatingSystem.WINDOWS,
        os_version="10.0 (Build 19045)",
        os_description="Windows 10 10.0 (Build 19045)",
        product_code=ProductCode.SAO,
        installed_product_codes=[ProductCode.SAO, ProductCode.XES],
    )


def side_effect(lambda_func, *args2, **args3):
    lambda_func(mock_get_endpoint_info_response())


# Test case for get endpoint information.
def test_get_endpoint_information(mocker):
    """Test get information from endpoint based on endpointName or agentGuid"""
    args = {
        "query_op": "and",
        "endpoint": json.dumps({"dpt": "443", "endpointName": "MSEDGEWIN10"}),
    }
    client = Mock()
    my_list = []
    client.endpoint.consume_data = Mock(side_effect=side_effect)
    client.endpoint.consume_data(lambda cons: my_list.append(cons), QueryOp.AND, **json.loads(args["endpoint"]))
    result = get_endpoint_info(client, args)
    assert isinstance(result.outputs[0]["agent_guid"], str)
    assert isinstance(result.outputs[0]["login_account"], dict)
    assert isinstance(result.outputs[0]["endpoint_name"], dict)
    assert isinstance(result.outputs[0]["mac_address"], dict)
    assert isinstance(result.outputs[0]["ip"], dict)
    assert isinstance(result.outputs[0]["os_name"], str)
    assert isinstance(result.outputs[0]["os_version"], str)
    assert isinstance(result.outputs[0]["os_description"], str)
    assert isinstance(result.outputs[0]["product_code"], str)
    assert isinstance(result.outputs[0]["installed_product_codes"], list)
    assert result.outputs_key_field == "endpoint_name"


# Mock response for get endpoint activity data
def get_endpoint_activity_data_mock_response(*args, **kwargs):
    with open("./test_data/get_endpoint_activity_data.json") as f:
        endpoint_activity: dict[str, Any] = json.load(f)
    return Result(
        result_code=ResultCode.SUCCESS,
        response=ListEndpointActivityResp(
            next_link="https://somelink.com",
            items=[EndpointActivity(**endpoint_activity)],
            progress_rate=30,
        ),
    )


# Test case for get alert details
def test_get_endpoint_activity_data(mocker):
    client = Mock()
    client.endpoint.get_activity_count = Mock(return_value=get_endpoint_activity_data_count_mock_response())
    client.endpoint.list_activity = Mock(return_value=get_endpoint_activity_data_mock_response())
    args = {
        "start": "2022-10-04T08:22:37Z",
        "end": "2023-10-04T08:22:37Z",
        "top": 500,
        "query_op": "or",
        "select": "dpt,dst,endpointHostName",
        "get_activity_data_count": "true",
        "fetch_all": "false",
        "fetch_max_count": "50",
        "fields": json.dumps({"dpt": "443", "endpointHostName": "MSEDGEWIN10"}),
    }
    result = get_endpoint_activity_data(client, args)
    assert isinstance(result.outputs[0]["endpoint_host_name"], str)
    assert result.outputs_key_field == "endpoint_host_name"


# Mock response for get endpoint activity data count
def get_endpoint_activity_data_count_mock_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=GetEmailActivitiesCountResp(total_count=10),
    )


# Test case for get alert details
def test_get_endpoint_activity_data_count(mocker):
    client = Mock()
    client.endpoint.get_activity_count = Mock(return_value=get_endpoint_activity_data_count_mock_response())
    args = {
        "start": "2022-10-04T08:22:37Z",
        "end": "2023-10-04T08:22:37Z",
        "query_op": "or",
        "select": "dpt,dst,endpointHostName",
        "get_activity_data_count": "true",
        "fields": json.dumps({"dpt": "443", "endpointHostName": "MSEDGEWIN10"}),
    }
    result = get_endpoint_activity_data_count(client, args)
    assert isinstance(result.outputs["endpoint_activity_count"], int)
    assert result.outputs_key_field == "endpoint_activity_count"


# Mock response for get endpoint activity data
def get_email_activity_data_mock_response(*args, **kwargs):
    with open("./test_data/get_email_activity_data.json") as f:
        email_activity: dict[str, Any] = json.load(f)
    return Result(
        result_code=ResultCode.SUCCESS,
        response=ListEmailActivityResp(
            next_link="https://somelink.com",
            items=[EmailActivity(**email_activity)],
            progress_rate=30,
        ),
    )


# Test case for get alert details
def test_get_email_activity_data(mocker):
    client = Mock()
    client.email.get_activity_count = Mock(return_value=get_email_activity_data_count_mock_response())
    client.email.list_activity = Mock(return_value=get_email_activity_data_mock_response())
    args = {
        "start": "2022-10-04T08:22:37Z",
        "end": "2023-10-04T08:22:37Z",
        "top": 50,
        "query_op": "or",
        "select": "mailFromAddresses,mailToAddresses",
        "fetch_all": "false",
        "fetch_max_count": "50",
        "fields": json.dumps({"mailToAddresses": "testemail@gmail.com", "mailMsgSubject": "spam"}),
    }
    result = get_email_activity_data(client, args)
    assert isinstance(result.outputs[0]["mail_msg_id"], str)
    assert result.outputs_key_field == "mail_to_addresses"


# Mock response for get email activity data count
def get_email_activity_data_count_mock_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=GetEmailActivitiesCountResp(total_count=10),
    )


# Test case for get email activity data count
def test_get_email_activity_data_count(mocker):
    client = Mock()
    client.email.get_activity_count = Mock(return_value=get_email_activity_data_count_mock_response())
    args = {
        "start": "2022-10-04T08:22:37Z",
        "end": "2023-10-04T08:22:37Z",
        "query_op": "or",
        "select": "mailFromAddresses,mailToAddresses",
        "fields": json.dumps({"mailToAddresses": "testemail@gmail.com", "mailMsgSubject": "spam"}),
    }
    result = get_email_activity_data_count(client, args)
    assert isinstance(result.outputs["email_activity_count"], int)
    assert result.outputs_key_field == "email_activity_count"


# Mock response for get alert details
def get_alert_details_mock_response(*args, **kwargs):
    with open("./test_data/get_alert_details.json") as f:
        alert = json.load(f)
    return Result(
        result_code=ResultCode.SUCCESS,
        response=GetAlertResp(etag="33a64df551425fcc55e4d42a148795d9f25f89d4", data=alert),
    )


# Test case for get alert details
def test_get_alert_details(mocker):
    client = Mock()
    client.alert.get = Mock(return_value=get_alert_details_mock_response())

    args = {"workbench_id": "WB-9002-20220909-00111"}
    result = get_alert_details(client, args)
    assert result.outputs["etag"] == "33a64df551425fcc55e4d42a148795d9f25f89d4"
    assert isinstance(result.outputs["alert"], dict)
    assert result.outputs_key_field == "etag"


# Mock response for add note.
def add_note_mock_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=AddAlertNoteResp(note_id="1"),
    )


# Test case for add note
def test_add_note(mocker):
    client = Mock()
    client.note.create = Mock(return_value=add_note_mock_response())
    args = {"workbench_id": "WB-14-20190709-00003", "content": "This is a new note."}
    result = add_note(client, args)
    assert isinstance(result.outputs["message"], str)
    assert isinstance(result.outputs["code"], int)
    assert result.outputs["note_id"] == "1"
    assert result.outputs_key_field == "note_id"


# Mock function for update alert status
def update_status_mock_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=NoContentResp(),
    )


# Test case for update alert status
def test_update_status(mocker):
    client = Mock()
    client.alert.update_status = Mock(return_value=update_status_mock_response())
    args = {
        "workbench_id": "WB-20837-20220418-00000",
        "if_match": "d41d8cd98f00b204e9800998ecf8427e",
        "status": "in_progress",
        "inv_result": "no_findings",
    }
    result = update_status(client, args)
    assert result.outputs["code"] == 204
    assert isinstance(result.outputs["message"], str)
    assert result.outputs["Workbench_Id"] == "WB-20837-20220418-00000"


# Mock function for run custom script
def run_custom_script_mock_response(*args, **kwargs):
    with open("./test_data/run_custom_script.json") as f:
        return_value: list[dict[str, Any]] = json.load(f)
    return MultiResult(
        result_code=ResultCode.SUCCESS,
        response=MultiResp(items=[MsData(**data) for data in return_value]),
    )


# Test case to run a custom script
def test_run_custom_script(mocker):
    """
    Given:
        - block_objects -> A dictionary object containing endpoint or agent_guid,
            optional description and optional parameter.
    When:
        - Execute run_custom_script command
    Then:
        - validate a success response and a task_id is generated
    """
    client = Mock()
    client.script.run = Mock(return_value=run_custom_script_mock_response())
    args = {
        "block_objects": json.dumps(
            [
                {
                    "filename": "test.ps1",
                    "endpoint": "custom-endpoint1",
                    "parameter": "string",
                    "description": "Run custom script.",
                }
            ]
        )
    }
    result = run_custom_script(client, args)
    assert result.outputs[0]["status"] == 202
    assert isinstance(result.outputs[0]["task_id"], str)
    assert result.outputs_prefix == "VisionOne.Run_Custom_Script"
    assert result.outputs_key_field == "task_id"


# Mock function to get custom script list
def get_custom_script_list_mock_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=ListCustomScriptsResp(
            items=[
                Script(
                    id="cb044c99-8fc5-2418-f5a5-2f15dbe62133",
                    file_name="string",
                    file_type=ScriptType.BASH,
                    description="Script to update some values",
                ),
                Script(
                    id="44c99cb0-8c5f-4182-af55-62135dbe32f1",
                    file_name="string",
                    file_type=ScriptType.POWERSHELL,
                    description="Script to delete duplicate values",
                ),
            ]
        ),
    )


# Test case to fetch custom script list
def test_get_custom_script_list(mocker):
    """
    Given:
        - fields -> A dictionary object containing fileName and/or fileType
        - query_op -> Operator used to build the query string, possible values are and/or
    When:
        - Execute get_custom_script_list command
    Then:
        - validate an id, filename and filetype are returned
    """
    client = Mock()
    client.script.list = Mock(return_value=get_custom_script_list_mock_response())
    args = {"filename": "test-script.sh", "filetype": "bash", "query_op": "or"}
    result = get_custom_script_list(client, args)
    assert isinstance(result.outputs[0]["id"], str)
    assert isinstance(result.outputs[0]["filename"], str)
    assert isinstance(result.outputs[0]["filetype"], str)
    assert result.outputs_prefix == "VisionOne.Get_Custom_Script_List"
    assert result.outputs_key_field == "id"


# Mock function to download custom script
def download_custom_script_mock_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=TextResp(text="#!/bin/sh echo 'Download script'"),
    )


# Test case to download a custom script
def test_download_custom_script(mocker):
    """
    Given:
        - script_id -> The ID for a custom script to download
    When:
        - Execute download_custom_script command
    Then:
        - validate text response for downloaded script
    """
    client = Mock()
    client.script.download = Mock(return_value=download_custom_script_mock_response())
    args = {"script_id": "44c99cb0-8c5f-4182-af55-62135dbe32f1"}
    result = download_custom_script(client, args)
    assert result.outputs["text"] == "#!/bin/sh echo 'Download script'"
    assert result.outputs_prefix == "VisionOne.Download_Custom_Script"
    assert result.outputs_key_field == "text"


# Mock function to delete custom script
def delete_custom_script_mock_response(*args, **kwargs):
    with open("./test_data/delete_custom_script.json") as f:
        return_value: dict[str, str] = json.load(f)
    return Result(
        result_code=ResultCode.SUCCESS,
        response=NoContentResp(**return_value),
    )


# Test case to delete a custom script
def test_delete_custom_script(mocker):
    """
    Given:
        - script_id -> The ID of a custom script to delete
    When:
        - Execute delete_custom_script command
    Then:
        - validate a success response
    """
    client = Mock()
    client.script.delete = Mock(return_value=delete_custom_script_mock_response())
    args = {"script_id": "44c99cb0-8c5f-4182-af55-62135dbe32f1"}
    result = delete_custom_script(client, args)
    assert isinstance(result.outputs["status"], str)
    assert result.outputs_prefix == "VisionOne.Delete_Custom_Script"
    assert result.outputs_key_field == "status"


# Mock function to add custom script
def add_custom_script_mock_response(*args, **kwargs):
    return Result(
        result_code=ResultCode.SUCCESS,
        response=AddCustomScriptResp(script_id="44c99cb0-8c5f-4182-af55-62135dbe32f1"),
    )


# Test case to add a custom script
def test_add_custom_script(mocker):
    """
    Given:
        - filename -> Name of the custom script
        - filetype -> Filetype of the custom script
        - description -> Optional description for the custom script
        - script_contents -> Contents of the custom script
    When:
        - Execute add_custom_script command
    Then:
        - validate an ID is returned after successful action completion
    """
    client = Mock()
    client.script.create = Mock(return_value=add_custom_script_mock_response())
    args = {
        "file_url": "http://someurl.com/testscript.sh",
        "filename": "test_script.sh",
        "filetype": "bash",
        "description": "Script to delete duplicates.",
    }
    mocker.patch("TrendMicroVisionOneV3.requests.get", mocked_requests_get)
    mocker.patch("TrendMicroVisionOneV3.requests.post", mocked_requests_post)
    result = add_custom_script(client, args)
    assert result.outputs["id"] == "44c99cb0-8c5f-4182-af55-62135dbe32f1"
    assert result.outputs_prefix == "VisionOne.Add_Custom_Script"
    assert result.outputs_key_field == "id"


# Mock function to update custom script
def update_custom_script_mock_response(*args, **kwargs):
    with open("./test_data/update_custom_script.json") as f:
        return_value: dict[str, str] = json.load(f)
    return Result(
        result_code=ResultCode.SUCCESS,
        response=NoContentResp(**return_value),
    )


# Test case to update a custom script
def test_update_custom_script(mocker):
    """
    Given:
        - filename -> Name of the custom script
        - filetype -> Filetype of the custom script
        - script_id -> ID of the custom script to update
        - script_contents -> New contents of the custom script
        - description -> Optional description for the custom script
    When:
        - Execute update_custom_script command
    Then:
        - validate a success response
    """
    client = Mock()
    client.script.update = Mock(return_value=update_custom_script_mock_response())
    mocker.patch("TrendMicroVisionOneV3.requests.get", mocked_requests_get)
    mocker.patch("TrendMicroVisionOneV3.requests.post", mocked_requests_post)
    args = {
        "filetype": "bash",
        "filename": "test_script.sh",
        "script_id": "44c99cb0-8c5f-4182-af55-62135dbe32f1",
        "file_url": "http://someurl.com/test1script.sh",
        "description": "Script to update values.",
    }
    result = update_custom_script(client, args)
    assert result.outputs["status"] == "SUCCESS"
    assert result.outputs_prefix == "VisionOne.Update_Custom_Script"
    assert result.outputs_key_field == "status"


# Mock response for get observed attack techniques events
def get_observed_attack_techniques_mock_response(*args, **kwargs):
    with open("./test_data/get_observed_attack_techniques.json") as f:
        attack_techniques: dict[str, Any] = json.load(f)
    return Result(
        result_code=ResultCode.SUCCESS,
        response=ListOatsResp(
            next_link="https://somelink.com",
            items=[OatEvent(**attack_techniques)],
            total_count=30,
            count=10,
        ),
    )


# Test case for fetching observed attack techniques
def test_get_observed_attack_techniques(mocker):
    """
    Given:
        - detected_start -> Detection start date time
        - detected_end -> Detection end date time
        - ingested_start -> Ingestion start date time
        - ingested_end -> Ingestion end date time
        - top -> Number of records displayed on a page.
        - query_op -> Conditional operator used to build request that allows
            user to retrieve a subset of the collected Observed Attack Techniques events
        - fields -> Required filter (A dictionary object with key/value used to create a query string) for
            retrieving a subset of the collected Observed Attack Techniques events
    When:
        - Execute get_observed_attack_techniques command
    Then:
        - validate a string id response
    """
    client = Mock()
    client.oat.list = Mock(return_value=get_observed_attack_techniques_mock_response())
    args = {
        "detected_start": "2024-01-15T10:00:00Z",
        "detected_end": "2024-05-15T10:00:00Z",
        "ingested_start": "2024-01-15T10:00:00Z",
        "ingested_end": "2024-05-15T10:00:00Z",
        "top": 10,
        "query_op": "or",
        "fields": json.dumps({"endpointName": "sample-host", "riskLevel": "low"}),
    }
    result = get_observed_attack_techniques(client, args)
    assert isinstance(result.outputs[0]["id"], str)
    assert result.outputs_prefix == "VisionOne.Get_Observed_Attack_Techniques"
    assert result.outputs_key_field == "id"


def test_xsoar_status_to_vision_one():
    """
    Test the xsoar_status_to_vision_one helper function that maps XSOAR incident statuses
    to Vision One alert statuses.

    Given:
        - incident_status: XSOAR IncidentStatus value (0=Pending, 1=Active, 2=Closed, or unknown)
    When:
        - Execute xsoar_status_to_vision_one function
    Then:
        - Validate correct mapping to Vision One status
    """
    # Test Pending (0) -> "open"
    status = xsoar_status_to_vision_one(0)
    assert status == "open"

    # Test Active (1) -> "in_progress"
    status = xsoar_status_to_vision_one(1)
    assert status == "in_progress"

    # Test Closed (2) -> "closed"
    status = xsoar_status_to_vision_one(2)
    assert status == "closed"

    # Test Unknown status (999) -> defaults to "open"
    status = xsoar_status_to_vision_one(999)
    assert status == "open"


# ========== Outgoing Mirroring Tests (update-remote-system) ==========


def test_update_remote_system_no_remote_id(mocker):
    """
    Test update_remote_system when no remote ID is provided.

    Given:
        - No remote incident ID (empty string)
    When:
        - Execute update_remote_system command
    Then:
        - Should return empty string without making API calls
    """
    client = Mock()
    mocker.patch.object(demisto, "error")

    args = {
        "remoteId": "",
        "data": {"status": 2},
        "entries": [],
        "incidentChanged": True,
    }

    result = update_remote_system_command(client, args)

    # Should return empty string without any API calls
    assert result == ""
    client.alert.get.assert_not_called()


def test_update_remote_system_incident_not_changed(mocker):
    """
    Test update_remote_system when incident has not changed.

    Given:
        - Remote incident ID
        - incidentChanged is False
    When:
        - Execute update_remote_system command
    Then:
        - Should return remote ID without making API calls
    """
    client = Mock()
    mocker.patch.object(demisto, "error")

    args = {
        "remoteId": "WB-14-20190709-00003",
        "data": {"status": 1},
        "entries": [],
        "incidentChanged": False,
    }

    result = update_remote_system_command(client, args)

    # Should return remote ID without calling API
    assert result == "WB-14-20190709-00003"
    client.alert.get.assert_not_called()


def test_update_remote_system_status_update_success(mocker):
    """
    Test update_remote_system when incident status changes successfully.

    Given:
        - Incident status changed to Closed (2)
        - Close reason "Resolved"
    When:
        - Execute update_remote_system command
    Then:
        - Should retrieve alert to get ETag
        - Should update Vision One alert status to "closed" with investigation result TRUE_POSITIVE
    """
    from pytmv1 import AlertStatus, InvestigationResult, GetAlertResp, Result, ResultCode, MultiResp

    client = Mock()
    mocker.patch.object(demisto, "error")

    # Mock alert.get() response - return success with etag
    mock_alert_resp = Mock(spec=GetAlertResp)
    mock_alert_resp.etag = "test-etag-123"

    mock_get_result = Mock(spec=Result)
    mock_get_result.result_code = ResultCode.SUCCESS
    mock_get_result.response = mock_alert_resp
    mock_get_result.error = None

    client.alert.get.return_value = mock_get_result

    # Mock alert.update_status() response - return success
    mock_update_result = Mock(spec=MultiResp)
    mock_update_result.result_code = ResultCode.SUCCESS
    mock_update_result.error = None

    client.alert.update_status.return_value = mock_update_result

    args = {
        "remoteId": "WB-14-20190709-00003",
        "data": {"status": 2, "closeReason": "Resolved"},
        "entries": [],
        "incidentChanged": True,
    }

    result = update_remote_system_command(client, args)

    # Should return remote ID
    assert result == "WB-14-20190709-00003"

    # Verify alert.get was called
    client.alert.get.assert_called_once_with(alert_id="WB-14-20190709-00003")

    # Verify alert.update_status was called with correct parameters
    client.alert.update_status.assert_called_once()
    call_args = client.alert.update_status.call_args
    assert call_args.kwargs["alert_id"] == "WB-14-20190709-00003"
    assert call_args.kwargs["status"] == AlertStatus.CLOSED
    assert call_args.kwargs["etag"] == "test-etag-123"
    assert call_args.kwargs["inv_result"] == InvestigationResult.TRUE_POSITIVE


def test_update_remote_system_with_close_notes(mocker):
    """
    Test update_remote_system when incident is closed with close notes.

    Given:
        - Incident closed with closeNotes
    When:
        - Execute update_remote_system command
    Then:
        - Should update status
        - Should add closing note to Vision One alert
    """
    from pytmv1 import GetAlertResp, Result, ResultCode, MultiResp

    client = Mock()
    mocker.patch.object(demisto, "error")

    # Mock alert.get() response
    mock_alert_resp = Mock(spec=GetAlertResp)
    mock_alert_resp.etag = "test-etag-456"

    mock_get_result = Mock(spec=Result)
    mock_get_result.result_code = ResultCode.SUCCESS
    mock_get_result.response = mock_alert_resp
    mock_get_result.error = None

    client.alert.get.return_value = mock_get_result

    # Mock alert.update_status() response
    mock_update_result = Mock(spec=MultiResp)
    mock_update_result.result_code = ResultCode.SUCCESS
    mock_update_result.error = None

    client.alert.update_status.return_value = mock_update_result

    # Mock note.create() response
    mock_note_result = Mock(spec=Result)
    mock_note_result.result_code = ResultCode.SUCCESS
    mock_note_result.error = None

    client.note.create.return_value = mock_note_result

    args = {
        "remoteId": "WB-14-20190709-00003",
        "data": {
            "status": 2,
            "closeReason": "Resolved",
            "closeNotes": "Confirmed false positive after investigation",
            "closingUserId": "analyst@example.com",
            "id": "12345",
        },
        "entries": [],
        "incidentChanged": True,
    }

    result = update_remote_system_command(client, args)

    # Should return remote ID
    assert result == "WB-14-20190709-00003"

    # Verify note.create was called
    client.note.create.assert_called_once()
    call_args = client.note.create.call_args
    assert call_args.kwargs["alert_id"] == "WB-14-20190709-00003"
    assert "XSOAR Incident ID: 12345" in call_args.kwargs["note_content"]
    assert "Close Reason: Resolved" in call_args.kwargs["note_content"]
    assert "analyst@example.com" in call_args.kwargs["note_content"]
    assert "Confirmed false positive after investigation" in call_args.kwargs["note_content"]


def test_update_remote_system_close_reason_mapping(mocker):
    """
    Test update_remote_system close reason to investigation result mapping.

    Given:
        - Incident closed with different close reasons
    When:
        - Execute update_remote_system command
    Then:
        - Should map close reasons correctly to investigation results
    """
    from pytmv1 import InvestigationResult, GetAlertResp, Result, ResultCode, MultiResp

    client = Mock()
    mocker.patch.object(demisto, "error")

    # Mock responses
    mock_alert_resp = Mock(spec=GetAlertResp)
    mock_alert_resp.etag = "test-etag"

    mock_get_result = Mock(spec=Result)
    mock_get_result.result_code = ResultCode.SUCCESS
    mock_get_result.response = mock_alert_resp
    mock_get_result.error = None

    client.alert.get.return_value = mock_get_result

    mock_update_result = Mock(spec=MultiResp)
    mock_update_result.result_code = ResultCode.SUCCESS
    mock_update_result.error = None

    client.alert.update_status.return_value = mock_update_result

    # Test case 1: "False Positive" -> FALSE_POSITIVE
    args_fp = {
        "remoteId": "WB-TEST",
        "data": {"status": 2, "closeReason": "False Positive"},
        "entries": [],
        "incidentChanged": True,
    }
    update_remote_system_command(client, args_fp)
    call_args = client.alert.update_status.call_args
    assert call_args.kwargs["inv_result"] == InvestigationResult.FALSE_POSITIVE

    # Reset mock
    client.alert.update_status.reset_mock()

    # Test case 2: "Resolved" -> TRUE_POSITIVE
    args_resolved = {
        "remoteId": "WB-TEST",
        "data": {"status": 2, "closeReason": "Resolved"},
        "entries": [],
        "incidentChanged": True,
    }
    update_remote_system_command(client, args_resolved)
    call_args = client.alert.update_status.call_args
    assert call_args.kwargs["inv_result"] == InvestigationResult.TRUE_POSITIVE

    # Reset mock
    client.alert.update_status.reset_mock()

    # Test case 3: "Duplicate" -> NO_FINDINGS
    args_duplicate = {
        "remoteId": "WB-TEST",
        "data": {"status": 2, "closeReason": "Duplicate"},
        "entries": [],
        "incidentChanged": True,
    }
    update_remote_system_command(client, args_duplicate)
    call_args = client.alert.update_status.call_args
    assert call_args.kwargs["inv_result"] == InvestigationResult.NO_FINDINGS

    # Reset mock
    client.alert.update_status.reset_mock()

    # Test case 4: "Other" -> NOTEWORTHY
    args_other = {
        "remoteId": "WB-TEST",
        "data": {"status": 2, "closeReason": "Other"},
        "entries": [],
        "incidentChanged": True,
    }
    update_remote_system_command(client, args_other)
    call_args = client.alert.update_status.call_args
    assert call_args.kwargs["inv_result"] == InvestigationResult.NOTEWORTHY


def test_update_remote_system_api_error(mocker):
    """
    Test update_remote_system when API returns an error.

    Given:
        - Vision One API returns error when getting alert
    When:
        - Execute update_remote_system command
    Then:
        - Should log error and return remote ID without updating
    """
    from pytmv1 import Result, ResultCode, Error

    client = Mock()
    mock_error_logger = mocker.patch.object(demisto, "error")

    # Mock alert.get() to return error
    mock_error = Mock(spec=Error)
    mock_error.message = "Alert not found"

    mock_get_result = Mock(spec=Result)
    mock_get_result.result_code = ResultCode.ERROR
    mock_get_result.response = None
    mock_get_result.error = mock_error

    client.alert.get.return_value = mock_get_result

    args = {
        "remoteId": "WB-INVALID",
        "data": {"status": 2},
        "entries": [],
        "incidentChanged": True,
    }

    result = update_remote_system_command(client, args)

    # Should return remote ID even on error
    assert result == "WB-INVALID"

    # Should have logged error
    assert mock_error_logger.called
    error_msg = mock_error_logger.call_args[0][0]
    assert "Error fetching alert" in error_msg
    assert "WB-INVALID" in error_msg

    # Should not call update_status
    client.alert.update_status.assert_not_called()


# ========== Incoming Mirroring Tests (get-modified-remote-data) ==========


def test_vision_one_status_to_xsoar():
    """
    Test the vision_one_status_to_xsoar helper function that maps Vision One alert statuses
    to XSOAR incident statuses.

    Given:
        - v1_status: Vision One alert status string
    When:
        - Execute vision_one_status_to_xsoar function
    Then:
        - Validate correct mapping to XSOAR IncidentStatus values
    """
    # Test "Open" -> 0 (Pending) - Vision One API format
    status = vision_one_status_to_xsoar("Open")
    assert status == 0

    # Test "In Progress" -> 1 (Active) - Vision One API format
    status = vision_one_status_to_xsoar("In Progress")
    assert status == 1

    # Test "Closed" -> 2 (Closed) - Vision One API format
    status = vision_one_status_to_xsoar("Closed")
    assert status == 2

    # Test unknown status -> defaults to 0 (Pending)
    status = vision_one_status_to_xsoar("unknown_status")
    assert status == 0


def test_get_modified_remote_data_success(mocker):
    """
    Test get_modified_remote_data returns modified alert IDs.

    Given:
        - last_update timestamp
    When:
        - Execute get_modified_remote_data command
        - Vision One returns alerts updated since last_update
    Then:
        - Should return list of modified alert IDs
    """
    from pytmv1 import SaeAlert

    client = Mock()
    mocker.patch.object(demisto, "error")

    # Mock alert.consume to call callback with test alerts
    def mock_consume(callback, **kwargs):
        # Create mock alerts
        alert1 = Mock(spec=SaeAlert)
        alert1.id = "WB-ALERT-001"

        alert2 = Mock(spec=SaeAlert)
        alert2.id = "WB-ALERT-002"

        # Call the callback for each alert
        callback(alert1)
        callback(alert2)

    client.alert.consume = mock_consume

    args = {
        "lastUpdate": "2025-01-01T00:00:00Z",
    }

    result = get_modified_remote_data_command(client, args)

    # Should return list of modified alert IDs
    assert len(result.modified_incident_ids) == 2
    assert "WB-ALERT-001" in result.modified_incident_ids
    assert "WB-ALERT-002" in result.modified_incident_ids


def test_get_modified_remote_data_no_last_update(mocker):
    """
    Test get_modified_remote_data when no last_update provided.

    Given:
        - No last_update timestamp
    When:
        - Execute get_modified_remote_data command
    Then:
        - Should default to 1 hour ago
        - Should return 0 modified alerts
    """
    from pytmv1 import SaeAlert

    client = Mock()
    mocker.patch.object(demisto, "error")

    # Mock alert.consume
    def mock_consume(callback, **kwargs):
        alert = Mock(spec=SaeAlert)
        alert.id = "WB-ALERT-003"
        callback(alert)

    client.alert.consume = mock_consume

    args = {}

    result = get_modified_remote_data_command(client, args)

    # Should return results even without last_update
    assert len(result.modified_incident_ids) == 0


def test_get_modified_remote_data_invalid_timestamp(mocker):
    """
    Test get_modified_remote_data with invalid timestamp format.

    Given:
        - Invalid last_update timestamp format
    When:
        - Execute get_modified_remote_data command
    Then:
        - Should log error
        - Should default to 1 hour ago
        - Should still return results
    """
    from pytmv1 import SaeAlert

    client = Mock()
    mock_error_logger = mocker.patch.object(demisto, "error")

    # Mock alert.consume
    def mock_consume(callback, **kwargs):
        alert = Mock(spec=SaeAlert)
        alert.id = "WB-ALERT-004"
        callback(alert)

    client.alert.consume = mock_consume

    args = {
        "lastUpdate": "invalid-timestamp-format",
    }

    result = get_modified_remote_data_command(client, args)

    # Should log error about invalid format
    assert mock_error_logger.called
    error_msg = mock_error_logger.call_args[0][0]
    assert "Invalid last_update format" in error_msg

    # Should still return results
    assert len(result.modified_incident_ids) == 1


def test_get_modified_remote_data_api_error(mocker):
    """
    Test get_modified_remote_data when API throws exception.

    Given:
        - Vision One API throws exception
    When:
        - Execute get_modified_remote_data command
    Then:
        - Should log error
        - Should return empty list
    """
    client = Mock()
    mock_error_logger = mocker.patch.object(demisto, "error")

    # Mock alert.consume to raise exception
    client.alert.consume.side_effect = Exception("API connection error")

    args = {
        "lastUpdate": "2025-01-01T00:00:00Z",
    }

    result = get_modified_remote_data_command(client, args)

    # Should log error
    assert mock_error_logger.called

    # Should return empty list
    assert len(result.modified_incident_ids) == 0


# ========== Incoming Mirroring Tests (get-remote-data) ==========


def test_get_remote_data_no_alert_id(mocker):
    """
    Test get_remote_data when no alert ID is provided.

    Given:
        - Empty or missing alert ID
    When:
        - Execute get_remote_data command
    Then:
        - Should return empty response
    """
    client = Mock()
    mocker.patch.object(demisto, "error")

    args = {
        "id": "",
        "lastUpdate": "2025-01-01T00:00:00Z",
    }

    result = get_remote_data_command(client, args)

    # Should return empty response
    assert result.mirrored_object == {}
    assert len(result.entries) == 0

    # Should not call API
    client.alert.get.assert_not_called()


def test_get_remote_data_alert_not_modified(mocker):
    """
    Test get_remote_data when alert was not modified since last_update.

    Given:
        - Alert updated time is before last_update
    When:
        - Execute get_remote_data command
    Then:
        - Should return empty response (optimization)
    """
    from pytmv1 import GetAlertResp, Result, ResultCode

    client = Mock()
    mocker.patch.object(demisto, "error")

    # Mock alert.get() to return alert with old update time
    mock_alert_data = Mock()
    mock_alert_data.model_dump.return_value = {
        "id": "WB-ALERT-OLD",
        "status": "Open",
        "severity": "medium",
        "updated_date_time": "2025-01-01T00:00:00Z",  # Before last_update
    }

    mock_alert_resp = Mock(spec=GetAlertResp)
    mock_alert_resp.data = mock_alert_data

    mock_get_result = Mock(spec=Result)
    mock_get_result.result_code = ResultCode.SUCCESS
    mock_get_result.response = mock_alert_resp
    mock_get_result.error = None

    client.alert.get.return_value = mock_get_result

    args = {
        "id": "WB-ALERT-OLD",
        "lastUpdate": "2025-01-02T00:00:00Z",  # After alert update time
    }

    result = get_remote_data_command(client, args)

    # Should return empty response (not modified)
    assert result.mirrored_object == {}
    assert len(result.entries) == 0


def test_get_remote_data_success_closed_alert(mocker):
    """
    Test get_remote_data when alert status is closed.

    Given:
        - Alert with status "Closed" (realistic Vision One data structure)
    When:
        - Execute get_remote_data command
    Then:
        - Should return incident data with status 2 (Closed)
        - Should add close entry
        - Should preserve impact_scope and indicators fields
    """
    from pytmv1 import GetAlertResp, Result, ResultCode

    client = Mock()
    mocker.patch.object(demisto, "error")

    # Mock alert.get() to return closed alert with realistic Vision One structure
    mock_alert_data = Mock()
    mock_alert_data.model_dump.return_value = {
        "schema_version": "1.12",
        "id": "WB-ALERT-CLOSED",
        "status": "Closed",
        "severity": "high",
        "investigation_status": "Closed",
        "investigation_result": "True Positive",
        "updated_date_time": "2025-01-03T00:00:00Z",
        "created_date_time": "2025-01-01T00:00:00Z",
        "model": "Privilege Escalation via UAC Bypass",
        "score": 64,
        "workbench_link": "test/...",
        "impact_scope": {
            "desktop_count": 1,
            "server_count": 0,
            "account_count": 1,
            "entities": [
                {
                    "entity_type": "account",
                    "entity_value": "domain\\user",
                    "entity_id": "domain\\user",
                    "related_entities": ["HOST-GUID"],
                    "provenance": ["Alert"],
                },
                {
                    "entity_type": "host",
                    "entity_value": {"guid": "HOST-GUID", "name": "test-host", "ips": ["10.0.0.1"]},
                    "entity_id": "HOST-GUID",
                    "related_entities": ["domain\\user"],
                    "related_indicator_ids": [1, 2],
                    "provenance": ["Alert"],
                },
            ],
        },
        "indicators": [
            {
                "id": 1,
                "type": "command_line",
                "field": "processCmd",
                "value": "powershell.exe -enc ...",
                "related_entities": ["HOST-GUID"],
                "provenance": ["Alert"],
            },
            {
                "id": 2,
                "type": "registry_key",
                "field": "objectRegistryKeyHandle",
                "value": "hkcr\\ms-settings\\shell\\open\\command",
                "related_entities": ["HOST-GUID"],
                "provenance": ["Alert"],
            },
        ],
        "matched_rules": [{"id": "rule-id", "name": "UAC Bypass Rule", "matched_filters": []}],
    }

    mock_alert_resp = Mock(spec=GetAlertResp)
    mock_alert_resp.data = mock_alert_data

    mock_get_result = Mock(spec=Result)
    mock_get_result.result_code = ResultCode.SUCCESS
    mock_get_result.response = mock_alert_resp
    mock_get_result.error = None

    client.alert.get.return_value = mock_get_result

    args = {
        "id": "WB-ALERT-CLOSED",
        "lastUpdate": "2025-01-01T00:00:00Z",
    }

    result = get_remote_data_command(client, args)

    # Should return incident data with closed status
    assert result.mirrored_object["id"] == "WB-ALERT-CLOSED"
    assert result.mirrored_object["status"] == "Closed"  # Closed

    # Should have close entry
    assert len(result.entries) == 1
    close_entry = result.entries[0]
    assert close_entry["Type"] == 1  # Note


def test_get_remote_data_success_open_alert(mocker):
    """
    Test get_remote_data when alert status is open or in progress.

    Given:
        - Alert with status "In Progress" (realistic Vision One data structure)
    When:
        - Execute get_remote_data command
    Then:
        - Should return incident data with status 1 (Active)
        - Should not add any entries (XSOAR handles status update automatically)
        - Should preserve impact_scope and indicators fields
    """
    from pytmv1 import GetAlertResp, Result, ResultCode

    client = Mock()
    mocker.patch.object(demisto, "error")

    # Mock alert.get() to return in-progress alert with realistic Vision One structure
    mock_alert_data = Mock()
    mock_alert_data.model_dump.return_value = {
        "schema_version": "1.12",
        "id": "WB-ALERT-ACTIVE",
        "status": "In Progress",
        "severity": "medium",
        "investigation_status": "In Progress",
        "updated_date_time": "2025-01-03T00:00:00Z",
        "created_date_time": "2025-01-01T00:00:00Z",
        "model": "Suspicious Network Activity",
        "score": 45,
        "workbench_link": "test/...",
        "impact_scope": {
            "desktop_count": 1,
            "server_count": 0,
            "account_count": 1,
            "entities": [
                {
                    "entity_type": "host",
                    "entity_value": {"guid": "HOST-GUID-123", "name": "workstation-01", "ips": ["192.168.1.100"]},
                    "entity_id": "HOST-GUID-123",
                    "related_entities": ["user@domain.com"],
                    "related_indicator_ids": [1],
                    "provenance": ["Alert"],
                }
            ],
        },
        "indicators": [
            {
                "id": 1,
                "type": "ip",
                "field": "dst",
                "value": "test value",
                "related_entities": ["HOST-GUID-123"],
                "provenance": ["Alert"],
            }
        ],
        "matched_rules": [{"id": "rule-id-456", "name": "Outbound Connection to Known Bad IP", "matched_filters": []}],
    }

    mock_alert_resp = Mock(spec=GetAlertResp)
    mock_alert_resp.data = mock_alert_data

    mock_get_result = Mock(spec=Result)
    mock_get_result.result_code = ResultCode.SUCCESS
    mock_get_result.response = mock_alert_resp
    mock_get_result.error = None

    client.alert.get.return_value = mock_get_result

    args = {
        "id": "WB-ALERT-ACTIVE",
        "lastUpdate": "2025-01-01T00:00:00Z",
    }

    result = get_remote_data_command(client, args)

    # Should return incident data with active status
    assert result.mirrored_object["id"] == "WB-ALERT-ACTIVE"
    assert result.mirrored_object["status"] == "In Progress"  # Active

    assert len(result.entries) == 1


def test_get_remote_data_alert_not_found(mocker):
    """
    Test get_remote_data when alert is not found.

    Given:
        - Vision One API returns error (alert not found)
    When:
        - Execute get_remote_data command
    Then:
        - Should log error
        - Should return empty response
    """
    from pytmv1 import Result, ResultCode, Error

    client = Mock()
    mock_error_logger = mocker.patch.object(demisto, "error")

    # Mock alert.get() to return error
    mock_error = Mock(spec=Error)
    mock_error.message = "Alert not found"

    mock_get_result = Mock(spec=Result)
    mock_get_result.result_code = ResultCode.ERROR
    mock_get_result.response = None
    mock_get_result.error = mock_error

    client.alert.get.return_value = mock_get_result

    args = {
        "id": "WB-NONEXISTENT",
        "lastUpdate": "2025-01-01T00:00:00Z",
    }

    result = get_remote_data_command(client, args)

    # Should log error
    assert mock_error_logger.called
    error_msg = mock_error_logger.call_args[0][0]
    assert "Error fetching alert" in error_msg

    # Should return empty response
    assert result.mirrored_object == {}
    assert len(result.entries) == 0


# ========== Mapping Fields Tests ==========


def test_get_mapping_fields(mocker):
    """
    Test get_mapping_fields returns correct field mappings.

    Given:
        - No arguments (function takes no parameters)
    When:
        - Execute get_mapping_fields command
    Then:
        - Should return GetMappingFieldsResponse with SchemeTypeMapping
        - Should include mirrored Vision One alert fields
    """
    mocker.patch.object(demisto, "error")

    # get_mapping_fields() takes no parameters
    result = get_mapping_fields_command()

    # Should return GetMappingFieldsResponse
    assert result is not None
    assert len(result.scheme_types_mappings) > 0

    # Verify incident type name
    scheme_type = result.scheme_types_mappings[0]
    assert scheme_type.type_name == "Trend Micro Vision One XDR Incident"
    fields: dict = scheme_type.fields
    # Verify mirrored fields are present
    field_names = [field_key for field_key, _ in fields.items()]
    assert "status" in field_names
    assert "severity" in field_names
    assert "investigation_result" in field_names