initial version
This commit is contained in:
commit
02e2c3592a
25
Integrations/DNSTest/README.md
Normal file
25
Integrations/DNSTest/README.md
Normal file
@ -0,0 +1,25 @@
|
||||
A simple tool for testing DNS, useful if you do not have access to the underlying server.
|
||||
|
||||
## Configure DNSTest on Cortes XSOAR
|
||||
1. Navigate to **Settings** > **Integrations** > **Servers & Services**.
|
||||
2. Search for DNSTest.
|
||||
3. Click **Add instance** to create and configure a new integration instance.
|
||||
|
||||
| **Parameter** | **Description** | **Required** |
|
||||
| --- | --- | --- |
|
||||
| Default domain | The domain to query for during inital testing (default: google.com)| False |
|
||||
| Timeout | Time in seconds to wait for response from DNS server (default: 1 sec) | False |
|
||||
|
||||
4. Click **Test** to verify operation, using default or provided parameters.
|
||||
|
||||
## Commands
|
||||
Run these commands from the Cortex XSOAR CLI
|
||||
### dns-test-get-resolvers
|
||||
Returns the nameserver IP addresses configured for the host (e.g. in /etc/resolv.conf)
|
||||
|
||||
Example: !dns-test-get-resolvers
|
||||
|
||||
### dns-test-resolve-domain
|
||||
Queries all available resolvers for A, AAAA and CNAME records for the provided domain name and returns the results. Optionally increase the wait time for the query by passing a timeout value greater than 1
|
||||
|
||||
Example: !dns-test-resolve-domain domain=test.com [timeout=5]
|
||||
148
Integrations/DNSTest/dnstest.py
Normal file
148
Integrations/DNSTest/dnstest.py
Normal file
@ -0,0 +1,148 @@
|
||||
register_module_line('DNSTest', 'start', __line__())
|
||||
demisto.debug('pack name = DNSTest, pack version = 1.0.0')
|
||||
|
||||
import dns.resolver
|
||||
from time import sleep
|
||||
|
||||
def get_dns_resolvers():
|
||||
# This function retrieves the DNS resolvers from the server configuration.
|
||||
resolver = dns.resolver.get_default_resolver()
|
||||
return resolver.nameservers
|
||||
|
||||
def resolve_domain(domain, timeout=1, iterations=100, delay=0):
|
||||
# This function resolves a given domain using all locally configured resolvers.
|
||||
resolvers = get_dns_resolvers()
|
||||
rtypes = ['A', 'AAAA', 'CNAME']
|
||||
|
||||
result = {}
|
||||
for resolver in resolvers:
|
||||
for rtype in rtypes:
|
||||
demisto.debug(f'Resolving {domain} using {resolver} for {rtype} records...')
|
||||
# run every query 100 times to handle cases where the DNS server is not responding.
|
||||
errors = set()
|
||||
for i in range(iterations):
|
||||
answers = []
|
||||
try:
|
||||
a = dns.resolver.resolve_at(resolver, domain, rtype, lifetime=timeout)
|
||||
|
||||
if a:
|
||||
answers = [str(answer) for answer in a]
|
||||
answers.sort()
|
||||
|
||||
except dns.resolver.NXDOMAIN:
|
||||
error = f'Domain {domain} does not exist.'
|
||||
errors.add(error)
|
||||
demisto.info(error)
|
||||
except dns.resolver.NoAnswer:
|
||||
error = f'No {rtype} records found for domain {domain}.'
|
||||
errors.add(error)
|
||||
demisto.info(error)
|
||||
except dns.resolver.Timeout:
|
||||
error = f'Timeout occurred while resolving domain {domain}.'
|
||||
errors.add(error)
|
||||
demisto.info(error)
|
||||
except Exception as e:
|
||||
error = f'An error occurred while resolving domain {domain}: {str(e)}'
|
||||
errors.add(error)
|
||||
demisto.info(error)
|
||||
|
||||
demisto.info(f'Results for {resolver} and {rtype}: {answers}')
|
||||
|
||||
if resolver in result and rtype in result[resolver]:
|
||||
demisto.debug(f'Previous results for {resolver} and {rtype} already exist.')
|
||||
if answers:
|
||||
if not result[resolver][rtype]['answers'] or answers == result[resolver][rtype]['answers']:
|
||||
demisto.debug(f'incrementing successes')
|
||||
result[resolver][rtype]['successes'] += 1
|
||||
else:
|
||||
demisto.info(f'got different answer for {rtype} from {resolver}: {answerlist}')
|
||||
result[resolver][rtype].setdefault('variants', []).append(answerlist)
|
||||
demisto.debug(f'incrementing successes')
|
||||
result[resolver][rtype]['successes'] += 1
|
||||
else:
|
||||
demisto.debug(f'incrementing failures')
|
||||
result[resolver][rtype]['failures'] += 1
|
||||
elif resolver in result:
|
||||
demisto.debug(f'Adding initial record for {rtype} from {resolver}.')
|
||||
if answers:
|
||||
result[resolver][rtype] = {'answers': [str(answer) for answer in answers], 'successes': 1}
|
||||
else:
|
||||
result[resolver][rtype] = {'answers': [], 'failures': 1, 'successes': 0}
|
||||
else:
|
||||
demisto.debug(f'Adding initial result for {resolver}.')
|
||||
if answers:
|
||||
result[resolver] = {rtype: {'answers': [str(answer) for answer in answers],'successes': 1}}
|
||||
else:
|
||||
result[resolver] = {rtype: {'answers': [], 'failures': 1, 'successes': 0}}
|
||||
|
||||
sleep(delay)
|
||||
|
||||
if errors:
|
||||
demisto.debug(f'errors for {resolver} and {rtype}: {errors}')
|
||||
result[resolver][rtype]['errors'] = list(errors)
|
||||
|
||||
return result
|
||||
|
||||
def test_module(default_domain, timeout):
|
||||
"""
|
||||
This is the test function that runs when the module is loaded for the first time.
|
||||
It tests the module's functions by calling them with sample inputs.
|
||||
"""
|
||||
|
||||
# Test resolve_domain function
|
||||
domain = 'google.com'
|
||||
result = resolve_domain(default_domain, timeout, iterations=1)
|
||||
|
||||
# Test get_dns_resolvers function
|
||||
resolvers = get_dns_resolvers()
|
||||
|
||||
if isinstance(resolvers, list) and len(resolvers) > 0:
|
||||
getresolversok = True
|
||||
else:
|
||||
return 'Get resolvers test failed'
|
||||
|
||||
if isinstance(result, dict) and len(result) > 0:
|
||||
resolveok = True
|
||||
else:
|
||||
return 'Resolve test failed'
|
||||
|
||||
if resolveok and getresolversok:
|
||||
return 'ok'
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Parse and Validate the commands, parameters, arguments
|
||||
and processes the api requests.
|
||||
"""
|
||||
|
||||
command = demisto.command()
|
||||
demisto.info(f'Executing command {command}')
|
||||
|
||||
args = demisto.args()
|
||||
params = demisto.params()
|
||||
timeout = int(params.get('timeout', 1))
|
||||
default_domain = params.get('default_domain', 'google.com')
|
||||
delay = int(params.get('delay', 0))
|
||||
iterations = int(params.get('iterations', 100))
|
||||
|
||||
if command == 'dns-test-resolve-domain':
|
||||
domain = args.get('domain')
|
||||
result = resolve_domain(domain, timeout, iterations=iterations, delay=delay)
|
||||
return_results(result)
|
||||
|
||||
elif command == 'dns-test-get-resolvers':
|
||||
resolvers = get_dns_resolvers()
|
||||
return_results(resolvers)
|
||||
|
||||
elif command == 'test-module':
|
||||
result = test_module(default_domain, timeout)
|
||||
return_results(result)
|
||||
|
||||
else:
|
||||
return_error(f'Unsupported command: {command}')
|
||||
|
||||
if __name__ in ['__main__', '__builtin__', 'builtins']:
|
||||
main()
|
||||
|
||||
register_module_line('DNSTest', 'end', __line__())
|
||||
39
Integrations/DNSTest/dnstest.yml
Normal file
39
Integrations/DNSTest/dnstest.yml
Normal file
@ -0,0 +1,39 @@
|
||||
commonfields:
|
||||
id: DNSTest
|
||||
version: -1
|
||||
name: DNSTest
|
||||
display: DNSTest
|
||||
category: Utilities
|
||||
configuration:
|
||||
- display: DNS query timeout
|
||||
name: timeout
|
||||
defaultvalue: "1"
|
||||
type: 0
|
||||
required: false
|
||||
additionalinfo: How long to wait for reply from the DNS server (default 1s)
|
||||
- display: Default domain
|
||||
name: default_domain
|
||||
defaultvalue: "google.com"
|
||||
type: 0
|
||||
required: false
|
||||
additionalinfo: The default domain used to test operation. May need to be configured if the local resolver is not recursive.
|
||||
script:
|
||||
script: ""
|
||||
type: python
|
||||
commands:
|
||||
- name: dns-test-resolve-domain
|
||||
description: Resolve a given domain using all locally configured resolvers
|
||||
arguments:
|
||||
- name: domain
|
||||
description: The domain to resolve
|
||||
required: true
|
||||
- name: dns-test-get-resolvers
|
||||
arguments: []
|
||||
description: Get the locally configured DNS resolvers
|
||||
dependencies:
|
||||
- name: dnspython
|
||||
version: ">=2.7.0"
|
||||
dockerimage: demisto/py3-tools:1.0.0.87415
|
||||
isfetch: false
|
||||
runonce: true
|
||||
subtype: python3
|
||||
3
ReleaseNotes/0_9.md
Normal file
3
ReleaseNotes/0_9.md
Normal file
@ -0,0 +1,3 @@
|
||||
Integrations
|
||||
DNSTest
|
||||
- initial release
|
||||
31
pack_metadata.json
Normal file
31
pack_metadata.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "DNSTest",
|
||||
"description": "A tool for troubleshooting and testing local DNS",
|
||||
"support": "developer",
|
||||
"currentVersion": "0.9",
|
||||
"author": "Nik Mitev",
|
||||
"email": "xsoar@mitev.net",
|
||||
"devEmail": "xsoar@mitev.net",
|
||||
"categories": [
|
||||
"Utilities"
|
||||
],
|
||||
"tags": [
|
||||
"dns",
|
||||
"troubleshooting"
|
||||
],
|
||||
"created": "2024-11-05T00:00:00Z",
|
||||
"useCases": [
|
||||
"Troubleshooting DNS issues",
|
||||
"Testing local DNS configurations"
|
||||
],
|
||||
"keywords": [
|
||||
"dns",
|
||||
"debugging"
|
||||
],
|
||||
"dependencies": {
|
||||
"dnspython": ">=2.7.0"
|
||||
},
|
||||
"githubUser": [
|
||||
"nikmit"
|
||||
]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user