GetDomainDNSDetails
Returns DNS details for a domain.
- Type
- python
- Pack
- CommonScripts
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 |