SymantecICDM

Query the Symantec Endpoint Security Cloud Portal (ICDM).

Data Enrichment & Threat Intelligence · SymantecICDM

Details

IDSymantecICDM
ProviderBroadcom
CategoryData Enrichment & Threat Intelligence
From Version6.10.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

Query the Symantec Endpoint Security Cloud Portal (ICDM).
This integration was integrated and tested with version 1 of SymantecICDM.

Configure Symantec Endpoint Security (ICDM) in Cortex

Parameter Description Required
Source Reliability Reliability of the source providing the intelligence data. True
Server URL (e.g. https://api.sep.securitycloud.symantec.com)   True
Fetch incidents   False
Incident type   False
Maximum number of incidents per fetch   False
API Key   True
First fetch time   False
Trust any certificate (not secure)   False
Use system proxy settings   False
Incidents Fetch Interval   False
Ignore Domains (e.g. domain.local) Comma-separated list of domains that shall be ignored for Urls and (Sub-)Domains reputation lookup False
Ignore Private IPs (e.g. 192.168.0.1)   False

Commands

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

file


Get file reputation for given SHA256.

Base Command

file

Input

Argument Name Description Required
file List of files. Optional

Context Output

Path Type Description
DBotScore.Indicator String The indicator that was tested.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the score.
DBotScore.Score Number The actual score.
DBotScore.Reliability String Reliability of the source providing the intelligence data.
File.SHA256 String The SHA256 hash of the file.

ip


Get ip reputation.

Base Command

ip

Input

Argument Name Description Required
ip List of IPs. Optional

Context Output

Path Type Description
DBotScore.Indicator String The indicator that was tested.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the score.
DBotScore.Score Number The actual score.
DBotScore.Reliability String Reliability of the source providing the intelligence data.
IP.Address String IP address.

url


Get reputation for given url.

Base Command

url

Input

Argument Name Description Required
url List of URLs. Optional

Context Output

Path Type Description
DBotScore.Indicator String The indicator that was tested.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the score.
DBotScore.Score Number The actual score.
DBotScore.Reliability String Reliability of the source providing the intelligence data.
URL.Data String The URL.

domain


Get reputation for given domain.

Base Command

domain

Input

Argument Name Description Required
domain List of domains. Optional

Context Output

Path Type Description
DBotScore.Indicator String The indicator that was tested.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the score.
DBotScore.Score Number The actual score.
DBotScore.Reliability String Reliability of the source providing the intelligence data.
Domain.Name String The domain name.

symantec-protection-file


Get information whether a given file has been blocked by any Symantec technologies.

Base Command

symantec-protection-file

Input

Argument Name Description Required
file Comma-separated list of file Sha256 hashes. Optional

Context Output

Path Type Description
Symantec.Protection.File.file String input file sha256.
Symantec.Protection.File.state.technology String Symantec technology providing protection.
Symantec.Protection.File.state.firstDefsetVersion String The first definition version with protection.
Symantec.Protection.File.state.threatName String The name of the threat the file is detected as.

symantec-protection-network


Get information whether given domain or ip has been blocked by any Symantec technologies.

Base Command

symantec-protection-network

Input

Argument Name Description Required
network Comma-separated list of domains or IPs. Optional

Context Output

Path Type Description
Symantec.Protection.Network.network String input domain or ip.
Symantec.Protection.Network.state.technology String Symantec technology providing protection.
Symantec.Protection.Network.state.firstDefsetVersion String The first definition version with protections.
Symantec.Protection.Network.state.threatName String The name of the threat the domain or is detected as.

symantec-protection-cve


Get returns information whether a given CVE has been blocked by any Symantec technologies.

Base Command

symantec-protection-cve

Input

Argument Name Description Required
cve Comma-separated list of CVEs. Optional

Context Output

Path Type Description
Symantec.Protection.CVE.cve String input CVE.
Symantec.Protection.CVE.state.technology String Symantec technology providing protection.
Symantec.Protection.CVE.state.firstDefsetVersion String The first definition version with protections.
Symantec.Protection.CVE.state.threatName String The name of the threat the domain or is detected as.

Configuration parameters

  • integrationReliability — Source Reliability (required)
  • url — Server URL (e.g. https://api.sep.securitycloud.symantec.com) (required)
  • isFetch — Fetch incidents
  • incidentType — Incident type
  • max_fetch — Maximum number of incidents per fetch
  • credentials — (required)
  • first_fetch — First fetch time
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings
  • incidentFetchInterval — Incidents Fetch Interval
  • ignored_domains — Ignore Domains (e.g. domain.local)
  • ignore_private_ip — Ignore Private IPs (e.g. 192.168.0.1)

Commands (7)

  • domain

    Get reputation for given domain.

  • file

    Get file reputation for given SHA256.

  • ip

    Get ip reputation.

  • symantec-protection-cve

    Get returns information whether a given CVE has been blocked by any Symantec technologies.

  • symantec-protection-file

    Get information whether a given file has been blocked by any Symantec technologies.

  • symantec-protection-network

    Get information whether given domain or ip has been blocked by any Symantec technologies.

  • url

    Get reputation for given url.

"""Symantec Endpoint Security Threat Intel- Unit Tests file

Pytest Unit Tests: all function names must start with "test_"
"""

import json
import pytest
from CommonServerPython import *
from datetime import datetime, timedelta
from freezegun import freeze_time
from SymantecICDM import (
    Client,
    icdm_fetch_incidents_command,
    fetch_incidents_command,
    ensure_max_age,
    file_reputation_command,
    url_reputation_command,
    domain_reputation_command,
    ip_reputation_command,
    ensure_argument,
    is_filtered,
    symantec_protection_file_command,
    symantec_protection_cve_command,
    symantec_protection_network_command,
    get_network_indicator_by_type,
)

BASE_RELIABILITY = DBotScoreReliability.B

FREEZE_TIME = "2026-04-18T03:00:00Z"
DATE_TIME = datetime.strptime(FREEZE_TIME, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc)
AN_HOUR_AGO = DATE_TIME - timedelta(hours=1)
TWO_MONTHS_AGO = DATE_TIME - timedelta(days=60)


def util_load_json(path):
    with open(path, encoding="utf-8") as f:
        return json.loads(f.read())


@freeze_time(FREEZE_TIME)
@pytest.mark.parametrize(
    "value, output",
    [
        (AN_HOUR_AGO, AN_HOUR_AGO),
        (TWO_MONTHS_AGO, DATE_TIME - timedelta(days=29, hours=23, minutes=59)),
    ],
)
def test_ensure_max_age(value: datetime, output: datetime):
    """
    Given:
        - Mocked date
    When:
        - sent to ensure_max_age
    Then:
        - ensure the age matches the expected output
    """
    value = value.replace(second=0, microsecond=0)
    result = ensure_max_age(value)
    result = result.replace(second=0, microsecond=0)
    assert result == output


def test_icdm_fetch_incidents_command(mocker):
    client = Client("", "")
    incidents = util_load_json("test_data/icdm_incidents_without_events.json")
    mocker.patch.object(Client, "_http_request", return_value=incidents)
    result = icdm_fetch_incidents_command(client, 100, datetime(2023, 4, 26, 0, 0, 0, tzinfo=timezone.utc))

    assert result.outputs == incidents.get("incidents")

    expected_hr = (
        "### Symantec Endpoint Security EDR Incidents\n"
        "|ref_incident_uid|type|conclusion|created|modified|\n"
        "|---|---|---|---|---|\n"
        "| 102106 | INCIDENT_UPDATE | Suspicious Activity | 2023-04-26T15:44:19.345+00:00 | 2023-04-26T23:38:48.634+00:00 |\n"
        "| 102109 | INCIDENT_CREATION | Suspicious Activity | 2023-04-26T21:28:00.467+00:00 | 2023-04-26T21:52:51.550+00:00 |\n"
        "| 102110 | INCIDENT_CREATION | Suspicious Activity | 2023-04-26T21:46:10.400+00:00 | 2023-04-26T22:01:58.648+00:00 |\n"
    )

    assert result.readable_output == expected_hr


def test_fetch_incidents_command(mocker):
    client = Client("", "")
    mocker.patch.object(
        Client,
        "_http_request",
        return_value=util_load_json("test_data/icdm_incidents_without_events.json"),
    )

    last_run, incidents = fetch_incidents_command(client, 100, datetime(2023, 4, 26, 0, 0, 0, tzinfo=timezone.utc))
    expected_incidents = util_load_json("test_data/outputs/icdm_incidents_output.json")
    assert last_run == {"last_fetch": 1682545570.4}
    assert incidents == expected_incidents


@pytest.mark.parametrize("response, result", [({"access_token": "YXNhbXBsZWFjY2Vzc3Rva2VudGNvZGU="}, True)])
def test_client_authenticate(response, result, mocker):
    client = Client("", "")
    mocker.patch.object(Client, "_http_request", return_value=response)
    assert client.authenticate() == result
    assert client._session_token == response.get("access_token")


@pytest.mark.parametrize(
    "file, output",
    [
        (
            "eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d",
            {
                "indicator": "eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d",
                "reputation": "BAD",
                "actors": ["Waterbug"],
            },
        )
    ],
)
def test_file_reputation_command(file, output, mocker):
    client = Client("", "")
    mocker.patch.object(
        Client,
        "_http_request",
        return_value=util_load_json("test_data/file_insight_reputation_response.json"),
    )
    response = file_reputation_command(client, {"file": file}, BASE_RELIABILITY)
    assert len(response) == 1
    assert response[0].outputs == output


@pytest.mark.parametrize(
    "url, output",
    [
        (
            "elblogdeloscachanillas.com.mx%2Fs3sy8rq10%2Fophn.png",
            {
                "indicator": "elblogdeloscachanillas.com.mx%2Fs3sy8rq10%2Fophn.png",
                "reputation": "BAD",
                "risk_level": 10,
                "categories": ["Malicious Sources/Malnets"],
                "first_seen": None,
                "last_seen": None,
            },
        )
    ],
)
def test_url_reputation_command(url, output, mocker):
    client = Client("", "")
    mocker.patch.object(
        Client,
        "_http_request",
        return_value=util_load_json("test_data/url_insight_reputation_response.json"),
    )
    response = url_reputation_command(client, {"url": url}, BASE_RELIABILITY)
    assert len(response) == 1
    assert response[0].outputs == output


@pytest.mark.parametrize(
    "domain, output",
    [
        (
            "elblogdeloscachanillas.com.mx",
            {
                "indicator": "elblogdeloscachanillas.com.mx",
                "reputation": "BAD",
                "risk_level": 10,
                "categories": ["Malicious Sources/Malnets"],
                "first_seen": "2019-08-30",
                "last_seen": "2024-01-24",
            },
        )
    ],
)
def test_domain_reputation_command(domain, output, mocker):
    client = Client("", "")
    mocker.patch.object(
        Client,
        "_http_request",
        return_value=util_load_json("test_data/domain_insight_reputation_response.json"),
    )

    response = domain_reputation_command(client, {"domain": domain}, BASE_RELIABILITY)
    assert len(response) == 1
    assert response[0].outputs == output


@pytest.mark.parametrize(
    "ip, output",
    [
        (
            "8.8.8.8",
            {
                "indicator": "8.8.8.8",
                "reputation": "GOOD",
                "risk_level": 2,
                "categories": ["Web Infrastructure"],
                "first_seen": "2023-07-10",
                "last_seen": "2023-12-18",
            },
        )
    ],
)
def test_ip_reputation_command(ip, output, mocker):
    client = Client("", "")
    mocker.patch.object(
        Client,
        "_http_request",
        return_value=util_load_json("test_data/ip_insight_reputation_response.json"),
    )
    response = ip_reputation_command(client, {"ip": ip}, BASE_RELIABILITY)
    assert len(response) == 1
    assert response[0].outputs == output


@pytest.mark.parametrize(
    "file, output",
    [
        (
            "eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d",
            util_load_json("test_data/file_protection_response.json"),
        )
    ],
)
def test_symantec_protection_file_command(file, output, mocker):
    client = Client("", "")
    mocker.patch.object(
        Client,
        "_http_request",
        return_value=util_load_json("test_data/file_protection_response.json"),
    )
    response = symantec_protection_file_command(client, {"file": file})
    assert len(response) == 1
    assert response[0].outputs == output


@pytest.mark.parametrize(
    "network, output",
    [
        (
            "eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d",
            util_load_json("test_data/network_protection_response.json"),
        )
    ],
)
def test_symantec_protection_network_command(network, output, mocker):
    client = Client("", "")
    mocker.patch.object(
        Client,
        "_http_request",
        return_value=util_load_json("test_data/network_protection_response.json"),
    )
    response = symantec_protection_network_command(client, {"network": network})
    assert len(response) == 1
    assert response[0].outputs == output


@pytest.mark.parametrize(
    "cve, output",
    [
        (
            "eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d",
            util_load_json("test_data/cve_protection_response.json"),
        )
    ],
)
def test_symantec_protection_cve_command(cve, output, mocker):
    client = Client("", "")
    mocker.patch.object(
        Client,
        "_http_request",
        return_value=util_load_json("test_data/cve_protection_response.json"),
    )
    response = symantec_protection_cve_command(client, {"cve": cve})
    assert len(response) == 1
    assert response[0].outputs == output


@pytest.mark.parametrize("args, name, output", [({"ip": "8.8.8.8"}, "ip", ["8.8.8.8"])])
def test_ensure_argument(args, name, output):
    assert ensure_argument(args, name) == output


@pytest.mark.parametrize("args, name", [({}, "ip"), ({"ip": ""}, "ip")])
def test_ensure_argument_exception(args, name):
    with pytest.raises(ValueError):
        ensure_argument(args, name)


@pytest.mark.parametrize(
    "value, filters, output",
    [("support.paloaltonetworks.com", ["paloaltonetworks.com"], True)],
)
def test_is_filtered(value: str, filters: list[str], output: bool):
    assert is_filtered(value, filters) == output


@pytest.mark.parametrize(
    "arg_type, indicator, score",
    [
        (
            DBotScoreType.IP,
            "8.8.8.8",
            Common.DBotScore.GOOD,
        ),
        (
            DBotScoreType.URL,
            "https://google.com",
            Common.DBotScore.GOOD,
        ),
        (
            DBotScoreType.DOMAIN,
            "google.com",
            Common.DBotScore.GOOD,
        ),
    ],
)
def test_get_network_indicator_by_type(arg_type: str, indicator: str, score: int):
    dbot_score = Common.DBotScore(
        indicator=indicator,
        indicator_type=arg_type,
        integration_name="INTEGRATION_NAME",
        score=score,
        reliability=DBotScoreReliability.A,
        malicious_description=None,
    )
    assert isinstance(get_network_indicator_by_type(type=arg_type, indicator=indicator, dbot_score=dbot_score), Common.Indicator)


@pytest.mark.parametrize(
    "type, indicator, score",
    [
        (
            "",
            "",
            Common.DBotScore.GOOD,
        )
    ],
)
def test_get_network_indicator_by_type_exception(type: str, indicator: str, score: Common.DBotScore):
    with pytest.raises(DemistoException):
        get_network_indicator_by_type(type, indicator, score)