Details
| ID | CheckPointXDR |
|---|---|
| Provider | CheckPoint Software Technologies |
| Category | Analytics & SIEM |
| From Version | 6.10.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
README
Check Point XDR Integration
The Check Point XDR (Extended Detection and Response) integration allows you to connect to Check Point’s CloudInfra platform to fetch and manage incidents. This integration enables you to retrieve incidents from Check Point XDR, convert them into Cortex XSOAR format, and manage them effectively within your security operations workflows.
Key Features
- Authentication: Secure OAuth2-based authentication using Client ID and Access Key.
- Incident Fetching: Retrieve incidents from Check Point XDR using flexible parameters such as timestamp and limit.
- Data Mapping: Automatically map Check Point fields such as severity, status, summary, and insights into XSOAR incident fields.
- Custom Fields Support: Includes mapping for MITRE ATT&CK techniques, assets, and alerts.
- Pagination Support: Automatically fetches additional pages of incidents if the result size equals the
max_fetchparameter. - Insights & Enrichment: Include related context such as associated users, endpoints, and threat intelligence.
Prerequisites
- A valid Check Point XDR account with API access enabled.
- API credentials:
- Client ID
- Access Key
- Cortex XSOAR version 6.10.0 or higher.
Use Cases
- Ingest Check Point XDR alerts and incidents into XSOAR for automated playbook-driven response.
- Correlate assets, users, and threats across your SOC toolset.
- Perform enrichment using insights and threat classifications included in the XDR data.
- Monitor status and severity changes and trigger escalation or remediation workflows.
Setup Instructions
1.
1. Navigate to Settings → Integrations → Servers & Services.
2. Search for Check Point XDR and click Add instance.
3. Configure the following parameters:
| **Parameter** | **Description** |
|-----------------------|-----------------------------------------------------------------------------------------------|
| Base URL | Default: `https://cloudinfra-gw.portal.checkpoint.com` |
| Client ID | Your Check Point XDR API Client ID |
| Access Key | Your Check Point XDR API Access Key |
| First fetch time | Format: `3 days`, `2 hours`, etc. Determines the starting point of the initial fetch. |
| Max fetch | Maximum number of incidents to fetch per API call (default recommended: 50-100) |
| Fetch incidents | Enable to allow scheduled fetching of incidents |
| Trust any certificate | Disable SSL validation (not recommended for production environments) |
| Use system proxy | Use the system proxy defined in Cortex XSOAR settings
- Test the Integration:
- Click the “Test” button to verify the connection and configuration.
- Fetch Incidents:
- Enable the “Fetches incidents” option to allow the integration to periodically fetch incidents from Check Point XDR.
Commands
fetch-incidents
Fetches incidents from Check Point XDR and converts them into Cortex XSOAR format.
Base Command
fetch-incidents
Input
This command uses the parameters from the integration instance configuration:
- First fetch time
- Max fetch
Context Output
| Path | Type | Description |
|---|---|---|
| incident.name | string | Incident name |
| incident.type | string | Incident type |
| incident.severity | number | Incident severity |
| incident.occurred | date | Incident timestamp |
| incident.xdrstatus | string | Incident status |
| incident.xdrid | string | Unique ID of the incident |
| incident.insights | string | Associated insights |
| incident.assets | string | Affected assets |
| incident.mitre | string | MITRE TTPs |
Human Readable Output
✅ Successfully fetched X incidents.
get-mapping-fields
Returns the fields available for mapping incoming incidents to Cortex XSOAR fields.
Base Command
get-mapping-fields
Input
None
Context Output
The fields available in XSOAR for incident mapping.
Command Example
!get-mapping-fields
Human Readable Output
Displays the supported incident fields for mapping from Check Point XDR.
update-remote-system
Sends updates from Cortex XSOAR to the corresponding incident in Check Point XDR, such as status changes or ownership updates.
Base Command
update-remote-system
Input
| Argument Name | Description | Required |
|---|---|---|
| remoteId | The ID of the incident in Check Point XDR. | True |
| data | The fields to update (status, owner, etc). | True |
| entries | Entries (comments, notes) to be pushed. | Optional |
Context Output
There is no context output for this command.
Command Example
!update-remote-system
Human Readable Output
✅ Remote incident successfully updated.
Incident Fields
| Field | Description |
|---|---|
| xdrid | Unique identifier of the incident |
| xdrstatus | Current status (e.g. New, In Progress, Resolved) |
| severity | Incident severity mapped to XSOAR levels |
| summary | Short summary of the incident |
| insights | Detailed related alerts and context |
| assets | Affected hosts, users, and services |
| mitre | Associated MITRE ATT&CK tactics and techniques |
Example Use Case
- Authenticate with Check Point XDR using your client credentials.
- Fetch incidents from Check Point XDR based on the specified date and limit.
- Convert the incidents into Cortex XSOAR format, including custom fields for insights, alerts, and assets.
- Manage and respond to incidents directly within Cortex XSOAR.
Troubleshooting
- Authentication Errors: Ensure the Client ID and Access Key are correct and have the necessary permissions.
- No Incidents Fetched:
- Verify the date range parameter is long enough (so there are incidents to fetch).
- Verify the limit parameter in the integration configuration is higher then 0.
- Verify your client Id and Access key are correct - copy them from the XDR portal under your settings.
- Verify the Fetch Incidents checkbox is cheked.
- SSL Errors: If SSL verification is enabled, ensure the base URL uses a valid SSL certificate.
Additional Resources
Support
For support, please contact Check Point or your system administrator.
Configuration parameters
url— Infinity XDR API URL (required)credentials— Client ID (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsfirst_fetch— First fetch timeisFetch— Fetch incidentsincidentFetchInterval— Incidents Fetch IntervalincidentType— Incident typemax_fetch— Maximum number of incidents per fetchclose_out— Close Mirrored XDR Incidentsmirror_direction— Incident Mirroring Direction
Commands (1)
-
get-mapping-fieldsReturns the list of fields to map in outgoing mirroring. This command is only used for debugging purposes.
import demistomock as demisto from CommonServerPython import * MIRROR_DIRECTION = {"None": None, "Incoming": "In", "Outgoing": "Out", "Incoming And Outgoing": "Both"} OUTGOING_MIRRORED_FIELDS_OBJ = { "Status", "Severity", } OUTGOING_MIRRORED_FIELDS = {filed: pascalToSpace(filed) for filed in OUTGOING_MIRRORED_FIELDS_OBJ} SCRIPT_BRAND = "CheckPointXDR" class Client(BaseClient): def __init__(self, base_url: str, client_id: str, access_key: str, verify: bool, proxy: bool): super().__init__(base_url=base_url, verify=verify, proxy=proxy) self.client_id = client_id self.access_key = access_key self.token: Optional[str] = None def _login(self) -> None: if self._session.cookies: self._session.cookies.clear() auth_data = {"clientId": self.client_id, "accessKey": self.access_key} res = self._http_request("POST", url_suffix="/auth/external", data=auth_data, resp_type="response") if res.status_code == 200: self.token = res.json().get("data").get("token") demisto.debug("Log-in successful! client's token was set!") else: raise DemistoException(f"Log-in failed: {str(res.status_code)}: {res.text}") def get_incidents(self, startTS: str, max_fetch: int): self._login() headers = {"Authorization": f"Bearer {self.token}"} demisto.debug(f"Fetching XDR incidents with start timestamp: {startTS} and max fetch: {max_fetch}") all_incidents = [] offset = 0 has_more = True while has_more: try: url = f"/app/xdr/api/xdr/v1/incidents?limit={max_fetch}&offset={offset}&from={startTS}" res = self._http_request("GET", url_suffix=url, headers=headers, resp_type="response") incidents = res.json().get("data", {}).get("incidents", []) demisto.debug(f"Fetched {len(incidents)} XDR incidents at offset {offset}.") all_incidents.extend(incidents) has_more = len(incidents) == max_fetch offset += max_fetch except Exception as e: demisto.error(f"Failed to fetch XDR incidents: {str(e)}") raise DemistoException(f"Failed to fetch XDR incidents: {str(e)}") demisto.debug(f"Total incidents fetched: {len(all_incidents)}") return all_incidents def update_incident(self, status: int, close_reason: str = "", incident_id: str = "") -> dict: """ Update an incident in CheckPoint XDR. Args: status (Optional[str]): The new status of the incident. incident_id (Optional[str]): The ID of the incident to update. Returns: dict: The response from the API. """ demisto.debug(f"XDR - Starting to update_incident with status: {status}") if not incident_id: raise DemistoException("No incident ID provided") demisto.debug(f"XDR - Updating incident with ID: {incident_id}") # Log in to ensure we have a valid token self._login() headers = {"Authorization": f"Bearer {self.token}"} update_data = {} # Only include status in the update if it was provided # if status: # new, in progress, close - handled, close - prevented, close - false positive, close - known activity status_map = { "Resolved": "close - handled", "Duplicate": "close - known activity", "False Positive": "close - false positive", "Other": "close - prevented", } update_data["status"] = status_map[close_reason] # If no fields to update, log and return if not update_data: demisto.debug("XDR - No fields to update, skipping API call") return {} demisto.debug(f"XDR - Sending update with data: {update_data}") try: res = self._http_request( "PUT", url_suffix=f"/app/xdr/api/xdr/v1/incidents/{incident_id}", headers=headers, json_data=update_data, resp_type="response", ) if res.status_code != 200: raise DemistoException(f"Failed to update XDR incident: {str(res.status_code)}: {res.text}") response_data = res.json().get("data", {}) demisto.debug(f"XDR - Successfully updated incident {incident_id}") return response_data except Exception as e: demisto.error(f"XDR - Error updating incident {incident_id}: {str(e)}") raise DemistoException(f"Error updating incident: {str(e)}") def test_module(client: Client, last_run: dict[str, str], first_fetch: datetime): try: fetch_incidents( client, {"mirror_direction": MIRROR_DIRECTION.get("Outgoing"), "mirror_instance": demisto.integrationInstance()}, last_run, first_fetch, 1, ) return "ok" except DemistoException as e: return e.message def map_severity(severity: str) -> int: """ Maps the severity from CheckPoint XDR to XSOAR severity levels. Args: severity (str): The severity level from CheckPoint XDR. Returns: int: The corresponding XSOAR severity level. """ severity_mapping = { "low": 1, "medium": 2, "high": 3, "critical": 4, } return severity_mapping.get(severity.lower(), 1) # If using incoming mapper then this function is not needed - validate def get_instances_id(): """ Get the instance ID for the specified script brand. :rtype: ``str`` :return: Instance ID of the integration with matching brand """ integration_context = demisto.getIntegrationContext() instances_id = integration_context.get("instances_id", "") return instances_id def parse_incidents(xdr_incidents: List, mirroring_fields: dict, startTS: int, max_fetch: int): incidents: list[dict[str, Any]] = [] for incident in xdr_incidents: incident.update(mirroring_fields) # Constructing the XSOAR incident incidents.append( { "dbotMirrorId": incident.get("id", "unknown_id"), "occurred": incident.get("created_at", ""), "severity": map_severity(incident.get("severity", "medium")), "name": f"#{incident.get('display_id', '')} - {incident.get('summary', '')}", "details": incident.get("summary", ""), "dbotMirrorDirection": "Out", "dbotMirrorInstance": get_instances_id(), "rawJSON": json.dumps(incident), } ) last_time = ( json.loads(incidents[0]["rawJSON"]).get("updated_at") if incidents and incidents[0].get("rawJSON") else datetime.utcfromtimestamp(startTS / 1000).isoformat() ) demisto.debug(f"Last incident time: {last_time}") return incidents, last_time def fetch_incidents(client: Client, mirroring_fields: dict, last_run: dict[str, str], first_fetch: datetime, max_fetch: int): last_fetch = last_run.get("last_fetch", first_fetch.isoformat()) last_fetch_time = arg_to_datetime(last_fetch) if not last_fetch_time: raise Exception(f"Invalid last fetch time value '{last_fetch}'") startTS = int(last_fetch_time.timestamp() * 1000) demisto.debug(f"Fetching incidents since {last_fetch} (timestamp: {startTS})") xdr_incidents = client.get_incidents(last_fetch, max_fetch) incidents, last_incident_time = parse_incidents(xdr_incidents, mirroring_fields, startTS, max_fetch) return {"last_fetch": last_incident_time}, incidents def update_remote_system_command(client: Client, args: Dict[str, Any]) -> str: update_remote_system_args = UpdateRemoteSystemArgs(args) remote_incident_id = update_remote_system_args.remote_incident_id delta = update_remote_system_args.delta incident_changed = update_remote_system_args.incident_changed inc_status = update_remote_system_args.inc_status data = update_remote_system_args.data demisto.debug( f"XDR - update_remote_system_command called with {remote_incident_id=}, {delta=}, " f"{incident_changed=}, {inc_status=}, {data=}" ) # Check if we're closing the incident if inc_status == IncidentStatus.DONE: close_reason = delta.get("closeReason", "") if argToBoolean(demisto.params().get("close_out", True)): demisto.debug("XDR - Incident is being updated, updating remote system") try: # Update XDR incident to Resolved status client.update_incident(status=int(inc_status), close_reason=close_reason, incident_id=remote_incident_id) demisto.debug(f"XDR - Successfully closed incident {remote_incident_id} in XDR") except Exception as e: demisto.error(f"XDR - Failed to close incident {remote_incident_id} in XDR: {str(e)}") else: demisto.debug("XDR - close_out is not enabled, skipping closure in XDR") return remote_incident_id def get_mapping_fields_command() -> GetMappingFieldsResponse: incident_type_scheme = SchemeTypeMapping(type_name="Check Point XDR Incident") for argument, description in OUTGOING_MIRRORED_FIELDS.items(): incident_type_scheme.add_field(name=argument, description=description) mapping_response = GetMappingFieldsResponse() mapping_response.add_scheme_type(incident_type_scheme) return mapping_response def main() -> None: params = demisto.params() base_url = params.get("url", "") client_id = params.get("credentials", {}).get("identifier") access_key = params.get("credentials", {}).get("password") verify = not params.get("insecure", False) proxy = params.get("proxy", False) max_fetch = int(params.get("max_fetch", 1000)) fetch_time = params.get("first_fetch", "3 days").strip() first_fetch = arg_to_datetime(fetch_time, is_utc=True) if not first_fetch: raise Exception(f"Invalid first fetch time value '{fetch_time}', must be '<number> <time unit>', e.g., '24 hours'") command = demisto.command() args = demisto.args() demisto.debug(f"Command being called is {command}") mirroring_fields = { "mirror_direction": MIRROR_DIRECTION.get(params.get("mirror_direction", "None")), "mirror_instance": get_instances_id(), } try: client = Client(base_url, client_id, access_key, verify, proxy) last_run = demisto.getLastRun() if command == "test-module": demisto.debug("XDR - test-module") return_results(test_module(client, last_run, first_fetch)) elif command == "fetch-incidents": demisto.debug("XDR - fetch-incidents") next_run, incidents = fetch_incidents(client, mirroring_fields, last_run, first_fetch, max_fetch) demisto.incidents(incidents) demisto.setLastRun(next_run) demisto.debug(f"Set last run to {next_run.get('last_fetch')}") elif command == "update-remote-system": demisto.debug("XDR - update-remote-system") return_results(update_remote_system_command(client, args)) elif command == "get-mapping-fields": return_results(get_mapping_fields_command()) except Exception as e: return_error(f"Failed to execute {demisto.command()} command.\nError:\n{str(e)}") if __name__ in ("__main__", "__builtin__", "builtins"): main()