Skip to content

Commit

Permalink
V 1.1.0 (demisto#37026)
Browse files Browse the repository at this point in the history
* V 1.1.0 (demisto#36767)

* V 1.1.0

- Added statistics fields
- Added fetching incidents with filtering by minimum probability

* Fix tests

* Set unsearchable

* RAN Review

* ohh

* update RN

---------

Co-authored-by: Max Nosko <[email protected]>
Co-authored-by: Aaron <[email protected]>
  • Loading branch information
3 people authored Nov 5, 2024
1 parent 61ae48f commit d81c9b0
Show file tree
Hide file tree
Showing 13 changed files with 339 additions and 160 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"id": "incident_appiname",
"version": -1,
"modified": "2024-10-20T22:22:45.48967185Z",
"name": "CheckPointNDR Application Names",
"ownerOnly": false,
"description": "",
"cliName": "appiname",
"type": "multiSelect",
"closeForm": false,
"editForm": true,
"required": false,
"neverSetAsRequired": false,
"isReadOnly": false,
"useAsKpi": false,
"locked": false,
"system": false,
"content": true,
"group": 0,
"hidden": false,
"openEnded": false,
"associatedTypes": [
"Check Point NDR Insight"
],
"associatedToAll": false,
"unmapped": false,
"unsearchable": true,
"caseInsensitive": true,
"sla": 0,
"threshold": 72,
"fromVersion": "6.9.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"id": "incident_receivedbytes",
"version": -1,
"modified": "2024-10-01T19:26:46.346683Z",
"name": "CheckPointNDR Received Bytes",
"ownerOnly": false,
"description": "The total number of bytes received in the event.",
"cliName": "receivedbytes",
"type": "number",
"closeForm": false,
"editForm": true,
"required": false,
"neverSetAsRequired": false,
"isReadOnly": false,
"useAsKpi": false,
"locked": false,
"system": false,
"content": true,
"group": 0,
"hidden": false,
"openEnded": false,
"associatedTypes": [
"Check Point NDR Insight"
],
"associatedToAll": false,
"unmapped": false,
"unsearchable": true,
"caseInsensitive": true,
"sla": 0,
"threshold": 72,
"fromVersion": "6.9.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"id": "incident_sentbytes",
"version": -1,
"modified": "2024-10-07T15:36:49.667762Z",
"name": "CheckPointNDR Sent Bytes",
"ownerOnly": false,
"description": "The total number of bytes sent in the event.",
"cliName": "sentbytes",
"type": "number",
"closeForm": false,
"editForm": true,
"required": false,
"neverSetAsRequired": false,
"isReadOnly": false,
"useAsKpi": false,
"locked": false,
"system": false,
"content": true,
"group": 0,
"hidden": false,
"openEnded": false,
"associatedTypes": [
"Check Point NDR Insight"
],
"associatedToAll": false,
"unmapped": false,
"unsearchable": true,
"caseInsensitive": true,
"sla": 0,
"threshold": 72,
"fromVersion": "6.9.0"
}
27 changes: 21 additions & 6 deletions Packs/CheckPointNDR/Integrations/CheckPointNDR/CheckPointNDR.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,27 @@ def get_insights(self, startTS: int, max_fetch: int):

def test_module(client: Client, last_run: dict[str, str], first_fetch: datetime, domain: str):
try:
fetch_incidents(client, last_run, first_fetch, domain, 1)
fetch_incidents(client, last_run, first_fetch, domain, 1, 0)
return 'ok'
except DemistoException as e:
return e.message


def parse_insights(insights: list[dict[str, Any]], domain: str, startTS: int, max_fetch: int):
def parse_insights(insights: list[dict[str, Any]], domain: str, startTS: int, max_fetch: int, min_probability: int):
incidents: list[dict[str, Any]] = []
for insight in insights:
for event in insight['events']:
if event['updated'] <= startTS:
continue
if event['probability'] < min_probability:
continue

id = f"{insight['id']}_{event['id']}"
name = insight['data'].get('name', insight['criteria'])
updated = int(event['data'].get('discovery_date', event['updated']))
desc_i = insight['data'].get('description', '')
desc_e = event['data'].get('description', '')
statistics = event['data'].get('statistics', {})
description = desc_i + "\n" + desc_e if desc_e else desc_i
link = f"{NDR_URL}/#/insights?id={insight['id']}&domain={domain}&startDate={event['from']}&endDate={event['to']}"
severity = 3
Expand All @@ -113,7 +116,17 @@ def parse_insights(insights: list[dict[str, Any]], domain: str, startTS: int, ma
'externalendtime': datetime.utcfromtimestamp(event['to'] / 1000).strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
'externallink': link,
'description': desc_i,
'eventdescriptions': desc_e
'eventdescriptions': desc_e,
'sourceips': statistics.get('top_src', []),
'sourceexternalips': statistics.get('top_proxy_src_ip', []),
'destinationips': statistics.get('top_dst', []),
'dstports': statistics.get('top_service', []),
'filemd5': statistics.get('top_file_md5', []),
'appiName': statistics.get('top_appi_name', []),
'users': statistics.get('top_src_user_name', []),
'hostnames': statistics.get('top_src_machine_name', []),
'sentbytes': statistics.get('total_bytes_sent', 0),
'receivedbytes': statistics.get('total_bytes_received', 0)
},
'rawJSON': json.dumps(event)
})
Expand All @@ -125,15 +138,16 @@ def parse_insights(insights: list[dict[str, Any]], domain: str, startTS: int, ma
return incidents, last_time


def fetch_incidents(client: Client, last_run: dict[str, str], first_fetch: datetime, domain: str, max_fetch: int):
def fetch_incidents(client: Client, last_run: dict[str, str], first_fetch: datetime, domain: str, max_fetch: int,
min_probability: int):
last_fetch = last_run.get('last_fetch', first_fetch.isoformat())
last_fetch_time = dateparser.parse(last_fetch)
if not last_fetch_time:
raise Exception(f"Invalid last fetch time value '{last_fetch}'")

startTS = int(last_fetch_time.timestamp() * 1000)
insights = client.get_insights(startTS, max_fetch)
incidents, last_insight_time = parse_insights(insights, domain, startTS, max_fetch)
incidents, last_insight_time = parse_insights(insights, domain, startTS, max_fetch, min_probability)

return {'last_fetch': last_insight_time}, incidents

Expand All @@ -148,6 +162,7 @@ def main() -> None: # pragma: no cover
verify = not params.get('insecure', False)
proxy = params.get('proxy', False)
max_fetch = int(params.get('max_fetch', 1000))
min_probability = int(params.get('min_probability', 0))

fetch_time = params.get('first_fetch', '3 days').strip()
first_fetch = dateparser.parse(fetch_time, settings={'TIMEZONE': 'UTC'})
Expand All @@ -163,7 +178,7 @@ def main() -> None: # pragma: no cover
if command == 'test-module':
return_results(test_module(client, last_run, first_fetch, domain))
elif command == 'fetch-incidents':
next_run, incidents = fetch_incidents(client, last_run, first_fetch, domain, max_fetch)
next_run, incidents = fetch_incidents(client, last_run, first_fetch, domain, max_fetch, min_probability)
demisto.incidents(incidents)
demisto.debug(f"Set last run to {next_run.get('last_fetch')}")
demisto.setLastRun(next_run)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ configuration:
defaultvalue: 'true'
type: 8
required: false
- section: Collect
display: Minimum probability level
additionalinfo: Filter out NDR insights with probability lower than this value
name: min_probability
defaultvalue: "0"
type: 0
required: false
- section: Collect
display: Incidents Fetch Interval
name: incidentFetchInterval
Expand All @@ -75,7 +82,7 @@ script:
script: '-'
type: python
subtype: python3
dockerimage: demisto/python3:3.10.14.91134
dockerimage: demisto/python3:3.11.10.113941
fromversion: 6.9.0
tests:
- No tests (auto formatted)
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def test_parse_insights():
mock_result = (util_load_json('./test_data/checkpointndr-parse_insights-output.json'),
datetime.datetime.fromtimestamp(1703387404.364).isoformat())

result = parse_insights(mock_insights, 'test', 0, 10)
result = parse_insights(mock_insights, 'test', 0, 10, 0)
assert result == mock_result


Expand Down Expand Up @@ -80,7 +80,7 @@ def test_fetch_incidents(mocker):
return_value=None,
)

fetch_incidents(client, {}, datetime.datetime(2024, 1, 1), 'test', 10)
fetch_incidents(client, {}, datetime.datetime(2024, 1, 1), 'test', 10, 0)
login.assert_called_once()
query_insights.assert_called()
logout.assert_called_once()
64 changes: 1 addition & 63 deletions Packs/CheckPointNDR/Integrations/CheckPointNDR/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Collect network security events from Check Point Infinity NDR for your secured SaaS periodically
This integration was integrated and tested with version 1.0.0 of CheckPointNDR
This integration was integrated and tested with version 1.1.0 of CheckPointNDR

## Configure Check Point Network Detection and Response (Infinity NDR) on Cortex XSOAR

Expand All @@ -18,65 +18,3 @@ This integration was integrated and tested with version 1.0.0 of CheckPointNDR
| Incidents Fetch Interval | False |

4. Click **Test** to validate the URLs, token, and connection.

## Commands

You can execute these commands from the Cortex XSOAR 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.

### check-point-ndr-fetch-insights

***
Retrieve all NDR Insights

#### Base Command

`check-point-ndr-fetch-insights`

#### Input

| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| from | Date and time from which to fetch insights. Default is Last 24 hours.| Optional |
| create_events | If true, the command will create events, otherwise it will only display them. Possible values are: true, false. Default is false. | Optional |


#### Context Output

| **Path** | **Type** | **Description** |
| --- | --- | --- |
| CheckPointHEC.Entity.internetMessageId | String | Email message id in internet. |
| CheckPointHEC.Entity.subject | String | Email subject. |
| CheckPointHEC.Entity.received | String | Datetime email was received in iso 8601 format. |
| CheckPointHEC.Entity.size | String | Email size. |
| CheckPointHEC.Entity.emailLinks | unknown | Links in email. |
| CheckPointHEC.Entity.attachmentCount | Number | Number of attachments in email. |
| CheckPointHEC.Entity.attachments | unknown | File attachments in email. |
| CheckPointHEC.Entity.mode | String | Internal policy rule. |
| CheckPointHEC.Entity.recipients | unknown | Recipient email addresses. |
| CheckPointHEC.Entity.subject | String | Email subject. |
| CheckPointHEC.Entity.fromEmail | String | Email sender. |
| CheckPointHEC.Entity.fromDomain | String | Domain where the email was sent from. |
| CheckPointHEC.Entity.fromUser | unknown | Sender user details. |
| CheckPointHEC.Entity.fromName | String | Sender name. |
| CheckPointHEC.Entity.to | unknown | Email main recipients. |
| CheckPointHEC.Entity.toUser | unknown | User details for main recipients. |
| CheckPointHEC.Entity.cc | unknown | Email carbon copy recipients. |
| CheckPointHEC.Entity.ccUser | unknown | User details for carbon copy recipients. |
| CheckPointHEC.Entity.bcc | unknown | Email blind carbon copy recipients. |
| CheckPointHEC.Entity.bccUser | unknown | User details for blind carbon copy recipients. |
| CheckPointHEC.Entity.replyToEmail | String | Email reply. |
| CheckPointHEC.Entity.replyToNickname | String | Email reply nickname. |
| CheckPointHEC.Entity.isRead | Boolean | Email has been read. |
| CheckPointHEC.Entity.isDeleted | Boolean | Email has been deleted. |
| CheckPointHEC.Entity.isIncoming | Boolean | Email is from external organization. |
| CheckPointHEC.Entity.isInternal | Boolean | Email is from same organization. |
| CheckPointHEC.Entity.isOutgoing | Boolean | Email is to an external organization. |
| CheckPointHEC.Entity.isQuarantined | Boolean | Email has been quarantined. |
| CheckPointHEC.Entity.isQuarantineNotification | Boolean | Email is a notification of another quarantined email. |
| CheckPointHEC.Entity.isRestored | Boolean | Email is restored from quarantine. |
| CheckPointHEC.Entity.isRestoreRequested | Boolean | Email is a request to restore. |
| CheckPointHEC.Entity.isRestoreDeclined | Boolean | Email is a declined restore request. |
| CheckPointHEC.Entity.saasSpamVerdict | String | Spam verdict. |
| CheckPointHEC.Entity.SpfResult | String | Sender Policy Framework check result. |
| CheckPointHEC.Entity.restoreRequestTime | String | Restore request datetime in iso 8601 format. |
Original file line number Diff line number Diff line change
@@ -1,26 +1,57 @@
{
"objects": [
{
"id": 950961,
"domain": "test",
"from": 1703258128000,
"to": 1703261728000,
"filter": "src:\"127.0.0.1\"",
"targetDomain": "test",
"type": "Behavioral",
"insight": "Behavioral.Geo.Bulgaria",
"count": 1,
"data": {
"discovery_date": "1703387402954"
},
"user": "Analytics",
"created": 1703387404364,
"updated": 1703387404364,
"mdr": false,
"probability": 64,
"externalId": null,
"editable": true
}
{
"id": 950961,
"domain": "test",
"from": 1703258128000,
"to": 1703261728000,
"filter": "src:\"127.0.0.1\"",
"targetDomain": "test",
"type": "Behavioral",
"insight": "Behavioral.Geo.Bulgaria",
"count": 1,
"data": {
"discovery_date": "1703387402954",
"statistics": {
"count": 1,
"top_dst": [
"192.168.0.1"
],
"top_src": [
"127.0.0.1"
],
"total_dst": 1,
"total_src": 1,
"top_service": [
"1434"
],
"top_file_md5": ["098f6bcd4621d373cade4e832627b4f6"],
"top_appi_name": ["TeamViewer", "google.com"],
"total_service": 1,
"total_file_md5": 1,
"total_appi_name": 2,
"top_proxy_src_ip": ["1.2.3.4"],
"total_bytes_sent": 512,
"top_src_user_name": ["maxn"],
"total_proxy_src_ip": 1,
"top_protection_name": [
"MS-SQL Monitor Protocol"
],
"total_src_user_name": 1,
"top_src_machine_name": ["DESKTOP1"],
"total_bytes_received": 1024,
"total_protection_name": 1,
"total_src_machine_name": 1
}
},
"user": "Analytics",
"created": 1703387404364,
"updated": 1703387404364,
"mdr": false,
"probability": 64,
"externalId": null,
"editable": true
}
],
"count": 1
}
Loading

0 comments on commit d81c9b0

Please sign in to comment.