GravityZone

GravityZone provides secure access to incident and endpoint data and enables remediation actions through its APIs.

Endpoint · GravityZone

Details

IDGravityZone
CategoryEndpoint
From Version6.10.0
Docker Imagedemisto/python3:3.12.13.10381435

README

GravityZone provides secure access to incident and endpoint data and enables remediation actions through its APIs.
This integration was integrated and tested with version 6.6 of GravityZone.

Configure GravityZone in Cortex

Parameter Description Required
Server URL The URL of your GravityZone Cloud instance. True
API key API key to access the service REST API. True
Trust any certificate (not secure) When selected, the server certificates are not verified. False
Use system proxy settings Use the system proxy settings for connecting to the server. False
Fetch incidents When selected, the integration will fetch incidents from the server. False
Maximum incidents to fetch Maximum number of incidents per fetch. The default value is 50. False
First fetch time The time period from which the first fetch will start. False
Mirroring Direction The mirroring direction in which to mirror the incident. You can mirror “Incoming” (from GravityZone to Cortex XSOAR), “Outgoing” (from Cortex XSOAR to GravityZone), or in both directions. False
Incident type   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.

fetch-incidents


Retrieves incidents from GravityZone Cloud.

Base Command

fetch-incidents

Context Output

There is no context output for this command.

gz-endpoint-list


Retrieves the list of managed endpoints.

Base Command

gz-endpoint-list

Input

Argument Name Description Required
limit The maximum number of endpoints to retrieve. Optional
name The endpoint name filter. Returns endpoints whose hostnames start with the specified value. The value must be at least 3 characters long. Supports an optional single leading ‘*’ wildcard pattern. Optional
node_id The ID of the target GravityZone company or network inventory group. If not specified, the default value is the ID of the company associated with the API key used to make the request. Optional

Context Output

Path Type Description
GravityZone.EndpointsList.ID String The endpoint ID.
GravityZone.EndpointsList.Hostname String The endpoint hostname.
GravityZone.EndpointsList.IP String The endpoint IP address.
GravityZone.EndpointsList.OS String The endpoint operating system version.
GravityZone.EndpointsList.MAC String The endpoint MAC address.
GravityZone.EndpointsList.Vendor String The endpoint vendor.
GravityZone.EndpointsList.FQDN String The endpoint’s fully qualified domain name (FQDN).
GravityZone.EndpointsList.CompanyID String The GravityZone company ID where the endpoint is located.
GravityZone.EndpointsList.GroupID String The GravityZone group ID where the endpoint is located.

Command example


#### Context Example

```json
{
    "GravityZone": {
        "EndpointsList": [
            {
                "CompanyID": "6909d1859866985b410b2969",
                "FQDN": "win",
                "GroupID": "6909d1869866985b410b296e",
                "Hostname": "WIN",
                "ID": "699d81cdab613e65696e452e",
                "IP": "IP1",
                "MAC": "005056b1b175",
                "OS": "Windows 10 Pro",
                "Vendor": "GravityZone"
            },
            {
                "CompanyID": "6909d1859866985b410b2969",
                "FQDN": "xdr-nsva",
                "GroupID": "6909d1869866985b410b296e",
                "Hostname": "xdr-nsva",
                "ID": "69fc10a547f2e985e6774a0f",
                "IP": "IP2",
                "MAC": "005056b156b1",
                "OS": "Linux Ubuntu 24.04.4 LTS",
                "Vendor": "GravityZone"
            },
            {
                "CompanyID": "6909d1859866985b410b2969",
                "FQDN": "ta349cf3rjt5",
                "GroupID": "6909d1869866985b410b296e",
                "Hostname": "TA349CF3RJT5",
                "ID": "6a6043865de62c6f81270b8d",
                "IP": "IP3",
                "MAC": "005056b8bfd3",
                "OS": "Windows 10 Enterprise",
                "Vendor": "GravityZone"
            }
        ]
    }
}

Human Readable Output

GravityZone Endpoints List

ID Hostname IP OS MAC Vendor FQDN CompanyID GroupID
699d81cdab613e65696e452e WIN IP1 Windows 10 Pro 005056b1b175 GravityZone win 6909d1859866985b410b2969 6909d1869866985b410b296e
69fc10a547f2e985e6774a0f xdr-nsva IP2 Linux Ubuntu 24.04.4 LTS 005056b156b1 GravityZone xdr-nsva 6909d1859866985b410b2969 6909d1869866985b410b296e
6a6043865de62c6f81270b8d TA349CF3RJT5 IP3 Windows 10 Enterprise 005056b8bfd3 GravityZone ta349cf3rjt5 6909d1859866985b410b2969 6909d1869866985b410b296e

Command example

!gz-endpoint-list name=TA66

Human Readable Output

GravityZone Endpoints List

No entries.

Command example

!gz-endpoint-list node_id=6909d1859866985b410b2969

Context Example

{
    "GravityZone": {
        "EndpointsList": [
            {
                "CompanyID": "6909d1859866985b410b2969",
                "FQDN": "win",
                "GroupID": "6909d1869866985b410b296e",
                "Hostname": "WIN",
                "ID": "699d81cdab613e65696e452e",
                "IP": "IP1",
                "MAC": "005056b1b175",
                "OS": "Windows 10 Pro",
                "Vendor": "GravityZone"
            },
            {
                "CompanyID": "6909d1859866985b410b2969",
                "FQDN": "xdr-nsva",
                "GroupID": "6909d1869866985b410b296e",
                "Hostname": "xdr-nsva",
                "ID": "69fc10a547f2e985e6774a0f",
                "IP": "IP2",
                "MAC": "005056b156b1",
                "OS": "Linux Ubuntu 24.04.4 LTS",
                "Vendor": "GravityZone"
            },
            {
                "CompanyID": "6909d1859866985b410b2969",
                "FQDN": "ta349cf3rjt5",
                "GroupID": "6909d1869866985b410b296e",
                "Hostname": "TA349CF3RJT5",
                "ID": "6a6043865de62c6f81270b8d",
                "IP": "IP3",
                "MAC": "005056b8bfd3",
                "OS": "Windows 10 Enterprise",
                "Vendor": "GravityZone"
            }
        ]
    }
}

Human Readable Output

GravityZone Endpoints List

ID Hostname IP OS MAC Vendor FQDN CompanyID GroupID
699d81cdab613e65696e452e WIN IP1 Windows 10 Pro 005056b1b175 GravityZone win 6909d1859866985b410b2969 6909d1869866985b410b296e
69fc10a547f2e985e6774a0f xdr-nsva IP2 Linux Ubuntu 24.04.4 LTS 005056b156b1 GravityZone xdr-nsva 6909d1859866985b410b2969 6909d1869866985b410b296e
6a6043865de62c6f81270b8d TA349CF3RJT5 IP3 Windows 10 Enterprise 005056b8bfd3 GravityZone ta349cf3rjt5 6909d1859866985b410b2969 6909d1869866985b410b296e

gz-endpoint-get


Retrieves endpoint details by endpoint ID.

Base Command

gz-endpoint-get

Input

Argument Name Description Required
id The ID of the endpoint to retrieve. Required

Context Output

Path Type Description
GravityZone.Endpoint.ID String The endpoint ID.
GravityZone.Endpoint.Hostname String The endpoint hostname.
GravityZone.Endpoint.IP String The endpoint IP address.
GravityZone.Endpoint.OS String The endpoint operating system version.
GravityZone.Endpoint.Status String The endpoint status.
GravityZone.Endpoint.Vendor String The endpoint vendor.
GravityZone.Endpoint.LastLoggedUsers String The last users who logged on the endpoint.
Endpoint.ID String The endpoint ID.
Endpoint.Hostname String The endpoint hostname.
Endpoint.IPAddress String The endpoint IP address.
Endpoint.OS String The endpoint operating system version.
Endpoint.Status String The endpoint status.
Endpoint.Vendor String The endpoint vendor.

Command example

!gz-endpoint-get id=6942a43afe8d4e463ca5c197

Context Example

{
    "Endpoint": {
        "Hostname": "bdvm",
        "ID": "6942a43afe8d4e463ca5c197",
        "IPAddress": "1.1.1.1",
        "OS": "Linux Ubuntu 24.04.2 LTS",
        "Status": "Online",
        "Vendor": "GravityZone"
    },
    "GravityZone": {
        "Endpoint": {
            "Hostname": "bdvm",
            "ID": "6942a43afe8d4e463ca5c197",
            "IP": "1.1.1.1",
            "LastLoggedUsers": "",
            "OS": "Linux Ubuntu 24.04.2 LTS",
            "Status": "Online",
            "Vendor": "GravityZone"
        }
    }
}

Human Readable Output

GravityZone Endpoint

ID Hostname IP OS Status Vendor LastLoggedUsers
6942a43afe8d4e463ca5c197 bdvm 1.1.1.1 Linux Ubuntu 24.04.2 LTS Online GravityZone  

gz-endpoint-download-investigation-package


Collects and downloads an investigation package from an endpoint.

Base Command

gz-endpoint-download-investigation-package

Input

Argument Name Description Required
id The ID of the endpoint from which to collect the investigation package. Required
output_file The output file name in Cortex XSOAR to save the collected package. For Windows and macOS use .zip, for Linux use .tgz. Required

Context Output

Path Type Description
GravityZone.Command.DownloadFile.EndpointID String The endpoint ID.
GravityZone.Command.DownloadFile.Status String The command status.
GravityZone.Command.DownloadFile.ErrorCode String The command error code.
GravityZone.Command.DownloadFile.OutputFile String The output file name.
GravityZone.Command.DownloadFile.RemoteFile String The remote file path.
GravityZone.Command.DownloadFile.FileID String The file ID.
File.SHA1 String The SHA1 hash of the downloaded file.
File.SHA256 String The SHA256 hash of the downloaded file.
File.SHA512 String The SHA512 hash of the downloaded file.
File.SSDeep String The SSDeep hash of the downloaded file.
File.EntryID String The EntryID hash of the downloaded file.
File.Info String Information about the downloaded file.
File.Type String The downloaded file type.
File.MD5 String The MD5 hash of the downloaded file.
File.Extension String The downloaded file extension.
File.Size Number The downloaded file size.
File.Name String The downloaded file name.

Command example

!gz-endpoint-download-investigation-package id=6942a43afe8d4e463ca5c197 output_file=investigation_package.zip

Context Example

{
    "GravityZone": {
        "Command": {
            "DownloadFile": {
                "ActivityID": "69443b020126750c1a0dbe2f",
                "ActivityType": "DownloadFile",
                "Status": "Success",
                "EndpointID": "6942a43afe8d4e463ca5c197",
                "ErrorCode": null,
                "RemoteFile": null,
                "OutputFile": "investigation_package.zip",
                "FileID": "LtvQ6B8eCFvTNo7bf3vDUD@25729aa7-7442-4231-8b98-ecb0fc29a642",
                "FileName": "investigation_package.zip"
            }
        }
    }
}

Human Readable Output

GravityZone.Command.DownloadFile command on host 6942a43afe8d4e463ca5c197

EndpointID Status ErrorCode OutputFile RemoteFile FileID
6942a43afe8d4e463ca5c197 Success   investigation_package.zip   LtvQ6B8eCFvTNo7bf3vDUD@25729aa7-7442-4231-8b98-ecb0fc29a642

gz-endpoint-download-file


Downloads a file from an endpoint.

Base Command

gz-endpoint-download-file

Input

Argument Name Description Required
id The ID of the endpoint to download the file from. Required
remote_file The full path of the remote file on the endpoint to download. Required
output_file The output file name in Cortex XSOAR to save the downloaded file to. Required

Context Output

Path Type Description
GravityZone.Command.DownloadFile.EndpointID String The endpoint ID.
GravityZone.Command.DownloadFile.Status String The command status.
GravityZone.Command.DownloadFile.ErrorCode String The command error code.
GravityZone.Command.DownloadFile.OutputFile String The output file name.
GravityZone.Command.DownloadFile.RemoteFile String The remote file path.
GravityZone.Command.DownloadFile.FileID String The file ID.
File.SHA1 String The SHA1 hash of the downloaded file.
File.SHA256 String The SHA256 hash of the downloaded file.
File.SHA512 String The SHA512 hash of the downloaded file.
File.SSDeep String The SSDeep hash of the downloaded file.
File.EntryID String The EntryID hash of the downloaded file.
File.Info String Information about the downloaded file.
File.Type String The downloaded file type.
File.MD5 String The MD5 hash of the downloaded file.
File.Extension String The downloaded file extension.
File.Size Number The downloaded file size.
File.Name String The downloaded file name.

Command example

!gz-endpoint-download-file id=6942a43afe8d4e463ca5c197 remote_file=/root/test/test.txt output_file=downloaded_file.gzip

Context Example

{
    "GravityZone": {
        "Command": {
            "DownloadFile": {
                "ActivityID": "6943fb82c1f339e18b0949a1",
                "ActivityType": "DownloadFile",
                "RemoteFile": "/root/test/test.txt",
                "Status": "Success",
                "EndpointID": "6942a43afe8d4e463ca5c197",
                "ErrorCode": null,
                "OutputFile": "downloaded_file.gzip",
                "FileID": "LtvQ6B8eCFvTNo7bf3vDUD@25729aa7-7442-4231-8b98-ecb0fc29a642",
                "FileName": "downloaded_file.gzip"
            }
        }
    }
}

Human Readable Output

GravityZone.Command.DownloadFile command on host 6942a43afe8d4e463ca5c197

EndpointID Status ErrorCode OutputFile RemoteFile FileID
6942a43afe8d4e463ca5c197 Success   downloaded_file.gzip /root/test/test.txt LtvQ6B8eCFvTNo7bf3vDUD@25729aa7-7442-4231-8b98-ecb0fc29a642

gz-endpoint-isolate


Isolates an endpoint from the network.

Base Command

gz-endpoint-isolate

Input

Argument Name Description Required
id The ID of the endpoint to isolate. Required

Context Output

Path Type Description
GravityZone.Command.Isolate.TaskID String The task ID.
GravityZone.Command.Isolate.TaskType String The task type.
GravityZone.Command.Isolate.EndpointID String The endpoint ID.
GravityZone.Command.Isolate.Hostname String The endpoint name.
GravityZone.Command.Isolate.Status String The command status.
GravityZone.Command.Isolate.ErrorCode String The command error code, or “Success”.
GravityZone.Command.Isolate.Error String The command error message, or “Success”.
GravityZone.Command.Isolate.StartDate Date The start date of the command execution.
GravityZone.Command.Isolate.EndDate Date The end date of the command execution.

Command example

!gz-endpoint-isolate id=6942a43afe8d4e463ca5c197

Context Example

{
    "GravityZone": {
        "Command" : {
            "Isolate" : {
                "TaskID": "6941bbc98ba450a5c10e5a16",
                "TaskType": "Isolate",
                "Status": "Processed",
                "EndDate": "2025-12-16T22:06:33Z",
                "EndpointID": "6942a43afe8d4e463ca5c197",
                "Hostname": "ENDPOINT_NAME",
                "ErrorCode": "Success",
                "Error": "Success",
                "StartDate": "2025-12-16T22:06:33Z"
            }
        }
    }
}

Human Readable Output

GravityZone.Command.Isolate command on hosts ENDPOINT_ID

EndpointID Hostname StartDate EndDate Error
6942a43afe8d4e463ca5c197 ENDPOINT_NAME 2025-12-16T22:06:33Z 2025-12-16T22:06:33Z Success

gz-endpoint-deisolate


Restores an isolated endpoint to the network.

Base Command

gz-endpoint-deisolate

Input

Argument Name Description Required
id The ID of the endpoint to restore from isolation. Required

Context Output

Path Type Description
GravityZone.Command.Deisolate.TaskID String The task ID.
GravityZone.Command.Deisolate.TaskType String The task type.
GravityZone.Command.Deisolate.EndpointID String The endpoint ID.
GravityZone.Command.Deisolate.Hostname String The endpoint name.
GravityZone.Command.Deisolate.Status String The command status.
GravityZone.Command.Deisolate.ErrorCode String The command error code, or “Success”.
GravityZone.Command.Deisolate.Error String The command error message, or “Success”.
GravityZone.Command.Deisolate.StartDate Date The start date of the command execution.
GravityZone.Command.Deisolate.EndDate Date The end date of the command execution.

Command example

!gz-endpoint-deisolate id=6942a43afe8d4e463ca5c197

Context Example

{
    "GravityZone": {
        "Command" : {
            "Deisolate" : {
                "TaskID": "6941bbc98ba450a5c10e5a16",
                "TaskType": "Deisolate",
                "Status": "Processed",
                "EndDate": "2025-12-16T22:08:33Z",
                "EndpointID": "6942a43afe8d4e463ca5c197",
                "Hostname": "ENDPOINT_NAME",
                "ErrorCode": "Success",
                "Error": "Success",
                "StartDate": "2025-12-16T22:08:33Z"
            }
        }
    }
}

Human Readable Output

GravityZone.Command.Deisolate command on hosts ENDPOINT_ID

EndpointID Hostname StartDate EndDate Error
6942a43afe8d4e463ca5c197 ENDPOINT_NAME 2025-12-16T22:08:33Z 2025-12-16T22:08:33Z Success

gz-endpoint-kill-process


Terminates a process on an endpoint by process ID.

Base Command

gz-endpoint-kill-process

Input

Argument Name Description Required
id The endpoint ID. Required
pid The ID of the process to kill. Required

Context Output

Path Type Description
GravityZone.Command.KillProcess.TaskID String The task ID.
GravityZone.Command.KillProcess.TaskType String The task type.
GravityZone.Command.KillProcess.EndpointID String The endpoint ID.
GravityZone.Command.KillProcess.Hostname String The endpoint name.
GravityZone.Command.KillProcess.Status String The command status.
GravityZone.Command.KillProcess.ErrorCode String The command error code, or “Success”.
GravityZone.Command.KillProcess.Error String The command error message, or “Success”.
GravityZone.Command.KillProcess.StartDate Date The start date of the command execution.
GravityZone.Command.KillProcess.EndDate Date The end date of the command execution.
GravityZone.Command.KillProcess.ProcessID Number The process ID.
GravityZone.Command.KillProcess.ProcessPath String The process path.

Command example

!gz-endpoint-kill-process id=6942a43afe8d4e463ca5c197 pid=5876

Context Example

{
    "GravityZone": {
        "Command": {
            "KillProcess": {
                "TaskID": "6941b6ffa830c3132b0d63d8",
                "TaskType": "KillProcess",
                "Status": "Processed",
                "EndDate": "2025-12-16T21:46:08Z",
                "EndpointID": "6942a43afe8d4e463ca5c197",
                "Hostname": "ENDPOINT_NAME",
                "ErrorCode": "Success",
                "Error": "Success",
                "StartDate": "2025-12-16T21:46:07Z",
                "ProcessID": 5876,
                "ProcessPath": ""
            }
        }
    }
}

Human Readable Output

GravityZone.Command.KillProcess command on hosts ENDPOINT_ID

EndpointID Hostname StartDate EndDate Error ProcessID
6942a43afe8d4e463ca5c197 ENDPOINT_NAME 2025-12-16T21:46:07Z 2025-12-16T21:46:08Z Success 5876

gz-endpoint-run-command


Runs a command on the endpoint. The applied policy must have Remote Shell enabled for this action to work.

Base Command

gz-endpoint-run-command

Input

Argument Name Description Required
id The ID of the endpoint on which to run the command. Required
command The command to run on the endpoint. Required

Context Output

Path Type Description
GravityZone.Command.RunCommand.ActivityID String The activity ID.
GravityZone.Command.RunCommand.ActivityType String The activity type.
GravityZone.Command.RunCommand.Status String The command status.
GravityZone.Command.RunCommand.EndpointID String The endpoint ID.
GravityZone.Command.RunCommand.ErrorCode String The command error code, or “Success”.
GravityZone.Command.RunCommand.Output String The command output.
GravityZone.Command.RunCommand.FileID String The stored file ID, when the command output cannot be extracted as an archive.
GravityZone.Command.RunCommand.FileName String The stored file name, when the command output cannot be extracted as an archive.

Command example

!gz-endpoint-run-command id=6942a43afe8d4e463ca5c197 command=whoami

Context Example

{
    "GravityZone": {
        "Command": {
            "RunCommand": {
                "ActivityID": "6943e3391e4fe5e8a40e51f6",
                "ActivityType": "RunCommand",
                "Status": "Success",
                "EndpointID": "6942a43afe8d4e463ca5c197",
                "ErrorCode": null,
                "Command": "whoami",
                "Output": "root"
            }
        }
    }
}

Human Readable Output

GravityZone.Command.RunCommand command on host 6942a43afe8d4e463ca5c197

EndpointID Status ErrorCode Command Output
6942a43afe8d4e463ca5c197 Success   whoami root

gz-endpoint-upload-file


Uploads a file to an endpoint.

Base Command

gz-endpoint-upload-file

Input

Argument Name Description Required
id The ID of the target endpoint for the file upload. Required
entry_id The entry ID of the file to upload. This file needs to exist in Cortex XSOAR. Required
remote_location The full folder path on the endpoint where the file will be uploaded. Required

Context Output

Path Type Description
GravityZone.Command.UploadFile.TaskID String The task ID.
GravityZone.Command.UploadFile.TaskType String The task type.
GravityZone.Command.UploadFile.EndpointID String The endpoint ID.
GravityZone.Command.UploadFile.Hostname String The endpoint name.
GravityZone.Command.UploadFile.Status String The command status.
GravityZone.Command.UploadFile.ErrorCode String The command error code, or “Success”.
GravityZone.Command.UploadFile.Error String The command error message, or “Success”.
GravityZone.Command.UploadFile.StartDate Date The start date of the command execution.
GravityZone.Command.UploadFile.EndDate Date The end date of the command execution.
GravityZone.Command.UploadFile.EntryID String The entry ID of the uploaded file.
GravityZone.Command.UploadFile.DestinationPath String The destination path of the uploaded file.

Command example

!gz-endpoint-upload-file id=6942a43afe8d4e463ca5c197 entry_id=LtvQ6B8eCFvTNo7bf3vDUD@25729aa7-7442-4231-8b98-ecb0fc29a642 remote_location=/root/test/

Context Example

{
    "GravityZone": {
        "Command": {
            "UploadFile": {
                "TaskID": "694447384f1ba9a2650ec75a",
                "TaskType": "UploadFile",
                "Status": "Processed",
                "EndDate": "2025-12-18T20:26:40Z",
                "EndpointID": "6942a43afe8d4e463ca5c197",
                "Hostname": "ENDPOINT_NAME",
                "ErrorCode": "Success",
                "Error": "Success",
                "StartDate": "2025-12-18T20:26:00Z",
                "EntryID": "LtvQ6B8eCFvTNo7bf3vDUD@25729aa7-7442-4231-8b98-ecb0fc29a642",
                "DestinationPath": "/root/test/"
            }
        }
    }
}

Human Readable Output

GravityZone.Command.UploadFile command on hosts 6942a43afe8d4e463ca5c197

EndpointID Hostname StartDate EndDate Error EntryID DestinationPath
6942a43afe8d4e463ca5c197 ENDPOINT_NAME 2025-12-18T20:26:00Z 2025-12-18T20:26:40Z Success LtvQ6B8eCFvTNo7bf3vDUD@25729aa7-7442-4231-8b98-ecb0fc29a642 /root/test/

gz-endpoint-list-by-running-process-hash


Retrieves endpoints that are running processes with a specified hash. The API key and the applied policy must allow Live Search. Endpoints must be online. The command waits up to five minutes for responses before timing out.

Base Command

gz-endpoint-list-by-running-process-hash

Input

Argument Name Description Required
process_hash Hash of the process. Required

Context Output

Path Type Description
GravityZone.Command.EndpointsRunningProcessHash.EndpointID String The endpoint ID.
GravityZone.Command.EndpointsRunningProcessHash.Path String The Live Search results.
GravityZone.Command.EndpointsRunningProcessHash.ProcessHash String The process hash.

Command example

!gz-endpoint-list-by-running-process-hash process_hash=b8412bcc6f47b2a11e4c39bc1bc9fab74969ff0648ba22db4c5254a0457af0c7

Context Example

{
    "GravityZone": {
        "Command": {
            "EndpointsRunningProcessHash": {
                "EndpointID": "6942a43afe8d4e463ca5c197",
                "Path": "/opt/bitdefender-security-tools/bin/epagngd",
                "ProcessHash": "b8412bcc6f47b2a11e4c39bc1bc9fab74969ff0648ba22db4c5254a0457af0c7"
            }
        }
    }
}

Human Readable Output

Live Search Results

EndpointID ProcessHash Results
6942a43afe8d4e463ca5c197 b8412bcc6f47b2a11e4c39bc1bc9fab74969ff0648ba22db4c5254a0457af0c7 {“hostname”:”ENDPOINT_NAME”,”path”:”/opt/bitdefender-security-tools/bin/epagngd”}

gz-endpoint-get-process-tree-by-hash


Retrieves the process tree on an endpoint for a specified process hash. The applied policy must allow Live Search, and the endpoint must be online.

Base Command

gz-endpoint-get-process-tree-by-hash

Input

Argument Name Description Required
id The ID of the targeted endpoint. Required
process_hash The hash of the process to search for. Required

Context Output

Path Type Description
GravityZone.Command.ProcessTreeForHash.EndpointID String The endpoint ID.
GravityZone.Command.ProcessTreeForHash.PID Number The process ID.
GravityZone.Command.ProcessTreeForHash.Path String The process path.
GravityZone.Command.ProcessTreeForHash.Cmdline String The command line used to start the process.
GravityZone.Command.ProcessTreeForHash.ParentPID Number The parent process ID.

Command example

!gz-endpoint-get-process-tree-by-hash id=6942a43afe8d4e463ca5c197 process_hash=b8412bcc6f47b2a11e4c39bc1bc9fab74969ff0648ba22db4c5254a0457af0c7

Context Example

{
    "GravityZone": {
        "Command": {
            "ProcessTreeForHash": {
                "EndpointID": "6942a43afe8d4e463ca5c197",
                "Cmdline": "/usr/lib/systemd/systemd --system --deserialize=73",
                "ParentPID": 0,
                "Path": "/usr/lib/systemd/systemd",
                "PID": 1
            }
        }
    }
}

Human Readable Output

Live Search Results

EndpointID ProcessHash Results
6942a43afe8d4e463ca5c197 b8412bcc6f47b2a11e4c39bc1bc9fab74969ff0648ba22db4c5254a0457af0c7 {“cmdline”:”/usr/lib/systemd/systemd –system –deserialize=73”,”parent”:”0”,”path”:”/usr/lib/systemd/systemd”,”pid”:”1”}

gz-incident-get


Retrieves incident details by ID.

Base Command

gz-incident-get

Input

Argument Name Description Required
id The ID of the incident to fetch. Required

Context Output

Path Type Description
GravityZone.Incident.ID String The incident ID.
GravityZone.Incident.Type String The incident type (‘incident’ / ‘extendedIncident’).
GravityZone.Incident.Company.Name String The GravityZone company name where the incident is located.
GravityZone.Incident.Company.ID String The GravityZone company ID where the incident is located.
GravityZone.Incident.Number Number The incident number (specific to the company).
GravityZone.Incident.Severity.Score Number The incident severity score (0 - 100).
GravityZone.Incident.Status Number The incident status.
GravityZone.Incident.ActionTaken String The action taken by the detecting technology (‘reported’ / ‘blocked’ / ‘partially_blocked’).
GravityZone.Incident.Created Date The date when the incident was detected on the endpoint / sensor.
GravityZone.Incident.LastUpdated Date The date when the incident was last updated in GravityZone or by the endpoint / sensor.
GravityZone.Incident.LastProcessed Date The date when the incident was last processed by GravityZone services.
GravityZone.Incident.Permalink String The incident URL in the GravityZone Console.
GravityZone.Incident.AssignedPriority String The priority assigned to the incident (‘unknown’ / ‘low’ / ‘medium’ / ‘high’ / ‘critical’).
GravityZone.Incident.Notes.Text String The note contents.
GravityZone.Incident.Notes.User String The username (email) of the user who wrote the note.
GravityZone.Incident.Notes.Date Date The note creation date.
GravityZone.Incident.Alerts.Name String The alert name.
GravityZone.Incident.Alerts.Date Date The date of when the alert was generated.
GravityZone.Incident.Alerts.Sensors String The list of sensors that generated the alert. Available only for ‘extendedIncident’-type incidents.
GravityZone.Incident.Alerts.Tactic String The list of tactics that generated the alert. Available only for ‘extendedIncident’-type incidents.
GravityZone.Incident.Alerts.Resources Array The list of resources involved in the ‘incident’-type incidents.
GravityZone.Incident.RawJSON JSON The raw JSON response from the GravityZone API.
GravityZone.Incident.EndpointID String The endpoint ID. Available only for ‘incident’-type incidents.
GravityZone.Incident.EndpointHostname String The endpoint hostname. Available only for ‘incident’-type incidents.
GravityZone.Incident.EndpointIP String The endpoint IP address. Available only for ‘incident’-type incidents.

Command example

!gz-incident-get id=69415c9d5f5c8b75247c58d1

Context Example

{
    "GravityZone": {
        "Incident": {
            "ActionTaken": "blocked",
            "Alerts": [
                {
                    "Date": "2025-12-16T15:20:19+02:00",
                    "DetectedBy": {
                        "Class": "EDR Detection",
                        "Name": "KeyloggingAPICall"
                    },
                    "Name": "KeyloggingAPICall",
                    "Resources": [
                        {
                            "CommandLine": "\"C:\\Windows\\System32\\notepad.exe\" C:\\Users\\bdvm\\Desktop\\New Text Document.txt",
                            "ParentPid": 5212,
                            "ParentProcessAccessPrivileges": "elevated",
                            "ParentProcessIntegrityLevel": "high",
                            "ParentProcessPath": "c:\\windows\\explorer.exe",
                            "ParentProcessUser": "TA66H0I6F225\\bdvm",
                            "Pid": 2592,
                            "ProcessAccessPrivileges": "elevated",
                            "ProcessIntegrityLevel": "high",
                            "ProcessPath": "c:\\windows\\system32\\notepad.exe",
                            "Type": "process",
                            "User": "TA66H0I6F225\\bdvm"
                        }
                    ]
                }
            ],
            "AssignedPriority": "unknown",
            "AssignedUser": null,
            "Company": {
                "ID": "611717cb22a30cee251b03f3",
                "Name": "Company"
            },
            "Created": "2025-12-16T15:20:21+02:00",
            "ID": "69415c9d5f5c8b75247c58d1",
            "LastProcessed": "2025-12-16T15:21:48+02:00",
            "LastUpdated": "2025-12-16T15:21:38+02:00",
            "Notes": [
                {
                    "Date": "2026-02-23T13:27:53+02:00",
                    "Text": "InvestigationInProgress",
                    "User": "user email"
                }
            ],
            "Number": 473,
            "Permalink": "https://gravityzone.domain/#!/incidents/view/69415c9d5f5c8b75247c58d1",
            "EndpointID" : "694148bffe8d4e463ca5bd1e",
            "EndpointHostname": "TA66H0I6F225",
            "EndpointIP": "1.1.1.1",
            "RawJSON": {
                "assignee": null,
                "attackTypes": [
                    "Malware"
                ],
                "company": {
                    "id": "611717cb22a30cee251b03f3",
                    "name": "Company"
                },
                "created": "2025-12-16T15:20:21+02:00",
                "details": {
                    "alerts": [
                        {
                            "date": "2025-12-16T15:20:19+02:00",
                            "detectedBy": {
                                "class": "EDR Detection",
                                "name": "KeyloggingAPICall"
                            },
                            "extra": [
                                {
                                    "key": "hookedApiName",
                                    "value": "Key Logging"
                                },
                                {
                                    "key": "extraInfo1",
                                    "value": "\nProcess PE VersionInfo and Certification Information: \nOriginal File Name: NOTEPAD.EXE\nInternal Name: Notepad\nFile Description: Notepad\nCompany Name: Microsoft Corporation\nFile Version: 10.0.19041.1865 (WinBuild.160101.0800)\nProduct Name: MicrosoftR WindowsR Operating System\nProduct Version: 10.0.19041.1865\nLegal Copyright: C Microsoft Corporation. All rights reserved.\nCertificate Serial: 330000033b655faefadb75e9d600000000033b\nCertificate Signer: Microsoft Corporation\nCertificate Issuer: Microsoft Corporation\n\nWorking Directory: c:\\users\\bdvm\\desktop\\"
                                }
                            ],
                            "id": "69415ce1997e9c48ed12c360",
                            "name": "KeyloggingAPICall",
                            "resources": [
                                {
                                    "details": {
                                        "commandLine": "\"C:\\Windows\\System32\\notepad.exe\" C:\\Users\\bdvm\\Desktop\\New Text Document.txt",
                                        "loadedModule": null,
                                        "loadedModulePid": null,
                                        "parentPid": 5212,
                                        "parentProcessAccessPrivileges": "elevated",
                                        "parentProcessCmdline": null,
                                        "parentProcessIntegrityLevel": "high",
                                        "parentProcessPath": "c:\\windows\\explorer.exe",
                                        "parentProcessUser": "TA66H0I6F225\\bdvm",
                                        "pid": 2592,
                                        "processAccessPrivileges": "elevated",
                                        "processInjectionSizeofWrite": null,
                                        "processInjectionTarget": null,
                                        "processInjectionTargetPid": null,
                                        "processInjectionWriter": null,
                                        "processInjectionWriterPid": null,
                                        "processIntegrityLevel": "high",
                                        "processPackerName": null,
                                        "processPath": "c:\\windows\\system32\\notepad.exe",
                                        "processPathSize": null,
                                        "user": "TA66H0I6F225\\bdvm"
                                    },
                                    "type": "process"
                                }
                            ]
                        }
                    ],
                    "computerFqdn": "ta66h0i6f225",
                    "computerId": "694148bffe8d4e463ca5bd1e",
                    "computerIp": "1.1.1.1",
                    "computerMacAddresses": [
                        "005056a7862b"
                    ],
                    "computerName": "TA66H0I6F225",
                    "counters": {
                        "domains": 0,
                        "endpoints": 1,
                        "events": 17,
                        "files": 3,
                        "processes": 4,
                        "registries": 0,
                        "storages": 0
                    },
                    "detectionName": "BAT.Trojan.FormatC.Z",
                    "mitreTags": [
                        {
                            "category": "Execution",
                            "techniques": [
                                {
                                    "id": "T1059",
                                    "name": "Command and Scripting Interpreter",
                                    "subtechniques": null
                                }
                            ]
                        }
                    ],
                    "nodes": [
                        {
                            "alertIds": [
                                "69415ce1997e9c48ed12c361"
                            ],
                            "details": {
                                "file": {
                                    "isExecutable": true,
                                    "md5": null,
                                    "name": "<system>",
                                    "path": "<system>",
                                    "sha256": null,
                                    "size": 0
                                },
                                "killProcess": null,
                                "process": {
                                    "commandLine": "<did_not_receive>",
                                    "date": "2025-12-16T14:05:30+02:00",
                                    "name": "<system>",
                                    "parent": {
                                        "name": "<SYSTEM>",
                                        "path": null,
                                        "pid": 0
                                    },
                                    "pid": 0,
                                    "userId": null,
                                    "userName": "NT AUTHORITY\\SYSTEM"
                                },
                                "quarantine": null,
                                "sandbox": null
                            },
                            "id": "69415c9d5f5c8b75247c58e4",
                            "name": "<system>",
                            "type": "process_execution"
                        }
                    ],
                    "partOf": null,
                    "transitions": [
                        {
                            "date": "2025-12-16T15:19:59+02:00",
                            "from": "69415c9d5f5c8b75247c58e2",
                            "to": "69415c9d5f5c8b75247c58e5"
                        }
                    ],
                    "triggerNodeId": "69415c9d5f5c8b75247c58e5"
                },
                "incidentId": "69415c9d5f5c8b75247c58d1",
                "incidentLink": "https://gravityzone.domain/#!/incidents/view/69415c9d5f5c8b75247c58d1",
                "incidentNumber": 473,
                "incidentType": "incident",
                "lastProcessed": "2025-12-16T15:21:48+02:00",
                "lastUpdated": "2025-12-16T15:21:38+02:00",
                "mainAction": "blocked",
                "notes": [
                    {
                        "created": "2026-02-23T13:27:53+02:00",
                        "id": "699c39b9cf8645f670042eb0",
                        "text": "InvestigationInProgress",
                        "userId": "6941466eda1158ec9f0ecb5d",
                        "userName": "user email"
                    }
                ],
                "priority": "unknown",
                "severityScore": 43,
                "status": "open"
            },
            "Severity": {
                "Score": 43
            },
            "Status": 0,
            "Type": "incident"
        }
    }
}

Human Readable Output

GravityZone Incident

Action Taken Assigned Priority Assigned User Company Name Created Endpoint ID Endpoint IP Endpoint Name ID Last Processed Last Updated Number Permalink Severity Score Status Type
Blocked Unknown Unassigned Company 2025-12-16T15:20:21+02:00 694148bffe8d4e463ca5bd1e 1.1.1.1 TA66H0I6F225 69415c9d5f5c8b75247c58d1 2025-12-16T15:21:48+02:00 2025-12-16T15:21:38+02:00 473 https://gravityzone.domain/#!/incidents/view/69415c9d5f5c8b75247c58d1 43% 0 (Pending) Incident (EDR)

Incident Notes

Text User Date
InvestigationInProgress user email 2026-02-23T13:27:53+02:00

Incident Alerts

Date Detected By Name Resources
2025-12-16T15:20:19+02:00 KeyloggingAPICall (EDR Detection) KeyloggingAPICall [{“Pid”: 2592,”ProcessPath”: “c:\windows\system32\notepad.exe”,”CommandLine”: “"C:\Windows\System32\notepad.exe" C:\Users\bdvm\Desktop\New Text Document.txt”,”ParentPid”: 5212,”ParentProcessPath”: “c:\windows\explorer.exe”,”ParentProcessUser”: “TA66H0I6F225\bdvm”,”User”: “TA66H0I6F225\bdvm”,”ProcessAccessPrivileges”: “elevated”,”ParentProcessAccessPrivileges”: “elevated”,”ProcessIntegrityLevel”: “high”,”ParentProcessIntegrityLevel”: “high”,”Type”: “process”}]

gz-incident-list


Retrieves incidents within the last three days from all endpoints or a specific endpoint.

Base Command

gz-incident-list

Input

Argument Name Description Required
from_date The start date to retrieve incidents from. The default value is the current date minus three days. Optional
to_date The end date to retrieve incidents until. The default value is the current date and time. Optional
limit The maximum number of incidents to retrieve. Optional
endpoint_id The ID of the endpoint to list incidents for. Optional

Context Output

Path Type Description
GravityZone.IncidentsList.ID String The incident ID.
GravityZone.IncidentsList.Type String The incident type (‘incident’ / ‘extendedIncident’).
GravityZone.IncidentsList.CompanyName String The GravityZone company name where the incident is located.
GravityZone.IncidentsList.Number Number The incident number (specific to the company).
GravityZone.IncidentsList.SeverityScore Number The incident severity score (0 - 100).
GravityZone.IncidentsList.Status Number The incident status.
GravityZone.IncidentsList.ActionTaken String The action taken by the detecting technology (‘reported’ / ‘blocked’ / ‘partially_blocked’).
GravityZone.IncidentsList.Created Date The date when the incident was detected on the endpoint / sensor.
GravityZone.IncidentsList.LastUpdated Date The date when the incident was last updated in GravityZone or by the endpoint / sensor.
GravityZone.IncidentsList.LastProcessed Date The incident last processed date by GravityZone services.
GravityZone.IncidentsList.Permalink String The incident URL in the GravityZone Console.
GravityZone.IncidentsList.AssignedPriority String The priority assigned to the incident (‘unknown’ / ‘low’ / ‘medium’ / ‘high’ / ‘critical’).
GravityZone.IncidentsList.AssignedUserId String The ID of the user assigned to the incident.
GravityZone.IncidentsList.RawJSON JSON The raw JSON response from the GravityZone API.
GravityZone.IncidentsList.EndpointID String The endpoint ID. Available only for ‘incident’-type incidents.
GravityZone.IncidentsList.EndpointHostname String The endpoint hostname. Available only for ‘incident’-type incidents.
GravityZone.IncidentsList.EndpointIP String The endpoint IP address. Available only for ‘incident’-type incidents.

Command example


#### Context Example

```json
{
    "GravityZone": {
        "IncidentsList": [
            {
                "ActionTaken": "reported",
                "AssignedPriority": "unknown",
                "AssignedUserId": null,
                "AttackTypes": [
                    "Persistence"
                ],
                "CompanyID": "611717cb22a30cee251b03f3",
                "CompanyName": "Company",
                "Created": "2026-02-23T13:09:34+02:00",
                "ID": "699c367136732459d7d3b1af",
                "LastProcessed": "2026-02-23T13:13:53+02:00",
                "LastUpdated": "2026-02-23T13:09:34+02:00",
                "Number": 1017,
                "Permalink": "https://gravityzone.domain/#!/incidents/view/699c367136732459d7d3b1af",
                "RawJSON": {
                    "assignee": null,
                    "attackTypes": [
                        "Persistence"
                    ],
                    "company": {
                        "id": "611717cb22a30cee251b03f3",
                        "name": "Company"
                    },
                    "created": "2026-02-23T13:09:34+02:00",
                    "details": {
                        "contains": null,
                        "counters": {
                            "ADInstances": 0,
                            "AWSInstances": 0,
                            "DGAs": 0,
                            "DNSs": 0,
                            "GCPInstances": 0,
                            "IPs": 0,
                            "IoTs": 0,
                            "atlassianBitbucketProducts": 0,
                            "atlassianConfluenceProducts": 0,
                            "atlassianInstances": 0,
                            "atlassianJiraProducts": 0,
                            "azureADInstances": 1,
                            "bitbucketProjects": 0,
                            "cloudStorages": 0,
                            "confluenceSpaces": 0,
                            "containers": 0,
                            "databases": 0,
                            "domains": 0,
                            "emails": 0,
                            "endpoints": 0,
                            "exfiltratedFiles": 0,
                            "externalDrives": 0,
                            "externalSources": 0,
                            "googleWorkspaceInstances": 0,
                            "identities": 1,
                            "internalEmails": 0,
                            "internalIPs": 0,
                            "mobileDevices": 0,
                            "office365Instances": 0,
                            "printers": 0,
                            "routers": 0,
                            "servers": 0,
                            "storages": 0,
                            "torNodes": 0,
                            "users": 1,
                            "virtualDesktops": 0
                        },
                        "partOf": null
                    },
                    "incidentId": "699c367136732459d7d3b1af",
                    "incidentLink": "https://gravityzone.domain/#!/incidents/view/699c367136732459d7d3b1af",
                    "incidentNumber": 1017,
                    "incidentType": "extendedIncident",
                    "lastProcessed": "2026-02-23T13:13:53+02:00",
                    "lastUpdated": "2026-02-23T13:09:34+02:00",
                    "mainAction": "reported",
                    "priority": "unknown",
                    "severityScore": 71,
                    "status": "in_progress"
                },
                "SeverityScore": 71,
                "Status": 1,
                "Type": "extendedIncident"
            }
        ]
    }
}

Human Readable Output

GravityZone Incidents List

ActionTaken Assigned Priority Assigned User ID Attack Types Company Name Created ID Last Processed Last Updated Number Permalink Severity Score Status Type
Reported Unknown Unassigned Persistence Company 2026-02-23T13:09:34+02:00 699c367136732459d7d3b1af 2026-02-23T13:13:53+02:00 2026-02-23T13:09:34+02:00 1017 https://gravityzone.domain/#!/incidents/view/699c367136732459d7d3b1af 71% 1 (Active) Extended Incident (XDR)

Command example

!gz-incident-list from_date="2026-02-20" to_date="2026-02-21" limit="1"

Context Example

{
    "GravityZone": {
        "IncidentsList": [
            {
                "ActionTaken": "reported",
                "AssignedPriority": "unknown",
                "AssignedUserId": null,
                "AttackTypes": [
                    "Persistence"
                ],
                "CompanyID": "611717cb22a30cee251b03f3",
                "CompanyName": "Company",
                "Created": "2026-02-20T20:58:17+02:00",
                "ID": "6998b40f36732459d7d3aa58",
                "LastProcessed": "2026-02-20T21:20:47+02:00",
                "LastUpdated": "2026-02-20T20:58:17+02:00",
                "Number": 998,
                "Permalink": "https://gravityzone.domain/#!/incidents/view/6998b40f36732459d7d3aa58",
                "RawJSON": {
                    "assignee": null,
                    "attackTypes": [
                        "Persistence"
                    ],
                    "company": {
                        "id": "611717cb22a30cee251b03f3",
                        "name": "Company"
                    },
                    "created": "2026-02-20T20:58:17+02:00",
                    "details": {
                        "contains": null,
                        "counters": {
                            "ADInstances": 0,
                            "AWSInstances": 0,
                            "DGAs": 0,
                            "DNSs": 0,
                            "GCPInstances": 0,
                            "IPs": 0,
                            "IoTs": 0,
                            "atlassianBitbucketProducts": 0,
                            "atlassianConfluenceProducts": 0,
                            "atlassianInstances": 0,
                            "atlassianJiraProducts": 0,
                            "azureADInstances": 1,
                            "bitbucketProjects": 0,
                            "cloudStorages": 0,
                            "confluenceSpaces": 0,
                            "containers": 0,
                            "databases": 0,
                            "domains": 0,
                            "emails": 0,
                            "endpoints": 0,
                            "exfiltratedFiles": 0,
                            "externalDrives": 0,
                            "externalSources": 0,
                            "googleWorkspaceInstances": 0,
                            "identities": 1,
                            "internalEmails": 0,
                            "internalIPs": 0,
                            "mobileDevices": 0,
                            "office365Instances": 0,
                            "printers": 0,
                            "routers": 0,
                            "servers": 0,
                            "storages": 0,
                            "torNodes": 0,
                            "users": 1,
                            "virtualDesktops": 0
                        },
                        "partOf": null
                    },
                    "incidentId": "6998b40f36732459d7d3aa58",
                    "incidentLink": "https://gravityzone.domain/#!/incidents/view/6998b40f36732459d7d3aa58",
                    "incidentNumber": 998,
                    "incidentType": "extendedIncident",
                    "lastProcessed": "2026-02-20T21:20:47+02:00",
                    "lastUpdated": "2026-02-20T20:58:17+02:00",
                    "mainAction": "reported",
                    "priority": "unknown",
                    "severityScore": 71,
                    "status": "open"
                },
                "SeverityScore": 71,
                "Status": 0,
                "Type": "extendedIncident"
            }
        ]
    }
}

Human Readable Output

GravityZone Incidents List

ActionTaken Assigned Priority Assigned User ID Attack Types Company Name Created ID Last Processed Last Updated Number Permalink Severity Score Status Type
Reported Unknown Unassigned Persistence Company 2026-02-20T20:58:17+02:00 6998b40f36732459d7d3aa58 2026-02-20T21:20:47+02:00 2026-02-20T20:58:17+02:00 998 http://gravityzone.domain/#!/incidents/view/6998b40f36732459d7d3aa58 71% 0 (Pending) Extended Incident (XDR)

Command example

!gz-incident-list endpoint_id=694148bffe8d4e463ca5bd1e from_date="2025-11-20"

Context Example

{
    "GravityZone": {
        "IncidentsList": [
            {
                "ActionTaken": "reported",
                "AssignedPriority": "critical",
                "AssignedUserId": "6540b72b1ffbc14e1808bc00",
                "AttackTypes": [
                    "Malware"
                ],
                "CompanyID": "611717cb22a30cee251b03f3",
                "CompanyName": "Company",
                "Created": "2025-12-17T09:02:03+02:00",
                "ID": "694255755f5c8b75247c7ce2",
                "LastProcessed": "2025-12-17T09:02:13+02:00",
                "LastUpdated": "2025-12-17T09:02:03+02:00",
                "Number": 477,
                "Permalink": "https://gravityzone.domain/#!/incidents/view/694255755f5c8b75247c7ce2",
                "EndpointID" : "694148bffe8d4e463ca5bd1e",
                "EndpointHostname": "TA66H0I6F225",
                "EndpointIP": "1.1.1.1",
                "RawJSON": {
                    "assignee": "6540b72b1ffbc14e1808bc00",
                    "attackTypes": [
                        "Malware"
                    ],
                    "company": {
                        "id": "611717cb22a30cee251b03f3",
                        "name": "Company"
                    },
                    "created": "2025-12-17T09:02:03+02:00",
                    "details": {
                        "computerFqdn": "ta66h0i6f225",
                        "computerId": "694148bffe8d4e463ca5bd1e",
                        "computerIp": "1.1.1.1",
                        "computerMacAddresses": [
                            "005056a7862b"
                        ],
                        "computerName": "TA66H0I6F225",
                        "counters": {
                            "domains": 0,
                            "endpoints": 1,
                            "events": 6,
                            "files": 0,
                            "processes": 2,
                            "registries": 0,
                            "storages": 0
                        },
                        "detectionName": "RegSecurityDump",
                        "partOf": null
                    },
                    "incidentId": "694255755f5c8b75247c7ce2",
                    "incidentLink": "https://gravityzone.domain/#!/incidents/view/694255755f5c8b75247c7ce2",
                    "incidentNumber": 477,
                    "incidentType": "incident",
                    "lastProcessed": "2025-12-17T09:02:13+02:00",
                    "lastUpdated": "2025-12-17T09:02:03+02:00",
                    "mainAction": "reported",
                    "priority": "critical",
                    "severityScore": 33,
                    "status": "closed"
                },
                "SeverityScore": 33,
                "Status": 2,
                "Type": "incident"
            }
        ]
    }
}

Human Readable Output

GravityZone Incidents List

ActionTaken Assigned Priority Assigned User ID Attack Types Company Name Created Endpoint ID Endpoint IP Endpoint Name ID Last Processed Last Updated Number Permalink Severity Score Status Type
Reported Critical 6540b72b1ffbc14e1808bc00 Malware Company 2025-12-17T09:02:03+02:00 694148bffe8d4e463ca5bd1e 1.1.1.1 TA66H0I6F225 694255755f5c8b75247c7ce2 2025-12-17T09:02:13+02:00 2025-12-17T09:02:03+02:00 477 https://gravityzone.domain/#!/incidents/view/694255755f5c8b75247c7ce2 33% 2 (Done) Incident (EDR)

gz-incident-add-note


Adds a note to one or more incidents.

Base Command

gz-incident-add-note

Input

Argument Name Description Required
id The IDs of the incidents to add a note to. Supports comma separated values. Required
note The note to add to the incidents. Required

Context Output

Path Type Description
GravityZone.Command.AddIncidentNote.IncidentID String The incident ID.
GravityZone.Command.AddIncidentNote.Note String The requested note.
GravityZone.Command.AddIncidentNote.CommandStatus String The command status.

Command example

!gz-incident-add-note id=69415c9d5f5c8b75247c58d1 note=InvestigationInProgress

Context Example

{
    "GravityZone": {
        "Command": {
            "AddIncidentNote": {
                "CommandStatus": "Success",
                "IncidentID": "69415c9d5f5c8b75247c58d1",
                "Note": "InvestigationInProgress"
            }
        }
    }
}

Human Readable Output

GravityZone.Command.AddIncidentNote command on incidents 69415c9d5f5c8b75247c58d1

IncidentID Note CommandStatus
69415c9d5f5c8b75247c58d1 InvestigationInProgress Success

gz-incident-change-status


Changes the status of one or more incidents.

Base Command

gz-incident-change-status

Input

Argument Name Description Required
id The IDs of the incidents to update. Supports comma separated values. Required
status The new status of the incidents. Possible values are: PENDING, ACTIVE, DONE, ARCHIVE. Required

Context Output

Path Type Description
GravityZone.Command.ChangeIncidentStatus.IncidentID String The incident ID.
GravityZone.Command.ChangeIncidentStatus.IncidentStatus String The requested status of the incident.
GravityZone.Command.ChangeIncidentStatus.CommandStatus String The command status.

Command example

!gz-incident-change-status id=69415c9d5f5c8b75247c58d1 status=ACTIVE

Context Example

{
    "GravityZone": {
        "Command": {
            "ChangeIncidentStatus": {
                "CommandStatus": "Success",
                "IncidentID": "69415c9d5f5c8b75247c58d1",
                "IncidentStatus": "ACTIVE"
            }
        }
    }
}

Human Readable Output

GravityZone.Command.ChangeIncidentStatus command on incidents 69415c9d5f5c8b75247c58d1

IncidentID IncidentStatus CommandStatus
69415c9d5f5c8b75247c58d1 ACTIVE Success

gz-poll-investigation-activity-status


Checks the status of an investigation activity. This command is not intended for direct use.

Base Command

gz-poll-investigation-activity-status

Input

Argument Name Description Required
target_id The endpoint ID. Required
activity_id The activity ID. Required
output_file The path of the output file. Optional
metadata The metadata to pass to the task. Optional

Context Output

There is no context output for this command.

gz-poll-live-search-status


Checks the status of a Live Search query. This command is not intended for direct use.

Base Command

gz-poll-live-search-status

Input

Argument Name Description Required
task_id The task ID. Required
search_type The Live Search query type. Optional
metadata The metadata to pass to the task. Optional

Context Output

There is no context output for this command.

gz-poll-task-status


Checks the status of a task. This command is not intended for direct use.

Base Command

gz-poll-task-status

Input

Argument Name Description Required
task_id The task ID. Required
metadata The metadata to pass to the task. Optional

Context Output

There is no context output for this command.

get-modified-remote-data


Retrieves incidents that were modified since the last data sync. This command is intended for debugging purposes.

Base Command

get-modified-remote-data

Input

Argument Name Description Required
lastUpdate The time when the incident was last updated. Required

Context Output

There is no context output for this command.

get-remote-data


Retrieves data from a remote incident without updating the current incident. This command is intended for debugging purposes.

Base Command

get-remote-data

Input

Argument Name Description Required
id The ID of the incident to fetch. Required
lastUpdate The time when the incident was last updated. Required

Context Output

There is no context output for this command.

update-remote-system


Updates the remote incident with local incident changes without updating the current incident. This command is intended for debugging purposes.

Base Command

update-remote-system

Input

There are no input arguments for this command.

Context Output

There is no context output for this command.

get-mapping-fields


Returns the list of fields available for outgoing mirroring. This command is intended for debugging purposes only.

Base Command

get-mapping-fields

Input

| Argument Name | Description | Required |
| — | — | — |

Context Output

There is no context output for this command.

Incident Mirroring

You can enable incident mirroring between Cortex XSOAR incidents and GravityZone corresponding incidents (available from Cortex XSOAR version 6.0.0).
To set up the mirroring:

  1. Enable Fetching incidents in your instance configuration.
  2. In the Mirroring Direction integration parameter, select in which direction the incidents should be mirrored:

    Option Description
    None Disables incident mirroring.
    Incoming Reflects status changes from GravityZone incidents in Cortex XSOAR incidents.
    Outgoing Reflects status changes from Cortex XSOAR incidents in GravityZone incidents.
    Both Synchronizes status changes bidirectionally between Cortex XSOAR and GravityZone incidents.

Newly fetched incidents will be mirrored in the chosen direction. However, this selection does not affect existing incidents.

gz-endpoint-users-loggedin


Retrieves details of all active user sessions on a specific managed endpoint.

Base Command

gz-endpoint-users-loggedin

Input

Argument Name Description Required
id The target endpoint ID. The endpoint must be accessible to you. Required

Context Output

Path Type Description
GravityZone.Endpoint.ID String The endpoint ID.
GravityZone.Endpoint.Hostname String The endpoint hostname.
GravityZone.Endpoint.ActiveSessions.Username String The username of the currently logged-in user.
GravityZone.Endpoint.ActiveSessions.ConnectionType String The connection type for the session.
GravityZone.Endpoint.ActiveSessions.StartTime Date The session start time, if available (e.g., “2021-05-19T10:37:56Z”).
GravityZone.Endpoint.ActiveSessions.UserSID String The Security Identifier (SID) of the logged-in user, if available.
GravityZone.Endpoint.ActiveSessions.DomainSID String The Security Identifier (SID) of the logged-in user’s domain, if available.
GravityZone.Endpoint.ActiveSessions.OrganizationalUnitDN String The full distinguished name (DN) of the organizational unit, if available.
GravityZone.Endpoint.ActiveSessions.MemberOfSIDs Array The SIDs for the groups to which the logged-in user belongs, if available.

Command example

!gz-endpoint-users-loggedin id=6942a43afe8d4e463ca5c197

Context Example

{
    "GravityZone": {
        "Endpoint": {
            "ID": "6942a43afe8d4e463ca5c197",
            "Hostname": "bdvm",
            "ActiveSessions": [
                {
                    "Username": "user@example.com",
                    "ConnectionType": "local",
                    "StartTime": "2021-05-19T10:37:56Z",
                    "UserSID": "S-1-5-21-1111111111-1111111111-1111111111-1001",
                    "DomainSID": "S-1-5-21-1111111111-1111111111-1111111111",
                    "OrganizationalUnitDN": "OU=Users,DC=example,DC=com",
                    "MemberOfSIDs": [
                        "S-1-5-32-544",
                        "S-1-5-32-545"
                    ]
                }
            ]
        }
    }
}

Human Readable Output

Active sessions on endpoint 6942a43afe8d4e463ca5c197

Username ConnectionType StartTime UserSID DomainSID OrganizationalUnitDN MemberOfSIDs
TESTDOMAIN\full.user local 2021-05-19T10:37:56Z S-1-2-25-33 S-1-23-131231 OU=office,OU=Developers,OU=Users,DC=microsoft,DC=com S-1-5-32-450
basic.user remote 2021-05-19T11:00:00Z        

gz-endpoint-create-memory-dump


Initiates the creation of a memory dump for the specified endpoint. Once the dump is successfully generated, the resulting archive is uploaded to the Bitdefender cloud.

Important:

  • Please contact Bitdefender Enterprise Support to configure this feature.
  • The resulting memory dump archive is automatically deleted from the Bitdefender cloud after 24 hours.
  • The memory dump creation task completes successfully only when the generated memory dump archive is 16 GB or smaller.

Base Command

gz-endpoint-create-memory-dump

Input

Argument Name Description Required
id The target endpoint ID. The endpoint must be accessible and run a Windows operating system. Required
path The full path to the destination folder on the specified endpoint where the memory dump archive will be created. Required
password The password used to secure the memory dump archive after it is created. It must contain at least 12 characters, including one uppercase letter, one lowercase letter, one digit, and one special character. Required
polling Whether the command waits for the memory dump task completion. If set to true, the command returns the final result after the task completes. If set to false, the command returns only the endpoint ID and task ID immediately after the task is initiated. Optional

Context Output

Path Type Description
GravityZone.MemoryDump.TaskID String The memory dump task ID.
GravityZone.MemoryDump.TaskType String The task type.
GravityZone.MemoryDump.Status String The memory dump task status.
GravityZone.MemoryDump.EndpointID String The endpoint ID.
GravityZone.MemoryDump.Hostname String The endpoint hostname.
GravityZone.MemoryDump.StartDate Date The date and time when the memory dump task started (e.g., “2026-05-25T10:00:00Z”).
GravityZone.MemoryDump.EndDate Date The date and time when the memory dump task ended, if available (e.g., “2026-05-25T10:01:00Z”).
GravityZone.MemoryDump.ErrorCode String An error code if the memory dump task fails, or “Success” if the task completes successfully.
GravityZone.MemoryDump.Error String An error message if the memory dump task fails, or “Success” if the task completes successfully.
GravityZone.MemoryDump.DownloadURL String The memory dump download URL, available after the task completes successfully.

Command example

!gz-endpoint-create-memory-dump id=6942a43afe8d4e463ca5c197 password="ComplexPass123!" path=C:\\test2

Context Example

{
    "GravityZone": {
        "MemoryDump": {
            "TaskID": "6836f4a01a2b3c4d5e6f7a8b",
            "TaskType": "CreateMemoryDump",
            "Status": "Processed",
            "EndpointID": "6942a43afe8d4e463ca5c197",
            "Hostname": "bdvm",
            "StartDate": "2026-05-25T10:00:00Z",
            "EndDate": "2026-05-25T10:01:00Z",
            "ErrorCode": "Success",
            "Error": "Success",
            "DownloadURL": "https://example.com/memory-dump.zip"
        }
    }
}

Human Readable Output

This example illustrates the human-readable output when polling is set to true. When polling is false, the table contains only the task ID and endpoint ID.

Memory dump for endpoint 6942a43afe8d4e463ca5c197

EndpointID Hostname StartDate EndDate Error DownloadURL
6942a43afe8d4e463ca5c197 bdvm 2026-05-25T10:00:00Z 2026-05-25T10:01:00Z Success https://example.com/memory-dump.zip

gz-endpoint-memory-dump-status


Verifies the status of a task initiated via gz-endpoint-create-memory-dump.

Base Command

gz-endpoint-memory-dump-status

Input

Argument Name Description Required
task_id The ID of the task started through gz-endpoint-create-memory-dump. This ID is returned upon task initiation. Required
endpoint_id The ID of the endpoint for which the specified task was initiated. Required
polling Whether the command waits for the gz-endpoint-create-memory-dump task completion. If set to true, the command returns the final result after the task completes successfully or fails. If set to false, the command returns immediately, providing only the task status. Optional

Context Output

Path Type Description
GravityZone.MemoryDump.TaskID String The ID of the task started through gz-endpoint-create-memory-dump.
GravityZone.MemoryDump.TaskType String The task type.
GravityZone.MemoryDump.Status String The status of the task started through gz-endpoint-create-memory-dump.
GravityZone.MemoryDump.EndpointID String The endpoint ID.
GravityZone.MemoryDump.Hostname String The endpoint hostname.
GravityZone.MemoryDump.StartDate Date The date and time when the memory dump task started (e.g., “2026-05-25T10:00:00Z”).
GravityZone.MemoryDump.EndDate Date The date and time when the memory dump task ended, if available (e.g., “2026-05-25T10:01:00Z”).
GravityZone.MemoryDump.ErrorCode String An error code if the task started through gz-endpoint-create-memory-dump fails, or “Success” if the task completes successfully.
GravityZone.MemoryDump.Error String An error message if the task started through gz-endpoint-create-memory-dump fails, or “Success” if the task completes successfully.
GravityZone.MemoryDump.DownloadURL String The memory dump download URL, available after the memory dump creation task completes successfully.

Command example

!gz-endpoint-memory-dump-status task_id=6836f4a01a2b3c4d5e6f7a8b endpoint_id=6942a43afe8d4e463ca5c197

Context Example

{
    "GravityZone": {
        "MemoryDump": {
            "TaskID": "6836f4a01a2b3c4d5e6f7a8b",
            "TaskType": "CreateMemoryDump",
            "Status": "Processed",
            "EndpointID": "6942a43afe8d4e463ca5c197",
            "Hostname": "bdvm",
            "StartDate": "2026-05-25T10:00:00Z",
            "EndDate": "2026-05-25T10:01:00Z",
            "ErrorCode": "Success",
            "Error": "Success",
            "DownloadURL": "https://example.com/memory-dump.zip"
        }
    }
}

Human Readable Output

This example illustrates the human-readable output when polling is set to true. When polling is false, only the status of the memory dump creation task is displayed.

Memory dump for endpoint 6942a43afe8d4e463ca5c197

EndpointID Hostname StartDate EndDate Error DownloadURL
6942a43afe8d4e463ca5c197 bdvm 2026-05-25T10:00:00Z 2026-05-25T10:01:00Z Success https://example.com/memory-dump.zip

gz-poll-endpoint-users-loggedin-status


Verifies the status of a task initiated via gz-endpoint-users-loggedin. This command is invoked automatically and is not intended for direct use.

Base Command

gz-poll-endpoint-users-loggedin-status

Input

Argument Name Description Required
task_id The ID of the task started through gz-endpoint-users-loggedin. Required
endpoint_id The ID of the managed endpoint associated with the specified task. Required

Context Output

There is no context output for this command.

Configuration parameters

  • url — Server URL (required)
  • credentials — (required)
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings
  • isFetch — Fetch incidents
  • max_fetch — Maximum incidents to fetch
  • first_fetch — First fetch time
  • mirror_direction — Mirroring Direction
  • incidentType — Incident type
  • incidentFetchInterval — Incidents Fetch Interval

Commands (27)

  • fetch-incidents

    Retrieves incidents from GravityZone Cloud.

  • get-mapping-fields

    Returns the list of fields available for outgoing mirroring. This command is intended for debugging purposes only.

  • get-modified-remote-data

    Retrieves incidents that were modified since the last data sync. This command is intended for debugging purposes.

  • get-remote-data

    Retrieves data from a remote incident without updating the current incident. This command is intended for debugging purposes.

  • gz-endpoint-create-memory-dump

    Initiates the creation of a memory dump for the specified endpoint. Once the dump is successfully generated, the resulting archive is uploaded to the Bitdefender cloud.

  • gz-endpoint-deisolate

    Restores an isolated endpoint to the network.

  • gz-endpoint-download-file

    Downloads a file from an endpoint.

  • gz-endpoint-download-investigation-package

    Collects and downloads an investigation package from an endpoint.

  • gz-endpoint-get

    Retrieves endpoint details by endpoint ID.

  • gz-endpoint-get-process-tree-by-hash

    Retrieves the process tree on an endpoint for a specified process hash. The applied policy must allow Live Search and the endpoint must be online.

  • gz-endpoint-isolate

    Isolates an endpoint from the network.

  • gz-endpoint-kill-process

    Terminates a process on an endpoint by process ID.

  • gz-endpoint-list

    Retrieves the list of managed endpoints.

  • gz-endpoint-list-by-running-process-hash

    Retrieves endpoints that are running processes with a specified hash. The API key and the applied policy must allow Live Search and endpoints must be online. The command waits up to five minutes for responses before timing out.

  • gz-endpoint-memory-dump-status

    Verifies the status of a task initiated via gz-endpoint-create-memory-dump.

  • gz-endpoint-run-command

    Runs a command on the endpoint. The applied policy must have remote shell enabled for this action to work.

  • gz-endpoint-upload-file

    Uploads a file to an endpoint.

  • gz-endpoint-users-loggedin

    Retrieves details of all active user sessions on a specific managed endpoint.

  • gz-incident-add-note

    Adds a note to one or more incidents.

  • gz-incident-change-status

    Changes the status of one or more incidents.

  • gz-incident-get

    Retrieves incident details by ID.

  • gz-incident-list

    Retrieves incidents from the last three days for all endpoints or for a specific endpoint.

  • gz-poll-endpoint-users-loggedin-status

    Verifies the status of a task initiated via gz-endpoint-users-loggedin. This command is invoked automatically and is not intended for direct use.

  • gz-poll-investigation-activity-status

    Checks the status of an investigation activity. This command is not intended for direct use.

  • gz-poll-live-search-status

    Checks the status of a Live Search query. This command is not intended for direct use.

  • gz-poll-task-status

    Checks the task status. This command is not intended for direct use.

  • update-remote-system

    Updates the remote incident with local incident changes without updating the current incident. This command is intended for debugging purposes.

import json
import os
from typing import cast
from unittest.mock import patch
from freezegun import freeze_time
import pytest

from CommonServerPython import CommandResults, EntryType


SERVER_URL = "https://localhost"


def util_load_json(path):
    with open(path, encoding="utf-8") as f:
        return json.loads(f.read())


def get_client():
    from GravityZone import Client

    return Client(url=SERVER_URL, verify=False, api_key="fake")


def load_api_mocked_data(requests_mock, command_name):
    command_renamed = command_name.replace("-", "_")
    function_name = f"{command_renamed}_command"

    api_file_path = os.path.join(os.path.dirname(__file__), "test_data", f"{function_name}_api.json")
    data = util_load_json(api_file_path)

    # Group responses by URL and method
    url_responses = {}
    for item in data:
        url = f"{SERVER_URL}{item['request']['url']}"
        method = "get" if item["request"].get("get", False) else "post"
        url_responses.setdefault((method, url), []).append(item["response"])

    # Register each URL/method with a callback to return responses sequentially
    for (method, url), responses in url_responses.items():
        response_iter = iter(responses)

        def get_callback(request, context, response_iter=response_iter, responses=responses):
            try:
                resp = next(response_iter)
            except StopIteration:
                resp = responses[-1]
            if "content" in resp:
                context.status_code = resp.get("status_code", 200)
                for k, v in resp.get("headers", {}).items():
                    context.headers[k] = v
                return resp["content"].encode()
            return resp

        def post_callback(request, context, response_iter=response_iter, responses=responses):
            try:
                return next(response_iter)
            except StopIteration:
                return responses[-1]

        if method == "post":
            requests_mock.post(url, json=post_callback)
        else:
            requests_mock.get(url, content=get_callback)


def assert_command_mocked_data(command_name, command_response, polling_func=None, client=None):
    test_data_dir = os.path.join(os.path.dirname(__file__), "test_data")

    command_renamed = command_name.replace("-", "_")
    function_name = f"{command_renamed}_command"

    if polling_func is not None and client is not None:
        while getattr(command_response, "scheduled_command", None):
            command_response = polling_func(command_response.scheduled_command._args, client)

    if isinstance(command_response, list):
        command_response = command_response[0]

    context = command_response.to_context()

    raw_response = context.get("Contents")
    human_readable = context.get("HumanReadable")
    outputs = context.get("EntryContext")

    def assert_file_content(actual, expected_paths, error_msg):
        if not any(os.path.exists(p) for p in expected_paths):
            raise FileNotFoundError(f"No expected file found for {function_name} in paths: {expected_paths}")
        for expected_path in expected_paths:
            if not os.path.exists(expected_path):
                continue
            with open(expected_path, encoding="utf-8") as f:
                expected = f.read() if expected_path.endswith((".md", ".txt")) else json.load(f)
                assert actual == expected, f"{error_msg} for {function_name}"

    assert_file_content(
        raw_response,
        [
            os.path.join(test_data_dir, f"{function_name}_raw_response.json"),
            os.path.join(test_data_dir, f"{function_name}_raw_response.txt"),
        ],
        "Raw response does not match",
    )
    assert_file_content(
        human_readable, [os.path.join(test_data_dir, f"{function_name}_human_readable.md")], "Human readable does not match"
    )
    assert_file_content(
        outputs, [os.path.join(test_data_dir, f"{function_name}_entry_context.json")], "Entry context does not match"
    )


@patch("GravityZone.demisto")
def test_fetch_incidents_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling fetch-incidents command
    Then
            Make sure the fetched incidents values are as expected.
    """

    # Prepare
    from GravityZone import fetch_incidents_command

    mock_demisto.command.return_value = "fetch-incidents"
    mock_demisto.args.return_value = {}
    mock_demisto.getLastRun.return_value = {}
    mock_demisto.integrationInstance.return_value = "GravityZone"
    mock_demisto.params.return_value = {"max_fetch": 2, "first_fetch": "3 days"}
    load_api_mocked_data(requests_mock, "fetch-incidents")
    client = get_client()
    fetch_incidents_command(client, {})

    assert mock_demisto.incidents.call_count == 1
    assert len(mock_demisto.incidents.call_args[0][0]) == 2

    incidents = mock_demisto.incidents.call_args[0][0]
    for incident in incidents:
        assert "name" in incident
        assert "occurred" in incident
        assert "rawJSON" in incident

    incident_names = [incident.get("name") for incident in incidents]
    assert incident_names == ["GravityZone Incident #477", "GravityZone Incident #475"]
    assert mock_demisto.setLastRun.call_count == 1


@patch("GravityZone.demisto")
def test_get_remote_data_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling get-remote-data command
    Then
            Make sure the mirrored incident values are as expected.
    """

    # Prepare
    from GravityZone import get_remote_data_command

    mock_demisto.command.return_value = "get-remote-data"
    mock_demisto.params.return_value = {"mirror_direction": "Both"}
    mock_demisto.integrationInstance.return_value = "GravityZone"
    load_api_mocked_data(requests_mock, "get-remote-data")
    client = get_client()
    result = get_remote_data_command(client, {"id": "6940ee975f5c8b75247c3f38", "lastUpdate": "2024-01-01T00:00:00Z"})
    assert result is not None, "get_remote_data_command returned None"
    local_data = result.extract_for_local() if hasattr(result, "extract_for_local") else None
    assert local_data is not None, "extract_for_local() returned None"
    assert isinstance(local_data, list), "extract_for_local() did not return a list"
    assert len(local_data) > 0, "extract_for_local() returned an empty list"
    assert local_data[0].get("id") == "6940ee975f5c8b75247c3f38"


@patch("GravityZone.demisto")
def test_get_modified_remote_data_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling get-modified-remote-data command
    Then
            Make sure the mirrored incident values are as expected.
    """
    # Prepare
    from GravityZone import get_modified_remote_data_command

    mock_demisto.command.return_value = "get-modified-remote-data"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "get-modified-remote-data")
    client = get_client()
    result = get_modified_remote_data_command(client, {"lastUpdate": "2026-01-01T00:00:00Z"})
    assert result.to_entry().get("Contents") == ["6940ee975f5c8b75247c3f38", "6940eeadaa87b3d57af088aa"]


@freeze_time("2025-12-16 13:00:00 UTC")
@patch("GravityZone.demisto")
def test_get_mapping_fields_command(mock_demisto, mocker, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling get-mapping-fields command
    Then
            Make sure the mappings values are as expected.
    """
    # Prepare
    from GravityZone import get_mapping_fields_command

    mock_demisto.command.return_value = "get-mapping-fields"
    mock_demisto.params.return_value = {}
    client = get_client()
    response = get_mapping_fields_command(client, {})
    schemes = response.extract_mapping()
    assert len(schemes) == 2

    xdr_scheme = next((s for s in schemes if s == "GravityZone XDR"), None)
    edr_scheme = next((s for s in schemes if s == "GravityZone EDR"), None)

    assert xdr_scheme is not None
    assert edr_scheme is not None


@freeze_time("2025-12-16 13:00:00 UTC")
@patch("GravityZone.demisto")
def test_test_module(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling test-module command
    Then
            Make sure the command works.
    """

    # Prepare
    from GravityZone import test_module

    mock_demisto.command.return_value = "test-module"
    mock_demisto.params.return_value = {
        "first_fetch": "3 days",
    }
    mock_demisto.args.return_value = {}
    load_api_mocked_data(requests_mock, "test-module")
    client = get_client()

    # Execute command
    result = test_module(client=client, args={})

    # Assert
    assert result == "ok"


@patch("GravityZone.demisto")
def test_gz_endpoint_list_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-endpoint-list command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import gz_endpoint_list_command

    mock_demisto.command.return_value = "gz-endpoint-list"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-list")
    client = get_client()

    # Execute command
    command_response = gz_endpoint_list_command(client=client, args={})

    # Assert command response
    assert_command_mocked_data("gz-endpoint-list", command_response)


@patch("GravityZone.demisto")
@pytest.mark.parametrize(
    "valid_name",
    [
        "ABC",
    ],
)
def test_gz_endpoint_list_command_valid_name_values(mock_demisto, requests_mock, valid_name):
    """
    Given
            A valid `name` argument value
    When
            Calling gz-endpoint-list command
    Then
            Make sure command execution succeeds.
    """

    # Prepare
    from GravityZone import gz_endpoint_list_command

    mock_demisto.command.return_value = "gz-endpoint-list"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-list-name")
    client = get_client()

    # Execute
    command_response = gz_endpoint_list_command(client=client, args={"name": valid_name})

    # Assert
    assert command_response is not None
    assert requests_mock.called

    # Assert command response
    assert_command_mocked_data("gz-endpoint-list-name", command_response)


@patch("GravityZone.demisto")
@pytest.mark.parametrize(
    ("invalid_name", "expected_error"),
    [
        ("ab", r"The 'name' argument must be at least 3 characters long\."),
        ("ac*b", r"If using a wildcard, the 'name' argument must start with '\*'\."),
        ("*ac*b*d", r"The 'name' argument can only contain one wildcard '\*' character\."),
    ],
)
def test_gz_endpoint_list_command_invalid_name_values(mock_demisto, requests_mock, invalid_name, expected_error):
    """
    Given
            An invalid `name` argument value
    When
            Calling gz-endpoint-list command
    Then
            Make sure command validation fails.
    """

    # Prepare
    from GravityZone import gz_endpoint_list_command

    mock_demisto.command.return_value = "gz-endpoint-list"
    mock_demisto.params.return_value = {}
    client = get_client()

    # Execute + Assert
    with pytest.raises(Exception, match=expected_error):
        gz_endpoint_list_command(client=client, args={"name": invalid_name})

    # Invalid input should fail before API calls
    assert not requests_mock.called


@patch("GravityZone.demisto")
@pytest.mark.parametrize(
    "node_id",
    [
        "COMPANY_ID",
    ],
)
def test_gz_endpoint_list_command_with_node_id_skips_get_my_company(mock_demisto, requests_mock, node_id):
    """
    Given
            A `node_id` argument value
    When
            Calling gz-endpoint-list command
    Then
            Make sure get_my_company is not called.
    """

    # Prepare
    from GravityZone import gz_endpoint_list_command

    mock_demisto.command.return_value = "gz-endpoint-list"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-list-node")
    client = get_client()

    with patch.object(client, "get_my_company", side_effect=AssertionError("get_my_company should not be called")) as mocked:
        # Execute
        command_response = gz_endpoint_list_command(client=client, args={"node_id": node_id})

        # Assert
        assert command_response is not None
        mocked.assert_not_called()
        assert requests_mock.called

        # Assert command response
        assert_command_mocked_data("gz-endpoint-list-node", command_response)


@patch("GravityZone.demisto")
def test_gz_endpoint_get_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-endpoint-get command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """
    # Prepare
    from GravityZone import gz_endpoint_get_command

    mock_demisto.command.return_value = "gz-endpoint-get"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-get")
    client = get_client()

    # Execute command
    command_response = gz_endpoint_get_command(client=client, args={"id": "ENDPOINT_ID"})

    # Assert command response
    assert_command_mocked_data("gz-endpoint-get", command_response)


@patch("GravityZone.demisto")
def test_gz_endpoint_users_loggedin_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-endpoint-users-loggedin command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import gz_endpoint_users_loggedin_command, gz_poll_endpoint_users_loggedin_status_command

    mock_demisto.command.return_value = "gz-endpoint-users-loggedin"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-users-loggedin")
    client = get_client()

    # Execute command
    command_response = gz_endpoint_users_loggedin_command(client=client, args={"id": "ENDPOINT_ID"})

    # Assert command response
    assert_command_mocked_data(
        "gz-endpoint-users-loggedin",
        command_response,
        polling_func=gz_poll_endpoint_users_loggedin_status_command,
        client=client,
    )


@patch("GravityZone.demisto")
def test_gz_endpoint_create_memory_dump_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-endpoint-create-memory-dump command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import gz_endpoint_create_memory_dump_command, gz_endpoint_memory_dump_status_command

    mock_demisto.command.return_value = "gz-endpoint-create-memory-dump"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-create-memory-dump")
    client = get_client()

    # Execute command
    command_response = gz_endpoint_create_memory_dump_command(
        client=client,
        args={"id": "ENDPOINT_ID", "path": "C:\\dumps\\", "password": "ComplexPass123!"},
    )

    # Assert command response
    assert_command_mocked_data(
        "gz-endpoint-create-memory-dump",
        command_response,
        polling_func=lambda poll_args, poll_client: gz_endpoint_memory_dump_status_command(poll_client, poll_args),
        client=client,
    )


@patch("GravityZone.demisto")
def test_gz_endpoint_create_memory_dump_command_no_polling(mock_demisto, requests_mock):
    from GravityZone import gz_endpoint_create_memory_dump_command
    from CommonServerPython import CommandResults

    mock_demisto.command.return_value = "gz-endpoint-create-memory-dump"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-create-memory-dump")
    client = get_client()

    command_response = cast(
        CommandResults,
        gz_endpoint_create_memory_dump_command(
            client=client,
            args={"id": "ENDPOINT_ID", "path": "C:\\dumps\\", "password": "ComplexPass123!", "polling": "false"},
        ),
    )

    assert getattr(command_response, "scheduled_command", None) is None
    context = command_response.to_context()
    output = context["EntryContext"]["GravityZone.MemoryDump(val.EndpointID && val.EndpointID == obj.EndpointID)"]

    assert output["TaskID"] == "TASK_ID"
    assert output["TaskType"] == "CreateMemoryDump"
    assert output["Status"] == "Pending"
    assert output["EndpointID"] == "ENDPOINT_ID"
    assert output["EndDate"] == ""
    assert output["ErrorCode"] == ""
    assert output["Error"] == ""
    assert output["DownloadURL"] == ""


@patch("GravityZone.check_endpoint_memory_dump_status")
def test_gz_endpoint_memory_dump_status_command_defaults_polling_true(mock_check_status):
    from GravityZone import gz_endpoint_memory_dump_status_command
    from GravityZone import Client

    client = cast(Client, object())

    gz_endpoint_memory_dump_status_command(client, {"task_id": "TASK_ID", "endpoint_id": "ENDPOINT_ID"})

    mock_check_status.assert_called_once_with(
        {"task_id": "TASK_ID", "endpoint_id": "ENDPOINT_ID", "polling": True},
        client,
    )


@patch("GravityZone.demisto")
def test_gz_endpoint_memory_dump_status_command(mock_demisto, requests_mock):
    from GravityZone import gz_endpoint_memory_dump_status_command

    mock_demisto.command.return_value = "gz-endpoint-memory-dump-status"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-memory-dump-status")
    client = get_client()

    command_response = gz_endpoint_memory_dump_status_command(
        client,
        {"task_id": "TASK_ID", "endpoint_id": "ENDPOINT_ID"},
    )

    assert_command_mocked_data(
        "gz-endpoint-memory-dump-status",
        command_response,
        polling_func=lambda poll_args, poll_client: gz_endpoint_memory_dump_status_command(poll_client, poll_args),
        client=client,
    )


def test_check_endpoint_users_loggedin_status_returns_error_on_unexpected_task_type():
    from GravityZone import check_endpoint_users_loggedin_status

    class MockClient:
        def get_task_status(self, _task_id):
            return {"status": 3, "type": 27, "subtasks": []}

    result = check_endpoint_users_loggedin_status(
        {"task_id": "TASK_ID", "endpoint_id": "ENDPOINT_ID"},
        MockClient(),
    )

    assert isinstance(result, CommandResults)
    assert result.readable_output is not None
    assert "unexpected type" in result.readable_output
    assert "GetActiveSessions" in result.readable_output


def test_check_endpoint_users_loggedin_status_returns_error_when_task_type_is_missing():
    from GravityZone import check_endpoint_users_loggedin_status

    class MockClient:
        def get_task_status(self, _task_id):
            return {"status": 3, "subtasks": []}

    result = check_endpoint_users_loggedin_status(
        {"task_id": "TASK_ID", "endpoint_id": "ENDPOINT_ID"},
        MockClient(),
    )

    assert isinstance(result, CommandResults)
    assert result.readable_output is not None
    assert "does not have a type" in result.readable_output
    assert "gz-poll-endpoint-users-loggedin-status" in result.readable_output


def test_check_endpoint_memory_dump_status_returns_error_on_unexpected_task_type():
    from GravityZone import check_endpoint_memory_dump_status

    class MockClient:
        def get_task_status(self, _task_id):
            return {"status": 3, "type": 26, "subtasks": []}

    result = check_endpoint_memory_dump_status(
        {"task_id": "TASK_ID", "endpoint_id": "ENDPOINT_ID"},
        MockClient(),
    )

    assert isinstance(result, CommandResults)
    assert result.readable_output is not None
    assert "unexpected type" in result.readable_output
    assert "CreateMemoryDump" in result.readable_output


def test_check_endpoint_memory_dump_status_returns_error_when_task_type_is_missing():
    from GravityZone import check_endpoint_memory_dump_status

    class MockClient:
        def get_task_status(self, _task_id):
            return {"status": 3, "subtasks": []}

    result = check_endpoint_memory_dump_status(
        {"task_id": "TASK_ID", "endpoint_id": "ENDPOINT_ID"},
        MockClient(),
    )

    assert isinstance(result, CommandResults)
    assert result.readable_output is not None
    assert "does not have a type" in result.readable_output
    assert "gz-endpoint-memory-dump-status" in result.readable_output


def test_extract_active_sessions_from_task_handles_missing_optional_fields():
    from GravityZone import _extract_active_sessions_from_task

    task_output = {
        "status": 3,
        "subtasks": [
            {
                "endpointId": "endpoint-1",
                "endpointName": "host-1",
                "status": 3,
                "result": [
                    {
                        "connection": {
                            "started": "2021-05-19T10:37:56Z",
                            "type": "local",
                        },
                        "user": {
                            "displayName": "user@example.com",
                        },
                    }
                ],
            }
        ],
    }

    sessions = _extract_active_sessions_from_task(task_output)

    assert len(sessions) == 1
    assert sessions[0]["Username"] == "user@example.com"
    assert sessions[0]["ConnectionType"] == "local"
    assert sessions[0]["StartTime"] == "2021-05-19T10:37:56Z"
    assert "UserSID" not in sessions[0]
    assert "DomainSID" not in sessions[0]
    assert "OrganizationalUnitDN" not in sessions[0]
    assert "MemberOfSIDs" not in sessions[0]


def test_extract_endpoint_summary_from_task_returns_hostname_for_matching_endpoint_id():
    from GravityZone import _extract_endpoint_summary_from_task

    task_output = {
        "subtasks": [
            {
                "endpointId": "endpoint-2",
                "endpointName": "host-2",
            },
            {
                "endpointId": "endpoint-1",
                "endpointName": "host-1-updated",
            },
        ]
    }

    endpoint_id, hostname = _extract_endpoint_summary_from_task(task_output, "endpoint-1")

    assert endpoint_id == "endpoint-1"
    assert hostname == "host-1-updated"


def test_build_users_loggedin_results_outputs_endpoint_scoped_context():
    from GravityZone import _build_users_loggedin_results

    task_output = {
        "status": 3,
        "subtasks": [
            {
                "endpointId": "endpoint-1",
                "endpointName": "host-1-updated",
                "status": 3,
                "result": [],
            }
        ],
    }

    result = _build_users_loggedin_results(task_output, "endpoint-1")

    assert result.outputs_prefix == "GravityZone.Endpoint"
    assert result.outputs_key_field == "ID"
    assert result.outputs == {
        "ID": "endpoint-1",
        "Hostname": "host-1-updated",
        "ActiveSessions": [],
    }


def test_extract_memory_dump_summary_uses_matching_endpoint_subtask_and_download_url():
    from GravityZone import _extract_memory_dump_summary

    task_output = {
        "subtasks": [
            {
                "endpointId": "endpoint-other",
                "status": 3,
                "downloadURL": "https://example.com/other",
            },
            {
                "endpointId": "endpoint-1",
                "status": 3,
                "downloadURL": "https://example.com/memory-dump",
            },
        ]
    }

    endpoint_id, endpoint_hostname, subtask, download_url = _extract_memory_dump_summary(task_output, "endpoint-1")
    assert endpoint_id == "endpoint-1"
    assert endpoint_hostname == ""
    assert subtask == {
        "endpointId": "endpoint-1",
        "status": 3,
        "downloadURL": "https://example.com/memory-dump",
    }
    assert download_url == "https://example.com/memory-dump"


def test_extract_memory_dump_summary_ignores_non_processed_subtask_for_download_url():
    from GravityZone import _extract_memory_dump_summary

    task_output = {
        "subtasks": [
            {
                "endpointId": "endpoint-1",
                "status": 2,
                "downloadURL": "https://example.com/should-not-be-used",
            }
        ]
    }

    endpoint_id, endpoint_hostname, subtask, download_url = _extract_memory_dump_summary(task_output, "endpoint-1")
    assert endpoint_id == "endpoint-1"
    assert endpoint_hostname == ""
    assert subtask == {
        "endpointId": "endpoint-1",
        "status": 2,
        "downloadURL": "https://example.com/should-not-be-used",
    }
    assert download_url == ""


def test_extract_memory_dump_summary_returns_none_when_endpoint_not_found():
    from GravityZone import _extract_memory_dump_summary

    task_output = {
        "subtasks": [
            {
                "endpointId": "endpoint-1",
                "status": 3,
                "downloadURL": "https://example.com/memory-dump",
            }
        ]
    }

    endpoint_id, endpoint_hostname, subtask, download_url = _extract_memory_dump_summary(task_output, "endpoint-missing")
    assert endpoint_id == "endpoint-missing"
    assert endpoint_hostname == ""
    assert subtask is None
    assert download_url == ""


def test_extract_memory_dump_task_id_from_string_result():
    from GravityZone import _extract_memory_dump_task_id

    assert _extract_memory_dump_task_id("TASK_ID") == "TASK_ID"


def test_extract_memory_dump_task_id_raises_on_invalid_result():
    from GravityZone import _extract_memory_dump_task_id

    with pytest.raises(Exception, match="createMemoryDumpTask response is missing task ID"):
        _extract_memory_dump_task_id({})


def test_build_memory_dump_results_outputs_download_url_on_success():
    from GravityZone import _build_memory_dump_results

    task_output = {
        "status": 3,
        "subtasks": [
            {
                "endpointId": "endpoint-1",
                "endpointName": "host-1",
                "status": 3,
                "startDate": "2026-05-25T10:00:00",
                "endDate": "2026-05-25T10:01:00",
                "errorCode": "Success",
                "errorMessage": "Success",
                "downloadURL": "https://example.com/memory-dump",
            }
        ],
    }

    result = _build_memory_dump_results(task_output, "TASK_ID", "endpoint-1")

    assert result.outputs_prefix == "GravityZone.MemoryDump"
    assert result.outputs_key_field == "EndpointID"
    assert result.outputs == {
        "TaskID": "TASK_ID",
        "TaskType": "CreateMemoryDump",
        "Status": "Processed",
        "EndpointID": "endpoint-1",
        "Hostname": "host-1",
        "StartDate": "2026-05-25T10:00:00Z",
        "EndDate": "2026-05-25T10:01:00Z",
        "ErrorCode": "Success",
        "Error": "Success",
        "DownloadURL": "https://example.com/memory-dump",
    }


def test_build_memory_dump_results_omits_download_url_when_unavailable():
    from GravityZone import _build_memory_dump_results

    task_output = {
        "status": 1,
        "subtasks": [
            {
                "endpointId": "endpoint-1",
                "endpointName": "host-1",
                "status": 1,
                "startDate": "2026-05-25T10:00:00",
            }
        ],
    }

    result = _build_memory_dump_results(task_output, "TASK_ID", "endpoint-1")

    assert result.outputs == {
        "TaskID": "TASK_ID",
        "TaskType": "CreateMemoryDump",
        "Status": "Pending",
        "EndpointID": "endpoint-1",
        "Hostname": "host-1",
        "StartDate": "2026-05-25T10:00:00Z",
        "EndDate": "",
        "ErrorCode": "",
        "Error": "",
        "DownloadURL": "",
    }


def test_build_memory_dump_results_returns_error_when_endpoint_not_found():
    from GravityZone import _build_memory_dump_results

    task_output = {
        "status": 3,
        "subtasks": [
            {
                "endpointId": "endpoint-1",
                "endpointName": "host-1",
                "status": 3,
                "startDate": "2026-05-25T10:00:00",
                "endDate": "2026-05-25T10:01:00",
            }
        ],
    }

    result = _build_memory_dump_results(task_output, "TASK_ID", "endpoint-missing")

    assert result.entry_type == EntryType.ERROR
    assert result.readable_output == "Invalid Endpoint ID. Available endpoint IDs for task 'TASK_ID': ['endpoint-1']"


def test_build_memory_dump_results_returns_error_when_task_has_no_results():
    from GravityZone import _build_memory_dump_results

    task_output = {
        "status": 3,
        "subtasks": [],
    }

    result = _build_memory_dump_results(task_output, "TASK_ID", "")

    assert result.entry_type == EntryType.ERROR
    assert result.readable_output == "Task 'TASK_ID' has no memory dump results."


def test_generate_processed_task_command_result_maps_memory_dump_task_type():
    from GravityZone import generate_processed_task_command_result

    task_output = {
        "type": 27,
        "subtasks": [
            {
                "endpointId": "endpoint-1",
                "endpointName": "host-1",
                "startDate": "2026-05-26T10:00:00",
                "endDate": "2026-05-26T10:01:00",
            }
        ],
    }

    result = generate_processed_task_command_result("parent-task-id", task_output, {})

    assert result.outputs_prefix == "GravityZone.Command.CreateMemoryDump"


@patch("GravityZone.demisto")
def test_gz_endpoint_isolate_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-endpoint-isolate command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import gz_endpoint_isolate_command, gz_poll_task_status_command

    mock_demisto.command.return_value = "gz-endpoint-isolate"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-isolate")
    client = get_client()

    # Execute command
    command_response = gz_endpoint_isolate_command(client=client, args={"id": "ENDPOINT_ID"})

    # Assert command response
    assert_command_mocked_data("gz-endpoint-isolate", command_response, polling_func=gz_poll_task_status_command, client=client)


@patch("GravityZone.demisto")
def test_gz_endpoint_deisolate_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-endpoint-deisolate command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import gz_endpoint_deisolate_command, gz_poll_task_status_command

    mock_demisto.command.return_value = "gz-endpoint-deisolate"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-deisolate")
    client = get_client()

    # Execute command
    command_response = gz_endpoint_deisolate_command(client=client, args={"id": "ENDPOINT_ID"})

    # Assert command response
    assert_command_mocked_data("gz-endpoint-deisolate", command_response, polling_func=gz_poll_task_status_command, client=client)


@patch("GravityZone.demisto")
def test_gz_endpoint_kill_process_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-endpoint-kill-process command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import (
        gz_endpoint_kill_process_command,
        gz_poll_task_status_command,
    )

    mock_demisto.command.return_value = "gz-endpoint-kill-process"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-kill-process")
    client = get_client()

    # Execute command
    command_response = gz_endpoint_kill_process_command(
        client=client,
        args={
            "id": "ENDPOINT_ID",
            "pid": "5876",
        },
    )

    # Assert command response
    assert_command_mocked_data(
        "gz-endpoint-kill-process", command_response, polling_func=gz_poll_task_status_command, client=client
    )


@patch("GravityZone.demisto")
def test_gz_endpoint_run_command_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-endpoint-run-command command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import (
        gz_endpoint_run_command_command,
        gz_poll_investigation_activity_status_command,
    )

    mock_demisto.command.return_value = "gz-endpoint-run-command"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-run-command")
    client = get_client()

    # Execute command
    command_response = gz_endpoint_run_command_command(
        client=client,
        args={
            "id": "6942a43afe8d4e463ca5c197",
            "command": "ls -1",
        },
    )

    # Assert command response
    assert_command_mocked_data(
        "gz-endpoint-run-command", command_response, polling_func=gz_poll_investigation_activity_status_command, client=client
    )


@patch("GravityZone.demisto")
def test_gz_endpoint_get_process_tree_by_hash(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-endpoint-get-process-tree-by-hash command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import (
        gz_endpoint_get_process_tree_by_hash_command,
        gz_poll_live_search_status_command,
    )

    mock_demisto.command.return_value = "gz-endpoint-get-process-tree-by-hash"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-get-process-tree-by-hash")
    client = get_client()

    # Execute command
    command_response = gz_endpoint_get_process_tree_by_hash_command(
        client=client,
        args={
            "id": "ENDPOINT_ID",
            "process_hash": "PROCESS_HASH",
        },
    )

    # Assert command response
    assert_command_mocked_data(
        "gz-endpoint-get-process-tree-by-hash",
        command_response,
        polling_func=gz_poll_live_search_status_command,
        client=client,
    )


@patch("GravityZone.demisto")
def test_gz_endpoint_list_by_running_process_hash_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-endpoint-list-by-running-process-hash command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import (
        gz_endpoint_list_by_running_process_hash_command,
        gz_poll_live_search_status_command,
    )

    mock_demisto.command.return_value = "gz-endpoint-list-by-running-process-hash"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-list-by-running-process-hash")
    client = get_client()

    # Execute command
    command_response = gz_endpoint_list_by_running_process_hash_command(
        client=client,
        args={
            "process_hash": "PROCESS_HASH",
        },
    )

    # Assert command response
    assert_command_mocked_data(
        "gz-endpoint-list-by-running-process-hash",
        command_response,
        polling_func=gz_poll_live_search_status_command,
        client=client,
    )


@patch("GravityZone.demisto")
def test_gz_poll_task_status_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-poll-task-status command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import gz_poll_task_status_command

    mock_demisto.command.return_value = "gz-poll-task-status"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-poll-task-status")
    client = get_client()

    # Execute command
    result = gz_poll_task_status_command(
        client=client,
        args={
            "task_id": "6941944218d1fb8aea04019b",
            "metadata": '{"targetId":"ENDPOINT_ID","processId":10252}',
        },
    )

    # Assert command response
    assert_command_mocked_data("gz-poll-task-status", result)


@patch("GravityZone.demisto")
def test_gz_poll_live_search_status_command(mock_demisto, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-poll-live-search-status command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import gz_poll_live_search_status_command

    mock_demisto.command.return_value = "gz-poll-live-search-status"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-poll-live-search-status")
    client = get_client()

    # Execute command
    result = gz_poll_live_search_status_command(
        client=client,
        args={
            "task_id": "694266e8b349a87d10079634",
            "search_type": "fake",
            "metadata": '{"process_hash": "process_hash"}',
        },
    )

    # Assert command response
    assert_command_mocked_data("gz-poll-live-search-status", result)


@patch("GravityZone.demisto")
def test_gz_poll_investigation_activity_status_command(mock_demisto, mocker, requests_mock):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-poll-investigation-activity-status command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import gz_poll_investigation_activity_status_command

    mock_demisto.command.return_value = "gz-poll-investigation-activity-status"
    mock_demisto.params.return_value = {}
    mocker.patch(
        "GravityZone.fileResult",
        return_value={
            "Contents": "",
            "ContentsFormat": "text",
            "Type": 3,
            "File": "downloaded_file.txt",
            "FileID": "abc",
        },
    )
    load_api_mocked_data(requests_mock, "gz-poll-investigation-activity-status")
    client = get_client()

    # Execute command
    result = gz_poll_investigation_activity_status_command(
        client=client,
        args={
            "target_id": "6942a43afe8d4e463ca5c197",
            "activity_id": "6943db6115457d24450196d3",
            "metadata": '{"activityType":2,"command":"ls -1"}',
        },
    )

    # Assert command response
    assert_command_mocked_data("gz-poll-investigation-activity-status", result)


@pytest.mark.parametrize(
    "args, api_mock_name",
    [
        ({}, "gz-incident-list"),
        ({"endpoint_id": "ENDPOINT_ID"}, "gz-incident-list-2"),
    ],
)
@patch("GravityZone.demisto")
def test_gz_incident_list_command(mock_demisto, requests_mock, args, api_mock_name):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-incident-list command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import gz_incident_list_command

    mock_demisto.command.return_value = "gz-incident-list"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, api_mock_name)
    client = get_client()

    # Execute command
    command_response = gz_incident_list_command(client=client, args=args)

    # Assert command response
    assert_command_mocked_data(api_mock_name, command_response)


@pytest.mark.parametrize(
    "incident_id",
    [
        ("INCIDENT_ID_1"),
    ],
)
@patch("GravityZone.demisto")
def test_gz_incident_get_edr_command(mock_demisto, requests_mock, incident_id):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-incident-get command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import gz_incident_get_command

    mock_demisto.command.return_value = "gz-incident-get"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-incident-get-edr")
    client = get_client()

    # Execute command
    command_response = gz_incident_get_command(client=client, args={"id": incident_id})

    # Assert command response
    assert_command_mocked_data("gz-incident-get-edr", command_response)


@pytest.mark.parametrize(
    "incident_id",
    [
        ("INCIDENT_ID_1"),
    ],
)
@patch("GravityZone.demisto")
def test_gz_incident_get_xdr_command(mock_demisto, requests_mock, incident_id):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-incident-get command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import gz_incident_get_command

    mock_demisto.command.return_value = "gz-incident-get"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-incident-get-xdr")
    client = get_client()

    # Execute command
    command_response = gz_incident_get_command(client=client, args={"id": incident_id})

    # Assert command response
    assert_command_mocked_data("gz-incident-get-xdr", command_response)


@pytest.mark.parametrize(
    "incident_id, note",
    [
        ("INCIDENT_ID_1", "This is a test note from unit test."),
    ],
)
@patch("GravityZone.demisto")
def test_gz_incident_add_note_command(mock_demisto, requests_mock, incident_id, note):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-incident-add-note command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import gz_incident_add_note_command

    mock_demisto.command.return_value = "gz-incident-add-note"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-incident-add-note")
    client = get_client()

    # Execute command
    command_response = gz_incident_add_note_command(
        client=client,
        args={
            "id": incident_id,
            "note": note,
        },
    )

    # Assert command response
    assert_command_mocked_data("gz-incident-add-note", command_response)


@pytest.mark.parametrize(
    "incident_id, status_param, api_mock_name",
    [
        ("INCIDENT_ID_1", "PENDING", "gz-incident-change-status-pending"),
        ("INCIDENT_ID_1", "ACTIVE", "gz-incident-change-status-active"),
        ("INCIDENT_ID_1", "DONE", "gz-incident-change-status-done"),
    ],
)
@patch("GravityZone.demisto")
def test_gz_incident_change_status_command(mock_demisto, requests_mock, incident_id, status_param, api_mock_name):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-incident-change-status command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import gz_incident_change_status_command

    mock_demisto.command.return_value = "gz-incident-change-status"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, api_mock_name)
    client = get_client()

    # Execute command
    command_response = gz_incident_change_status_command(
        client=client,
        args={
            "id": incident_id,
            "status": status_param,
        },
    )

    # Assert command response
    assert_command_mocked_data(api_mock_name, command_response)


@pytest.mark.parametrize(
    "incident_id, status_param, note",
    [
        ("INCIDENT_ID_1", 0, "incident pending"),
        ("INCIDENT_ID_1", 1, "incident active"),
        ("INCIDENT_ID_1", 2, "incident done"),
    ],
)
@patch("GravityZone.demisto")
def test_update_remote_system_command(mock_demisto, requests_mock, incident_id, status_param, note):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling update-remote-system command
    Then
            Make sure the the return value is as expected.
    """

    # Prepare
    from GravityZone import update_remote_system_command

    mock_demisto.command.return_value = "update-remote-system"
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "update-remote-system")
    client = get_client()

    # Execute command
    command_response = update_remote_system_command(
        client=client,
        args={
            "remoteId": incident_id,
            "data": {},
            "entries": [],
            "status": status_param,
            "incidentChanged": True,
            "delta": {"closeNotes": note},
        },
    )

    # Assert command response
    assert command_response == incident_id
    assert requests_mock.called


@pytest.mark.parametrize(
    "endpoint_id, mock_data_suffix",
    [("6942a43afe8d4e463ca5c197", ""), ("ENDPOINT_ID", "-failed")],
)
@patch("GravityZone.demisto")
def test_gz_endpoint_download_file_command(mock_demisto, mocker, requests_mock, endpoint_id, mock_data_suffix):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-endpoint-download-file command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import (
        gz_endpoint_download_file_command,
        gz_poll_investigation_activity_status_command,
    )

    mock_demisto.command.return_value = "gz-endpoint-download-file"
    mock_demisto.params.return_value = {}
    mocker.patch(
        "GravityZone.fileResult",
        return_value={
            "Contents": "",
            "ContentsFormat": "text",
            "Type": 3,
            "File": "downloaded_file.txt",
            "FileID": "abc",
        },
    )
    load_api_mocked_data(requests_mock, f"gz-endpoint-download-file{mock_data_suffix}")
    client = get_client()

    # Execute command
    command_response = gz_endpoint_download_file_command(
        client=client,
        args={
            "id": endpoint_id,
            "remote_file": "/home/ENDPOINT_NAME/test.txt",
            "output_file": "downloaded_file.txt",
        },
    )

    # Assert command response
    assert_command_mocked_data(
        f"gz-endpoint-download-file{mock_data_suffix}",
        command_response,
        polling_func=gz_poll_investigation_activity_status_command,
        client=client,
    )


@pytest.mark.parametrize(
    "endpoint_id",
    [("6942a43afe8d4e463ca5c197")],
)
@patch("GravityZone.demisto")
def test_gz_endpoint_download_investigation_package_command(mock_demisto, mocker, requests_mock, endpoint_id):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-endpoint-download-investigation-package command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import (
        gz_endpoint_download_investigation_package_command,
        gz_poll_investigation_activity_status_command,
    )

    mock_demisto.command.return_value = "gz-endpoint-download-investigation-package"
    mock_demisto.params.return_value = {}
    mocker.patch(
        "GravityZone.fileResult",
        return_value={
            "Contents": "",
            "ContentsFormat": "text",
            "Type": 3,
            "File": "investigation_package.zip",
            "FileID": "abc",
        },
    )
    load_api_mocked_data(requests_mock, "gz-endpoint-download-investigation-package")
    client = get_client()

    # Execute command
    command_response = gz_endpoint_download_investigation_package_command(
        client=client,
        args={"id": endpoint_id, "output_file": "investigation_package.zip"},
    )

    # Assert command response
    assert_command_mocked_data(
        "gz-endpoint-download-investigation-package",
        command_response,
        polling_func=gz_poll_investigation_activity_status_command,
        client=client,
    )


@pytest.mark.parametrize(
    "endpoint_id",
    [("6942a43afe8d4e463ca5c197")],
)
@patch("GravityZone.demisto")
@patch("GravityZone.FileManagement.get_file")
def test_gz_endpoint_upload_file_command(mock_get_file, mock_demisto, requests_mock, endpoint_id):
    """
    Given
            All relevant arguments for the command that is executed
    When
            Calling gz-endpoint-upload-file command
    Then
            Make sure the outputs, outputs_prefix and outputs_key_field values are as expected.
    """

    # Prepare
    from GravityZone import (
        gz_endpoint_upload_file_command,
        gz_poll_task_status_command,
    )

    mock_demisto.command.return_value = "gz-endpoint-upload-file"
    mock_get_file.return_value = ("file_to_upload.txt", b"file_content")
    mock_demisto.params.return_value = {}
    load_api_mocked_data(requests_mock, "gz-endpoint-upload-file")
    client = get_client()

    # Execute command
    command_response = gz_endpoint_upload_file_command(
        client=client,
        args={"id": endpoint_id, "remote_location": "/home/ENDPOINT_NAME/", "entry_id": "abc"},
    )

    # Assert command response
    assert_command_mocked_data(
        "gz-endpoint-upload-file", command_response, polling_func=gz_poll_task_status_command, client=client
    )