Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CS Falcon] Use date format with fractional seconds in detections fetch #30650

Merged
merged 8 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
TOKEN_LIFE_TIME = 28
INCIDENTS_PER_FETCH = int(demisto.params().get('incidents_per_fetch', 15))
DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
IDP_DATE_FORMAT = IOM_DATE_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
DETECTION_DATE_FORMAT = IDP_DATE_FORMAT = IOM_DATE_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
DEFAULT_TIMEOUT = 30
# Remove proxy if not set to true in params
handle_proxy()
Expand Down Expand Up @@ -2538,7 +2538,7 @@ def fetch_incidents():
start_fetch_time, end_fetch_time = get_fetch_run_time_range(last_run=current_fetch_info_detections,
first_fetch=FETCH_TIME,
look_back=look_back,
date_format=DATE_FORMAT)
date_format=DETECTION_DATE_FORMAT)
fetch_limit = current_fetch_info_detections.get('limit') or INCIDENTS_PER_FETCH
incident_type = 'detection'
fetch_query = demisto.params().get('fetch_query')
Expand Down Expand Up @@ -2573,7 +2573,7 @@ def fetch_incidents():
for detection in detections:
occurred = dateparser.parse(detection["occurred"])
if occurred:
detection["occurred"] = occurred.strftime(DATE_FORMAT)
detection["occurred"] = occurred.strftime(DETECTION_DATE_FORMAT)
demisto.debug(f"CrowdStrikeFalconMsg: Detection {detection['name']} occurred at {detection['occurred']}")
current_fetch_info_detections = update_last_run_object(last_run=current_fetch_info_detections,
incidents=detections,
Expand All @@ -2583,7 +2583,7 @@ def fetch_incidents():
look_back=look_back,
created_time_field='occurred',
id_field='name',
date_format=DATE_FORMAT,
date_format=DETECTION_DATE_FORMAT,
new_offset=detections_offset)
demisto.debug(f"CrowdstrikeFalconMsg: Ending fetch idp_detections. Fetched {len(detections) if detections else 0}")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4696,7 +4696,7 @@ script:
auto: PREDEFINED
description: Perform actions on alerts.
name: cs-falcon-resolve-identity-detection
dockerimage: demisto/py3-tools:1.0.0.79743
dockerimage: demisto/py3-tools:1.0.0.79870
isfetch: true
ismappable: true
isremotesyncin: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2186,10 +2186,10 @@ def set_up_mocks(self, requests_mock, mocker):
'meta': {'pagination': {'total': 2}}})
requests_mock.post(f'{SERVER_URL}/detects/entities/summaries/GET/v1',
json={'resources': [{'detection_id': 'ldt:1',
'created_timestamp': '2020-09-04T09:16:11Z',
'created_timestamp': '2020-09-04T09:16:11.000000Z',
'max_severity_displayname': 'Low'},
{'detection_id': 'ldt:2',
'created_timestamp': '2020-09-04T09:20:11Z',
'created_timestamp': '2020-09-04T09:20:11.000000Z',
'max_severity_displayname': 'Low'}]})
requests_mock.get(f'{SERVER_URL}/incidents/queries/incidents/v1', json={})
requests_mock.post(f'{SERVER_URL}/incidents/entities/incidents/GET/v1', json={})
Expand All @@ -2209,38 +2209,16 @@ def test_old_fetch_to_new_fetch(self, set_up_mocks, mocker):
from CrowdStrikeFalcon import fetch_incidents
mocker.patch.object(demisto, 'params', return_value={})
mocker.patch.object(demisto, 'getLastRun',
return_value={'first_behavior_detection_time': '2020-09-04T09:16:10Z',
return_value={'first_behavior_detection_time': '2020-09-04T09:16:10.000000Z',
'detection_offset': 2,
'first_behavior_incident_time': '2020-09-04T09:22:10Z',
'first_behavior_incident_time': '2020-09-04T09:22:10.000000Z',
'last_fetched_incident': '3',
'incident_offset': 4,
})
fetch_incidents()
assert demisto.setLastRun.mock_calls[0][1][0] == [
{'time': '2020-09-04T09:16:10Z'}, {'time': '2020-09-04T09:22:10Z'}, {}, {}, {}]

@freeze_time("2020-08-26 17:22:13 UTC")
def delete_offset_test(self, set_up_mocks, mocker):
"""
Tests the change of logic done in fetch. Validates that it's done smoothly
Given:
Old getLastRun which holds two lists with offset key
When:
The offset is inside the lastRun
Then:
The offset is deleted from the lastRun

"""

from CrowdStrikeFalcon import fetch_incidents
mocker.patch.object(demisto, 'params', return_value={})
mocker.patch.object(demisto, 'getLastRun',
return_value=[{'time': '2020-09-04T09:16:10Z', 'offset': 2},
{'time': '2020-09-04T09:22:10Z', 'offset': 4}])
fetch_incidents()
assert demisto.setLastRun.mock_calls[0][1][0] == [{'time': '2020-09-04T09:16:10Z'},
{'time': '2020-09-04T09:22:10Z'}]

@freeze_time("2020-09-04T09:16:10Z")
def test_new_fetch(self, set_up_mocks, mocker, requests_mock):
"""
Expand All @@ -2253,18 +2231,19 @@ def test_new_fetch(self, set_up_mocks, mocker, requests_mock):
The `first_behavior_time` changes and no `offset` is added.
"""
mocker.patch.object(demisto, 'getLastRun',
return_value=[{'time': '2020-09-04T09:16:10Z',
return_value=[{'time': '2020-09-04T09:16:10.000000Z',
'offset': 2}, {}, {}])
# Override post to have 1 results so FETCH_LIMIT won't be reached
requests_mock.post(f'{SERVER_URL}/detects/entities/summaries/GET/v1',
json={'resources': [{'detection_id': 'ldt:1',
'created_timestamp': '2020-09-04T09:16:11Z',
'created_timestamp': '2020-09-04T09:16:11.000000Z',
'max_severity_displayname': 'Low'}],
})
from CrowdStrikeFalcon import fetch_incidents
fetch_incidents()
assert demisto.setLastRun.mock_calls[0][1][0][0] == {
'time': '2020-09-04T09:16:11Z', 'limit': 2, 'offset': 0, "found_incident_ids": {'Detection ID: ldt:1': 1599210970}}
'time': '2020-09-04T09:16:11.000000Z', 'limit': 2, 'offset': 0, "found_incident_ids":
{'Detection ID: ldt:1': 1599210970}}

@freeze_time("2020-09-04T09:16:10Z")
def test_fetch_with_offset(self, set_up_mocks, mocker, requests_mock):
Expand All @@ -2284,19 +2263,20 @@ def test_fetch_with_offset(self, set_up_mocks, mocker, requests_mock):
'meta': {'pagination': {'total': 4}}})

mocker.patch.object(demisto, 'getLastRun',
return_value=[{'time': '2020-09-04T09:16:10Z',
return_value=[{'time': '2020-09-04T09:16:10.000000Z',
'offset': 0}, {}, {}])
# Override post to have 1 results so FETCH_LIMIT won't be reached
requests_mock.post(f'{SERVER_URL}/detects/entities/summaries/GET/v1',
json={'resources': [{'detection_id': 'ldt:1',
'created_timestamp': '2020-09-04T09:16:11Z',
'created_timestamp': '2020-09-04T09:16:11.000000Z',
'max_severity_displayname': 'Low'}],
})
from CrowdStrikeFalcon import fetch_incidents
fetch_incidents()
# the offset should be increased to 2, and the time should be stay the same
expected_last_run = {
'time': '2020-09-04T09:16:10Z', 'limit': 2, 'offset': 2, "found_incident_ids": {'Detection ID: ldt:1': 1599210970}}
'time': '2020-09-04T09:16:10.000000Z', 'limit': 2, 'offset': 2, "found_incident_ids":
{'Detection ID: ldt:1': 1599210970}}
assert demisto.setLastRun.mock_calls[0][1][0][0] == expected_last_run

requests_mock.get(f'{SERVER_URL}/detects/queries/detects/v1', json={'resources': ['ldt:3', 'ldt:4'],
Expand All @@ -2307,15 +2287,16 @@ def test_fetch_with_offset(self, set_up_mocks, mocker, requests_mock):

requests_mock.post(f'{SERVER_URL}/detects/entities/summaries/GET/v1',
json={'resources': [{'detection_id': 'ldt:2',
'created_timestamp': '2020-09-04T09:16:13Z',
'created_timestamp': '2020-09-04T09:16:13.000000Z',
'max_severity_displayname': 'Low'}],
})

fetch_incidents()
# the offset should be 0 because all detections were fetched, and the time should update to the latest detection
assert demisto.setLastRun.mock_calls[1][1][0][0] == {
'time': '2020-09-04T09:16:13Z', 'limit': 2, 'offset': 0, "found_incident_ids": {'Detection ID: ldt:1': 1599210970,
'Detection ID: ldt:2': 1599210970}}
'time': '2020-09-04T09:16:13.000000Z', 'limit': 2, 'offset': 0, "found_incident_ids":
{'Detection ID: ldt:1': 1599210970,
'Detection ID: ldt:2': 1599210970}}

def test_fetch_incident_type(self, set_up_mocks, mocker):
"""
Expand Down Expand Up @@ -2460,7 +2441,7 @@ def test_new_fetch(self, set_up_mocks, mocker, requests_mock):
'offset': 0,
'found_incident_ids': {'Incident ID: ldt:1': 1598462533}}

@freeze_time("2020-09-04T09:16:10Z")
@freeze_time("2020-09-04T09:16:10.000000Z")
def test_fetch_with_offset(self, set_up_mocks, mocker, requests_mock):
"""
Tests the correct flow of fetch with offset
Expand Down
7 changes: 7 additions & 0 deletions Packs/CrowdStrikeFalcon/ReleaseNotes/1_12_4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

#### Integrations

##### CrowdStrike Falcon

- Fixed an issue in `Detections` **fetch-incidents** where there were missing detections due to missing fractional seconds in the date format.
- Updated the Docker image to: *demisto/py3-tools:1.0.0.79870*.
2 changes: 1 addition & 1 deletion Packs/CrowdStrikeFalcon/pack_metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "CrowdStrike Falcon",
"description": "The CrowdStrike Falcon OAuth 2 API (formerly the Falcon Firehose API), enables fetching and resolving detections, searching devices, getting behaviors by ID, containing hosts, and lifting host containment.",
"support": "xsoar",
"currentVersion": "1.12.3",
"currentVersion": "1.12.4",
"author": "Cortex XSOAR",
"url": "https://www.paloaltonetworks.com/cortex",
"email": "",
Expand Down
Loading