DomainToolsIrisDetect

DomainTools is an essential component in the security stack of mature enterprises and performance-driven security teams.

Data Enrichment & Threat Intelligence · DomainTools Iris Detect

Details

IDDomainToolsIrisDetect
ProviderDomainTools
CategoryData Enrichment & Threat Intelligence
From Version6.8.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

DomainTools Iris Detect

Threat Actors Move Fast. Detect Helps You Move Faster

Iris Detect is an Internet infrastructure detection, monitoring, and enforcement tool built on the industry’s fastest and broadest domain discovery engine and the largest databases of domain data. Capturing key data on new domains and risk-scoring them within minutes of discovery, Detect is a game-changer for brand managers, digital risk and fraud prevention teams, and network defenders.

Key Benefits

Rapid Discovery of Infringing Domains Continuous Monitoring of Evolving Infrastructure Enforcement Actions for Dangerous Domains

Fastest New Domain Discovery

Iris Detect employs the most sophisticated and extensive new-domain discovery capabilities, across all TLDs globally. Domains are enriched with preliminary Whois, DNS, and Risk Score data. The Iris Detect for Cortex XSOAR integration can create incidents as frequently as hourly, incidents containing mapped indicators of newly-discovered domains matching the monitored keywords.

Watch Suspicious Domains for Changes

Through ad-hoc War-Room commands or on the incidents directly, domains of interest may be added to Iris Detect’s Watchlist, which triggers automatic daily updates, looking for hosting infrastructure or webpage changes. These changes can be consumed as their own incidents or sent to a separate workflow, giving you the ability to track evolving threat campaigns, classify, and identify which domains are most likely to do harm.

Enable Effective Enforcement

Merely knowing about malicious infrastructure is not enough. Iris Detect offers impactful enforcement options: Block flagged domains from incidents directly or using ad-hoc War-Room commands. Additionally, blocked domains can appear on their own feed, enabling you to take scripted enforcement actions in your security controls. Take action by sending domains to Google Phishing Protection, which can block them in Chrome, Firefox, and Safari, among other browsers.

Configure DomainTools Iris Detect on Cortex XSOAR

  1. Navigate to Settings > Integrations > Servers & Services.
  2. Search for DomainTools Iris Detect.
  3. Click Add instance to create and configure a new integration instance.

    Parameter Description Required
    DomainTools API Username DomainTools API Username True
    DomainTools API Key DomainTools API Key to use for authentication True
    Enabled on New Domains Monitors the Iris Detect endpoint for newly discovered domains for active monitors in an account. This is the most commonly used option. If selected, each pull will create a new incident every time the enrichment is run, with the new domains attached as indicators to the incident. Whois and DNS information is preserved in comments. False
    Enabled on Changed Domains Monitors the Iris Detect endpoint for recent changes to domains added to the watchlist. This is useful for monitoring changes to infrastructure after a domain has been triaged from the “new” endpoint or within the Iris Detect UI. If selected, each pull will create a new incident every time the enrichment is run, with the new domains attached as indicators to the incident. Whois and DNS information is preserved in comments. False
    Enabled on Blocked Domains Monitors the Iris Detect endpoint for additions to domains added to the blocklist. Additions can be made via this app or the Iris Detect UI. This is useful for teams wishing to route triage domains to firewall software for blocking. If selected, each pull will create a new incident every time the enrichment is run, with the new domains attached as indicators to the incident. Whois and DNS information is preserved in comments. False
    Risk score Ranges Optionally specify a risk score range to triage higher risk indicators to different routing. A higher number indicates higher confidence a domain is likely to be used for malicious purposes. False
    Include Domain Data Includes DNS and whois data in the response False
    First fetch timestamp For the first time the enrichment is run, specify how far back should it pull indicators. First Fetch timestamp, Default is 3 days. The maximum time range is 30 days. False
    Trust any certificate (not secure) Trust any certificate (not secure) False
    Use system proxy settings Use system proxy settings False
    Incident type Optionally specify an incident type for incidents created by this integration to work with specific playbooks False
    Fetch incidents This is a required field by XSOAR and should be set to 3, one for each possible feed type: new, changed, blocked. False
  4. To ensure that fetch incidents works:
    1. Select the Fetches incidents radio button.
    2. Select DomainTools Iris Detect - Classifier from classifier drop-down.
    3. Select DomainTools Iris Detect - Incoming Mapper from mapper drop-down.
    4. Select Create Incidents and Import Indicators from Enabled on New Domains drop-down.
    5. Select Create Incidents and Import Indicators from Enabled on Changed Domains drop-down.
    6. Select Create Incidents and Import Indicators from Enabled on Blocked Domains drop-down.
  5. Click Test to validate the URLs, token, and connection.

Commands

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

domaintools-iris-detect-escalate-domains


Reports a domain to Google’s Safe Browsing API. After approval, their block list is picked up by Chrome and most modern browsers.

Base Command

domaintools-iris-detect-escalate-domains

Input

Argument Name Description Required
watchlist_domain_ids List of Iris Detect domain IDs to escalate. The domain ID can be found using ‘domaintools-iris-detect-get-new-domains’ command. Required

Context Output

Path Type Description
DomainToolsIrisDetect.EscalatedDomain.watchlist_domain_id String The blocked domain ID.
DomainToolsIrisDetect.EscalatedDomain.escalation_type String The escalation type.
DomainToolsIrisDetect.EscalatedDomain.id String The ID.
DomainToolsIrisDetect.EscalatedDomain.created_date String The date and time when the domain was created.
DomainToolsIrisDetect.EscalatedDomain.updated_date String The date and time when the domain was updated.
DomainToolsIrisDetect.EscalatedDomain.created_by String The email address of the person who created the escalated entry.

Command example

!domaintools-iris-detect-escalate-domains watchlist_domain_ids="ba476NwNJW"

Context Example

{
    "DomainToolsIrisDetect": {
        "EscalatedDomain": [
            {
                "dt_created_by": "user@example.com",
                "dt_created_date_result": "2023-06-18T07:09:56.638704+00:00",
                "dt_escalation_type": "google_safe",
                "dt_id": "LpbmA0lboB",
                "dt_updated_date": "2023-06-18T07:09:56.638704+00:00",
                "dt_watchlist_domain_id": "ba476NwNJW"
            }
        ]
    }
}

Human Readable Output

Escalated Domains

dt_created_by dt_created_date_result dt_escalation_type dt_id dt_updated_date dt_watchlist_domain_id
user@example.com 2023-06-18T07:09:56.638704+00:00 google_safe LpbmA0lboB 2023-06-18T07:09:56.638704+00:00 ba476NwNJW

domaintools-iris-detect-blocklist-domains


Mark a given domain as blocked, which allows a script against the Iris Detect API to pass these domains on to other teams or security controls within your organization to block them in email, web, or other filtering controls.

Base Command

domaintools-iris-detect-blocklist-domains

Input

Argument Name Description Required
watchlist_domain_ids List of Iris Detect domain IDs to escalate. The domain ID can be found using ‘domaintools-iris-detect-get-new-domains, domaintools-iris-detect-get-watched-domains’ commands. Required

Context Output

Path Type Description
DomainToolsIrisDetect.BlockedDomain.watchlist_domain_id String The blocked domain ID.
DomainToolsIrisDetect.BlockedDomain.escalation_type String The escalation type.
DomainToolsIrisDetect.BlockedDomain.id String The ID.
DomainToolsIrisDetect.BlockedDomain.created_date String The date and time when the domain was created.
DomainToolsIrisDetect.BlockedDomain.updated_date String The date and time when the domain was updated.
DomainToolsIrisDetect.BlockedDomain.created_by String The email address of the person who created the blocked entry.

Command example

!domaintools-iris-detect-blocklist-domains watchlist_domain_ids="7WbwkN9wGa"

Context Example

{
    "DomainToolsIrisDetect": {
        "BlockedDomain": [
            {
                "dt_created_by": "user@example.com",
                "dt_created_date_result": "2023-06-18T07:09:48.626367+00:00",
                "dt_escalation_type": "blocked",
                "dt_id": "qabz2ekbP1",
                "dt_updated_date": "2023-06-18T07:09:48.626367+00:00",
                "dt_watchlist_domain_id": "7WbwkN9wGa"
            }
        ]
    }
}

Human Readable Output

Blocked Domains

dt_created_by dt_created_date_result dt_escalation_type dt_id dt_updated_date dt_watchlist_domain_id
user@example.com 2023-06-18T07:09:48.626367+00:00 blocked qabz2ekbP1 2023-06-18T07:09:48.626367+00:00 7WbwkN9wGa

domaintools-iris-detect-watch-domains


Mark a given domain as watched, which will trigger more frequent scanning by DomainTools automation. Changes to watched domains can trigger incidents if enabled, or manually queried via the domaintools-iris-detect-get-watched-domains command.

Base Command

domaintools-iris-detect-watch-domains

Input

Argument Name Description Required
watchlist_domain_ids List of Iris Detect domain IDs to escalate. The domain ID can be found using ‘domaintools-iris-detect-get-new-domains’ command. Required

Context Output

Path Type Description
DomainToolsIrisDetect.WatchedDomain.state String Indicates that the domain is watched.
DomainToolsIrisDetect.WatchedDomain.domain String The domain name.
DomainToolsIrisDetect.WatchedDomain.discovered_date String The date and time when the domain was discovered (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.WatchedDomain.changed_date String The date and time when the domain information was last changed (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.WatchedDomain.id String The domain ID.
DomainToolsIrisDetect.WatchedDomain.assigned_by String The email address of the person who assigned the domain to the watchlist.
DomainToolsIrisDetect.WatchedDomain.assigned_date String The date and time when the domain was assigned to the watchlist (e.g.,”2023-04-20T13:13:23.000000+00:00”).

Command example

!domaintools-iris-detect-watch-domains watchlist_domain_ids="Ya2q68ldnW"

Context Example

{
    "DomainToolsIrisDetect": {
        "WatchedDomain": [
            {
                "dt_changed_date": "2023-06-18T02:18:06.000000+00:00",
                "dt_discovered_date": "2023-06-18T02:08:14.821000+00:00",
                "dt_domain": "suspicious-domain",
                "dt_domain_id": "Ya2q68ldnW",
                "dt_state": "watched"
            }
        ]
    }
}

Human Readable Output

Watched Domains

dt_changed_date dt_discovered_date dt_domain dt_domain_id dt_state
2023-06-18T02:18:06.000000+00:00 2023-06-18T02:08:14.821000+00:00 suspicious-domain Ya2q68ldnW watched

domaintools-iris-detect-ignore-domains


Ignore a given domain, removing it from new and block lists, if applicable.

Base Command

domaintools-iris-detect-ignore-domains

Input

Argument Name Description Required
watchlist_domain_ids List of Iris Detect domain IDs to escalate. The domain ID can be found using ‘domaintools-iris-detect-get-new-domains, domaintools-iris-detect-get-watched-domains’ command. Required

Context Output

Path Type Description
DomainToolsIrisDetect.IgnoredDomain.state String Indicates that the domain is ignored.
DomainToolsIrisDetect.IgnoredDomain.domain String The domain name.
DomainToolsIrisDetect.IgnoredDomain.discovered_date String The date and time when the domain was discovered (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.IgnoredDomain.changed_date String The date and time when the domain information was last changed (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.IgnoredDomain.id String The domain ID.
DomainToolsIrisDetect.IgnoredDomain.assigned_by String The email address of the person who assigned the domain to the watchlist.
DomainToolsIrisDetect.IgnoredDomain.assigned_date String The date and time when the domain was assigned to the watchlist (e.g.,”2023-04-20T13:13:23.000000+00:00”).

Command example

!domaintools-iris-detect-ignore-domains watchlist_domain_ids="XEmKQoLBPW"

Context Example

{
    "DomainToolsIrisDetect": {
        "IgnoredDomain": [
            {
                "dt_changed_date": "2023-06-18T03:21:47.000000+00:00",
                "dt_discovered_date": "2023-06-18T02:44:42.448000+00:00",
                "dt_domain": "benign-domain.com",
                "dt_domain_id": "XEmKQoLBPW",
                "dt_state": "ignored"
            }
        ]
    }
}

Human Readable Output

Ignored Domains

dt_changed_date dt_discovered_date dt_domain dt_domain_id dt_state
2023-06-18T03:21:47.000000+00:00 2023-06-18T02:44:42.448000+00:00 benign-domain.com XEmKQoLBPW ignored

domaintools-iris-detect-get-monitors-list


This command allows users to retrieve the list of monitored terms and respective IDs associated with your organization’s Iris Detect account. New terms can only be set up and configured directly within the Iris Detect UI (https://iris.domaintools.com/detect/). The results are limited to 100 monitors if include_counts is True, or 500 otherwise.

Base Command

domaintools-iris-detect-get-monitors-list

Input

Argument Name Description Required
datetime_counts_since ISO 8601 datetime format: default None. Conditionally required if the include_counts parameter is set to True. for example 2022-05-18T12:19:51.685496. Required
include_counts Includes counts for each monitor for new, watched, changed, and escalated domains. Possible values are: True, False. Optional
sort Sort order for monitor list. Valid values are an ordered list of the following: [“term”, “created_date”, “domain_counts_changed”, “domain_counts_discovered”]. Optional
order Sort order “asc” or “desc”. Optional

Context Output

Path Type Description
DomainToolsIrisDetect.Monitor.term String The keyword being monitored.
DomainToolsIrisDetect.Monitor.match_substring_variations Boolean A boolean indicating whether substring variations of the term should be matched.
DomainToolsIrisDetect.Monitor.nameserver_exclusions Unknown An array for nameserver exclusions.
DomainToolsIrisDetect.Monitor.text_exclusions unknown An array for text exclusions.
DomainToolsIrisDetect.Monitor.id String A unique identifier for the monitor entry.
DomainToolsIrisDetect.Monitor.created_date String The timestamp when the monitor entry was created.
DomainToolsIrisDetect.Monitor.updated_date String The timestamp when the monitor entry was last updated.
DomainToolsIrisDetect.Monitor.state String The state of the monitor entry.
DomainToolsIrisDetect.Monitor.status String The status of the monitor entry.
DomainToolsIrisDetect.Monitor.created_by String The email address of the person who created the monitor entry..

Command example

!domaintools-iris-detect-get-monitors-list datetime_counts_since="2022-01-01"

Context Example

{
  "DomainToolsIrisDetect": {
    "Monitor": [
      {
        "created_by": "user@example.com",
        "created_date": "2022-09-20T06:01:56.760955+00:00",
        "id": "QEMba8wmXo",
        "match_substring_variations": false,
        "nameserver_exclusions": [],
        "state": "active",
        "status": "completed",
        "term": "monitored_term1",
        "text_exclusions": [],
        "updated_date": "2022-09-20T06:02:33.358799+00:00"
      },
      {
        "created_by": "user@example.com",
        "created_date": "2022-09-16T22:29:20.567614+00:00",
        "id": "rA7bn46jq3",
        "match_substring_variations": false,
        "nameserver_exclusions": [],
        "state": "active",
        "status": "completed",
        "term": "monitored_term2",
        "text_exclusions": [],
        "updated_date": "2022-09-16T22:30:16.212269+00:00"
      },
      {
        "created_by": "user@example.com",
        "created_date": "2022-09-20T05:35:21.203482+00:00",
        "id": "YNrbr6GbKx",
        "match_substring_variations": false,
        "nameserver_exclusions": [],
        "state": "active",
        "status": "completed",
        "term": "monitored_term3",
        "text_exclusions": [],
        "updated_date": "2022-09-20T05:35:28.630194+00:00"
      }
    ]
  }
}

Human Readable Output

Monitor List

dt_created_by dt_created_date dt_match_substring_variations dt_monitor_id dt_nameserver_exclusions dt_state dt_status dt_term dt_text_exclusions dt_updated_date
user@example.com 2022-09-20T06:01:56.760955+00:00 false QEMba8wmXo   active completed monitored_term1   2022-09-20T06:02:33.358799+00:00
user@example.com 2022-09-16T22:29:20.567614+00:00 false rA7bn46jq3   active completed monitored_term2   2022-09-16T22:30:16.212269+00:00
user@example.com 2022-09-20T05:35:21.203482+00:00 false YNrbr6GbKx   active completed monitored_term3   2022-09-20T05:35:28.630194+00:00

domaintools-iris-detect-get-new-domains


Manually retrieve new domains matching all of your monitored terms, or a specific term specified by a “monitor_id” that can be retrieved using the domaintools-iris-detect-get-monitors-list command. The number of domains returned is limited to 50 if including DNS and whois details, or 100 otherwise. Use the page and page_size parameter for pagination.

Base Command

domaintools-iris-detect-get-new-domains

Input

Argument Name Description Required
discovered_since Filter domains by when they were discovered. Provide a datetime in ISO 8601 format, for example 2022-05-18T12:19:51.685496. Optional
monitor_id Monitor ID is used when requesting domains for a specific monitor. The monitor ID can be found using the ‘domaintools-iris-detect-get-monitors-list’ command. Optional
tlds List of TLDs to filter domains by. E.g. top. Optional
mx_exists Filter domains by if they have an MX record in DNS. Possible values are: True, False. Optional
risk_score_ranges List of risk score ranges to filter domains by. Valid values are: [“0-0”, “1-39”, “40-69”, “70-99”, “100-100”]. Optional
search A “contains” search for any portion of a domain name. Optional
sort Sort order for domain list. Valid values are an ordered list of the following: [“discovered_date”, “changed_date”, “risk_score”]. Optional
include_domain_data Includes DNS and whois data in the response. Possible values are: True, False. Optional
preview “Preview” mode is helpful for initial setup and configuration. It limits the results to the first 10 results but removes hourly API restrictions. Possible values are: True, False. Optional
order Sort order “asc” or “desc”. Optional
limit Default 100. Limit for pagination. Restricted to maximum 50 if include_domain_data is set to True. Optional
page The page number. Default is 1. Optional
page_size The number of requested results per page. Default is 50. Optional

Context Output

Path Type Description
DomainToolsIrisDetect.New.state String Indicates that the domain is newly discovered.
DomainToolsIrisDetect.New.domain String The domain name.
DomainToolsIrisDetect.New.status String Indicates the status of the Domain (e.g., “active”).
DomainToolsIrisDetect.New.discovered_date String The date and time when the domain was discovered (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.New.changed_date String The date and time when the domain information was last changed (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.New.risk_score String The risk score associated with the domain.
DomainToolsIrisDetect.New.risk_score_status Number The status of the risk score.
DomainToolsIrisDetect.New.risk_score_components.proximity Number The domain’s proximity risk score.
DomainToolsIrisDetect.New.risk_score_components.threat_profile.phishing Number The domain’s phishing threat score.
DomainToolsIrisDetect.New.risk_score_components.threat_profile.malware Number The domain’s malware threat score.
DomainToolsIrisDetect.New.risk_score_components.threat_profile.spam Number The domain’s spam threat score.
DomainToolsIrisDetect.New.risk_score_components.threat_profile.evidence unknown The list of evidence supporting the threat scores.
DomainToolsIrisDetect.New.mx_exists Boolean Indicates that there is no MX record for the domain.
DomainToolsIrisDetect.New.tld String The top-level domain.
DomainToolsIrisDetect.New.id String The domain ID.
DomainToolsIrisDetect.New.escalations.escalation_type String The type of escalation.
DomainToolsIrisDetect.New.escalations.id String The escalation ID.
DomainToolsIrisDetect.New.escalations.created String The date and time when the escalation was created.
DomainToolsIrisDetect.New.escalations.created_by String The email address of the person who assigned the domain to the watchlist.
DomainToolsIrisDetect.New.monitor_ids String An array containing a single monitor ID.
DomainToolsIrisDetect.New.assigned_by String The email address of the person who assigned the domain to the watchlist.
DomainToolsIrisDetect.New.assigned_date String The date and time when the domain was assigned to the watchlist (e.g.,”2023-04-20T13:13:23.000000+00:00”).
DomainToolsIrisDetect.New.registrant_contact_email String Registrant Email.
DomainToolsIrisDetect.New.name_server String An array of objects containing name server information.
DomainToolsIrisDetect.New.registrar String The domain registrar.
DomainToolsIrisDetect.New.create_date String The date when the domain was created.
DomainToolsIrisDetect.New.ip.country_code String Country code for the ip.
DomainToolsIrisDetect.New.ip.ip String Associated ip for the Domain.
DomainToolsIrisDetect.New.ip.isp String Associated isp for the Domain.

Command example

!domaintools-iris-detect-get-new-domains limit="2"

Context Example

{
  "DomainToolsIrisDetect": {
    "New": [
      {
        "changed_date": "2023-04-11T05:16:56.483000+00:00",
        "discovered_date": "2023-04-11T05:16:56.483000+00:00",
        "domain": "fakedomaintask.shop",
        "escalations": [],
        "id": "KW3ykVGZRE",
        "monitor_ids": [
          "rA7bn46jq3"
        ],
        "mx_exists": false,
        "risk_score": null,
        "risk_score_status": null,
        "state": "new",
        "status": "active",
        "tld": "shop"
      },
      {
        "changed_date": "2023-04-11T05:15:42.000000+00:00",
        "discovered_date": "2023-04-11T05:12:22.081000+00:00",
        "domain": "fakedomain.com",
        "escalations": [],
        "id": "gWlYVZxmJa",
        "monitor_ids": [
          "rA7bn46jq3"
        ],
        "mx_exists": false,
        "risk_score": 79,
        "risk_score_components": {
          "proximity": 4,
          "threat_profile": {
            "phishing": 79
          }
        },
        "risk_score_status": "provisional",
        "state": "new",
        "status": "active",
        "tld": "com"
      }
    ]
  }
}

Human Readable Output

New Domains

dt_changed_date dt_create_date dt_discovered_date dt_domain dt_domain_id dt_escalations dt_monitor_ids dt_mx_exists dt_proximity_score dt_registrant_contact_email dt_registrar dt_risk_score dt_risk_status dt_state dt_status dt_threat_profile_evidence dt_threat_profile_malware dt_threat_profile_phishing dt_threat_profile_spam dt_tld
2023-04-11T05:16:56.483000+00:00   2023-04-11T05:16:56.483000+00:00 fakedomaintask.shop KW3ykVGZRE   rA7bn46jq3 false           new active         shop
2023-04-11T05:15:42.000000+00:00   2023-04-11T05:12:22.081000+00:00 fakedomain.com gWlYVZxmJa   rA7bn46jq3 false 4     79 provisional new active     79   com

domaintools-iris-detect-get-watched-domains


Manually retrieve changes to domains that have been marked as “watched” by users of your organization, matching all of your monitored terms, or a specific term specified by a “monitor_id” that can be retrieved using the domaintools-iris-detect-get-monitors-list command. The number of domains returned is limited to 50 if including DNS and whois details, or 100 otherwise. Use the page and page_size parameter for pagination.

Base Command

domaintools-iris-detect-get-watched-domains

Input

Argument Name Description Required
escalation_types escalation_types: List[str]: default None. List of escalation types to filter domains by. Valid values are: [“blocked”, “google_safe”]. Optional
monitor_id Monitor ID is used when requesting domains for a specific monitor. The monitor ID can be found using the ‘domaintools-iris-detect-get-monitors-list’ command. Optional
tlds List of TLDs to filter domains by. E.g. top. Optional
mx_exists Filter domains by if they have an MX record in DNS. Possible values are: True, False. Optional
changed_since Filter domains by when they were last changed. Provide a datetime in ISO 8601 format, for example 2022-05-18T12:19:51.685496. Optional
search A “contains” search for any portion of a domain name. Optional
sort Sort order for domain list. Valid values are an ordered list of the following: [“discovered_date”, “changed_date”, “risk_score”]. Optional
include_domain_data Includes DNS and whois data in the response. Possible values are: True, False. Optional
preview “Preview” mode is helpful for initial setup and configuration. It limits the results to the first 10 results but removes hourly API restrictions. Possible values are: True, False. Optional
escalated_since Filter domains by when they were last escalated. Provide a datetime in ISO 8601 format, for example 2022-05-18T12:19:51.685496. Optional
order Sort order “asc” or “desc”. Optional
risk_score_ranges List of risk score ranges to filter domains by. Valid values are: [“0-0”, “1-39”, “40-69”, “70-99”, “100-100”]. Optional
limit Default 100. Limit for pagination. Restricted to maximum 50 if include_domain_data is set to True. Optional
page The page number. Default is 1. Optional
page_size The number of requested results per page. Default is 50. Optional

Context Output

Path Type Description
DomainToolsIrisDetect.Watched.state String Indicates that the domain is being watched.
DomainToolsIrisDetect.Watched.domain String The domain name.
DomainToolsIrisDetect.Watched.status String Indicates the status of the Domain (e.g., “active”).
DomainToolsIrisDetect.Watched.discovered_date String The date and time when the domain was discovered (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.Watched.changed_date String The date and time when the domain information was last changed (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.Watched.risk_score String The risk score associated with the domain.
DomainToolsIrisDetect.Watched.risk_score_status Number The status of the risk score.
DomainToolsIrisDetect.Watched.risk_score_components.proximity Number The domain’s proximity risk score.
DomainToolsIrisDetect.Watched.risk_score_components.threat_profile.phishing Number The domain’s phishing threat score.
DomainToolsIrisDetect.Watched.risk_score_components.threat_profile.malware Number The domain’s malware threat score.
DomainToolsIrisDetect.Watched.risk_score_components.threat_profile.spam Number The domain’s spam threat score.
DomainToolsIrisDetect.Watched.risk_score_components.threat_profile.evidence Unknown The list of evidence supporting the threat scores.
DomainToolsIrisDetect.Watched.mx_exists Boolean Indicates that there is no MX record for the domain.
DomainToolsIrisDetect.Watched.tld String The top-level domain.
DomainToolsIrisDetect.Watched.id String The domain ID.
DomainToolsIrisDetect.Watched.escalations.escalation_type String The type of escalation.
DomainToolsIrisDetect.Watched.escalations.id String The escalation ID.
DomainToolsIrisDetect.Watched.escalations.created String The date and time when the escalation was created.
DomainToolsIrisDetect.Watched.escalations.created_by String The email address of the person who created the escalation.
DomainToolsIrisDetect.Watched.monitor_ids String An array containing a single monitor ID.
DomainToolsIrisDetect.Watched.assigned_by String The email address of the person who assigned the domain to the watchlist.
DomainToolsIrisDetect.Watched.assigned_date String The date and time when the domain was assigned to the watchlist (e.g.,”2023-04-20T13:13:23.000000+00:00”).
DomainToolsIrisDetect.Watched.registrant_contact_email String Registrant Email.
DomainToolsIrisDetect.Watched.name_server String The domain registrar.
DomainToolsIrisDetect.Watched.registrar String The domain registrar.
DomainToolsIrisDetect.Watched.create_date String The date when the domain was created.
DomainToolsIrisDetect.Watched.ip.country_code String Country code for the ip.
DomainToolsIrisDetect.Watched.ip.ip String Associated ip for the Domain.
DomainToolsIrisDetect.Watched.ip.isp String Associated isp for the Domain.

Command example

!domaintools-iris-detect-get-watched-domains limit="2"

Context Example

{
  "DomainToolsIrisDetect": {
    "Watched": [
      {
        "assigned_by": "user@example.com",
        "assigned_date": "2023-04-11T04:46:39.000000+00:00",
        "changed_date": "2023-04-10T07:52:11.000000+00:00",
        "discovered_date": "2023-04-10T07:45:31.478000+00:00",
        "domain": "fakedomain.net.tr",
        "escalations": [
          {
            "created": "2023-04-11T04:46:39.181378+00:00",
            "created_by": "user@example.com",
            "escalation_type": "google_safe",
            "id": "43gB2PwG6m"
          }
        ],
        "id": "8Wq8Qj9x7P",
        "monitor_ids": [
          "rA7bn46jq3"
        ],
        "mx_exists": false,
        "risk_score": 8,
        "risk_score_components": {
          "proximity": 5,
          "threat_profile": {
            "evidence": [],
            "malware": 1,
            "phishing": 6,
            "spam": 8
          }
        },
        "risk_score_status": "full",
        "state": "watched",
        "status": "active",
        "tld": "net.tr"
      },
      {
        "changed_date": "2023-04-10T05:58:01.000000+00:00",
        "discovered_date": "2023-04-10T04:52:28.545000+00:00",
        "domain": "fakedomain.co",
        "escalations": [
          {
            "created": "2023-04-10T14:33:11.342255+00:00",
            "created_by": "user@example.com",
            "escalation_type": "blocked",
            "id": "nzgWDr3B9Y"
          }
        ],
        "id": "gaeMyYl1va",
        "monitor_ids": [
          "QEMba8wmXo"
        ],
        "mx_exists": true,
        "risk_score": 21,
        "risk_score_components": {
          "proximity": 21,
          "threat_profile": {
            "evidence": [],
            "malware": 20,
            "phishing": 15,
            "spam": 17
          }
        },
        "risk_score_status": "full",
        "state": "watched",
        "status": "active",
        "tld": "co"
      }
    ]
  }
}

Human Readable Output

Watched Domains

dt_changed_date dt_create_date dt_discovered_date dt_domain dt_domain_id dt_escalations dt_monitor_ids dt_mx_exists dt_proximity_score dt_registrant_contact_email dt_registrar dt_risk_score dt_risk_status dt_state dt_status dt_threat_profile_evidence dt_threat_profile_malware dt_threat_profile_phishing dt_threat_profile_spam dt_tld
2023-04-10T07:52:11.000000+00:00   2023-04-10T07:45:31.478000+00:00 fakedomain.net.tr 8Wq8Qj9x7P {‘escalation_type’: ‘google_safe’, ‘id’: ‘43gB2PwG6m’, ‘created’: ‘2023-04-11T04:46:39.181378+00:00’, ‘created_by’: ‘user@example.com’} rA7bn46jq3 false 5     8 full watched active   1 6 8 net.tr
2023-04-10T05:58:01.000000+00:00   2023-04-10T04:52:28.545000+00:00 fakedomain.co gaeMyYl1va {‘escalation_type’: ‘blocked’, ‘id’: ‘nzgWDr3B9Y’, ‘created’: ‘2023-04-10T14:33:11.342255+00:00’, ‘created_by’: ‘user@example.com’} QEMba8wmXo true 21     21 full watched active   20 15 17 co

domaintools-iris-detect-get-ignored-domains


Manually retrieve domains that your organization has marked as ignored, matching all of your monitored terms, or a specific term specified by a “monitor_id” that can be retrieved using the domaintools-iris-detect-get-monitors-list command. This is most useful in cases when a domain might have been mistakenly ignored. The number of domains returned is limited to 50 if including DNS and whois details, or 100 otherwise. Use the page and page_size parameter for pagination.

Base Command

domaintools-iris-detect-get-ignored-domains

Input

Argument Name Description Required
risk_score_ranges List of risk score ranges to filter domains by. Valid values are: [“0-0”, “1-39”, “40-69”, “70-99”, “100-100”]. Optional
monitor_id Monitor ID is used when requesting domains for a specific monitor. The monitor ID can be found using the ‘domaintools-iris-detect-get-monitors-list’ command. Optional
tlds List of TLDs to filter domains by. E.g. top. Optional
mx_exists Filter domains by if they have an MX record in DNS. Possible values are: True, False. Optional
changed_since Filter domains by when they were last changed. Provide a datetime in ISO 8601 format, for example 2022-05-18T12:19:51.685496. Optional
escalated_since Filter domains by when they were last escalated. Provide a datetime in ISO 8601 format, for example 2022-05-18T12:19:51.685496. Optional
search A “contains” search for any portion of a domain name. Optional
sort Sort order for domain list. Valid values are an ordered list of the following: [“discovered_date”, “changed_date”, “risk_score”]. Optional
include_domain_data Includes DNS and whois data in the response. Possible values are: True, False. Optional
preview “Preview” mode is helpful for initial setup and configuration. It limits the results to the first 10 results but removes hourly API restrictions. Possible values are: True, False. Optional
order Sort order “asc” or “desc”. Optional
limit Default 100. Limit for pagination. Restricted to maximum 50 if include_domain_data is set to True. Optional
page The page number. Default is 1. Optional
page_size The number of requested results per page. Default is 50. Optional

Context Output

Path Type Description
DomainToolsIrisDetect.Ignored.state String Indicates that the domain is being ignored.
DomainToolsIrisDetect.Ignored.domain String The domain name.
DomainToolsIrisDetect.Ignored.status String Indicates the status of the Domain (e.g., “active”).
DomainToolsIrisDetect.Ignored.discovered_date String The date and time when the domain was discovered (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.Ignored.changed_date String The date and time when the domain information was last changed (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.Ignored.risk_score String The risk score associated with the domain.
DomainToolsIrisDetect.Ignored.risk_score_status Number The status of the risk score.
DomainToolsIrisDetect.Ignored.risk_score_components.proximity Number The domain’s proximity risk score.
DomainToolsIrisDetect.Ignored.risk_score_components.threat_profile.phishing Number The domain’s phishing threat score.
DomainToolsIrisDetect.Ignored.risk_score_components.threat_profile.malware Number The domain’s malware threat score.
DomainToolsIrisDetect.Ignored.risk_score_components.threat_profile.spam Number The domain’s spam threat score.
DomainToolsIrisDetect.Ignored.risk_score_components.threat_profile.evidence unknown The list of evidence supporting the threat scores.
DomainToolsIrisDetect.Ignored.mx_exists Boolean Indicates that there is no MX record for the domain.
DomainToolsIrisDetect.Ignored.tld String The top-level domain.
DomainToolsIrisDetect.Ignored.id String The domain ID.
DomainToolsIrisDetect.Ignored.escalations.escalation_type String The type of escalation.
DomainToolsIrisDetect.Ignored.escalations.id String The escalation ID.
DomainToolsIrisDetect.Ignored.escalations.created String The date and time when the escalation was created.
DomainToolsIrisDetect.Ignored.escalations.created_by String The email address of the person who created the escalation.
DomainToolsIrisDetect.Ignored.monitor_ids String An array containing a single monitor ID.
DomainToolsIrisDetect.Ignored.assigned_by String The email address of the person who assigned the domain to the watchlist.
DomainToolsIrisDetect.Ignored.assigned_date String The date and time when the domain was assigned to the watchlist (e.g.,”2023-04-20T13:13:23.000000+00:00”).
DomainToolsIrisDetect.Ignored.registrant_contact_email String Registrant Email.
DomainToolsIrisDetect.Ignored.name_server String An array of objects containing name server information.
DomainToolsIrisDetect.Ignored.registrar String The domain registrar.
DomainToolsIrisDetect.Ignored.create_date String The date when the domain was created.
DomainToolsIrisDetect.Ignored.ip.country_code String Country code for the ip.
DomainToolsIrisDetect.Ignored.ip.ip String Associated ip for the Domain.
DomainToolsIrisDetect.Ignored.ip.isp String Associated isp for the Domain.

Command example

!domaintools-iris-detect-get-ignored-domains limit="2"

Context Example

{
  "DomainToolsIrisDetect": {
    "Ignored": [
      {
        "assigned_by": "user@example.com",
        "assigned_date": "2023-03-27T04:45:19.000000+00:00",
        "changed_date": "2023-03-30T09:07:59.000000+00:00",
        "discovered_date": "2023-03-21T13:57:47.094000+00:00",
        "domain": "fakedomainn.shop",
        "escalations": [
          {
            "created": "2023-03-21T17:33:51.787271+00:00",
            "created_by": "user@example.com",
            "escalation_type": "blocked",
            "id": "VrxaQQ2xNK"
          },
          {
            "created": "2023-03-21T17:35:10.150279+00:00",
            "created_by": "user@example.com",
            "escalation_type": "google_safe",
            "id": "kzbwQQ2EY2"
          }
        ],
        "id": "VE87zKvOxa",
        "monitor_ids": [
          "rA7bn46jq3"
        ],
        "mx_exists": true,
        "risk_score": 100,
        "risk_score_components": {
          "proximity": 100,
          "threat_profile": {
            "evidence": [
              "registrant",
              "domain name",
              "name server"
            ],
            "malware": 98,
            "phishing": 99,
            "spam": 82
          }
        },
        "risk_score_status": "full",
        "state": "ignored",
        "status": "active",
        "tld": "shop"
      },
      {
        "changed_date": "2023-03-25T08:04:15.000000+00:00",
        "discovered_date": "2023-02-08T10:32:18.665000+00:00",
        "domain": "walletfakedomain.com",
        "escalations": [],
        "id": "ya6dKwrRzP",
        "monitor_ids": [
          "rA7bn46jq3"
        ],
        "mx_exists": true,
        "risk_score": 100,
        "risk_score_components": {
          "proximity": 100,
          "threat_profile": {
            "evidence": [
              "domain name",
              "registrar",
              "name server"
            ],
            "malware": 19,
            "phishing": 95,
            "spam": 43
          }
        },
        "risk_score_status": "full",
        "state": "ignored",
        "status": "active",
        "tld": "com"
      }
    ]
  }
}

Human Readable Output

Ignored Domains

dt_changed_date dt_create_date dt_discovered_date dt_domain dt_domain_id dt_escalations dt_monitor_ids dt_mx_exists dt_proximity_score dt_registrant_contact_email dt_registrar dt_risk_score dt_risk_status dt_state dt_status dt_threat_profile_evidence dt_threat_profile_malware dt_threat_profile_phishing dt_threat_profile_spam dt_tld
2023-03-30T09:07:59.000000+00:00   2023-03-21T13:57:47.094000+00:00 fakedomainn.shop VE87zKvOxa {‘escalation_type’: ‘blocked’, ‘id’: ‘VrxaQQ2xNK’, ‘created’: ‘2023-03-21T17:33:51.787271+00:00’, ‘created_by’: ‘user@example.com’}, {‘escalation_type’: ‘google_safe’, ‘id’: ‘kzbwQQ2EY2’, ‘created’: ‘2023-03-21T17:35:10.150279+00:00’, ‘created_by’: ‘user@example.com’} rA7bn46jq3 true 100     100 full ignored active registrant, domain name, name server 98 99 82 shop
2023-03-25T08:04:15.000000+00:00   2023-02-08T10:32:18.665000+00:00 walletfakedomain.com ya6dKwrRzP   rA7bn46jq3 true 100     100 full ignored active domain name, registrar, name server 19 95 43 com

domaintools-iris-detect-get-escalated-domains


Manually retrieve domains that your organization has escalated to Google Safe Browsing, matching all of your monitored terms, or a specific term specified by a “monitor_id” that can be retrieved using the domaintools-iris-detect-get-monitors-list command. The number of domains returned is limited to 50 if including DNS and whois details, or 100 otherwise. Use the page and page_size parameter for pagination.

Base Command

domaintools-iris-detect-get-escalated-domains

Input

Argument Name Description Required
risk_score_ranges List of risk score ranges to filter domains by. Valid values are: [“0-0”, “1-39”, “40-69”, “70-99”, “100-100”]. Optional
monitor_id Monitor ID is used when requesting domains for a specific monitor. The monitor ID can be found using the ‘domaintools-iris-detect-get-monitors-list’ command. Optional
tlds List of TLDs to filter domains by. E.g. top. Optional
mx_exists Filter domains by if they have an MX record in DNS. Optional
changed_since Filter domains by when they were last changed. Provide a datetime in ISO 8601 format, for example 2022-05-18T12:19:51.685496. Optional
escalated_since Filter domains by when they were last escalated. Provide a datetime in ISO 8601 format, for example 2022-05-18T12:19:51.685496. Optional
search A “contains” search for any portion of a domain name. Optional
sort Sort order for domain list. Valid values are an ordered list of the following: [“discovered_date”, “changed_date”, “risk_score”]. Optional
include_domain_data Includes DNS and whois data in the response. Possible values are: True, False. Optional
preview “Preview” mode is helpful for initial setup and configuration. It limits the results to the first 10 results but removes hourly API restrictions. Possible values are: True, False. Optional
order Sort order “asc” or “desc”. Optional
limit Default 100. Limit for pagination. Restricted to maximum 50 if include_domain_data is set to True. Optional
page The page number. Default is 1. Optional
page_size The number of requested results per page. Default is 50. Optional

Context Output

Path Type Description
DomainToolsIrisDetect.Escalated.state String Indicates that the domain is being watched.
DomainToolsIrisDetect.Escalated.domain String The domain name.
DomainToolsIrisDetect.Escalated.status String Indicates the status of the Domain (e.g., “active”).
DomainToolsIrisDetect.Escalated.discovered_date String The date and time when the domain was discovered (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.Escalated.changed_date String The date and time when the domain information was last changed (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.Escalated.risk_score String The risk score associated with the domain.
DomainToolsIrisDetect.Escalated.risk_score_status Number The status of the risk score.
DomainToolsIrisDetect.Escalated.risk_score_components.proximity Number The domain’s proximity risk score.
DomainToolsIrisDetect.Escalated.risk_score_components.threat_profile.phishing Number The domain’s phishing threat score.
DomainToolsIrisDetect.Escalated.risk_score_components.threat_profile.malware Number The domain’s malware threat score.
DomainToolsIrisDetect.Escalated.risk_score_components.threat_profile.spam Number The domain’s spam threat score.
DomainToolsIrisDetect.Escalated.risk_score_components.threat_profile.evidence Unknown The list of evidence supporting the threat scores.
DomainToolsIrisDetect.Escalated.mx_exists Boolean Indicates that there is no MX record for the domain.
DomainToolsIrisDetect.Escalated.tld String The top-level domain.
DomainToolsIrisDetect.Escalated.id String The domain ID.
DomainToolsIrisDetect.Escalated.escalations.escalation_type String The type of escalation.
DomainToolsIrisDetect.Escalated.escalations.id String The escalation ID.
DomainToolsIrisDetect.Escalated.escalations.created String The date and time when the escalation was created.
DomainToolsIrisDetect.Escalated.escalations.created_by String The email address of the person who created the escalation.
DomainToolsIrisDetect.Escalated.monitor_ids String An array containing monitor IDs.
DomainToolsIrisDetect.Escalated.assigned_by String The email address of the person who assigned the domain to the watchlist.
DomainToolsIrisDetect.Escalated.assigned_date String The date and time when the domain was assigned to the escalated list (e.g.,”2023-04-20T13:13:23.000000+00:00”).
DomainToolsIrisDetect.Escalated.registrant_contact_email String Registrant Email.
DomainToolsIrisDetect.Escalated.name_server String An array of objects containing name server information.
DomainToolsIrisDetect.Escalated.registrar String The domain registrar.
DomainToolsIrisDetect.Escalated.create_date String The date when the domain was created.
DomainToolsIrisDetect.Escalated.ip.country_code String Country code for the ip.
DomainToolsIrisDetect.Escalated.ip.ip String Associated ip for the Domain.
DomainToolsIrisDetect.Escalated.ip.isp String Associated isp for the Domain.

Command example

!domaintools-iris-detect-get-escalated-domains limit="2"

Context Example

{
  "DomainToolsIrisDetect": {
    "Escalated": [
      {
        "assigned_by": "user@example.com",
        "assigned_date": "2023-04-11T04:46:39.000000+00:00",
        "changed_date": "2023-04-10T07:52:11.000000+00:00",
        "discovered_date": "2023-04-10T07:45:31.478000+00:00",
        "domain": "fakedomain.net.tr",
        "escalations": [
          {
            "created": "2023-04-11T04:46:39.181378+00:00",
            "created_by": "user@example.com",
            "escalation_type": "google_safe",
            "id": "43gB2PwG6m"
          }
        ],
        "id": "8Wq8Qj9x7P",
        "monitor_ids": [
          "rA7bn46jq3"
        ],
        "mx_exists": false,
        "risk_score": 8,
        "risk_score_components": {
          "proximity": 5,
          "threat_profile": {
            "evidence": [],
            "malware": 1,
            "phishing": 6,
            "spam": 8
          }
        },
        "risk_score_status": "full",
        "state": "watched",
        "status": "active",
        "tld": "net.tr"
      },
      {
        "assigned_by": "user@example.com",
        "assigned_date": "2023-04-11T05:18:05.000000+00:00",
        "changed_date": "2023-04-05T12:44:21.000000+00:00",
        "discovered_date": "2023-04-05T12:07:54.646000+00:00",
        "domain": "fakedomain.nexus",
        "escalations": [
          {
            "created": "2023-04-11T05:18:05.262047+00:00",
            "created_by": "user@example.com",
            "escalation_type": "google_safe",
            "id": "43gB2a3G6m"
          }
        ],
        "id": "ZadmVQOj0E",
        "monitor_ids": [
          "rA7bn46jq3"
        ],
        "mx_exists": false,
        "risk_score": 0,
        "risk_score_components": {
          "proximity": 0,
          "threat_profile": {
            "phishing": 53
          }
        },
        "risk_score_status": "full",
        "state": "watched",
        "status": "active",
        "tld": "nexus"
      }
    ]
  }
}

Human Readable Output

Escalated Domains

dt_changed_date dt_create_date dt_discovered_date dt_domain dt_domain_id dt_escalations dt_monitor_ids dt_mx_exists dt_proximity_score dt_registrant_contact_email dt_registrar dt_risk_score dt_risk_status dt_state dt_status dt_threat_profile_evidence dt_threat_profile_malware dt_threat_profile_phishing dt_threat_profile_spam dt_tld
2023-04-10T07:52:11.000000+00:00   2023-04-10T07:45:31.478000+00:00 fakedomain.net.tr 8Wq8Qj9x7P {‘escalation_type’: ‘google_safe’, ‘id’: ‘43gB2PwG6m’, ‘created’: ‘2023-04-11T04:46:39.181378+00:00’, ‘created_by’: ‘user@example.com’} rA7bn46jq3 false 5     8 full watched active   1 6 8 net.tr
2023-04-05T12:44:21.000000+00:00   2023-04-05T12:07:54.646000+00:00 fakedomain.nexus ZadmVQOj0E {‘escalation_type’: ‘google_safe’, ‘id’: ‘43gB2PwG6m’, ‘created’: ‘2023-04-11T05:18:05.262047+00:00’, ‘created_by’: ‘user@example.com’} rA7bn46jq3 false 0     0 full watched active     53   nexus

domaintools-iris-detect-get-blocklist-domains


Manually retrieve domains that your organization has marked as “blocklisted”, matching all of your monitored terms, or a specific term specified by a “monitor_id” that can be retrieved using the domaintools-iris-detect-get-monitors-list command. The number of domains returned is limited to 50 if including DNS and whois details, or 100 otherwise. Use the page and page_size parameter for pagination. Use the page and page_size parameter for pagination.

Base Command

domaintools-iris-detect-get-blocklist-domains

Input

Argument Name Description Required
monitor_id Monitor ID is used when requesting domains for a specific monitor. The monitor ID can be found using the ‘domaintools-iris-detect-get-monitors-list’ command. Optional
tlds List of TLDs to filter domains by. E.g. top. Optional
mx_exists Filter domains by if they have an MX record in DNS. Possible values are: True, False. Optional
changed_since Filter domains by when they were last changed. Provide a datetime in ISO 8601 format, for example 2022-05-18T12:19:51.685496. Optional
search Sort order for domain list. Valid values are an ordered list. Optional
sort Sort order for domain list. Possible values are: discovered_date, changed_date, risk_score. Optional
include_domain_data Includes DNS and whois data in the response. Possible values are: True, False. Optional
preview “Preview” mode is helpful for initial setup and configuration. It limits the results to the first 10 results but removes hourly API restrictions. Possible values are: True, False. Optional
escalated_since Filter domains by when they were last escalated. Provide a datetime in ISO 8601 format, for example 2022-05-18T12:19:51.685496. Optional
order Sort order “asc” or “desc”. Optional
risk_score_ranges List of risk score ranges to filter domains by. Valid values are: [“0-0”, “1-39”, “40-69”, “70-99”, “100-100”]. Optional
limit Default 100. Limit for pagination. Restricted to maximum 50 if include_domain_data is set to True. Optional
page The page number. Default is 1. Optional
page_size The number of requested results per page. Default is 50. Optional

Context Output

Path Type Description
DomainToolsIrisDetect.Blocked.state String Indicates that the domain is being watched.
DomainToolsIrisDetect.Blocked.domain String The domain name.
DomainToolsIrisDetect.Blocked.status String Indicates the status of the Domain (e.g., “active”).
DomainToolsIrisDetect.Blocked.discovered_date String The date and time when the domain was discovered (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.Blocked.changed_date String The date and time when the domain information was last changed (e.g., “2023-04-21T01:56:14.652000+00:00”).
DomainToolsIrisDetect.Blocked.risk_score String The risk score associated with the domain.
DomainToolsIrisDetect.Blocked.risk_score_status Number The status of the risk score.
DomainToolsIrisDetect.Blocked.risk_score_components.proximity Number The domain’s proximity risk score.
DomainToolsIrisDetect.Blocked.risk_score_components.threat_profile.phishing Number The domain’s phishing threat score.
DomainToolsIrisDetect.Blocked.risk_score_components.threat_profile.malware Number The domain’s malware threat score.
DomainToolsIrisDetect.Blocked.risk_score_components.threat_profile.spam Number The domain’s spam threat score.
DomainToolsIrisDetect.Blocked.risk_score_components.threat_profile.evidence Unknown The list of evidence supporting the threat scores.
DomainToolsIrisDetect.Blocked.mx_exists Boolean Indicates that there is no MX record for the domain.
DomainToolsIrisDetect.Blocked.tld String The top-level domain.
DomainToolsIrisDetect.Blocked.id String The domain ID.
DomainToolsIrisDetect.Blocked.escalations.escalation_type String The type of escalation.
DomainToolsIrisDetect.Blocked.escalations.id String The escalation ID.
DomainToolsIrisDetect.Blocked.escalations.created String The date and time when the escalation was created.
DomainToolsIrisDetect.Blocked.escalations.created_by String The email address of the person who created the escalation.
DomainToolsIrisDetect.Blocked.monitor_ids String An array containing monitor IDs.
DomainToolsIrisDetect.Blocked.assigned_by String The email address of the person who assigned the domain to the watchlist..
DomainToolsIrisDetect.Blocked.assigned_date String The date and time when the domain was assigned to the blocked list (e.g.,”2023-04-20T13:13:23.000000+00:00”).
DomainToolsIrisDetect.Blocked.registrant_contact_email String Registrant Email.
DomainToolsIrisDetect.Blocked.name_server String An array of objects containing name server information.
DomainToolsIrisDetect.Blocked.registrar String The domain registrar.
DomainToolsIrisDetect.Blocked.create_date String The date when the domain was created.
DomainToolsIrisDetect.Blocked.ip.country_code String Country code for the ip.
DomainToolsIrisDetect.Blocked.ip.ip String Associated ip for the Domain.
DomainToolsIrisDetect.Blocked.ip.isp String Associated isp for the Domain.

Command example

!domaintools-iris-detect-get-blocklist-domains limit="2"

Context Example

{
  "DomainToolsIrisDetect": {
    "Blocked": [
      {
        "changed_date": "2023-04-10T05:58:01.000000+00:00",
        "discovered_date": "2023-04-10T04:52:28.545000+00:00",
        "domain": "fakedomain.co",
        "escalations": [
          {
            "created": "2023-04-10T14:33:11.342255+00:00",
            "created_by": "user@example.com",
            "escalation_type": "blocked",
            "id": "nzgWDr3B9Y"
          }
        ],
        "id": "gaeMyYl1Va",
        "monitor_ids": [
          "QEMba8wmXo"
        ],
        "mx_exists": true,
        "risk_score": 21,
        "risk_score_components": {
          "proximity": 21,
          "threat_profile": {
            "evidence": [],
            "malware": 20,
            "phishing": 15,
            "spam": 17
          }
        },
        "risk_score_status": "full",
        "state": "watched",
        "status": "active",
        "tld": "co"
      },
      {
        "assigned_by": "user@example.com",
        "assigned_date": "2023-04-11T05:18:00.000000+00:00",
        "changed_date": "2023-04-05T15:08:54.000000+00:00",
        "discovered_date": "2023-04-05T15:01:50.701000+00:00",
        "domain": "fakedomain.mov",
        "escalations": [
          {
            "created": "2023-04-11T05:17:59.782456+00:00",
            "created_by": "user@example.com",
            "escalation_type": "blocked",
            "id": "nzgWDAzB9Y"
          }
        ],
        "id": "gaeMVJX8ea",
        "monitor_ids": [
          "rA7bn46jq3"
        ],
        "mx_exists": false,
        "risk_score": 0,
        "risk_score_components": {
          "proximity": 0,
          "threat_profile": {
            "phishing": 53
          }
        },
        "risk_score_status": "full",
        "state": "watched",
        "status": "active",
        "tld": "mov"
      }
    ]
  }
}

Human Readable Output

Blocked Domains

dt_changed_date dt_create_date dt_discovered_date dt_domain dt_domain_id dt_escalations dt_monitor_ids dt_mx_exists dt_proximity_score dt_registrant_contact_email dt_registrar dt_risk_score dt_risk_status dt_state dt_status dt_threat_profile_evidence dt_threat_profile_malware dt_threat_profile_phishing dt_threat_profile_spam dt_tld
2023-04-10T05:58:01.000000+00:00   2023-04-10T04:52:28.545000+00:00 fakedomain.co gaeMyYl1Va {‘escalation_type’: ‘blocked’, ‘id’: ‘nzgWDr3B9Y’, ‘created’: ‘2023-04-10T14:33:11.342255+00:00’, ‘created_by’: ‘user@example.com’} QEMba8wmXo true 21     21 full watched active   20 15 17 co
2023-04-05T15:08:54.000000+00:00   2023-04-05T15:01:50.701000+00:00 fakedomain.mov gaeMVJX8ea {‘escalation_type’: ‘blocked’, ‘id’: ‘nzgWDr3B9Y’, ‘created’: ‘2023-04-11T05:17:59.782456+00:00’, ‘created_by’: ‘user@example.com’} rA7bn46jq3 false 0     0 full watched active     53   mov

domaintools-iris-detect-reset-fetch-indicators


This command will reset your fetch history.

Base Command

domaintools-iris-detect-reset-fetch-indicators

Input

There are no input arguments for this command.

Context Output

There is no context output for this command.

Command example

!domaintools-iris-detect-reset-fetch-indicators

Human Readable Output

Fetch history deleted successfully

Configuration parameters

  • credentials — DomainTools API Username (required)
  • new_domains — Enabled on New Domains
  • changed_domains — Enabled on Changed Domains
  • blocked_domains — Enabled on Blocked Domains
  • risk_score_ranges — Risk score Ranges
  • include_domain_data — Include Domain Data
  • first_fetch — First fetch timestamp (example 7 days)
  • max_fetch — Maximum number of incidents to fetch
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings
  • incidentFetchInterval — Incidents Fetch Interval
  • incidentType — Incident type
  • isFetch — Fetch incidents

Commands (11)

  • domaintools-iris-detect-blocklist-domains

    Mark a given domain as blocked, which allows a script against the Iris Detect API to pass these domains on to other teams or security controls within your organization to block them in email, web, or other filtering controls.

  • domaintools-iris-detect-escalate-domains

    Reports a domain to Google's Safe Browsing API. After approval, their block list is picked up by Chrome and most modern browsers.

  • domaintools-iris-detect-get-blocklist-domains

    Manually retrieve domains that your organization has marked as "blocklisted", matching all of your monitored terms, or a specific term specified by a "monitor_id" that can be retrieved using the domaintools-iris-detect-get-monitors-list command. The number of domains returned is limited to 50 if including DNS and whois details, or 100 otherwise. Use the page and page_size parameter for pagination. Use the page and page_size parameter for pagination.

  • domaintools-iris-detect-get-escalated-domains

    Manually retrieve domains that your organization has escalated to Google Safe Browsing, matching all of your monitored terms, or a specific term specified by a "monitor_id" that can be retrieved using the domaintools-iris-detect-get-monitors-list command. The number of domains returned is limited to 50 if including DNS and whois details, or 100 otherwise. Use the page and page_size parameter for pagination.

  • domaintools-iris-detect-get-ignored-domains

    Manually retrieve domains that your organization has marked as ignored, matching all of your monitored terms, or a specific term specified by a "monitor_id" that can be retrieved using the domaintools-iris-detect-get-monitors-list command. This is most useful in cases when a domain might have been mistakenly ignored. The number of domains returned is limited to 50 if including DNS and whois details, or 100 otherwise. Use the page and page_size parameter for pagination.

  • domaintools-iris-detect-get-monitors-list

    This command allows users to retrieve the list of monitored terms and respective IDs associated with your organization's Iris Detect account. New terms can only be set up and configured directly within the Iris Detect UI (https://iris.domaintools.com/detect/). The results are limited to 100 monitors if include_counts is True, or 500 otherwise.

  • domaintools-iris-detect-get-new-domains

    Manually retrieve new domains matching all of your monitored terms, or a specific term specified by a "monitor_id" that can be retrieved using the domaintools-iris-detect-get-monitors-list command. The number of domains returned is limited to 50 if including DNS and whois details, or 100 otherwise. Use the page and page_size parameter for pagination.

  • domaintools-iris-detect-get-watched-domains

    Manually retrieve changes to domains that have been marked as "watched" by users of your organization, matching all of your monitored terms, or a specific term specified by a "monitor_id" that can be retrieved using the domaintools-iris-detect-get-monitors-list command. The number of domains returned is limited to 50 if including DNS and whois details, or 100 otherwise. Use the page and page_size parameter for pagination.

  • domaintools-iris-detect-ignore-domains

    Ignore a given domain, removing it from new and block lists, if applicable.

  • domaintools-iris-detect-reset-fetch-indicators

    This command will reset your fetch history.

  • domaintools-iris-detect-watch-domains

    Mark a given domain as watched, which will trigger more frequent scanning by DomainTools automation. Changes to watched domains can trigger incidents if enabled, or manually queried via the domaintools-iris-detect-get-watched-domains command.

"""
DomainTools Iris Detect XSOAR Integration
"""

from collections.abc import Callable
from hashlib import sha256
from hmac import new
from math import ceil
from urllib.parse import urlencode, urlunparse

from CommonServerPython import *  # noqa # pylint: disable=unused-wildcard-import
from urllib3 import disable_warnings

# Disable insecure warnings
disable_warnings()  # pylint: disable=no-member

""" CONSTANTS """

INTEGRATION_CONTEXT_NAME = "DomainToolsIrisDetect"
DOMAINTOOLS_PARAMS: Dict[str, Any] = {
    "app_partner": "cortex_xsoar",
    "app_name": "iris_detect_for_xsoar",
    "app_version": "1",
}

DEFAULT_HEADERS: Dict[str, str] = {
    "accept": "application/json",
    "Content-Type": "application/json",
}
TIMEOUT = 60.0
RETRY = 3
DOMAINTOOLS_API_BASE_URL = "api.domaintools.com"
DOMAINTOOLS_API_VERSION = "v1"

DOMAINTOOLS_MANAGE_WATCHLIST_ENDPOINT = f"/{DOMAINTOOLS_API_VERSION}/iris-detect/domains/"
DOMAINTOOLS_NEW_DOMAINS_ENDPOINT = f"/{DOMAINTOOLS_API_VERSION}/iris-detect/domains/new/"
DOMAINTOOLS_WATCHED_DOMAINS_ENDPOINT = f"/{DOMAINTOOLS_API_VERSION}/iris-detect/domains/watched/"
DOMAINTOOLS_IGNORED_DOMAINS_ENDPOINT = f"/{DOMAINTOOLS_API_VERSION}/iris-detect/domains/ignored/"
DOMAINTOOLS_MONITOR_DOMAINS_ENDPOINT = f"/{DOMAINTOOLS_API_VERSION}/iris-detect/monitors/"
DOMAINTOOLS_ESCALATE_DOMAINS_ENDPOINT = f"/{DOMAINTOOLS_API_VERSION}/iris-detect/escalations/"

DOMAINTOOLS_ESCALATE_DOMAINS_HEADER = "Escalated Domains"
DOMAINTOOLS_WATCHED_DOMAINS_HEADER = "Watched Domains"
DOMAINTOOLS_IGNORE_DOMAINS_HEADER = "Ignored Domains"
DOMAINTOOLS_BLOCKED_DOMAINS_HEADER = "Blocked Domains"
DOMAINTOOLS_NEW_DOMAINS_HEADER = "New Domains"
DOMAINTOOLS_MONITORS_HEADER = "Monitor List"
DOMAINTOOLS_NEW_DOMAINS_INCIDENT_NAME = "DomainTools Iris Detect New Domains Since"
DOMAINTOOLS_CHANGED_DOMAINS_INCIDENT_NAME = "DomainTools Iris Detect Changed Domains Since"
DOMAINTOOLS_BLOCKED_DOMAINS_INCIDENT_NAME = "DomainTools Iris Detect Blocked Domains Since"
NEW_DOMAIN_TIMESTAMP = "new_domain_last_run"
CHANGED_DOMAIN_TIMESTAMP = "changed_domain_last_run"
DT_TIMESTAMP_DICT = {
    NEW_DOMAIN_TIMESTAMP: "discovered_since",
    CHANGED_DOMAIN_TIMESTAMP: "changed_since",
}
CONTEXT_PATH_KEY = {
    DOMAINTOOLS_ESCALATE_DOMAINS_HEADER: "Escalated",
    DOMAINTOOLS_WATCHED_DOMAINS_HEADER: "Watched",
    DOMAINTOOLS_IGNORE_DOMAINS_HEADER: "Ignored",
    DOMAINTOOLS_BLOCKED_DOMAINS_HEADER: "Blocked",
    DOMAINTOOLS_NEW_DOMAINS_HEADER: "New",
    DOMAINTOOLS_MONITORS_HEADER: "Monitor",
}
INCIDENT_TYPE = {
    DOMAINTOOLS_NEW_DOMAINS_INCIDENT_NAME: "DomainTools Iris Detect New Domains",
    DOMAINTOOLS_CHANGED_DOMAINS_INCIDENT_NAME: "DomainTools Iris Detect Changed Domains",
    DOMAINTOOLS_BLOCKED_DOMAINS_INCIDENT_NAME: "DomainTools Iris Detect Blocked Domains",
}
INDICATOR_TYPE = "DomainTools Iris Detect"
INCLUDE_DOMAIN_DATA_VALUE = 1
DATE_TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"  # ISO8601 format with UTC, default in XSOAR
NO_DOMAINS_FOUND = "No Domains Found."
LIMIT_ERROR_MSG = "Invalid Input Error: limit should be greater than zero."
DEFAULT_DAYS_BACK = "3 days"
MAX_DAYS_BACK = 30
DATE_FORMAT = "%Y-%m-%d %H:%M:%S.%f"
DEFAULT_PAGE_SIZE = 50
DEFAULT_OFFSET = 0
PAGE_NUMBER_ERROR_MSG = "Invalid Input Error: page number should be greater than zero."
PAGE_SIZE_ERROR_MSG = "Invalid Input Error: page size should be greater than zero."
MONITOR_DOMAINS_LIMIT = 500
INCLUDE_COUNTS_LIMIT = 100
INCLUDE_DOMAIN_DATA_LIMIT = 50
DEFAULT_LIMIT = 100
DEFAULT_PREVIEW_LIMIT = 10
BATCH_SIZE = 2000


class DTSigner:
    """
    A class for generating digital signatures using the DomainTools API.

    Args:
        api_username (str): The API username for the DomainTools API.
        api_key (str): The API key for the DomainTools API.

    Attributes:
        api_username (str): The API username for the DomainTools API.
        api_key (str): The API key for the DomainTools API.

    Methods:
        sign(timestamp, uri): Generates a digital signature for the given timestamp and URI.
    """

    def __init__(self, api_username: str, api_key: str) -> None:
        self.api_username = api_username
        self.api_key = api_key

    def sign(self, timestamp: str, uri: str) -> str:
        """
        Generates a digital signature for the given timestamp and URI.

        Args:
            timestamp (str): The timestamp to include in the signature.
            uri (str): The URI to include in the signature.

        Returns:
            str: The generated digital signature.
        """
        params = "".join([self.api_username, timestamp, uri])
        return new(self.api_key.encode("utf-8"), params.encode("utf-8"), digestmod=sha256).hexdigest()


""" CLIENT CLASS """


class Client(BaseClient):
    """
    This Client implements API calls, and does not contain any XSOAR logic.
    Should only do requests and return data.
    It inherits from BaseClient defined in CommonServer Python.
    Most calls use _http_request() that handles proxy, SSL verification, etc.
    For this implementation, no special attributes defined
    Args:
          username (str): Domaintools username.
          api_key (str): Domaintools api key.
          new_domains (str): Specifies the action for new domains, either "Import Indicators Only" or
          "Create Incidents and Import Indicators".
          changed_domains (str): Specifies the action for changed domains, either "Import Indicators Only" or
          "Create Incidents and Import Indicators".
          blocked_domains (str): Specifies the action for blocked domains, either "Import Indicators Only" or
          "Create Incidents and Import Indicators"
          risk_score_ranges(List): List of risk score ranges to filter domains by
          include_domain_data(bool): specifies whether to include DomainTools
          Iris Detect Whois, DNS Records or not.
          verify (bool): specifies whether to verify the SSL certificate or not.
          proxy (bool): specifies if to use XSOAR proxy settings.
    """

    def __init__(
        self,
        username: str,
        api_key: str,
        new_domains: str,
        changed_domains: str,
        blocked_domains: str,
        risk_score_ranges: List,
        include_domain_data: Optional[bool] = None,
        first_fetch: str = "3 days",
        fetch_limit: Optional[int] = 50,
        verify=None,
        proxy=None,
    ):
        super().__init__(
            DOMAINTOOLS_API_BASE_URL,
            verify=verify,
            headers=DEFAULT_HEADERS,
            proxy=proxy,
        )
        self.username = username
        self.api_key = api_key
        self.risk_score_ranges = risk_score_ranges
        self.include_domain_data = include_domain_data
        self.first_fetch = first_fetch
        self.fetch_limit = fetch_limit
        self.new_domains = new_domains
        self.changed_domains = changed_domains
        self.blocked_domains = blocked_domains

    def query_dt_api(self, end_point: str, method: str, **kwargs):
        """
        Send a query to the DomainTools Iris API and get the response.

        Args:
            end_point (str): DomainTools Iris API endpoint to send the query_dt_api to.
            method (str): The HTTP method to use for the request ('GET', 'POST', 'PATCH').
            kwargs: Additional parameters for the request:
                params (Dict): URL parameters to include in the request.
                json_data (Dict): JSON data to include in the request.

        Returns:
            response (requests.Response): The server response from the DomainTools Iris API.
        """
        signer = DTSigner(self.username, self.api_key)
        timestamp = datetime.utcnow().strftime(DATE_TIME_FORMAT)

        query = {
            "api_username": self.username,
            "signature": signer.sign(timestamp, end_point),
            "timestamp": timestamp,
        }
        full_url = urlunparse(("https", DOMAINTOOLS_API_BASE_URL, end_point, "", urlencode(query), None))
        return self._http_request(
            method=method,
            full_url=full_url,
            headers=DEFAULT_HEADERS,
            params=kwargs.get("params", {}),
            json_data=kwargs.get("json_data", {}),
            timeout=TIMEOUT,
            retries=RETRY,
            error_handler=dt_error_handler,
        )

    def create_indicator_from_detect_domain(self, item: Dict, term: Dict) -> Dict[str, Any]:
        """Return the indicator object for the given DomainTools Iris Detect domain object.

        Args:
            item (Dict): A DomainTools Iris Detect domain object.
            term (Dict): A dictionary to get term values from the monitor list.

        Returns:
            Dict: The indicator object containing various fields and values.
        """
        risk_score_components = flatten_nested_dict(item.get("risk_score_components", {}))

        return {
            "name": "DomainTools Iris Detect",
            "value": item.get("domain", ""),
            "occurred": item.get("discovered_date", ""),
            "type": INDICATOR_TYPE,
            "rawJSON": item,
            "fields": {
                "irisdetectterm": item.get("monitor_term"),
                "domainname": item.get("domain", ""),
                "creation_date": item.get("discovered_date", ""),
                "updated_date": item.get("changed_date", ""),
                "domain_status": item.get("status", ""),
                "irisdetectdiscovereddate": item.get("discovered_date", ""),
                "irisdetectchangeddate": item.get("changed_date", ""),
                "irisdetectdomainstatus": item.get("status", ""),
                "irisdetectdomainstate": (
                    "blocked"
                    if any(result.get("escalation_type", "") == "blocked" for result in item.get("escalations", []))
                    else item.get("state", "")
                ),
                "domaintoolsriskscore": item.get("risk_score", ""),
                "domaintoolsriskscorestatus": item.get("risk_score_status", ""),
                "irisdetectdomainid": item.get("id", ""),
                "irisdetectescalations": [
                    {
                        "escalationtype": result.get("escalation_type", ""),
                        "id": result.get("id", ""),
                        "created": result.get("created", ""),
                        "createdby": result.get("created_by", ""),
                    }
                    for result in item.get("escalations", [])
                ],
                "irisdetecthostingipdetails": [
                    {
                        "countrycode": result.get("country_code", ""),
                        "ip": result.get("ip", ""),
                        "isp": result.get("isp", ""),
                    }
                    for result in item.get("ip", [])
                ],
                "registrant_name": item.get("registrar", ""),
                "registrant_email": ", ".join(item.get("registrant_contact_email", [])),
                "name_servers": ", ".join(result.get("host", "") for result in item.get("name_server", [])),
                "irisdetectmailserversexists": item.get("mx_exists", ""),
                "irisdetectmailserverdetails": [{"host": result.get("host", "")} for result in item.get("mx", [])],
                "domaintoolsriskscorecomponents": {
                    key: risk_score_components.get(key, "") for key in ["proximity", "phishing", "malware", "spam", "evidence"]
                },
                "last_seen_by_source": item.get("changed_date", ""),
                "first_seen_by_source": item.get("discovered_date", ""),
            },
        }

    def process_dt_domains_into_xsoar(
        self,
        domains_list: List[Dict[str, Any]],
        incident_name: str,
        last_run: str,
        term: Dict[str, Any],
        enable_incidents: bool = True,
    ) -> List[Any]:
        """
        Create indicators and, optionally, an incident in XSOAR for a list of
        DomainTools Iris Detect domains.

        Args:
            domains_list (List[Dict[str, Any]]): A list of DomainTools Iris Detect domain objects.
            incident_name (str): The name of the incident to be created based on the domain type.
            term (Dict[str, Any]): A dictionary containing the domains that need to be monitored.
            last_run (str): A timestamp string indicating the last run.
            enable_incidents (bool): Specifies whether to create an incident or not. Default is True.

        Returns:
            List[Dict[str, Any]]: A list containing the incident object if one was created,
            otherwise an empty list.
        """
        for domain in domains_list:
            domain["monitor_term"] = join_dict_values_for_keys(domain.get("monitor_ids", []), term)
        indicators = [self.create_indicator_from_detect_domain(item, term) for item in domains_list]
        if not indicators:
            return []

        for batched in batch(indicators, batch_size=BATCH_SIZE):
            demisto.createIndicators(batched)
        demisto.info(f"Added {len(indicators)} indicators to demisto")

        if enable_incidents:
            last_run_dt_without_ms = (
                datetime.strptime(get_last_run(last_run), DATE_FORMAT).replace(microsecond=0) if get_last_run(last_run) else None
            )
            first_run_dt_without_ms = (datetime.now() - timedelta(days=validate_first_fetch(self.first_fetch))).replace(
                microsecond=0
            )
            incident = {
                "name": f"{incident_name} {last_run_dt_without_ms or first_run_dt_without_ms}",
                "details": json.dumps(domains_list),
                "rawJSON": json.dumps({"incidents": domains_list}),
                "type": INCIDENT_TYPE[incident_name],
            }
            return [incident]

        return []

    def fetch_dt_domains_from_api(self, end_point: str, last_run: str) -> tuple[List[Dict], str]:
        """
        Makes an API call to the Domain Tools API endpoint and retrieves domain data based on the provided
        parameters.

        Args:
            end_point (str): The API endpoint to call.
            last_run (str): The timestamp of the last successful API call.

        Returns:
            Tuple[List[Dict], str]: A tuple containing a list of watchlist domains and a timestamp of the current
            API call.

        """

        last_run_value = get_last_run(last_run)
        if last_run_value:
            params = DOMAINTOOLS_PARAMS | {
                DT_TIMESTAMP_DICT[last_run]: last_run_value,
                "include_domain_data": (INCLUDE_DOMAIN_DATA_VALUE if self.include_domain_data else 0),
            }
            demisto.info(f"Found last run, fetching domains from {last_run_value}")
        else:
            days_back = validate_first_fetch(self.first_fetch)
            params = DOMAINTOOLS_PARAMS | {
                DT_TIMESTAMP_DICT[last_run]: datetime.now() - timedelta(days=days_back),
                "include_domain_data": (INCLUDE_DOMAIN_DATA_VALUE if self.include_domain_data else 0),
            }
            demisto.info(f"First run, fetching domains from last {days_back} days")

        if self.risk_score_ranges:
            params["risk_score_ranges[]"] = self.risk_score_ranges

        results: List = []
        while True:
            response = self.query_dt_api(end_point, "GET", params=params)
            results.extend(response.get("watchlist_domains", []))
            if response.get("total_count") == len(results):
                break
            params["offset"] = response.get("offset") + response.get("limit")
        return results, str(datetime.utcnow())

    def fetch_and_process_domains(self) -> None:
        """Fetches DomainTools domain information and creates incidents in XSOAR."""

        def process_domains(
            process_endpoint: str,
            process_timestamp_key: str,
            process_incident_name: str,
            import_only: bool,
            process_filter_func: Optional[Callable[[List[Dict[str, Any]]], List[Dict[str, Any]]]] = None,
        ) -> str:
            """
            Process domains by calling DomainTools API, filtering results, and converting them into XSOAR incidents.

            Args:
                process_endpoint (str): The DomainTools API endpoint to call.
                process_timestamp_key (str): The key for the timestamp of the domain.
                process_incident_name (str): The incident name to use for the created incidents.
                import_only (bool): If True, import only indicators.
                process_filter_func (Optional[Callable[[List[Dict[str, Any]]], List[Dict[str, Any]]]]):
                 Optional function to filter the domains.

            Returns:
                str: The last run timestamp.
            """
            domains_list, last_run = self.fetch_dt_domains_from_api(process_endpoint, process_timestamp_key)
            if process_filter_func:
                domains_list = process_filter_func(domains_list)
            incidents.extend(
                self.process_dt_domains_into_xsoar(
                    domains_list,
                    process_incident_name,
                    process_timestamp_key,
                    term,
                    not import_only,
                )
            )
            return last_run

        def filter_blocked_domains(domains: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
            """
            Filters the list of domains to return only the blocked domains.

            Args:
                domains (List[Dict[str, Any]]): The list of domains to filter.

            Returns:
                List[Dict[str, Any]]: The filtered list of blocked domains.
            """
            return [
                domain
                for domain in domains
                if domain.get("escalations")
                and any(escalation.get("escalation_type") == "blocked" for escalation in domain["escalations"])
            ]

        monitor_result = self.query_dt_api(DOMAINTOOLS_MONITOR_DOMAINS_ENDPOINT, "GET", params=DOMAINTOOLS_PARAMS)
        term = {results.get("id"): results.get("term") for results in monitor_result.get("monitors", [])}
        incidents: List[Any] = []

        domains_to_process = [
            (
                DOMAINTOOLS_WATCHED_DOMAINS_ENDPOINT,
                CHANGED_DOMAIN_TIMESTAMP,
                DOMAINTOOLS_CHANGED_DOMAINS_INCIDENT_NAME,
                self.changed_domains,
                None,  # add default value for filter_func parameter
            ),
            (
                DOMAINTOOLS_WATCHED_DOMAINS_ENDPOINT,
                CHANGED_DOMAIN_TIMESTAMP,
                DOMAINTOOLS_BLOCKED_DOMAINS_INCIDENT_NAME,
                self.blocked_domains,
                filter_blocked_domains,
            ),
            (
                DOMAINTOOLS_NEW_DOMAINS_ENDPOINT,
                NEW_DOMAIN_TIMESTAMP,
                DOMAINTOOLS_NEW_DOMAINS_INCIDENT_NAME,
                self.new_domains,
                None,  # add default value for filter_func parameter
            ),
        ]

        last_runs = {CHANGED_DOMAIN_TIMESTAMP: "", NEW_DOMAIN_TIMESTAMP: ""}

        for (
            endpoint,
            timestamp_key,
            incident_name,
            domain_setting,
            filter_func,
        ) in domains_to_process:
            if domain_setting:
                last_runs[timestamp_key] = process_domains(
                    endpoint,
                    timestamp_key,
                    incident_name,
                    domain_setting == "Import Indicators Only",
                    filter_func,
                )

        demisto.setIntegrationContext(last_runs)
        demisto.info(f"Adding {len(incidents)} incidents to demisto")
        demisto.incidents(incidents)


def join_dict_values_for_keys(key_ids: List, term: Dict) -> str:
    """
    Generates the term to use for a DomainTools Iris Detect API request.

    Args:
        key_ids (List): The key_ids to use to generate the monitor term.
        term (Dict): The term to update with the generated term.

    Returns:
        str: The generated term.

    """
    values = [term.get(key, "") for key in key_ids]
    return ", ".join(filter(None, values)) if any(values) else ""


def validate_first_fetch(value: str) -> int:
    """
    Validates the input value of first_fetch and returns the corresponding number of days back.

    Args:
        value (str): The input value for first_fetch.

    Returns:
        int: The number of days back.

    """
    try:
        days_ago = int(value.strip().split()[0])
        if days_ago <= 0:
            days_ago = MAX_DAYS_BACK
    except (ValueError, IndexError):
        days_ago = MAX_DAYS_BACK

    return min(MAX_DAYS_BACK, days_ago)


def get_last_run(context_key) -> str:
    """
    Gets last run time
    Returns:
        last run for specific domain type.
    """
    return demisto.getIntegrationContext().get(context_key)


def fetch_domains(client: Client) -> bool:
    """
    Calling fetch_and_process_domains.

    Args:
        client(object): Client class object.
    """
    client.fetch_and_process_domains()
    return True


def module_test(client: Client) -> str:
    """
    Tests API connectivity and authentication
    When 'ok' is returned it indicates the integration works like
    it is supposed to and connection to the service is successful.
    Args:
        client(Client): Client class object.
    Returns:
        Connection ok.
    """
    DOMAINTOOLS_PARAMS["preview"] = True
    client.query_dt_api(
        DOMAINTOOLS_NEW_DOMAINS_ENDPOINT,
        "GET",
        params=DOMAINTOOLS_PARAMS,
    )
    return "ok"


def dt_error_handler(response: requests.Response) -> None:
    """
    Error Handler for DomainTools Iris Detect
    Args:
        response (response): DomainTools Iris Detect response
    Raise:
        DemistoException
    """

    specific_error_messages = {
        400: "Bad Request: The request was invalid or cannot be otherwise served.",
        401: "Unauthorized: Authentication is required and has failed or has not been provided.",
        403: "Forbidden: The request is understood, but it has been refused or access is not allowed.",
        404: "Not Found: The requested resource could not be found.",
        500: "Internal Server Error: An error occurred on the server side.",
        206: "Partial Content: The requested resource has been partially returned.",
    }

    if response.status_code in {206} | set(range(400, 600)):
        try:
            error_json = response.json().get("error", {})
            error_message = (
                error_json.get("message")
                or " ".join(error_json.get("messages", []))
                or specific_error_messages.get(response.status_code, "An unknown error occurred.")
            )
        except ValueError:
            error_message = specific_error_messages.get(response.status_code, "An unknown error occurred.")

        raise DemistoException(error_message, res=response)


def format_common_fields(result: Dict[Any, Any]) -> Dict[str, Any]:
    """
    Formats the common fields of the given result dictionary.

    Args:
        result (Dict[Any, Any]): The input result dictionary containing the raw data.

    Returns:
        Dict[str, Any]: A formatted dictionary with the common fields mapped to their respective keys.
    """

    return {
        "dt_domain": result.get("domain"),
        "dt_state": result.get("state"),
        "dt_status": result.get("status"),
        "dt_discovered_date": result.get("discovered_date"),
        "dt_changed_date": result.get("changed_date"),
        "dt_escalations": result.get("escalations"),
        "dt_risk_score": result.get("risk_score"),
        "dt_risk_status": result.get("risk_score_status"),
        "dt_mx_exists": result.get("mx_exists"),
        "dt_tld": result.get("tld"),
        "dt_domain_id": result.get("id"),
        "dt_monitor_ids": result.get("monitor_ids"),
        "dt_create_date": result.get("create_date"),
        "dt_registrar": result.get("registrar"),
        "dt_registrant_contact_email": result.get("registrant_contact_email"),
    }


def format_monitor_fields(result: Dict[Any, Any]) -> Dict[str, Any]:
    """
    Formats the monitor fields.

    Args:
        result (Dict[Any, Any]): The input result dictionary containing the raw data.

    Returns:
        Dict[str, Any]: A formatted dictionary with the monitor fields mapped to their respective keys.
    """

    return {
        "dt_term": result.get("term"),
        "dt_monitor_id": result.get("id"),
        "dt_state": result.get("state"),
        "dt_match_substring_variations": result.get("match_substring_variations"),
        "dt_nameserver_exclusions": result.get("nameserver_exclusions"),
        "dt_text_exclusions": result.get("text_exclusions"),
        "dt_created_date": result.get("created_date"),
        "dt_updated_date": result.get("updated_date"),
        "dt_status": result.get("status"),
        "dt_created_by": result.get("created_by"),
    }


def format_blocklist_fields(result: Dict[Any, Any]) -> Dict[str, Any]:
    """
    Formats the block list fields.

    Args:
        result (Dict[Any, Any]): The input result dictionary containing the raw data.

    Returns:
        Dict[str, Any]: A formatted dictionary with the block fields mapped to their respective keys.
    """
    return {
        "dt_watchlist_domain_id": result.get("watchlist_domain_id"),
        "dt_escalation_type": result.get("escalation_type"),
        "dt_id": result.get("id"),
        "dt_created_date_result": result.get("created_date"),
        "dt_updated_date": result.get("updated_date"),
        "dt_created_by": result.get("created_by"),
    }


def format_watchlist_fields(result: Dict[Any, Any]) -> Dict[str, Any]:
    """
    Formats the watchlist fields.

    Args:
        result (Dict[Any, Any]): The input result dictionary containing the raw data.

    Returns:
        Dict[str, Any]: A formatted dictionary with the watch fields mapped to their respective keys.
    """
    return {
        "dt_domain": result.get("domain"),
        "dt_state": result.get("state"),
        "dt_discovered_date": result.get("discovered_date"),
        "dt_changed_date": result.get("changed_date"),
        "dt_domain_id": result.get("id"),
    }


def format_data(
    result: Dict[str, List[Dict[str, Any]]],
    field: str,
    output_prefix: str,
    data_key: str,
) -> Dict[str, Any]:
    """
    Extracts and formats data.

    Args:
        result: A dictionary containing data to be formatted.
        field: The key for the field in the `result` dictionary that contains the relevant data.
        output_prefix: A prefix to use when creating keys for the formatted output.
        data_key: The key for the data within each item in the `field` list.

    Returns:
        A dictionary with the formatted data. If the data is empty or missing, returns None.
        If the data contains a single item, returns a dictionary with the formatted data.
        If the data contains multiple items, returns a list of dictionaries, each with the formatted data.
    """
    data = result.get(field, [])
    output = {f"{output_prefix}_raw": data if data else None}

    for count, item in enumerate(data, start=1):
        output[f"{output_prefix}_{count}"] = item.get(data_key)

    return output


def format_risk_score_components(result: Dict[Any, Any]) -> Dict[str, Any]:
    """
    Map fields from Iris Detect risk score components.

    Args:
        result(Dict): Domain Object
    Returns:
        Dict: mapped risk score components object
    """
    components = result.get("risk_score_components", {})
    threat_profile = components.get("threat_profile", {})
    return {
        "dt_proximity_score": components.get("proximity"),
        "dt_threat_profile_malware": threat_profile.get("malware"),
        "dt_threat_profile_phishing": threat_profile.get("phishing"),
        "dt_threat_profile_spam": threat_profile.get("spam"),
        "dt_threat_profile_evidence": threat_profile.get("evidence"),
    }


def flatten_nested_dict(nested_dict: Dict[Any, Any]) -> Dict[str, Any]:
    """
    To flatten dict.

    Args:
        nested_dict(Dict): nested dict
    Returns:
        Dict: flatted dict
    """

    result: Dict[Any, Any] = {}
    for key, value in nested_dict.items():
        if isinstance(value, dict):
            result.update(flatten_nested_dict(value))
        else:
            result[key] = value
    return result


def create_common_api_arguments(args: Dict[str, Any]) -> Dict[str, Any]:
    """
    Constructs a dictionary of arguments that are commonly used when querying the DomainTools Iris Detect API.

    Args:
        args (Dict[str, Any]): A dictionary of arguments specifying the options for retrieving domains.

    Returns:
        Dict[str, Any]: A dictionary of arguments to use when querying the DomainTools Iris API.
            - "monitor_id" (str): The ID of the monitor to filter domains by.
            - "tlds[]" (List[str]): A list of TLDs to filter domains by.
            - "include_domain_data" (bool): Whether to include full domain data in the response.
            - "risk_score_ranges[]" (List[str]): A list of risk score ranges to filter domains by.
            - "sort[]" (List[str]): A list of fields to sort the results by.
            - "order" (str): The order to sort the results by ("asc" or "desc").
            - "mx_exists" (bool): Whether to filter domains by whether they have MX records.
            - "preview" (bool): Whether to return only a preview of the results.
            - "search" (str): A search query to filter domains by.
            - "limit" (int): The maximum number of results to return.
            - "page" (int): The page number of the results to retrieve.
            - "page_size" (int): The number of results to display per page.
    """
    return {
        "monitor_id": args.get("monitor_id"),
        "tlds[]": argToList(args.get("tlds")),
        "include_domain_data": (argToBoolean(args.get("include_domain_data")) if args.get("include_domain_data") else None),
        "risk_score_ranges[]": argToList(args.get("risk_score_ranges")),
        "sort[]": argToList(args.get("sort")),
        "order": args.get("order"),
        "mx_exists": (argToBoolean(args.get("mx_exists")) if args.get("mx_exists") else None),
        "preview": argToBoolean(args.get("preview")) if args.get("preview") else None,
        "search": args.get("search"),
        "limit": arg_to_number(args.get("limit")),
        "page": arg_to_number(args.get("page")),
        "page_size": arg_to_number(args.get("page_size")),
    }


def create_escalated_api_arguments(args: Dict[str, Any]) -> Dict[str, Any]:
    """
    Constructs a dictionary of arguments to use when query the DomainTools Iris API for escalated domains.

    Args:
        args (Dict): A dictionary of arguments specifying the options for retrieving escalated domains.

    Returns:
        Dict: A dictionary of arguments to use when query the DomainTools Iris API for escalated domains.
            - "escalated_since" (str): The start of the escalation period to search for.
            - "escalation_types[]" (List[str]): A list of escalation types to filter by.
            - "changed_since" (str): The start of the date range to filter domains that have changed since.
            - "discovered_since" (str): The start of the date range to filter domains that have been discovered since.
    """
    return {
        "escalated_since": args.get("escalated_since"),
        "escalation_types[]": args.get("escalation_types"),
        "changed_since": args.get("changed_since"),
    }


def pagination(page: Optional[int], page_size: Optional[int], limit: Optional[int]) -> tuple[int, int]:
    """
    Define pagination.
    Args:
       limit: Records per page.
       page: The page number.
       page_size: The number of requested results per page.
    Returns:
       limit (int): Records per page.
       offset (int): The number of records to be skipped.
    """

    if page is not None and page <= 0:
        raise DemistoException(PAGE_NUMBER_ERROR_MSG)
    if page_size is not None and page_size <= 0:
        raise DemistoException(PAGE_SIZE_ERROR_MSG)
    if limit is not None and limit <= 0:
        raise DemistoException(LIMIT_ERROR_MSG)
    if page_size and limit:
        limit = page_size
    return limit or page_size or DEFAULT_PAGE_SIZE, (page - 1 if page else DEFAULT_OFFSET) * (page_size or DEFAULT_PAGE_SIZE)


def get_command_title_string(sub_context: str, page: Optional[int], page_size: Optional[int], hits: Optional[int]) -> str:
    """
    Generates a command title string based on the provided context and pagination information.

    Args:
        sub_context (str): The sub-context to be included in the command title string.
        page (Optional[int]): The current page number in the pagination.
        page_size (Optional[int]): The number of items per page in the pagination.
        hits (Optional[int]): The total number of items available in the pagination.

    Returns:
        str: The command title string with the provided sub-context and pagination information.
    """
    if page and page_size and hits is not None and (page > 0 and page_size > 0):
        total_page = ceil(hits / page_size) if hits > 0 else 1
        return f"{sub_context} \nCurrent page size: {page_size}\nShowing page {page} out of {total_page}"

    return f"{sub_context}"


def get_max_limit(end_point: str, dt_args: Dict[str, Any]) -> int:
    """
    Calculate the maximum limit of results that can be fetched from a specific API endpoint.

    This function determines the maximum limit based on the provided endpoint and arguments.
    It considers the endpoint, and the boolean flags `include_counts` and `include_domain_data` in the `dt_args` dictionary.

    Args:
        end_point (str): The API endpoint.
        dt_args (Dict[str, Any]): A dictionary containing the arguments required for the API query.

    Returns:
        int: The maximum limit of results that can be fetched.

    Constants:
        MONITOR_DOMAINS_LIMIT (int): The maximum limit for the monitor domains endpoint when include_counts is False (500).
        INCLUDE_COUNTS_LIMIT (int): The maximum limit when include_counts is True (100).
        INCLUDE_DOMAIN_DATA_LIMIT (int): The maximum limit when include_domain_data is True (50).
        DEFAULT_LIMIT (int): The default maximum limit when none of the other conditions are met (100).
    """
    include_counts = dt_args.get("include_counts", False)
    include_domain_data = dt_args.get("include_domain_data", False)

    return (
        MONITOR_DOMAINS_LIMIT
        if end_point == DOMAINTOOLS_MONITOR_DOMAINS_ENDPOINT and not include_counts
        else (INCLUDE_COUNTS_LIMIT if include_counts else INCLUDE_DOMAIN_DATA_LIMIT if include_domain_data else DEFAULT_LIMIT)
    )


def get_results_helper(
    client: Client,
    end_point: str,
    dt_args: Dict[str, Any],
    result_key: str,
    tb_header_name: str,
) -> tuple[List[Any], str]:
    """
    Helper function to get results for the given endpoint and result_key.

    Args:
        client: DomainTools client to use.
        end_point: The endpoint to query_dt_api for results.
        dt_args: Dictionary containing arguments for the query_dt_api.
        result_key: The key in the response JSON to get results from.
        tb_header_name: The readable output header.

    Returns:
        Tuple containing the results list and the title of the readable output str.
    """
    max_limit = get_max_limit(end_point, dt_args)
    page = dt_args.get("page", 1)
    page_size = dt_args.get("page_size", DEFAULT_PAGE_SIZE)
    limit = dt_args.get("limit")
    preview = dt_args.get("preview")
    limit, offset = pagination(page, page_size, limit)
    if preview:
        limit = DEFAULT_PREVIEW_LIMIT
    results: List = []
    total_count = 0

    while True:
        fetch_size = min(limit - len(results), max_limit) if limit is not None else max_limit
        if fetch_size <= 0:
            break

        dt_args.update({"offset": offset, "limit": fetch_size})

        response = client.query_dt_api(end_point, "GET", params=DOMAINTOOLS_PARAMS | dt_args)

        total_count = response.get("total_count", 0)
        new_results = response.get(result_key, [])

        if not new_results:
            break

        results.extend(new_results)
        offset += len(new_results)
        if len(new_results) < fetch_size:
            break

    return results, get_command_title_string(tb_header_name, page, page_size, total_count)


def fetch_domain_tools_api_results(
    client: Client, end_point: str, tb_header_name: str, dt_args: Dict[str, Any]
) -> CommandResults:
    """
    Gets the results for a DomainTools API endpoint.

    Args:
        client (Client): The instance of the client to use.
        end_point (str): The API endpoint to query_dt_api.
        tb_header_name (str): The name to use for the table header in the command results.
        dt_args (Dict): The arguments to use for the API request.

    Returns:
        CommandResults: The results of the command.

    """

    results, title = get_results_helper(client, end_point, dt_args, "watchlist_domains", tb_header_name)
    indicator_list: List[Dict] = []

    if results:
        if dt_args.get("include_domain_data"):
            for result in results:
                indicator = format_common_fields(result) | format_risk_score_components(result)
                indicator.update(
                    format_data(result, "ip", "dt_ip_address", "ip")
                    | format_data(result, "name_server", "dt_nameServer", "host")
                    | format_data(result, "mx", "dt_mailServer", "host")
                )
                indicator_list.append(indicator)
        else:
            for result in results:
                indicator = format_common_fields(result) | format_risk_score_components(result)
                indicator_list.append(indicator)
    return CommandResults(
        outputs=results,
        outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.{CONTEXT_PATH_KEY[tb_header_name]}",
        outputs_key_field="domain",
        readable_output=(tableToMarkdown(name=title, t=indicator_list) if indicator_list else NO_DOMAINS_FOUND),
    )


def domaintools_iris_detect_get_watched_domains_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    domaintools_iris_detect_get_watched_domains_command: Get the watched domains list.
    Args:
        client: DomainTools client to use.
        args: all command arguments, usually passed from ``demisto.args()``.
    Returns:
        fetch_domain_tools_api_results: A ``CommandResults`` object that is then passed
         to ``return_results``, that contains result which will display in
         war room.
    """
    return fetch_domain_tools_api_results(
        client,
        DOMAINTOOLS_WATCHED_DOMAINS_ENDPOINT,
        DOMAINTOOLS_WATCHED_DOMAINS_HEADER,
        create_common_api_arguments(args) | create_escalated_api_arguments(args),
    )


def domaintools_iris_detect_get_new_domains_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    domaintools_iris_detect_get_new_domains_command: Get the new domains list.
    Args:
        client: DomainTools client to use.
        args: all command arguments, usually passed from ``demisto.args()``.
    Returns:
        fetch_domain_tools_api_results: A ``CommandResults`` object that is then passed
         to ``return_results``, that contains result which will display in
         war room.
    """
    return fetch_domain_tools_api_results(
        client,
        DOMAINTOOLS_NEW_DOMAINS_ENDPOINT,
        DOMAINTOOLS_NEW_DOMAINS_HEADER,
        create_common_api_arguments(args) | {"discovered_since": args.get("discovered_since")},
    )


def domaintools_iris_detect_get_ignored_domains_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    domaintools_iris_detect_get_ignored_domains_command: Get the ignored domains list.
    Args:
        client: DomainTools client to use.
        args: all command arguments, usually passed from ``demisto.args()``.
    Returns:
        fetch_domain_tools_api_results: A ``CommandResults`` object that is then passed
         to ``return_results``, that contains result which will display in
         war room.
    """
    return fetch_domain_tools_api_results(
        client,
        DOMAINTOOLS_IGNORED_DOMAINS_ENDPOINT,
        DOMAINTOOLS_IGNORE_DOMAINS_HEADER,
        create_common_api_arguments(args) | create_escalated_api_arguments(args),
    )


def domaintools_iris_detect_get_blocklist_domains_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    domaintools_iris_detect_get_blocklist_domains_command: Get the blocked domains list.
    Args:
        client: DomainTools client to use.
        args: all command arguments, usually passed from ``demisto.args()``.
    Returns:
        fetch_domain_tools_api_results: A ``CommandResults`` object that is then passed
         to ``return_results``, that contains result which will display in
         war room.
    """
    return fetch_domain_tools_api_results(
        client,
        DOMAINTOOLS_WATCHED_DOMAINS_ENDPOINT,
        DOMAINTOOLS_BLOCKED_DOMAINS_HEADER,
        create_common_api_arguments(args) | create_escalated_api_arguments(args) | {"escalation_types[]": "blocked"},
    )


def domaintools_iris_detect_get_escalated_domains_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    domaintools_iris_detect_get_escalated_domains_command: Get the escalated domains
    list.
    Args:
        client: DomainTools client to use.
        args: all command arguments, usually passed from ``demisto.args()``.
    Returns:
        fetch_domain_tools_api_results: A ``CommandResults`` object that is then passed
         to ``return_results``, that contains result which will display in
         war room.
    """
    return fetch_domain_tools_api_results(
        client,
        DOMAINTOOLS_WATCHED_DOMAINS_ENDPOINT,
        DOMAINTOOLS_ESCALATE_DOMAINS_HEADER,
        create_common_api_arguments(args) | create_escalated_api_arguments(args) | {"escalation_types[]": "google_safe"},
    )


def domaintools_iris_detect_get_monitors_list_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Get the monitor domains list.

    Args:
        client: DomainTools client to use.
        args: Command arguments, usually passed from ``demisto.args()``.

    Returns:
        A ``CommandResults`` object that is then passed to ``return_results``,
        which contains the result to display in the war room.
    """

    results, title = get_results_helper(
        client,
        DOMAINTOOLS_MONITOR_DOMAINS_ENDPOINT,
        {
            "datetime_counts_since": arg_to_datetime(args.get("datetime_counts_since")),
        }
        | create_common_api_arguments(args)
        | create_escalated_api_arguments(args),
        "monitors",
        DOMAINTOOLS_MONITORS_HEADER,
    )

    if results:
        monitor_data = [format_monitor_fields(result) for result in results]
        headers = list(monitor_data[0].keys())
        readable_output = tableToMarkdown(name=title, t=monitor_data, removeNull=True, headers=headers)
    else:
        readable_output = NO_DOMAINS_FOUND
    return CommandResults(
        outputs=results,
        outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.Monitor",
        outputs_key_field="",
        readable_output=readable_output,
    )


def handle_domain_action(client: Client, args: Dict[str, Any], action: str) -> CommandResults:
    """
    Performs the specified action on one or more watchlist domains.

    Args:
        client (Client): The instance of the client to use.
        args (Dict[str, Any]): A dictionary containing the command arguments.
        action (str): The name of the action to perform.

    Returns:
        CommandResults: The results of the command.

    """
    action_params = {
        "watched": (
            "PATCH",
            DOMAINTOOLS_MANAGE_WATCHLIST_ENDPOINT,
            DOMAINTOOLS_WATCHED_DOMAINS_HEADER,
            format_watchlist_fields,
            "WatchedDomain",
        ),
        "ignored": (
            "PATCH",
            DOMAINTOOLS_MANAGE_WATCHLIST_ENDPOINT,
            DOMAINTOOLS_IGNORE_DOMAINS_HEADER,
            format_watchlist_fields,
            "IgnoredDomain",
        ),
        "google_safe": (
            "POST",
            DOMAINTOOLS_ESCALATE_DOMAINS_ENDPOINT,
            DOMAINTOOLS_ESCALATE_DOMAINS_HEADER,
            format_blocklist_fields,
            "EscalatedDomain",
        ),
        "blocked": (
            "POST",
            DOMAINTOOLS_ESCALATE_DOMAINS_ENDPOINT,
            DOMAINTOOLS_BLOCKED_DOMAINS_HEADER,
            format_blocklist_fields,
            "BlockedDomain",
        ),
    }
    method, endpoint, header, format_func, context_output_string = action_params[action]

    data = {"watchlist_domain_ids": argToList(args.get("watchlist_domain_ids"))} | DOMAINTOOLS_PARAMS

    if action in ["watched", "ignored"]:
        data |= {"state": action}
    else:
        data |= {"escalation_type": action}

    indicators_list = [
        dict(format_func(result))
        for result in client.query_dt_api(endpoint, method, json_data=data).get(
            "watchlist_domains" if action in ["watched", "ignored"] else "escalations",
            [],
        )
    ]

    return CommandResults(
        outputs=indicators_list,
        outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.{context_output_string}",
        outputs_key_field="",
        readable_output=(tableToMarkdown(name=header, t=indicators_list) if indicators_list else NO_DOMAINS_FOUND),
        raw_response=indicators_list,
    )


def domaintools_iris_detect_watch_domains_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Watch domains for changes using DomainTools Iris API.

    Args:
        client (Client): A DomainTools Iris API client.
        args (args: Dict[str, Any]): A dictionary of arguments specifying the domains to watch.

    Returns:
        A ``CommandResults`` object that is then passed to ``return_results``,
        which contains the result to display in the war room.
    """
    return handle_domain_action(client, args, "watched")


def domaintools_iris_detect_ignore_domains_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Ignore domains using DomainTools Iris API.

    Args:
        client (Client): A DomainTools Iris API client.
        args (args: Dict[str, Any]): A dictionary of arguments specifying the domains to ignore.

    Returns:
        A ``CommandResults`` object that is then passed to ``return_results``,
        which contains the result to display in the war room.
    """
    return handle_domain_action(client, args, "ignored")


def domaintools_iris_detect_escalate_domains_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Escalate domains to Google Safe Browsing using DomainTools Iris API.

    Args:
        client (Client): A DomainTools Iris API client.
        args (Dict[str, Any]): A dictionary of arguments specifying the domains to escalate.

    Returns:
        A ``CommandResults`` object that is then passed to ``return_results``,
         which contains the result to display in the war room.
    """
    return handle_domain_action(client, args, "google_safe")


def domaintools_iris_detect_blocklist_domains_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Blocklist domains using DomainTools Iris API.

    Args:
        client (Client): A DomainTools Iris API client.
        args (Dict): A dictionary of arguments specifying the domains to blocklist.

    Returns:
        A ``CommandResults`` object that is then passed to ``return_results``,
         which contains the result to display in the war room.
    """
    return handle_domain_action(client, args, "blocked")


def reset_last_run() -> CommandResults:
    """
    Reset the last run from the integration context
    """
    demisto.setIntegrationContext({})
    return CommandResults(readable_output="Fetch history deleted successfully")


def main() -> None:
    """PARSE AND VALIDATE INTEGRATION PARAMS"""
    command = demisto.command()
    args = demisto.args()
    params = demisto.params()
    username = params.get("credentials", {}).get("identifier")
    api_key = params.get("credentials", {}).get("password")
    verify_certificate = not params.get("insecure", False)
    proxy = params.get("proxy", False)
    handle_proxy()
    risk_score_ranges = argToList(params.get("risk_score_ranges"))
    include_domain_data = params.get("include_domain_data")
    first_fetch_time = params.get("first_fetch", DEFAULT_DAYS_BACK).strip()
    fetch_limit = arg_to_number(params.get("max_fetch", 50))
    new_domains = params.get("new_domains")
    changed_domains = params.get("changed_domains")
    blocked_domains = params.get("blocked_domains")
    try:
        client = Client(
            username,
            api_key,
            new_domains,
            changed_domains,
            blocked_domains,
            risk_score_ranges,
            include_domain_data,
            first_fetch_time,
            fetch_limit,
            verify=verify_certificate,
            proxy=proxy,
        )
        commands = {
            "domaintools-iris-detect-get-new-domains": domaintools_iris_detect_get_new_domains_command,
            "domaintools-iris-detect-get-watched-domains": domaintools_iris_detect_get_watched_domains_command,
            "domaintools-iris-detect-get-ignored-domains": domaintools_iris_detect_get_ignored_domains_command,
            "domaintools-iris-detect-get-escalated-domains": domaintools_iris_detect_get_escalated_domains_command,
            "domaintools-iris-detect-get-blocklist-domains": domaintools_iris_detect_get_blocklist_domains_command,
            "domaintools-iris-detect-get-monitors-list": domaintools_iris_detect_get_monitors_list_command,
            "domaintools-iris-detect-escalate-domains": domaintools_iris_detect_escalate_domains_command,
            "domaintools-iris-detect-blocklist-domains": domaintools_iris_detect_blocklist_domains_command,
            "domaintools-iris-detect-watch-domains": domaintools_iris_detect_watch_domains_command,
            "domaintools-iris-detect-ignore-domains": domaintools_iris_detect_ignore_domains_command,
        }
        demisto.info(f"Command being called is {command}")
        command_output: Any
        if command == "test-module":
            command_output = module_test(client)

        elif command in commands:
            command_output = commands[command](client, args)

        elif command == "fetch-incidents":
            command_output = fetch_domains(client)

        elif command == "domaintools-iris-detect-reset-fetch-indicators":
            command_output = reset_last_run()

        else:
            raise NotImplementedError(f"Command {command} is not supported")
        return_results(command_output)
    except Exception as err:
        return_error(f"Failed to execute {command} command.\nError: {err}")


""" ENTRY POINT """

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