Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
40 changes: 24 additions & 16 deletions Packs/Flashpoint/Integrations/Ignite/Ignite.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
"""Ignite Main File."""

from copy import deepcopy
import ipaddress

import requests
import urllib3
import re
from copy import deepcopy

import demistomock as demisto
import requests
import urllib3
from CommonServerPython import * # noqa # pylint: disable=unused-wildcard-import
from CommonServerUserPython import * # noqa

Expand Down Expand Up @@ -323,15 +322,17 @@ def http_request(self, method, url_suffix, params=None, json_data=None):

return resp_json

def get_indicator(self, indicator_value: str, indicator_type: str):
def get_indicator(self, indicator_value: str, indicator_type: str, exact_match: bool = False):
"""
Get an indicator by its type and value.

:param indicator_type: The indicator type.
:param indicator_value: The indicator value.
:param exact_match: Whether to perform an exact match. If true, the indicator value is enclosed in quotes.

:return: The indicator response.
"""
indicator_value = f'"{indicator_value}"' if exact_match else indicator_value
params = {"ioc_types": indicator_type, "ioc_value": indicator_value, "embed": "all"}

return self.http_request("GET", URL_SUFFIX["LIST_INDICATORS"], params=params)
Expand Down Expand Up @@ -1696,7 +1697,7 @@ def filename_lookup_command(client: Client, filename: str) -> CommandResults:
)


def ip_lookup_command(client: Client, ip: str) -> CommandResults:
def ip_lookup_command(client: Client, ip: str, exact_match: bool = False) -> CommandResults:
"""
Lookup a particular ip-address.

Expand All @@ -1705,6 +1706,7 @@ def ip_lookup_command(client: Client, ip: str) -> CommandResults:

: param client: object of client class
: param ip: ip-address
: param exact_match: Whether to perform an exact match. If true, the indicator value is enclosed in quotes.
: return: command output
"""
if not is_ip_valid(ip, True):
Expand All @@ -1714,9 +1716,9 @@ def ip_lookup_command(client: Client, ip: str) -> CommandResults:
return CommandResults(readable_output=f"Skipping internal IP: {ip}")

if is_ipv6_valid(ip):
response = client.get_indicator(ip, "ipv6")
response = client.get_indicator(ip, "ipv6", exact_match)
else:
response = client.get_indicator(ip, "ipv4")
response = client.get_indicator(ip, "ipv4", exact_match)
items = response.get("items", [])

if items:
Expand Down Expand Up @@ -2116,16 +2118,16 @@ def indicator_get_command(client: Client, args: dict) -> CommandResults:
)


def url_lookup_command(client: Client, url: str) -> CommandResults:
def url_lookup_command(client: Client, url: str, exact_match: bool = False) -> CommandResults:
"""
Lookup a particular url.

:param client: object of client class
:param url: url as indicator

:param exact_match: Whether to perform an exact match. If true, the indicator value is enclosed in quotes.
:return: command output
"""
response = client.get_indicator(url, "url")
response = client.get_indicator(url, "url", exact_match)
items = response.get("items", [])

if items:
Expand Down Expand Up @@ -2236,16 +2238,17 @@ def url_lookup_command(client: Client, url: str) -> CommandResults:
return command_results


def domain_lookup_command(client: Client, domain: str) -> CommandResults:
def domain_lookup_command(client: Client, domain: str, exact_match: bool = False) -> CommandResults:
"""
Lookup a particular domain.

:param client: object of client class
:param domain: domain
:param exact_match: Whether to perform an exact match. If true, the indicator value is enclosed in quotes.
:return: command output
"""

response = client.get_indicator(domain, "domain")
response = client.get_indicator(domain, "domain", exact_match)
items = response.get("items", [])

if items:
Expand Down Expand Up @@ -2350,16 +2353,17 @@ def domain_lookup_command(client: Client, domain: str) -> CommandResults:
return CommandResults(indicator=domain_ioc, readable_output=human_readable, raw_response=response)


def file_lookup_command(client: Client, file: str) -> CommandResults:
def file_lookup_command(client: Client, file: str, exact_match: bool = False) -> CommandResults:
"""
Lookup a particular file hash.

:param client: object of client class
:param file: file as indicator
:param exact_match: Whether to perform an exact match. If true, the indicator value is enclosed in quotes.
:return: command output
"""

response = client.get_indicator(file, "file")
response = client.get_indicator(file, "file", exact_match)
items = response.get("items", [])

if items:
Expand Down Expand Up @@ -2977,11 +2981,15 @@ def main():
raise ValueError(MESSAGES["MISSING_REQUIRED_ARGS"].format(command))
indicator_list = argToList(args.get(command))
indicator_list = [indicator.strip() for indicator in indicator_list if indicator.strip()]
exact_match = argToBoolean(args.get("exact_match", False))
results = []
if not indicator_list:
raise ValueError(MESSAGES["MISSING_REQUIRED_ARGS"].format(command))
for indicator in indicator_list:
results.append(REPUTATION_COMMAND_TO_FUNCTION[command](client, indicator))
arguments = (client, indicator)
if exact_match:
arguments += (exact_match,) # type: ignore
results.append(REPUTATION_COMMAND_TO_FUNCTION[command](*arguments))
return_results(results)

elif COMMAND_TO_FUNCTION.get(command):
Expand Down
34 changes: 33 additions & 1 deletion Packs/Flashpoint/Integrations/Ignite/Ignite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,14 @@ script:
default: true
description: A comma-separated list of IP addresses.
isArray: true
- name: exact_match
required: false
defaultValue: "False"
description: Whether to perform an exact match on the IP address value.
auto: PREDEFINED
predefined:
- "True"
- "False"
outputs:
- contextPath: DBotScore.Indicator
description: The indicator that was tested.
Expand Down Expand Up @@ -2587,6 +2595,14 @@ script:
default: true
description: A comma-separated list of URLs.
isArray: true
- name: exact_match
required: false
defaultValue: "False"
description: Whether to perform an exact match on the URL value.
auto: PREDEFINED
predefined:
- "True"
- "False"
outputs:
- contextPath: DBotScore.Indicator
description: The indicator that was tested.
Expand Down Expand Up @@ -2791,6 +2807,14 @@ script:
default: true
description: A comma-separated list of domains.
isArray: true
- name: exact_match
required: false
defaultValue: "False"
description: Whether to perform an exact match on the domain value.
auto: PREDEFINED
predefined:
- "True"
- "False"
outputs:
- contextPath: DBotScore.Indicator
description: The indicator that was tested.
Expand Down Expand Up @@ -2995,6 +3019,14 @@ script:
default: true
description: List of files.
isArray: true
- name: exact_match
required: false
defaultValue: "False"
description: Whether to perform an exact match on the file hash value.
auto: PREDEFINED
predefined:
- "True"
- "False"
outputs:
- contextPath: DBotScore.Indicator
description: The indicator that was tested.
Expand Down Expand Up @@ -3215,7 +3247,7 @@ script:
description: Looks up the "File" type indicator details. The reputation of the file is decided from the indicator score if it is found in the Ignite IOC database.
script: ''
type: python
dockerimage: demisto/python3:3.12.11.4508456
dockerimage: demisto/python3:3.12.12.6947692
isfetch: true
runonce: false
subtype: python3
Expand Down
42 changes: 34 additions & 8 deletions Packs/Flashpoint/Integrations/Ignite/Ignite_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1212,7 +1212,8 @@ def test_filename_empty_response(mock_return, requests_mock, mocker):


@patch("demistomock.results")
def test_domain_lookup_command_success(mock_return, requests_mock, mocker):
@pytest.mark.parametrize("exact_match", [True, False])
def test_domain_lookup_command_success(mock_return, requests_mock, mocker, exact_match):
"""
Test case for successful execution of domain look up command through main function
when it returns reputation about given domain indicator.
Expand All @@ -1234,13 +1235,18 @@ def test_domain_lookup_command_success(mock_return, requests_mock, mocker):

requests_mock.get(url, json=domain_lookup_reputation, status_code=200)
params = {**BASIC_PARAMS, "integrationReliability": "B - Usually reliable"}
args = {"domain": "dummy_domain.com"}
domain_value = "dummy_domain.com"
args = {"domain": domain_value, "exact_match": exact_match}
mocker.patch.object(demisto, "params", return_value=params)
mocker.patch.object(demisto, "command", return_value="domain")
mocker.patch.object(demisto, "args", return_value=args)

main()

last_request = requests_mock.last_request
domain_value = f'"{domain_value}"' if exact_match else domain_value
assert last_request.qs["ioc_value"] == [domain_value]

assert hr_output_for_domain_lookup_reputation == mock_return.call_args.args[0].get("HumanReadable")
assert domain_lookup_reputation_context == mock_return.call_args.args[0].get("EntryContext")
assert domain_lookup_reputation == mock_return.call_args.args[0].get("Contents")
Expand Down Expand Up @@ -1306,7 +1312,8 @@ def test_domain_lookup_command_when_invalid_value_is_provided(mocker):


@patch("demistomock.results")
def test_ip_lookup_command_success(mock_return, requests_mock, mocker):
@pytest.mark.parametrize("exact_match", [True, False])
def test_ip_lookup_command_success(mock_return, requests_mock, mocker, exact_match):
"""
Test case for successful execution of ip look up command through main function
when it returns reputation about given ip indicator.
Expand All @@ -1327,13 +1334,18 @@ def test_ip_lookup_command_success(mock_return, requests_mock, mocker):
url = f'{MOCK_URL}{URL_SUFFIX["LIST_INDICATORS"]}'
requests_mock.get(url, json=ip_lookup_reputation, status_code=200)
params = {**BASIC_PARAMS, "integrationReliability": "B - Usually reliable"}
args = {"ip": "0.0.0.1"}
ip_value = "0.0.0.1"
args = {"ip": ip_value, "exact_match": exact_match}
mocker.patch.object(demisto, "params", return_value=params)
mocker.patch.object(demisto, "command", return_value="ip")
mocker.patch.object(demisto, "args", return_value=args)
mocker.patch("Ignite.is_ip_address_internal", return_value=False)
main()

last_request = requests_mock.last_request
ip_value = f'"{ip_value}"' if exact_match else ip_value
assert last_request.qs["ioc_value"] == [ip_value]

assert hr_output_for_ip_lookup_reputation == mock_return.call_args.args[0].get("HumanReadable")
assert ip_lookup_reputation_context == mock_return.call_args.args[0].get("EntryContext")
assert ip_lookup_reputation == mock_return.call_args.args[0].get("Contents")
Expand Down Expand Up @@ -1761,7 +1773,8 @@ def test_indicator_get_command_when_invalid_value_is_provided(mocker):


@patch("demistomock.results")
def test_url_lookup_command_success(mock_return, requests_mock, mocker):
@pytest.mark.parametrize("exact_match", [True, False])
def test_url_lookup_command_success(mock_return, requests_mock, mocker, exact_match):
"""
Test case for successful execution of url lookup command through main function
when it returns reputation about given url.
Expand All @@ -1781,12 +1794,18 @@ def test_url_lookup_command_success(mock_return, requests_mock, mocker):

requests_mock.get(f'{MOCK_URL}{URL_SUFFIX["LIST_INDICATORS"]}', json=url_reputation, status_code=200)
params = {**BASIC_PARAMS, "integrationReliability": "B - Usually reliable"}
args = {"url": "http://dummy.com"}
url_value = "http://dummy.com"
args = {"url": url_value, "exact_match": exact_match}
mocker.patch.object(demisto, "params", return_value=params)
mocker.patch.object(demisto, "command", return_value="url")
mocker.patch.object(demisto, "args", return_value=args)

main()

last_request = requests_mock.last_request
url_value = f'"{url_value}"' if exact_match else url_value
assert last_request.qs["ioc_value"] == [url_value]

assert url_reputation_hr == mock_return.call_args.args[0].get("HumanReadable")
assert url_reputation_context == mock_return.call_args.args[0].get("EntryContext")
assert url_reputation == mock_return.call_args.args[0].get("Contents")
Expand Down Expand Up @@ -1850,7 +1869,8 @@ def test_url_lookup_command_when_invalid_value_is_provided(mocker):


@patch("demistomock.results")
def test_file_lookup_command_success(mock_return, requests_mock, mocker):
@pytest.mark.parametrize("exact_match", [True, False])
def test_file_lookup_command_success(mock_return, requests_mock, mocker, exact_match):
"""
Test case for successful execution of file command through main function
when it returns reputation about given file.
Expand All @@ -1871,12 +1891,18 @@ def test_file_lookup_command_success(mock_return, requests_mock, mocker):
url = f'{MOCK_URL}{URL_SUFFIX["LIST_INDICATORS"]}'
requests_mock.get(url, json=file_reputation, status_code=200)
params = {**BASIC_PARAMS, "integrationReliability": "B - Usually reliable"}
args = {"file": "00000000000000000000000000000001"}
file_value = "00000000000000000000000000000001"
args = {"file": file_value, "exact_match": exact_match}
mocker.patch.object(demisto, "params", return_value=params)
mocker.patch.object(demisto, "command", return_value="file")
mocker.patch.object(demisto, "args", return_value=args)

main()

last_request = requests_mock.last_request
file_value = f'"{file_value}"' if exact_match else file_value
assert last_request.qs["ioc_value"] == [file_value]

assert file_reputation_hr == mock_return.call_args.args[0].get("HumanReadable")
assert file_reputation_context == mock_return.call_args.args[0].get("EntryContext")
assert file_reputation == mock_return.call_args.args[0].get("Contents")
Expand Down
4 changes: 4 additions & 0 deletions Packs/Flashpoint/Integrations/Ignite/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,7 @@ Looks up the "IP" type indicator details. The reputation of the IP address is de
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| ip | A comma-separated list of IP addresses. | Required |
| exact_match | Whether to perform an exact match on the IP address value. Possible values are: True, False. Default is False. | Optional |

#### Context Output

Expand Down Expand Up @@ -2047,6 +2048,7 @@ Looks up the "URL" type indicator details. The reputation of the URL is decided
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| url | A comma-separated list of URLs. | Required |
| exact_match | Whether to perform an exact match on the URL value. Possible values are: True, False. Default is False. | Optional |

#### Context Output

Expand Down Expand Up @@ -2242,6 +2244,7 @@ Looks up the "Domain" type indicator details. The reputation of the domain is de
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| domain | A comma-separated list of domains. | Required |
| exact_match | Whether to perform an exact match on the domain value. Possible values are: True, False. Default is False. | Optional |

#### Context Output

Expand Down Expand Up @@ -2435,6 +2438,7 @@ Looks up the "File" type indicator details. The reputation of the file is decide
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| file | List of files. | Required |
| exact_match | Whether to perform an exact match on the file hash value. Possible values are: True, False. Default is False. | Optional |

#### Context Output

Expand Down
7 changes: 7 additions & 0 deletions Packs/Flashpoint/ReleaseNotes/2_1_5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

#### Integrations

##### Flashpoint Ignite

- Added support for *exact_match* argument in the **domain**, **ip**, **url**, **file** commands.
- Updated the Docker image to: *demisto/python3:3.12.12.6947692*.
2 changes: 1 addition & 1 deletion Packs/Flashpoint/pack_metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "Flashpoint",
"description": "Use the Flashpoint integration to reduce business risk.",
"support": "partner",
"currentVersion": "2.1.4",
"currentVersion": "2.1.5",
"author": "Flashpoint",
"url": "https://flashpoint.my.site.com/helpcenter/s/",
"email": "support@flashpoint-intel.com",
Expand Down
Loading