GetDomainDNSDetails

Returns DNS details for a domain.

python · Common Scripts

Source

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

from typing import Any
import traceback

import dns.resolver
import dns.rdatatype
import dns.rdataclass
import dns.rdata


DNS_QUERY_TTL = 10.0
QTYPES = ["CNAME", "NS", "A", "AAAA"]


""" STANDALONE FUNCTION """


def make_query(resolver: dns.resolver.Resolver, qname: str, qtype: str, use_tcp: bool) -> dict[str, Any]:
    q_rdtype = dns.rdatatype.from_text(qtype)
    q_rdclass = dns.rdataclass.from_text("IN")

    try:
        ans = resolver.resolve(qname, q_rdtype, q_rdclass, tcp=use_tcp, lifetime=DNS_QUERY_TTL, raise_on_no_answer=True)

    except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN):
        return {}

    if ans.rrset is None:
        return {}

    result: dict[str, list[str]] = {}

    result[qtype] = [rr.to_text() for rr in ans.rrset if (rr is not None and rr.rdtype == q_rdtype and rr.rdclass == q_rdclass)]

    return result


""" COMMAND FUNCTION """


def get_domain_dns_details_command(args: dict[str, Any]) -> CommandResults:
    outputs: dict[str, dict[str, Any]] | None
    answer: str | dict[str, Any]

    server = args.get("server")
    use_tcp = argToBoolean(args.get("use_tcp", "Yes"))

    qtypes = QTYPES
    if (arg_qtype := args.get("qtype")) is not None:
        qtypes = argToList(arg_qtype)

    qname = args.get("domain")
    if qname is None:
        raise ValueError("domain is required")

    resolver = dns.resolver.Resolver()
    if server is not None:
        resolver.nameservers = [server]

    answer = {"domain": qname, "server": server if server is not None else "system"}

    # we ask specifically for CNAMEs
    for qtype in qtypes:
        answer.update(make_query(resolver, qname, qtype, use_tcp=use_tcp))

    outputs = {"DomainDNSDetails": answer}

    markdown = tableToMarkdown(f"Domain DNS Details for {qname}", answer, headers=["domain", "server"] + qtypes)

    return CommandResults(readable_output=markdown, outputs=outputs, outputs_key_field=["domain", "server"])


""" MAIN FUNCTION """


def main():
    try:
        return_results(get_domain_dns_details_command(demisto.args()))
    except Exception as ex:
        demisto.error(traceback.format_exc())  # print the traceback
        return_error(f"Failed to execute GetDomainDNSDetails. Error: {ex!s}")


""" ENTRY POINT """


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

README

Returns DNS details for a domain

Script Data


Name Description
Script Type python3
Tags  
Cortex XSOAR Version 5.0.0

Inputs


Argument Name Description
domain The domain to query
server IP of the DNS Server to use (default: system settings)
use_tcp Use TCP for the query (default: False)
qtype Comma separated list of query types (default: CNAME,NS,A,AAAA)

Outputs


Path Description Type
DomainDNSDetails.A Domain A records. String
DomainDNSDetails.AAAA Domain AAAA records. String
DomainDNSDetails.CNAME Domain CNAME records. String
DomainDNSDetails.NS Domain NS records. String
DomainDNSDetails.domain Domain name used in the query. String
DomainDNSDetails.server Name server that returned the result. String

Script Example

!GetDomainDNSDetails domain=example.com

Context Example

{
    "DomainDNSDetails": {
        "A": [
            "10.11.12.13"
        ],
        "AAAA": [
            "2001:2001:200:1:200:2001:2001:2001"
        ],
        "CNAME": [
            "test.example.com"
        ],
        "NS": [
            "a.iana-servers.net.",
            "b.iana-servers.net."
        ],
        "domain": "example.com",
        "server": "system"
    }
}

Human Readable Output

 Domain DNS Details for example.com

domain server CNAME NS A AAAA
example.com system test.example.com a.iana-servers.net.,
b.iana-servers.net.
10.11.12.13 2001:2001:200:1:200:2001:2001:2001