Pulsedive

Enrich and analyze any domain, URL, or IP. Pivot to search on data points and linked indicators to investigate risky properties.

Data Enrichment & Threat Intelligence · Pulsedive

Details

IDPulsedive
ProviderPulsedive LLC
CategoryData Enrichment & Threat Intelligence
From Version6.0.0
Docker Imagedemisto/python3:3.12.8.3296088
Supported ModulesAgentix XSIAM

README

Enrich and analyze any domain, URL, or IP. Pivot to search on data points and linked indicators to investigate risky properties.
This integration was integrated and tested with version 5.1.15 of Pulsedive

Configure Pulsedive in Cortex

Parameter Description Required
API Key   True
Minimum severity of alerts to fetch   True
Trust any certificate (not secure)   False
Use system proxy settings   False
Fetch indicators   False
Indicator Reputation Indicators from this integration instance will be marked with this reputation False
Source Reliability Reliability of the source providing the intelligence data True
    False
    False
Feed Fetch Interval   False
Bypass exclusion list When selected, the exclusion list is ignored for indicators from this feed. This means that if an indicator from this feed is on the exclusion list, the indicator might still be added to the system. 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.

ip


Return IP information and reputation

Base Command

ip

Input

Argument Name Description Required
ip List of IPs. Required

Context Output

Path Type Description
DBotScore.Indicator String The indicator that was tested.
DBotScore.Score Number The actual score.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the score.
Pulsedive.IP.asn String The autonomous system name for the IP address.
Pulsedive.IP.asn_cidr String The ASN CIDR.
Pulsedive.IP.asn_country_code String The ASN country code.
Pulsedive.IP.asn_date Date The date on which the ASN was assigned.
Pulsedive.IP.asn_description String The ASN description.
Pulsedive.IP.asn_registry String The registry the ASN belongs to.
Pulsedive.IP.entities String Entities associated to the IP.
Pulsedive.IP.ip String The actual IP address.
Pulsedive.IP.network.cidr String Network CIDR for the IP address.
Pulsedive.IP.network.country Unknown The country of the IP address.
Pulsedive.IP.network.end_address String The last IP address of the CIDR.
Pulsedive.IP.network.events.action String The action that happened on the event.
Pulsedive.IP.network.events.actor Unknown The actor that performed the action on the event.
Pulsedive.IP.network.events.timestamp String The timestamp when the event occurred.
Pulsedive.IP.network.handle String The handle of the network.
Pulsedive.IP.network.ip_version String The IP address version.
Pulsedive.IP.network.links String Links associated to the IP address.
Pulsedive.IP.network.name String The name of the network.
Pulsedive.IP.network.notices.description String The description of the notice.
Pulsedive.IP.network.notices.links Unknown Links associated with the notice.
Pulsedive.IP.network.notices.title String Title of the notice.
Pulsedive.IP.network.parent_handle String Handle of the parent network.
Pulsedive.IP.network.raw Unknown Additional raw data for the network.
Pulsedive.IP.network.remarks Unknown Additional remarks for the network.
Pulsedive.IP.network.start_address String The first IP address of the CIDR.
Pulsedive.IP.network.status String Status of the network.
Pulsedive.IP.network.type String The type of the network.
Pulsedive.IP.query String IP address that was queried.
Pulsedive.IP.raw Unknown Additional raw data for the IP address.
Pulsedive.IP.score Number Reputation score from HelloWorld for this IP (0 to 100, where higher is worse).
IP.Address String IP address.
IP.Malicious.Vendor String The vendor reporting the IP address as malicious.
IP.Malicious.Description String A description explaining why the IP address was reported as malicious.
IP.ASN String The autonomous system name for the IP address.

domain


Returns Domain information and reputation.

Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.

Base Command

domain

Input

Argument Name Description Required
domain List of Domains. Required

Context Output

Path Type Description
DBotScore.Indicator String The indicator that was tested.
DBotScore.Score Number The actual score.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the score.
Domain.Name String The domain name.
Domain.Malicious.Vendor String The vendor reporting the domain as malicious.
Domain.Malicious.Description String A description explaining why the domain was reported as malicious.
Domain.Registrant.Name String The name of the registrant.
Domain.Registrant.Country String The country of the registrant.
Domain.Organization String The organization of the domain.
Domain.CreationDate Date The creation date of the domain. Format is ISO8601 (i.e. ‘2020-04-30T10:35:00.000Z’).
Domain.ExpirationDate Date The expiration date of the domain. Format is ISO8601 (i.e. ‘2020-04-30T10:35:00.000Z’).
Domain.UpdatedDate Date The date when the domain was last updated. Format is ISO8601 (i.e. ‘2020-04-30T10:35:00.000Z’).
Domain.NameServers String Name servers of the domain.
Domain.WHOIS.NameServers String A CSV string of name servers, for example ‘ns1.bla.com, ns2.bla.com’.
Domain.WHOIS.CreationDate Date The creation date of the domain. Format is ISO8601 (i.e. ‘2020-04-30T10:35:00.000Z’).
Domain.WHOIS.UpdatedDate Date The date when the domain was last updated. Format is ISO8601 (i.e. ‘2020-04-30T10:35:00.000Z’).
Domain.WHOIS.ExpirationDate Date The expiration date of the domain.
Domain.WHOIS.Registrar.Name String The name of the registrar, for example ‘GoDaddy’
IP.ASN String The autonomous system name for the IP address.
Pulsedive.Domain.address String Domain admin address.
Pulsedive.Domain.city String Domain admin city.
Pulsedive.Domain.country String Domain admin country.
Pulsedive.Domain.creation_date Date Domain creation date. Format is ISO8601.
Pulsedive.Domain.dnssec String DNSSEC status.
Pulsedive.Domain.domain String The domain name.
Pulsedive.Domain.domain_name String Domain name options.
Pulsedive.Domain.emails String Contact emails.
Pulsedive.Domain.expiration_date Date Expiration date. Format is ISO8601.
Pulsedive.Domain.name String Domain admin name.
Pulsedive.Domain.name_servers String Name server.
Pulsedive.Domain.org String Domain organization.
Pulsedive.Domain.referral_url Unknown Referral URL.
Pulsedive.Domain.registrar String Domain registrar.
Pulsedive.Domain.score Number Reputation score from HelloWorld for this domain (0 to 100, where higher is worse).
Pulsedive.Domain.state String Domain admin state.
Pulsedive.Domain.status String Domain status.
Pulsedive.Domain.updated_date Date Updated date. Format is ISO8601.
Pulsedive.Domain.whois_server String WHOIS server.
Pulsedive.Domain.zipcode Unknown Domain admin zipcode.

url


Returns URL information and reputation.

Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.

Base Command

url

Input

Argument Name Description Required
url List of Urls. Required

Context Output

Path Type Description
URL.Data string The URL.
URL.Malicious.Vendor string The vendor reporting the URL as malicious.
URL.Malicious.Description string A description of the malicious URL.
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.
URL.DetectionEngines string The total number of engines that checked the indicator.
URL.PositiveDetections string The number of engines that positively detected the indicator as malicious.

pulsedive-scan


Scan an indicator (IP/URL/Domain)

Base Command

pulsedive-scan

Input

Argument Name Description Required
value The value to scan. Required
scan_type You can choose between passive and active scanning. Passive scans fetch data without reaching out directly to the indicator, including performing WHOIS and DNS requests. Active scans are more noisy; we’ll do a quick port scan and reach out to the indicator with a web browser. Possible values are: active, passiv. Default is active. Optional

Context Output

Path Type Description
Pulsedive.Scan.qid Number QID of the scan.
Pulsedive.Scan.value string The value which was scanned.
Pulsedive.Scan.success string The success message.

pulsedive-scan-result


Retrieve the Result

Base Command

pulsedive-scan-result

Input

Argument Name Description Required
qid QID recieved from scan command. Required

Context Output

Path Type Description
DBotScore.Indicator String The indicator that was tested.
DBotScore.Score Number The actual score.
DBotScore.Type String The indicator type.
DBotScore.Vendor unknown The vendor used to calculate the score.
Pulsedive.ScanResult Unknown Complete data returned from the scan.
Domain.Name String The domain name.
Domain.DomainStatus String The status of the domain.
Domain.NameServers String Name servers of the domain.
Domain.WHOIS.NameServers String A CSV string of name servers, for example ‘ns1.bla.com, ns2.bla.com’.
Pulsedive.Scan.success string The success message.
IP.Address String IP address.
IP.Geo.Country String The country in which the IP address is located.
IP.Port String Ports that are associated with the IP.
IP.ASN String The autonomous system name for the URL, for example: ‘AS8948’.
URL.DATA String The URL.

Configuration parameters

  • apikey — API Key (required)
  • min_severity — Minimum severity of alerts to fetch (required)
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings
  • feed — Fetch indicators
  • feedReputation — Indicator Reputation
  • feedReliability — Source Reliability (required)
  • feedExpirationPolicy
  • feedExpirationInterval
  • feedFetchInterval — Feed Fetch Interval
  • feedBypassExclusionList — Bypass exclusion list

Commands (5)

  • domain

    Returns Domain information and reputation.

  • ip

    Return IP information and reputation

  • pulsedive-scan

    Scan an indicator (IP/URL/Domain)

  • pulsedive-scan-result

    Retrieve the Result

  • url

    Returns URL information and reputation.

import traceback

import dateparser
import demistomock as demisto  # noqa: F401
import requests
import urllib3
from CommonServerPython import *  # noqa: F401

urllib3.disable_warnings()


""" CONSTANTS """


DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
MAX_INCIDENTS_TO_FETCH = 50
HELLOWORLD_SEVERITIES = ["Low", "Medium", "High", "Critical"]

""" CLIENT CLASS """


class Client(BaseClient):
    def test_connect(self, api_key):
        return self._http_request(method="GET", url_suffix="/info.php?", params={"indicator": "pulsedive.com", "key": api_key})

    def get_ip_reputation(self, ip: str, api_key) -> dict[str, Any]:
        return self._http_request(method="GET", url_suffix="/info.php?", params={"indicator": ip, "pretty": "1", "key": api_key})

    def get_domain_reputation(self, domain: str, api_key) -> dict[str, Any]:
        return self._http_request(
            method="GET", url_suffix="/info.php?", params={"indicator": domain, "pretty": "1", "key": api_key}
        )

    def get_url_reputation(self, url: str, api_key) -> dict[str, Any]:
        return self._http_request(method="GET", url_suffix="/info.php?", params={"indicator": url, "pretty": "1", "key": api_key})

    def post_value_scan(self, value: str, probe: str, api_key) -> dict[str, Any]:
        return self._http_request(
            method="POST", url_suffix="/analyze.php", params={"value": value, "probe": probe, "pretty": "1", "key": api_key}
        )

    def get_value_scan(self, qid: str, api_key) -> dict[str, Any]:
        return self._http_request(method="GET", url_suffix="/analyze.php?", params={"qid": qid, "pretty": "1", "key": api_key})


""" HELPER FUNCTIONS """


def parse_domain_date(domain_date: list[str] | str, date_format: str = "%Y-%m-%dT%H:%M:%S.000Z") -> str | None:
    """Converts whois date format to an ISO8601 string
    Converts the HelloWorld domain WHOIS date (YYYY-mm-dd HH:MM:SS) format
    in a datetime. If a list is returned with multiple elements, takes only
    the first one.
    :type domain_date: ``Union[List[str],str]``
    :param severity:
        a string or list of strings with the format 'YYYY-mm-DD HH:MM:SS'
    :return: Parsed time in ISO8601 format
    :rtype: ``Optional[str]``
    """

    if isinstance(domain_date, str):
        # if str parse the value
        if _date := dateparser.parse(domain_date).strftime(date_format):  # type: ignore[union-attr]
            return _date
        return None
    elif isinstance(domain_date, list) and len(domain_date) > 0 and isinstance(domain_date[0], str):
        # if list with at least one element, parse the first element
        return dateparser.parse(domain_date[0]).strftime(date_format)  # type: ignore[union-attr]
    # in any other case return nothing
    return None


def convert_to_xsoar_severity(pulsedive_severity) -> int:
    if pulsedive_severity == "unknown" or pulsedive_severity == "none":
        xsoar_severity = Common.DBotScore.NONE  # unknown
    elif pulsedive_severity == "high":
        xsoar_severity = Common.DBotScore.SUSPICIOUS  # suspicious
    elif pulsedive_severity == "critical":
        xsoar_severity = Common.DBotScore.BAD  # bad
    else:
        xsoar_severity = Common.DBotScore.GOOD  # good
    return xsoar_severity


""" COMMAND FUNCTIONS """


def test_module(client: Client, api_key) -> str:
    """Tests API connectivity and authentication"""

    try:
        client.test_connect(api_key)
    except DemistoException:
        return "Could not connect to Pulsedive"
    return "ok"


def ip_reputation_command(client: Client, args: dict[str, Any], api_key) -> list[CommandResults]:
    ips = argToList(args.get("ip"))
    if len(ips) == 0:
        raise ValueError("IP(s) not specified")

    command_results: list[CommandResults] = []
    for ip in ips:
        try:
            ip_data = client.get_ip_reputation(ip, api_key)
            indicator_ip = ip_data["indicator"]
            reputation = ip_data["risk"]
            score = convert_to_xsoar_severity(reputation)

            # Create the DBotScore structure first using the Common.DBotScore class.
            dbot_score = Common.DBotScore(
                indicator=indicator_ip,
                indicator_type=DBotScoreType.IP,
                integration_name="Pulsedive",
                score=score,
                malicious_description=f"Pulsedive returned reputation {reputation}",
            )

            # Create the IP Standard Context structure using Common.IP and add
            # dbot_score to it.
            ip_standard_context = Common.IP(ip=indicator_ip, dbot_score=dbot_score)

            ip_data.pop("objects", None)
            ip_data.pop("nir", None)
            command_results.append(
                CommandResults(
                    readable_output=tableToMarkdown("IP Details:", ip_data),
                    outputs_prefix="Pulsedive.IP",
                    outputs_key_field="indicator",
                    outputs=ip_data,
                    indicator=ip_standard_context,
                )
            )
        except DemistoException:
            # Create the DBotScore structure first using the Common.DBotScore class.
            dbot_score = Common.DBotScore(
                indicator=ip,
                indicator_type=DBotScoreType.IP,
                integration_name="Pulsedive",
                score=Common.DBotScore.NONE,
                malicious_description="Pulsedive returned reputation None",
            )

            # Create the IP Standard Context structure using Common.IP and add
            # dbot_score to it.
            ip_standard_context = Common.IP(ip=ip, dbot_score=dbot_score)

            command_results.append(
                CommandResults(
                    readable_output=str(ip) + " not found in indicator data",
                    outputs_prefix="Pulsedive.IP",
                    outputs_key_field="indicator",
                    indicator=ip_standard_context,
                )
            )

    return command_results


def domain_reputation_command(client: Client, args: dict[str, Any], api_key) -> list[CommandResults]:
    domains = argToList(args.get("domain"))
    if len(domains) == 0:
        raise ValueError("domain(s) not specified")

    command_results: list[CommandResults] = []
    for domain in domains:
        try:
            domain_data = client.get_domain_reputation(domain, api_key)
            indicator_domain = domain_data["indicator"]
            reputation = domain_data["risk"]
            score = convert_to_xsoar_severity(reputation)

            if "creation_date" in domain_data:
                domain_data["creation_date"] = parse_domain_date(domain_data["creation_date"])
            if "expiration_date" in domain_data:
                domain_data["expiration_date"] = parse_domain_date(domain_data["expiration_date"])
            if "updated_date" in domain_data:
                domain_data["updated_date"] = parse_domain_date(domain_data["updated_date"])

            dbot_score = Common.DBotScore(
                indicator=indicator_domain,
                integration_name="Pulsedive",
                indicator_type=DBotScoreType.DOMAIN,
                score=score,
                malicious_description="Pulsedive returned reputation {reputation}",
            )

            domain_standard_context = Common.Domain(domain=indicator_domain, dbot_score=dbot_score)

            command_results.append(
                CommandResults(
                    readable_output=tableToMarkdown("Domain Details:", domain_data),
                    outputs_prefix="Pulsedive.Domain",
                    outputs_key_field="indicator",
                    outputs=domain_data,
                    indicator=domain_standard_context,
                )
            )
        except DemistoException:
            # Create the DBotScore structure first using the Common.DBotScore class.
            dbot_score = Common.DBotScore(
                indicator=domain,
                indicator_type=DBotScoreType.DOMAIN,
                integration_name="Pulsedive",
                score=Common.DBotScore.NONE,
                malicious_description="Pulsedive returned reputation None",
            )

            domain_standard_context = Common.Domain(domain=domain, dbot_score=dbot_score)

            command_results.append(
                CommandResults(
                    readable_output=str(domain) + " not found in indicator data",
                    outputs_prefix="Pulsedive.Domain",
                    outputs_key_field="indicator",
                    indicator=domain_standard_context,
                )
            )

    return command_results


def url_reputation_command(client: Client, args: dict[str, Any], api_key) -> list[CommandResults]:
    urls = argToList(args.get("url"))
    if len(urls) == 0:
        raise ValueError("URL(s) not specified")

    command_results: list[CommandResults] = []
    for url in urls:
        try:
            url_data = client.get_url_reputation(url, api_key)
            indicator_url = url_data["indicator"]
            reputation = url_data["risk"]
            score = convert_to_xsoar_severity(reputation)

            dbot_score = Common.DBotScore(
                indicator=str(indicator_url),
                indicator_type=DBotScoreType.URL,
                integration_name="Pulsedive",
                score=score,
                malicious_description=f"Pulsedive returned reputation {reputation}",
            )

            url_standard_context = Common.URL(url=indicator_url, dbot_score=dbot_score)

            url_data.pop("objects", None)
            url_data.pop("nir", None)
            command_results.append(
                CommandResults(
                    readable_output=tableToMarkdown("URL Details:", url_data),
                    outputs_prefix="Pulsedive.URL",
                    outputs_key_field="indicator",
                    outputs=url_data,
                    indicator=url_standard_context,
                )
            )
        except DemistoException:
            # Create the DBotScore structure first using the Common.DBotScore class.
            dbot_score = Common.DBotScore(
                indicator=str(url),
                indicator_type=DBotScoreType.URL,
                integration_name="Pulsedive",
                score=Common.DBotScore.NONE,
                malicious_description="Pulsedive returned reputation None",
            )

            url_standard_context = Common.URL(url=str(url), dbot_score=dbot_score)

            command_results.append(
                CommandResults(
                    readable_output=str(url) + " not found in indicator data",
                    outputs_prefix="Pulsedive.URL",
                    outputs_key_field="indicator",
                    indicator=url_standard_context,
                )
            )

    return command_results


def scan_value_command(client: Client, args: dict[str, Any], api_key) -> list[CommandResults]:
    values = argToList(args.get("value"))
    if len(values) == 0:
        raise ValueError("Value(s) not specified")

    scan_type_value = "0" if args.get("scan_type") == "passiv" else "1"

    command_results: list[CommandResults] = []
    for value in values:
        try:
            value_data = client.post_value_scan(value, scan_type_value, api_key)
            value_data.update({"value": value})
            command_results.append(
                CommandResults(
                    readable_output=tableToMarkdown("Value Details:", value_data),
                    outputs_prefix="Pulsedive.Scan",
                    outputs_key_field="value",
                    outputs=value_data,
                )
            )
        except DemistoException:
            raise DemistoException(
                f"Failed to execute {demisto.command()} command. Error: Problem submitting the data for scanning"
            )

    return command_results


def scan_result_command(client: Client, args: dict[str, Any], api_key) -> list[CommandResults]:
    """
    Scan result command
    """
    qids = argToList(args.get("qid"))
    if len(qids) == 0:
        raise ValueError("QID(s) not specified")

    command_results: list[CommandResults] = []
    for qid in qids:
        try:
            qid_data = client.get_value_scan(qid, api_key)
            if qid_data.get("data"):
                qid_data.update({"qid": qid, "indicator": qid_data["data"]["indicator"]})
                if qid_data["data"]["type"] == "url" or qid_data["data"]["type"] == "domain":
                    if "dom" in qid_data["data"]["properties"]:
                        screenshot = requests.get(qid_data["data"]["properties"]["dom"]["screenshot"])
                        screenshot_file = fileResult(
                            qid_data["data"]["properties"]["dom"]["screenshot"],
                            screenshot.content,
                            file_type=EntryType.ENTRY_INFO_FILE,
                        )
                        screenshot_file["Type"] = entryTypes["image"]
                        demisto.results(screenshot_file)
                    else:
                        demisto.results("No screenshot available")
                reputation = qid_data["data"]["risk"]
                score = convert_to_xsoar_severity(reputation)
                if qid_data["data"]["type"] == "url":
                    dbot_score = Common.DBotScore(
                        indicator=qid_data["data"]["indicator"],
                        indicator_type=DBotScoreType.URL,
                        integration_name="Pulsedive",
                        score=score,
                    )

                    url_indicator = Common.URL(url=qid_data["data"]["indicator"], dbot_score=dbot_score)

                    command_results.append(
                        CommandResults(
                            readable_output=tableToMarkdown(
                                "Value Details:", qid_data, headers=("indicator", "qid", "status", "success")
                            ),
                            outputs_prefix="Pulsedive.ScanResult",
                            outputs_key_field="qid",
                            outputs=qid_data["data"],
                            indicator=url_indicator,
                        )
                    )

                if qid_data["data"]["type"] == "ip":
                    dbot_score = Common.DBotScore(
                        indicator=qid_data["data"]["indicator"],
                        indicator_type=DBotScoreType.IP,
                        integration_name="Pulsedive",
                        score=score,
                    )

                    if "geo" in qid_data["data"]["properties"]:
                        ip_indicator = Common.IP(
                            ip=qid_data["data"]["indicator"],
                            asn=qid_data["data"]["properties"]["geo"].get("asn"),
                            geo_country=qid_data["data"]["properties"]["geo"].get("country"),
                            port=qid_data.get("data", {}).get("attributes", {}).get("port")
                            if qid_data["data"]["attributes"] != []
                            else None,
                            dbot_score=dbot_score,
                        )
                    else:
                        ip_indicator = Common.IP(ip=qid_data["data"]["indicator"], dbot_score=dbot_score)

                    command_results.append(
                        CommandResults(
                            readable_output=tableToMarkdown(
                                "Value Details:", qid_data, headers=("indicator", "qid", "status", "success")
                            ),
                            outputs_prefix="Pulsedive.ScanResult",
                            outputs_key_field="qid",
                            outputs=qid_data["data"],
                            indicator=ip_indicator,
                        )
                    )

                if qid_data["data"]["type"] == "domain":
                    dbot_score = Common.DBotScore(
                        indicator=qid_data["data"]["indicator"],
                        indicator_type=DBotScoreType.DOMAIN,
                        integration_name="Pulsedive",
                        score=score,
                    )

                    if "whois" in qid_data["data"]["properties"]:
                        domain_indicator = Common.Domain(
                            domain=qid_data["data"]["indicator"],
                            domain_status=qid_data["data"]["properties"]["whois"].get("status"),
                            name_servers=qid_data["data"]["properties"]["whois"].get("nserver"),
                            dbot_score=dbot_score,
                        )
                    else:
                        domain_indicator = Common.Domain(domain=qid_data["data"]["indicator"], dbot_score=dbot_score)

                    command_results.append(
                        CommandResults(
                            readable_output=tableToMarkdown(
                                "Value Details:", qid_data, headers=("indicator", "qid", "status", "success")
                            ),
                            outputs_prefix="Pulsedive.ScanResult",
                            outputs_key_field="qid",
                            outputs=qid_data["data"],
                            indicator=domain_indicator,
                        )
                    )

            else:
                command_results.append(
                    CommandResults(
                        readable_output=tableToMarkdown("Value Details:", qid_data),
                        outputs_prefix="Pulsedive.ScanResult",
                        outputs_key_field="qid",
                        outputs=qid_data,
                    )
                )
        except DemistoException:
            return_error(f"Failed to execute {demisto.command()} command. Error: Problem with processing the scan results")

    return command_results


""" MAIN FUNCTION """


def main() -> None:
    api_key = demisto.params().get("apikey")
    base_url = "https://www.pulsedive.com/api"
    verify_certificate = not demisto.params().get("insecure", False)
    proxy = demisto.params().get("proxy", False)
    headers = {"User-Agent": "XSOAR - Integration"}

    try:
        client = Client(base_url=base_url, verify=verify_certificate, proxy=proxy, headers=headers)

        if demisto.command() == "test-module":
            # This is the call made when pressing the integration Test button.
            return_results(test_module(client, api_key))

        elif demisto.command() == "ip":
            return_results(ip_reputation_command(client, demisto.args(), api_key))

        elif demisto.command() == "domain":
            return_results(domain_reputation_command(client, demisto.args(), api_key))

        elif demisto.command() == "url":
            return_results(url_reputation_command(client, demisto.args(), api_key))

        elif demisto.command() == "pulsedive-scan":
            return_results(scan_value_command(client, demisto.args(), api_key))

        elif demisto.command() == "pulsedive-scan-result":
            return_results(scan_result_command(client, demisto.args(), api_key))

    # Log exceptions and return errors
    except Exception as e:
        demisto.error(traceback.format_exc())  # print the traceback
        return_error(f"Failed to execute {demisto.command()} command.\nError:\n{e!s}")


""" ENTRY POINT """


if __name__ in ("__main__", "__builtin__", "builtins"):
    main()