Skip to content

Commit bbebbad

Browse files
GuyAfikContent Bot
authored andcommitted
Audit Logs Endpoints Scripts Aligments for Xsoar-8 (demisto#29781)
* test * fix core api * ExportAuditLogsToFile - add support for xsoar-8 * add ExportAuditLogsToFile UTs * add forward audit logs uts * update ut * validation fixes * mypy * bump rns * update docker * update docker image * fix ut * format * Bump pack from version CommonScripts to 1.12.25. * Bump pack from version CommonScripts to 1.12.26. * cr * cr fixes * update * fix uts --------- Co-authored-by: Content Bot <[email protected]>
1 parent efd5591 commit bbebbad

File tree

13 files changed

+238
-38
lines changed

13 files changed

+238
-38
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
#### Scripts
3+
4+
##### ExportAuditLogsToFile
5+
6+
- Added support to XSOAR 8.
7+
- Updated the Docker image to: *demisto/python3:3.10.13.74666*.

Packs/CommonScripts/Scripts/ExportAuditLogsToFile/ExportAuditLogsToFile.py

Lines changed: 77 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,100 @@
66
from datetime import date, timedelta
77

88

9+
def get_audit_logs(res: Dict):
10+
11+
def get_xsoar6_audit_logs():
12+
return res.get('audits') or []
13+
14+
def get_xsoar8_audit_logs():
15+
return (res.get('reply') or {}).get('data') or []
16+
17+
return get_xsoar6_audit_logs() or get_xsoar8_audit_logs()
18+
19+
20+
def get_audit_logs_count(res: Dict):
21+
def get_xsoar6_audit_logs_count():
22+
return res.get('total') or 0
23+
24+
def get_xsoar8_audit_logs_count():
25+
return res.get('total_count') or 0
26+
27+
return arg_to_number(get_xsoar6_audit_logs_count() or get_xsoar8_audit_logs_count())
28+
29+
930
def main(): # pragma: no cover
1031
# get the file type
1132
file_type = demisto.args().get("output")
1233

1334
# set time back for fetching
1435
fetch_back_date = date.today() - timedelta(days=int(demisto.args().get("days_back")))
1536
fetch_from = fetch_back_date.strftime("%Y-%m-%dT00:00:00Z")
16-
file_date = fetch_back_date.strftime("%Y-%m-%d")
1737

18-
# body of the request
19-
body = {
20-
'fromDate': fetch_from,
21-
'query': "",
22-
'page': 0,
23-
'size': 100
24-
}
38+
demisto_version: str = get_demisto_version().get("version")
39+
demisto.debug(f'The version of XSOAR is: {demisto_version}')
40+
if not demisto_version:
41+
raise ValueError('Could not get the version of XSOAR')
42+
43+
page_num = 0
44+
size = 100
45+
46+
if demisto_version.startswith("6"): # xsoar 6
47+
uri = "/settings/audits"
48+
body = {
49+
'fromDate': fetch_from,
50+
'query': "",
51+
'page': page_num,
52+
'size': size
53+
}
54+
else: # xsoar 8
55+
uri = "/public_api/v1/audits/management_logs"
56+
body = {
57+
"request_data": {
58+
"search_from": page_num,
59+
"search_to": size,
60+
"filters": [
61+
{
62+
'field': 'timestamp',
63+
'operator': 'gte',
64+
'value': date_to_timestamp(fetch_back_date)
65+
},
66+
]
67+
}
68+
}
2569

26-
# get the logs
27-
res = demisto.executeCommand("demisto-api-post", {"uri": "/settings/audits", "body": body})[0]["Contents"][
28-
"response"]
70+
args = {"uri": uri, "body": body}
71+
res = demisto.executeCommand("demisto-api-post", args)
72+
demisto.debug(f'demisto-api-post with {args} returned {res}')
73+
if is_error(res):
74+
raise DemistoException(f'error occurred when trying to retrieve the audit logs using {args=}, error: {res}')
75+
76+
response = res[0]["Contents"]["response"]
2977

3078
# set the initial counts
31-
total = res.get('total', 0)
32-
audits = res.get('audits', [])
33-
count = 1
79+
total = get_audit_logs_count(response)
80+
audits = get_audit_logs(response)
81+
page_num += 1
3482

3583
# if there are more events than the default size, page through and get them all
3684
while len(audits) < total:
37-
body['page'] = count
38-
res = demisto.executeCommand("demisto-api-post", {"uri": "/settings/audits", "body": body})[0]["Contents"][
39-
"response"]
40-
audits.extend(res.get('audits', []))
41-
count += 1
85+
if body.get("page"): # pagination for xsoar-6
86+
body["page"] = page_num
87+
else: # pagination for xsoar-8
88+
body["request_data"]["search_from"] = page_num # type: ignore[index]
89+
args = {"uri": uri, "body": body}
90+
res = demisto.executeCommand("demisto-api-post", args)
91+
demisto.debug(f'demisto-api-post with {args} returned {res}')
92+
if is_error(res):
93+
raise DemistoException(f'error occurred when trying to retrieve the audit logs using {args=}, error: {res}')
94+
response = res[0]["Contents"]["response"]
95+
audits.extend(get_audit_logs(response))
96+
page_num += 1
4297
# break if this goes crazy, if there are more than 100 pages of audit log entries.
43-
if count == 100:
98+
if page_num == 100:
4499
break
45100

101+
file_date = fetch_back_date.strftime("%Y-%m-%d")
102+
46103
if file_type == "csv":
47104
# write the results to a CSV
48105
si = io.StringIO()

Packs/CommonScripts/Scripts/ExportAuditLogsToFile/ExportAuditLogsToFile.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ args:
1010
required: true
1111
- auto: PREDEFINED
1212
defaultValue: csv
13-
description: Type of File to return, either JSON, or CSV
13+
description: Type of File to return, either JSON, or CSV.
1414
name: output
1515
predefined:
1616
- csv
@@ -25,7 +25,7 @@ contentitemexportablefields:
2525
dependson:
2626
must:
2727
- demisto-api-post
28-
dockerimage: demisto/python3:3.10.12.63474
28+
dockerimage: demisto/python3:3.10.13.74666
2929
enabled: true
3030
name: ExportAuditLogsToFile
3131
runas: DBotWeakRole
Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,59 @@
11
import demistomock as demisto
2-
from ExportAuditLogsToFile import main
2+
import pytest
3+
import ExportAuditLogsToFile
34
from freezegun import freeze_time
5+
from CommonServerPython import *
6+
7+
8+
def execute_command_side_effect(command: str, args: Dict):
9+
if command == "splunk-submit-event-hec":
10+
return [{'Contents': {'response': ["result1"]}}]
11+
if command == "demisto-api-post":
12+
if args["uri"] == '/settings/audits':
13+
return [{'Contents': {'response': {'total': 2, "audits": ["audit1", "audit2"]}}, "Type": entryTypes["note"]}]
14+
return [{'Contents': {'response': {'total': 2, "reply": {"data": ["audit1", "audit2"]}}}, "Type": entryTypes["note"]}]
15+
return None
416

517

618
@freeze_time('2020-04-20')
7-
def test_main(mocker):
19+
def test_main_no_logs_xsoar6(mocker):
820
mocker.patch.object(demisto, 'args', return_value={'output': 'html', 'days_back': '5'})
9-
execute_command_mock = mocker.patch.object(demisto, 'executeCommand',
10-
return_value=[{'Contents': {'response': {'total': 0}}}])
11-
main()
21+
execute_command_mock = mocker.patch.object(
22+
demisto, 'executeCommand', return_value=[{'Contents': {'response': {'total': 0}}, "Type": entryTypes["note"]}]
23+
)
24+
mocker.patch.object(ExportAuditLogsToFile, "get_demisto_version", return_value={"version": "6.10"})
25+
ExportAuditLogsToFile.main()
1226
assert execute_command_mock.call_args.args[1]['body']['fromDate'] == '2020-04-15T00:00:00Z'
27+
28+
29+
@freeze_time('2020-04-20')
30+
@pytest.mark.parametrize(
31+
'xsoar_version, expected_uri',
32+
[
33+
({"version": "6.10"}, "/settings/audits"),
34+
({"version": "8.1"}, '/public_api/v1/audits/management_logs')
35+
]
36+
)
37+
def test_main_with_logs(mocker, xsoar_version, expected_uri):
38+
"""
39+
Given:
40+
- xsoar version
41+
When:
42+
- Calling main flow
43+
Then:
44+
- make sure the correct uri is called for each xsoar version
45+
- make sure audit logs are fetched when its xsoar 6/8
46+
"""
47+
mocker.patch.object(demisto, 'args', return_value={'output': 'json', 'days_back': '5'})
48+
execute_command_mocker = mocker.patch.object(
49+
demisto,
50+
'executeCommand',
51+
side_effect=execute_command_side_effect
52+
)
53+
mocker.patch.object(ExportAuditLogsToFile, "fileResult", return_value=["audit1", "audit2"])
54+
mocker.patch.object(ExportAuditLogsToFile, "get_demisto_version", return_value=xsoar_version)
55+
demisto_results_mocker = mocker.patch.object(demisto, "results", return_value=[])
56+
ExportAuditLogsToFile.main()
57+
assert demisto_results_mocker.called
58+
assert "Fetched 2 audit log events" in demisto_results_mocker.call_args_list[1][0][0]
59+
assert execute_command_mocker.call_args_list[0][0][1]["uri"] == expected_uri

Packs/CommonScripts/pack_metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "Common Scripts",
33
"description": "Frequently used scripts pack.",
44
"support": "xsoar",
5-
"currentVersion": "1.12.25",
5+
"currentVersion": "1.12.26",
66
"author": "Cortex XSOAR",
77
"url": "https://www.paloaltonetworks.com/cortex",
88
"email": "",

Packs/DemistoRESTAPI/Integrations/CoreRESTAPI/CoreRESTAPI.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11

22
const MIN_HOSTED_XSOAR_VERSION = '8.0.0';
3+
// list was taken from https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR-8-API
4+
const SYSTEM_ENDPOINTS = [
5+
"/public_api/v1/audits/management_logs",
6+
"/public_api/v1/rbac/get_roles",
7+
"/public_api/v1/rbac/get_user_group",
8+
"/public_api/v1/rbac/get_users",
9+
"/public_api/v1/rbac/set_user_role"
10+
]
311

412
var serverURL = params.url;
513
if (serverURL.slice(-1) === '/') {
@@ -17,8 +25,9 @@ isHosted = function () {
1725
}
1826

1927
// only when using XSIAM or XSOAR >= 8.0 we will add the /xsoar suffix
28+
// and only when it is not a system endpoint (note: this list does not include all system endpoints!)
2029
if (isHosted()) {
21-
if (!serverURL.endsWith('/xsoar')){
30+
if ((!serverURL.endsWith('/xsoar')) && (!SYSTEM_ENDPOINTS.includes(args.uri))) {
2231
serverURL = serverURL + '/xsoar'
2332
}
2433
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
#### Integrations
3+
4+
##### Core REST API
5+
6+
- Fixed an issue where the integration would not work with XSOAR endpoints that do not start with the **/xsoar** prefix.

Packs/DemistoRESTAPI/pack_metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "Cortex REST API",
33
"description": "Use Demisto REST APIs",
44
"support": "xsoar",
5-
"currentVersion": "1.3.36",
5+
"currentVersion": "1.3.37",
66
"author": "Cortex XSOAR",
77
"url": "https://www.paloaltonetworks.com/cortex",
88
"email": "",
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
#### Scripts
3+
4+
##### ForwardAuditLogsToSplunkHEC
5+
6+
- Added support for XSOAR 8.
7+
- Updated the Docker image to: *demisto/python3:3.10.13.74666*.

Packs/ForwardXSOARAuditLogsToSplunkHEC/Scripts/ForwardAuditLogsToSplunkHEC/ForwardAuditLogsToSplunkHEC.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,36 @@
44

55

66
def get_audit_logs(timeframe: int) -> Dict:
7+
demisto_version: str = get_demisto_version().get("version")
8+
demisto.debug(f'{demisto_version=}')
9+
if not demisto_version:
10+
raise ValueError('Could not get the version of XSOAR')
11+
712
timefrom = datetime.now() - timedelta(hours=int(timeframe))
813
timestring = timefrom.strftime('%Y-%m-%dT%H:%M:%S')
9-
parameters = {"uri": "/settings/audits",
10-
"body": {"size": 1000,
11-
"query": f"modified:>{timestring}"}}
12-
results = demisto.executeCommand('demisto-api-post', parameters)
14+
15+
if demisto_version.startswith("6"): # xsoar 6
16+
uri = "/settings/audits"
17+
body = {
18+
'size': 1000,
19+
"query": f"modified:>{timestring}"
20+
}
21+
else: # xsoar 8
22+
uri = "/public_api/v1/audits/management_logs"
23+
body = {
24+
"request_data": {
25+
"search_to": 1000,
26+
"filters": [
27+
{
28+
'field': 'modification_time',
29+
'operator': 'gte',
30+
'value': date_to_timestamp(timestring)
31+
},
32+
]
33+
}
34+
}
35+
36+
results = demisto.executeCommand('demisto-api-post', {"uri": uri, "body": body})
1337
return results[0]['Contents']['response']
1438

1539

0 commit comments

Comments
 (0)