Skip to content

Commit 1af90d0

Browse files
authored
Fix DomainGlob expansion and legacy query mode persistence in EDL (#43809)
* DomainGlob expansion and legacy query mode persistence in EDL * Create 3_3_28.md * Update EDL.py * Update EDL.py * Update 3_3_28.md * Update unit tests * Update EDL.py * Update release notes again * Update EDL.py
1 parent 71b05ef commit 1af90d0

4 files changed

Lines changed: 82 additions & 11 deletions

File tree

Packs/EDL/Integrations/EDL/EDL.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,9 @@ def from_context_json(cls, ctx_dict):
226226
def get_fields_to_present(self, fields_to_present: str) -> str:
227227
# based on func ToIoC https://github.com/demisto/server/blob/master/domain/insight.go
228228

229-
if fields_to_present == "use_legacy_query":
229+
# Fixes legacy query mode silently lost after the first refresh because
230+
# `get_fields_to_present("")` returned "name,type" instead of ""
231+
if fields_to_present == "use_legacy_query" or (not fields_to_present and self.out_format == FORMAT_TEXT):
230232
return ""
231233

232234
fields_for_format = {
@@ -867,7 +869,8 @@ def create_text_out_format(iocs: IO, request_args: RequestArguments) -> tuple[Un
867869
# for PAN-OS *.domain.com does not match domain.com
868870
# we should provide both
869871
# this could generate more than num entries according to PAGE_SIZE
870-
if indicator.startswith("*."):
872+
# Handle DomainGlob type indicators even when value doesn't start with "*."
873+
if indicator.startswith("*.") or ioc_type == FeedIndicatorType.DomainGlob:
871874
domain = str(indicator.lstrip("*."))
872875
# if we should ignore TLDs and the domain is a TLD
873876
if request_args.no_wildcard_tld and tldextract.extract(domain).suffix == domain:

Packs/EDL/Integrations/EDL/EDL_test.py

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,11 @@ def test_get_edl_on_demand__with_refresh_signal(self, mocker):
142142

143143
expected_edl = "8.8.8.8"
144144
edl_log_line = "\nAdded | 8.8.8.8 | 8.8.8.8 | Found new Domain."
145-
ctx = {edl.EDL_ON_DEMAND_KEY: True, edl.RequestArguments.CTX_QUERY_KEY: "*"}
145+
ctx = {
146+
edl.EDL_ON_DEMAND_KEY: True,
147+
edl.RequestArguments.CTX_QUERY_KEY: "*",
148+
edl.RequestArguments.CTX_FIELDS_TO_PRESENT: "name,type",
149+
}
146150
tmp_dir = mkdtemp()
147151
edl.EDL_ON_DEMAND_CACHE_PATH = os.path.join(tmp_dir, "cache")
148152
mocker.patch.object(edl, "get_integration_context", return_value=ctx)
@@ -525,7 +529,9 @@ def test_create_csv_out_format(self):
525529

526530
with open("test_data/demisto_url_iocs.json") as iocs_json_f:
527531
iocs_json = json.loads(iocs_json_f.read())
528-
request_args = RequestArguments(query="", drop_invalids=True, url_port_stripping=True, url_protocol_stripping=True)
532+
request_args = RequestArguments(
533+
query="", drop_invalids=True, url_port_stripping=True, url_protocol_stripping=True, fields_to_present="name,type"
534+
)
529535
returned_output = ""
530536
not_first_call = False
531537
for ioc in iocs_json:
@@ -1488,19 +1494,73 @@ def test_store_log_data(mocker, wip_exist):
14881494
"out_format, fields_to_present, expected",
14891495
[
14901496
# Case 1: use_legacy_query returns ""
1491-
(FORMAT_TEXT, "use_legacy_query", ""),
1497+
pytest.param(FORMAT_TEXT, "use_legacy_query", "", id="legacy_query_mode"),
14921498
# Case 2: FORMAT_CSV with 'all' returns ""
1493-
(FORMAT_CSV, "all", ""),
1499+
pytest.param(FORMAT_CSV, "all", "", id="csv_all_fields"),
14941500
# Case 3: FORMAT_JSON with 'value' replaced to 'name'
1495-
(FORMAT_JSON, "value,type", "name,type"),
1501+
pytest.param(FORMAT_JSON, "value,type", "name,type", id="json_value_to_name"),
14961502
# Case 4: FORMAT_MWG with no fields_to_present
1497-
(FORMAT_MWG, "", RequestArguments.FILTER_FIELDS_ON_FORMAT_MWG),
1503+
pytest.param(FORMAT_MWG, "", RequestArguments.FILTER_FIELDS_ON_FORMAT_MWG, id="mwg_default_fields"),
14981504
# Case 5: FORMAT_PROXYSG with no fields_to_present
1499-
(FORMAT_PROXYSG, "", RequestArguments.FILTER_FIELDS_ON_FORMAT_PROXYSG),
1505+
pytest.param(FORMAT_PROXYSG, "", RequestArguments.FILTER_FIELDS_ON_FORMAT_PROXYSG, id="proxysg_default_fields"),
15001506
# Case 6: Unknown format fallback to FILTER_FIELDS_ON_FORMAT_TEXT
1501-
("unknown_format", "", RequestArguments.FILTER_FIELDS_ON_FORMAT_TEXT),
1507+
pytest.param("unknown_format", "", RequestArguments.FILTER_FIELDS_ON_FORMAT_TEXT, id="unknown_format_fallback"),
1508+
# Case 7: Empty string returns "" (fix for XSUP-67083 - legacy mode preservation)
1509+
pytest.param(FORMAT_TEXT, "", "", id="empty_string_returns_empty"),
15021510
],
15031511
)
15041512
def test_get_fields_to_present(out_format, fields_to_present, expected):
1513+
"""
1514+
Given:
1515+
- Various output formats and fields_to_present values
1516+
When:
1517+
- Creating RequestArguments with different field configurations
1518+
Then:
1519+
- Ensure get_fields_to_present returns the correct field list
1520+
- Ensure empty string is treated as legacy query mode (returns "")
1521+
"""
15051522
args = RequestArguments(out_format=out_format, fields_to_present=fields_to_present)
15061523
assert args.fields_to_present == expected
1524+
1525+
1526+
@pytest.mark.parametrize(
1527+
"indicator_value, indicator_type, expected_output",
1528+
[
1529+
pytest.param("*.example.org", "DomainGlob", ["example.org", "*.example.org"], id="domainglob_with_wildcard_prefix"),
1530+
pytest.param("*.example.org", "URL", ["example.org", "*.example.org"], id="url_with_wildcard_prefix"),
1531+
pytest.param("example.com", "Domain", ["example.com"], id="domain_without_wildcard"),
1532+
],
1533+
)
1534+
def test_domain_glob_wildcard_expansion(indicator_value: str, indicator_type: str, expected_output: list):
1535+
"""
1536+
Given:
1537+
- Indicators with different types (DomainGlob, URL, Domain) and values
1538+
When:
1539+
- Processing indicators through create_text_out_format for PAN-OS text output
1540+
Then:
1541+
- Ensure DomainGlob indicators produce both wildcard and bare domain forms
1542+
- Ensure URL wildcards are handled correctly
1543+
- Ensure regular domains produce only the domain itself
1544+
- Ensure DomainGlob type triggers expansion even without "*." prefix
1545+
"""
1546+
import json
1547+
from io import StringIO
1548+
from EDL import create_text_out_format
1549+
1550+
# Create indicator data in memory (no file writing)
1551+
indicator_json = json.dumps({"value": indicator_value, "indicator_type": indicator_type})
1552+
indicators_data = StringIO(indicator_json + "\n")
1553+
1554+
# Create request arguments for PAN-OS text format
1555+
request_args = RequestArguments(out_format=FORMAT_TEXT)
1556+
1557+
# Process the indicator
1558+
output, _ = create_text_out_format(indicators_data, request_args)
1559+
1560+
# Parse the output - seek to beginning and read
1561+
output.seek(0)
1562+
output_content = output.read().strip()
1563+
output_lines = output_content.split("\n") if output_content else []
1564+
1565+
# Verify the output matches expected
1566+
assert sorted(output_lines) == sorted(expected_output)

Packs/EDL/ReleaseNotes/3_3_31.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
#### Integrations
3+
4+
##### Generic Export Indicators Service
5+
6+
- Fixed an issue where DomainGlob wildcard indicators (e.g., `*.example.com`) were not appearing in the EDL output when the platform returned the bare domain instead of the wildcard form.
7+
8+
- Fixed an issue where legacy query mode was silently lost after the first EDL refresh, causing the integration to present the `name` and `type` fields only instead of no field filtering.

Packs/EDL/pack_metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "Generic Export Indicators Service",
33
"description": "Use this pack to generate a list based on your Threat Intel Library, and export it to any product in your network, such as firewalls, agents or SIEMs. This pack supports ongoing distribution of indicators from XSOAR to other products in the network, by creating an endpoint with a list of indicators that can be pulled by external vendors.",
44
"support": "xsoar",
5-
"currentVersion": "3.3.30",
5+
"currentVersion": "3.3.31",
66
"author": "Cortex XSOAR",
77
"url": "https://www.paloaltonetworks.com/cortex",
88
"email": "",

0 commit comments

Comments
 (0)