SysdigResponseActions
Uses the Sysdig agent to respond to malicious activity by triggering different actions at the host or container level, such as killing a container, quarantining a file, or performing a system capture.
Data Enrichment & Threat Intelligence · Sysdig Response Actions
Details
| ID | SysdigResponseActions |
|---|---|
| Provider | Sysdig |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 6.10.0 |
| To Version | 99.99.99 |
| Docker Image | demisto/python3:3.12.13.10116658 |
README
This is an integration that will use Sysdig agent to respond to malicious activity by triggering different actions at the host or container level like killing a container, quarantine a file or perform a system capture
This integration was integrated and tested with Host shield 13.9.1 of the Sysdig Agent and ResponseActions version 0.1.0
This is the default integration for this content pack when configured by the Data Onboarder in Cortex XSIAM.
Configure Sysdig Response Actions in Cortex
| Parameter | Required |
|---|---|
| Your server URL | True |
| API Key | True |
| Trust any certificate (not secure) | False |
| Use system proxy settings | False |
| Classifier | False |
| Incident type (if classifier doesn’t exist) | False |
| Mapper (incoming) | 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.
execute-response-action
Executes response actions through the Sysdig API. Each action type requires a specific set of parameters.
Base Command
execute-response-action
Input
| Argument Name | Description | Required |
|---|---|---|
| actionType | The action type to perform. Required parameters per action: - KILL_PROCESS: host_id, process_id (startTime defaults to -1) - KILL_CONTAINER: host_id, container_id - STOP_CONTAINER: host_id, container_id - PAUSE_CONTAINER: host_id, container_id - UNPAUSE_CONTAINER: host_id, container_id - START_CONTAINER: host_id, container_id - FILE_QUARANTINE: host_id, path_absolute (optional: container_id) - FILE_ACQUIRE: host_id, path_absolute (optional: container_id) - FILE_UNQUARANTINE: host_id, path_absolute, quarantined_file_path (optional: container_id) - DELETE_POD: k8s_cluster_name, k8s_namespace_name, k8s_pod_name - ROLLOUT_RESTART: k8s_cluster_name, k8s_namespace_name, k8s_workload_type, k8s_workload_name - ISOLATE_NETWORK: k8s_cluster_name, k8s_namespace_name, k8s_workload_type, k8s_workload_name (optional: network_protocol, network_port, network_cidr, network_direction) - DELETE_NETWORK_POLICY: k8s_cluster_name, k8s_namespace_name, network_policy_name - GET_LOGS: k8s_cluster_name, k8s_namespace_name (optional: k8s_workload_type, k8s_workload_name, k8s_pod_name, k8s_container_name, previous, all_containers) - KUBERNETES_VOLUME_SNAPSHOT: k8s_cluster_name, k8s_namespace_name (optional: k8s_pvc_name, k8s_workload_type, k8s_workload_name) - KUBERNETES_DELETE_VOLUME_SNAPSHOT: k8s_cluster_name, k8s_namespace_name, k8s_pvc_name, k8s_volume_snapshot_name - CAPTURE: host_id, capture_storage_config_id, capture_duration_ns, capture_past_duration_ns (optional: capture_filters, capture_max_size, container_id, capture_token) - IAM_QUARANTINE: cloud_provider, cloud_account_id (optional: ct_user_arn, ct_user_identity_type, ct_user) - IAM_UNQUARANTINE: cloud_provider, cloud_account_id, iam_policy_name, ct_user_identity_type, ct_user - MAKE_PRIVATE_CLOUD_RESOURCE: cloud_provider, cloud_account_id, cloud_resource_type, cloud_resource_name (optional: cloud_region) - UNDO_MAKE_PRIVATE_CLOUD_RESOURCE: cloud_provider, cloud_account_id, cloud_resource_type, cloud_resource_name, previous_public_access_settings (optional: cloud_region) - CLOUD_VOLUME_SNAPSHOT: cloud_provider, cloud_account_id, cloud_region, aws_instance_id - UNDO_CLOUD_VOLUME_SNAPSHOT: cloud_provider, cloud_account_id, cloud_region, snapshot_ids, aws_instance_id - FETCH_CLOUD_LOGS: cloud_provider, cloud_account_id, cloud_region, from_timestamp, to_timestamp (optional: ct_original_user, ct_name, ct_src). Possible values are: KILL_PROCESS, KILL_CONTAINER, STOP_CONTAINER, PAUSE_CONTAINER, UNPAUSE_CONTAINER, START_CONTAINER, FILE_QUARANTINE, FILE_ACQUIRE, FILE_UNQUARANTINE, DELETE_POD, ROLLOUT_RESTART, ISOLATE_NETWORK, DELETE_NETWORK_POLICY, GET_LOGS, KUBERNETES_VOLUME_SNAPSHOT, KUBERNETES_DELETE_VOLUME_SNAPSHOT, CAPTURE, IAM_QUARANTINE, IAM_UNQUARANTINE, MAKE_PRIVATE_CLOUD_RESOURCE, UNDO_MAKE_PRIVATE_CLOUD_RESOURCE, CLOUD_VOLUME_SNAPSHOT, UNDO_CLOUD_VOLUME_SNAPSHOT, FETCH_CLOUD_LOGS. |
Required |
| callerId | The unique caller identifier for the audit trail. | Required |
| host_id | The host ID where the agent runs. Required for: KILL_PROCESS, KILL_CONTAINER, STOP_CONTAINER, PAUSE_CONTAINER, UNPAUSE_CONTAINER, START_CONTAINER, FILE_QUARANTINE, FILE_ACQUIRE, FILE_UNQUARANTINE, CAPTURE. | Optional |
| container_id | The container ID. Required for: KILL_CONTAINER, STOP_CONTAINER, PAUSE_CONTAINER, UNPAUSE_CONTAINER, START_CONTAINER. Optional for: FILE_QUARANTINE, FILE_ACQUIRE, FILE_UNQUARANTINE, CAPTURE. | Optional |
| process_id | The process ID to kill. Required for: KILL_PROCESS. | Optional |
| path_absolute | The absolute file path. Required for: FILE_QUARANTINE, FILE_ACQUIRE, FILE_UNQUARANTINE. | Optional |
| quarantined_file_path | The path of the quarantined file. Required for: FILE_UNQUARANTINE. | Optional |
| k8s_cluster_name | The Kubernetes cluster name. Required for: DELETE_POD, ROLLOUT_RESTART, ISOLATE_NETWORK, DELETE_NETWORK_POLICY, GET_LOGS, KUBERNETES_VOLUME_SNAPSHOT, KUBERNETES_DELETE_VOLUME_SNAPSHOT. | Optional |
| k8s_namespace_name | The Kubernetes namespace. Required for: DELETE_POD, ROLLOUT_RESTART, ISOLATE_NETWORK, DELETE_NETWORK_POLICY, GET_LOGS, KUBERNETES_VOLUME_SNAPSHOT, KUBERNETES_DELETE_VOLUME_SNAPSHOT. | Optional |
| k8s_pod_name | The Kubernetes pod name. Required for: DELETE_POD. Optional for: GET_LOGS. | Optional |
| k8s_workload_type | The Kubernetes workload type (for example, Deployment, StatefulSet, DaemonSet). Required for: ROLLOUT_RESTART, ISOLATE_NETWORK. Optional for: GET_LOGS, KUBERNETES_VOLUME_SNAPSHOT. | Optional |
| k8s_workload_name | The Kubernetes workload name. Required for: ROLLOUT_RESTART, ISOLATE_NETWORK. Optional for: GET_LOGS, KUBERNETES_VOLUME_SNAPSHOT. | Optional |
| k8s_pvc_name | The PVC name. Optional for: KUBERNETES_VOLUME_SNAPSHOT. Required for: KUBERNETES_DELETE_VOLUME_SNAPSHOT. | Optional |
| k8s_volume_snapshot_name | The volume snapshot name. Required for: KUBERNETES_DELETE_VOLUME_SNAPSHOT. | Optional |
| k8s_container_name | The container name for log retrieval. Optional for: GET_LOGS. | Optional |
| network_policy_name | The network policy name. Required for: DELETE_NETWORK_POLICY. | Optional |
| network_protocol | The network protocol (TCP, UDP). Optional for: ISOLATE_NETWORK. | Optional |
| network_port | The port number. Optional for: ISOLATE_NETWORK. | Optional |
| network_cidr | The CIDR range. Optional for: ISOLATE_NETWORK. | Optional |
| network_direction | The traffic direction (ingress, egress). Optional for: ISOLATE_NETWORK. | Optional |
| previous | Whether to retrieve logs from the previous container instance. Optional for: GET_LOGS. | Optional |
| all_containers | Whether to retrieve logs from all containers. Optional for: GET_LOGS. | Optional |
| capture_storage_config_id | The remote storage configuration ID. Required for: CAPTURE. | Optional |
| capture_duration_ns | The capture duration in nanoseconds. Required for: CAPTURE. | Optional |
| capture_past_duration_ns | The amount of time to capture retroactively, in nanoseconds. Required for: CAPTURE. | Optional |
| capture_filters | The syscall filter expression. Optional for: CAPTURE. | Optional |
| capture_max_size | The maximum capture file size in bytes (0 = no limit). Optional for: CAPTURE. | Optional |
| capture_token | The base name of the capture file. Optional for: CAPTURE. | Optional |
| cloud_provider | The cloud provider name (for example, aws). Required for: IAM_QUARANTINE, IAM_UNQUARANTINE, MAKE_PRIVATE_CLOUD_RESOURCE, UNDO_MAKE_PRIVATE_CLOUD_RESOURCE, CLOUD_VOLUME_SNAPSHOT, UNDO_CLOUD_VOLUME_SNAPSHOT, FETCH_CLOUD_LOGS. | Optional |
| cloud_account_id | The cloud account ID. Required for: IAM_QUARANTINE, IAM_UNQUARANTINE, MAKE_PRIVATE_CLOUD_RESOURCE, UNDO_MAKE_PRIVATE_CLOUD_RESOURCE, CLOUD_VOLUME_SNAPSHOT, UNDO_CLOUD_VOLUME_SNAPSHOT, FETCH_CLOUD_LOGS. | Optional |
| cloud_region | The cloud region. Required for: CLOUD_VOLUME_SNAPSHOT, UNDO_CLOUD_VOLUME_SNAPSHOT, FETCH_CLOUD_LOGS. Optional for: MAKE_PRIVATE_CLOUD_RESOURCE, UNDO_MAKE_PRIVATE_CLOUD_RESOURCE. | Optional |
| ct_user_arn | The AWS identity ARN. Optional for: IAM_QUARANTINE. | Optional |
| ct_user_identity_type | The AWS identity type (IAMUser, Role, AssumedRole). Required for: IAM_UNQUARANTINE. Optional for: IAM_QUARANTINE. | Optional |
| ct_user | The AWS identity name. Required for: IAM_UNQUARANTINE. Optional for: IAM_QUARANTINE. | Optional |
| ct_original_user | The CloudTrail original user. Optional for: FETCH_CLOUD_LOGS. | Optional |
| ct_name | The CloudTrail event name. Optional for: FETCH_CLOUD_LOGS. | Optional |
| ct_src | The CloudTrail source. Optional for: FETCH_CLOUD_LOGS. | Optional |
| iam_policy_name | The IAM policy name to remove. Required for: IAM_UNQUARANTINE. | Optional |
| cloud_resource_type | The cloud resource type (rds, s3). Required for: MAKE_PRIVATE_CLOUD_RESOURCE, UNDO_MAKE_PRIVATE_CLOUD_RESOURCE. | Optional |
| cloud_resource_name | The cloud resource name. Required for: MAKE_PRIVATE_CLOUD_RESOURCE, UNDO_MAKE_PRIVATE_CLOUD_RESOURCE. | Optional |
| previous_public_access_settings | The previous public access settings. Required for: UNDO_MAKE_PRIVATE_CLOUD_RESOURCE. | Optional |
| aws_instance_id | The AWS instance ID. Required for: CLOUD_VOLUME_SNAPSHOT, UNDO_CLOUD_VOLUME_SNAPSHOT. | Optional |
| snapshot_ids | The comma-separated snapshot IDs. Required for: UNDO_CLOUD_VOLUME_SNAPSHOT. | Optional |
| from_timestamp | The start timestamp for the log search. Required for: FETCH_CLOUD_LOGS. | Optional |
| to_timestamp | The end timestamp for the log search. Required for: FETCH_CLOUD_LOGS. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| execute_response_action.Output | Dict | The output of the response-actions API. |
create-system-capture
Triggers a system capture, recording all system calls at the host level.
Base Command
create-system-capture
Input
| Argument Name | Description | Required |
|---|---|---|
| container_id | The container ID to apply the action. Example “container.id”: “123456789123”. | Required |
| host_name | The host name. Example “ip-1-1-1-1.us-west-1.compute.internal”. | Required |
| capture_name | The capture name. | Required |
| agent_id | The agent ID. | Required |
| customer_id | The customer ID. | Required |
| machine_id | The machine ID/MAC. Example “01:aa:02:bb:03:cc”. | Required |
| scan_duration | The capture duration in seconds. | Optional |
| scap_filter | The filter for the scope of the capture to take. Example: (proc.name=ncat or proc.name=vi). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| create_system_capture.Output | Dict | The output of the created system capture. |
get-capture-file
Gets a system capture based on the capture ID.
Base Command
get-capture-file
Input
| Argument Name | Description | Required |
|---|---|---|
| capture_id | The system capture ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| get_capture_file.Output | Dict | The output of the downloaded system capture. |
get-action-execution
Gets the status and information of a triggered action execution.
Base Command
get-action-execution
Input
| Argument Name | Description | Required |
|---|---|---|
| action_execution_id | The action execution ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| get_action_execution.Output | Dict | The output of the action execution info. |
sysdig-agent-info-get
Resolves a host MAC address to its Sysdig agent details (agent ID, customer ID, hostname). The result is cached per MAC address.
Base Command
sysdig-agent-info-get
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | The MAC address (machineId) of the host to look up. | Required |
| force_refresh | Whether to force a refresh of the cached agent info from the Sysdig API. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Sysdig.Agent.agentId | String | The Sysdig agent ID. |
| Sysdig.Agent.customerId | String | The Sysdig customer ID. |
| Sysdig.Agent.hostName | String | The agent hostname. |
| Sysdig.Agent.machineId | String | The host MAC address. |
| Sysdig.Agent.hostId | String | The opaque host identifier. |
| Sysdig.Agent.clusterName | String | The Kubernetes cluster name. |
sysdig-customer-info-get
Gets the Sysdig customer ID and name. The result is cached per integration instance.
Base Command
sysdig-customer-info-get
Input
| Argument Name | Description | Required |
|---|---|---|
| force_refresh | Whether to force a refresh of the cached customer info from the Sysdig API. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Sysdig.Customer.customerId | String | The Sysdig customer ID. |
| Sysdig.Customer.customerName | String | The Sysdig customer name. |
Configuration parameters
url— Your server URL (required)credentials— (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsclassifier— Classifiermapper— Mapper (incoming)isFetch— Fetch incidentsincidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervalmax_fetch— The maximum number of incidents per fetchfirst_fetch— First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days)
Commands (6)
-
create-system-captureTriggers a system capture, recording all system calls at the host level.
-
execute-response-actionExecutes response actions through the Sysdig API. Each action type requires a specific set of parameters. Use the actionType description to see which parameters are required for each action.
-
get-action-executionGets the status and information of a triggered action execution.
-
get-capture-fileGets a system capture based on the capture ID.
-
sysdig-agent-info-getResolves a host MAC address to its Sysdig agent details (agent ID, customer ID, hostname). The result is cached per MAC address.
-
sysdig-customer-info-getGets the Sysdig customer ID and name. The result is cached per integration instance.
""" Sysdig Response Actions Integration - Unit Tests file """ import pytest from http import HTTPStatus import requests from unittest.mock import patch import demistomock as demisto # noqa: F401 from SysdigResponseActions import ( Client, execute_response_action_command, create_system_capture_command, get_capture_file_command, get_action_execution_command, get_agent_by_mac_command, get_customer_info_command, _cache_is_valid, ) import json import time def util_load_json(path): with open(path, encoding="utf-8") as f: return json.loads(f.read()) KILL_CONTAINER_RESPONSE = util_load_json("test_data/response_api/kill_container_response.json") GET_ACTION_EXECUTION_RESPONSE = util_load_json("test_data/response_api/get_execution_response.json") SYSTEM_CAPTURE_RESPONSE = util_load_json("test_data/system_capture/create_response.json") GET_AGENTS_CONNECTED_RESPONSE = util_load_json("test_data/response_api/get_agents_connected_response.json") GET_USERS_ME_RESPONSE = util_load_json("test_data/response_api/get_users_me_response.json") @pytest.fixture def mock_response(): """Fixture to mock the session.request method""" with patch.object(requests.Session, "request") as mock_request: yield mock_request def test_execute_response_action(mock_response): # Successful response mock_response.return_value.json.return_value = KILL_CONTAINER_RESPONSE mock_response.return_value.status_code = HTTPStatus.OK client = Client(base_url="https://us2.app.sysdig.com", verify=False, headers={"Authorization": "Bearer token"}, proxy=False) result = execute_response_action_command( client, { "actionType": "KILL_CONTAINER", "container_id": "123456789012", "host_id": "abc123def456", "callerId": "test_kill_container_07", }, ) result = result.to_context().get("Contents") assert result.get("actionType") == "KILL_CONTAINER" assert result.get("status") == "created" assert result.get("callerId") == "test_kill_container_07" assert result.get("executionContext").get("container.id") == "123456789012" def test_create_system_capture(mock_response): # Successful response mock_response.return_value.json.return_value = SYSTEM_CAPTURE_RESPONSE mock_response.return_value.status_code = HTTPStatus.OK client = Client(base_url="https://us2.app.sysdig.com", verify=False, headers={"Authorization": "Bearer token"}, proxy=False) result = create_system_capture_command( client, { "host_name": "ip-1-2-3-4.us-west-1.compute.internal", "container_id": "123456789012", "capture_name": "test_capture", "agent_id": "123456789012", "customer_id": "123456789012", "machine_id": "aa:bb:cc:11:22:33", }, ) result = result.to_context().get("Contents").get("capture") assert result.get("status") == "requested" assert result.get("agent").get("machineId") == "aa:bb:cc:11:22:33" assert result.get("containerId") == "123456789012" assert result.get("agent").get("hostName") == "ip-1-2-3-4.us-west-1.compute.internal" def test_get_capture_file(mock_response): # Successful response mock_response.return_value.content = b"abc" # Dummy bytes mock_response.return_value.status_code = HTTPStatus.OK client = Client(base_url="https://us2.app.sysdig.com", verify=False, headers={"Authorization": "Bearer token"}, proxy=False) result = get_capture_file_command(client, {"capture_id": "1234567890"}) result = result.to_context().get("Contents") def test_get_action_execution(mock_response): # Successful response mock_response.return_value.json.return_value = GET_ACTION_EXECUTION_RESPONSE mock_response.return_value.status_code = HTTPStatus.OK client = Client(base_url="https://us2.app.sysdig.com", verify=False, headers={"Authorization": "Bearer token"}, proxy=False) result = get_action_execution_command(client, {"action_execution_id": "b137bf86-399f-43f7-8d2b-53060af4da9f"}) result = result.to_context().get("Contents") assert result.get("actionType") == "KILL_CONTAINER" assert result.get("status") == "COMPLETED" assert result.get("callerId") == "test_kill_container_07" assert result.get("executionContext").get("container.id") == "123456789012" # --- _cache_is_valid --- def test_cache_is_valid_returns_false_when_none(): assert _cache_is_valid(None) is False def test_cache_is_valid_returns_false_when_missing_cached_at(): assert _cache_is_valid({"data": {}}) is False def test_cache_is_valid_returns_true_when_fresh(): entry = {"cached_at": time.time() - 100, "data": {}} assert _cache_is_valid(entry, ttl=3600) is True def test_cache_is_valid_returns_false_when_expired(): entry = {"cached_at": time.time() - 7200, "data": {}} assert _cache_is_valid(entry, ttl=3600) is False # --- get_agent_by_mac_command --- def test_get_agent_by_mac_api_hit(mock_response, mocker): mock_response.return_value.json.return_value = GET_AGENTS_CONNECTED_RESPONSE mock_response.return_value.status_code = HTTPStatus.OK mocker.patch.object(demisto, "getIntegrationContext", return_value={}) mock_set_ctx = mocker.patch.object(demisto, "setIntegrationContext") client = Client(base_url="https://us2.app.sysdig.com", verify=False, headers={"Authorization": "Bearer token"}, proxy=False) result = get_agent_by_mac_command(client, {"machine_id": "aa:bb:cc:dd:ee:01"}) outputs = result.to_context().get("Contents") assert outputs["agentId"] == "99001" assert outputs["customerId"] == "55001" assert outputs["hostName"] == "ip-10-0-1-100.us-west-2.compute.internal" assert outputs["machineId"] == "aa:bb:cc:dd:ee:01" assert outputs["hostId"] == "host-uid-aaaa-0001" assert outputs["clusterName"] == "prod-us-west-2" mock_set_ctx.assert_called_once() def test_get_agent_by_mac_cache_hit(mocker): cached_agent = { "agentId": "99001", "customerId": "55001", "hostName": "cached-host", "machineId": "aa:bb:cc:dd:ee:01", "hostId": "host-uid-cached", "clusterName": "cached-cluster", } ctx = {"agent_aa:bb:cc:dd:ee:01": {"data": cached_agent, "cached_at": time.time()}} mocker.patch.object(demisto, "getIntegrationContext", return_value=ctx) client = Client(base_url="https://us2.app.sysdig.com", verify=False, headers={"Authorization": "Bearer token"}, proxy=False) result = get_agent_by_mac_command(client, {"machine_id": "aa:bb:cc:dd:ee:01"}) outputs = result.to_context().get("Contents") assert outputs["hostName"] == "cached-host" assert outputs["clusterName"] == "cached-cluster" def test_get_agent_by_mac_force_refresh(mock_response, mocker): cached_agent = { "agentId": "99001", "customerId": "55001", "hostName": "stale-host", "machineId": "aa:bb:cc:dd:ee:01", "hostId": "old-uid", "clusterName": "old-cluster", } ctx = {"agent_aa:bb:cc:dd:ee:01": {"data": cached_agent, "cached_at": time.time()}} mocker.patch.object(demisto, "getIntegrationContext", return_value=ctx) mocker.patch.object(demisto, "setIntegrationContext") mock_response.return_value.json.return_value = GET_AGENTS_CONNECTED_RESPONSE mock_response.return_value.status_code = HTTPStatus.OK client = Client(base_url="https://us2.app.sysdig.com", verify=False, headers={"Authorization": "Bearer token"}, proxy=False) result = get_agent_by_mac_command(client, {"machine_id": "aa:bb:cc:dd:ee:01", "force_refresh": "true"}) outputs = result.to_context().get("Contents") assert outputs["hostName"] == "ip-10-0-1-100.us-west-2.compute.internal" def test_get_agent_by_mac_not_found(mock_response, mocker): mock_response.return_value.json.return_value = GET_AGENTS_CONNECTED_RESPONSE mock_response.return_value.status_code = HTTPStatus.OK mocker.patch.object(demisto, "getIntegrationContext", return_value={}) client = Client(base_url="https://us2.app.sysdig.com", verify=False, headers={"Authorization": "Bearer token"}, proxy=False) with pytest.raises(ValueError, match="No connected agent found"): get_agent_by_mac_command(client, {"machine_id": "ff:ff:ff:ff:ff:ff"}) def test_get_agent_by_mac_missing_machine_id(): client = Client(base_url="https://us2.app.sysdig.com", verify=False, headers={"Authorization": "Bearer token"}, proxy=False) with pytest.raises(ValueError, match="machine_id .* is required"): get_agent_by_mac_command(client, {}) # --- get_customer_info_command --- def test_get_customer_info_api_hit(mock_response, mocker): mock_response.return_value.json.return_value = GET_USERS_ME_RESPONSE mock_response.return_value.status_code = HTTPStatus.OK mocker.patch.object(demisto, "getIntegrationContext", return_value={}) mock_set_ctx = mocker.patch.object(demisto, "setIntegrationContext") client = Client(base_url="https://us2.app.sysdig.com", verify=False, headers={"Authorization": "Bearer token"}, proxy=False) result = get_customer_info_command(client, {}) outputs = result.to_context().get("Contents") assert outputs["customerId"] == "55001" assert outputs["customerName"] == "Acme Corp" mock_set_ctx.assert_called_once() def test_get_customer_info_cache_hit(mocker): ctx = {"customer_info": {"data": {"customer_id": "55001", "customer_name": "Cached Corp"}, "cached_at": time.time()}} mocker.patch.object(demisto, "getIntegrationContext", return_value=ctx) client = Client(base_url="https://us2.app.sysdig.com", verify=False, headers={"Authorization": "Bearer token"}, proxy=False) result = get_customer_info_command(client, {}) outputs = result.to_context().get("Contents") assert outputs["customerId"] == "55001" assert outputs["customerName"] == "Cached Corp" def test_get_customer_info_force_refresh(mock_response, mocker): ctx = {"customer_info": {"data": {"customer_id": "00000", "customer_name": "Old Corp"}, "cached_at": time.time()}} mocker.patch.object(demisto, "getIntegrationContext", return_value=ctx) mocker.patch.object(demisto, "setIntegrationContext") mock_response.return_value.json.return_value = GET_USERS_ME_RESPONSE mock_response.return_value.status_code = HTTPStatus.OK client = Client(base_url="https://us2.app.sysdig.com", verify=False, headers={"Authorization": "Bearer token"}, proxy=False) result = get_customer_info_command(client, {"force_refresh": "true"}) outputs = result.to_context().get("Contents") assert outputs["customerId"] == "55001" assert outputs["customerName"] == "Acme Corp"