From dee2ee91ef71151d9d1f7a139b972a1464a02ada Mon Sep 17 00:00:00 2001 From: phillip-stephens Date: Fri, 23 Aug 2024 09:45:04 -0400 Subject: [PATCH 1/6] only add 'lookup_module' if we're using multiple modules to save storage space --- src/cli/worker_manager.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cli/worker_manager.go b/src/cli/worker_manager.go index e873fae8..84117b8c 100644 --- a/src/cli/worker_manager.go +++ b/src/cli/worker_manager.go @@ -577,7 +577,11 @@ func doLookupWorker(gc *CLIConf, rc *zdns.ResolverConfig, input <-chan string, o for line := range input { // we'll process each module sequentially, parallelism is per-domain for moduleName, module := range gc.ActiveModules { - res := zdns.Result{Module: moduleName} + var res zdns.Result + if len(gc.ActiveModules) > 1 { + // if we have multiple modules, give module to allow user to disambiguate + res.Module = moduleName + } var innerRes interface{} var trace zdns.Trace var status zdns.Status From b665ad9745afb30e21083a259fdf2d41d8c73005 Mon Sep 17 00:00:00 2001 From: phillip-stephens Date: Fri, 23 Aug 2024 10:28:45 -0400 Subject: [PATCH 2/6] collect output --- src/cli/worker_manager.go | 95 ++++++++++++++++++++------------------- src/zdns/qa.go | 32 +++++++------ 2 files changed, 67 insertions(+), 60 deletions(-) diff --git a/src/cli/worker_manager.go b/src/cli/worker_manager.go index 84117b8c..231826ed 100644 --- a/src/cli/worker_manager.go +++ b/src/cli/worker_manager.go @@ -17,6 +17,8 @@ import ( "encoding/csv" "encoding/json" "fmt" + "github.com/hashicorp/go-version" + "github.com/liip/sheriff" "net" "os" "runtime" @@ -25,8 +27,6 @@ import ( "sync" "time" - "github.com/hashicorp/go-version" - "github.com/liip/sheriff" "github.com/pkg/errors" log "github.com/sirupsen/logrus" "github.com/zmap/dns" @@ -576,73 +576,76 @@ func doLookupWorker(gc *CLIConf, rc *zdns.ResolverConfig, input <-chan string, o metadata.Status = make(map[zdns.Status]int) for line := range input { // we'll process each module sequentially, parallelism is per-domain - for moduleName, module := range gc.ActiveModules { - var res zdns.Result - if len(gc.ActiveModules) > 1 { - // if we have multiple modules, give module to allow user to disambiguate - res.Module = moduleName + res := zdns.Result{Results: make(map[string]zdns.SingleModuleResult, len(gc.ActiveModules))} + // get the fields that won't change for each lookup module + rawName := "" + nameServer := "" + var rank int + var entryMetadata string + if gc.AlexaFormat { + rawName, rank = parseAlexa(line) + res.AlexaRank = rank + } else if gc.MetadataFormat { + rawName, entryMetadata = parseMetadataInputLine(line) + res.Metadata = entryMetadata + } else if gc.NameServerMode { + nameServer, err = util.AddDefaultPortToDNSServerName(line) + if err != nil { + log.Fatal("unable to parse name server: ", line) } + } else { + rawName, nameServer = parseNormalInputLine(line) + } + res.Name = rawName + // handle per-module lookups + for moduleName, module := range gc.ActiveModules { var innerRes interface{} var trace zdns.Trace var status zdns.Status var err error var changed bool var lookupName string - rawName := "" - nameServer := "" - var rank int - var entryMetadata string - if gc.AlexaFormat { - rawName, rank = parseAlexa(line) - res.AlexaRank = rank - } else if gc.MetadataFormat { - rawName, entryMetadata = parseMetadataInputLine(line) - res.Metadata = entryMetadata - } else if gc.NameServerMode { - nameServer, err = util.AddDefaultPortToDNSServerName(line) - if err != nil { - log.Fatal("unable to parse name server: ", line) - } - } else { - rawName, nameServer = parseNormalInputLine(line) - } lookupName, changed = makeName(rawName, gc.NamePrefix, gc.NameOverride) if changed { res.AlteredName = lookupName } - res.Name = rawName res.Class = dns.Class(gc.Class).String() startTime := time.Now() innerRes, trace, status, err = module.Lookup(resolver, lookupName, nameServer) - res.Timestamp = time.Now().Format(gc.TimeFormat) - res.Duration = time.Since(startTime).Seconds() + lookupRes := zdns.SingleModuleResult{ + Timestamp: time.Now().Format(gc.TimeFormat), + Duration: time.Since(startTime).Seconds(), + } if status != zdns.StatusNoOutput { - res.Status = string(status) - res.Data = innerRes - res.Trace = trace - if err != nil { - res.Error = err.Error() - } - v, _ := version.NewVersion("0.0.0") - o := &sheriff.Options{ - Groups: gc.OutputGroups, - ApiVersion: v, - } - data, err := sheriff.Marshal(o, res) - if err != nil { - log.Fatalf("unable to marshal result to JSON: %v", err) - } - jsonRes, err := json.Marshal(data) + lookupRes.Status = string(status) + lookupRes.Data = innerRes + lookupRes.Trace = trace if err != nil { - log.Fatalf("unable to marshal JSON result: %v", err) + lookupRes.Error = err.Error() } - output <- string(jsonRes) + res.Results[moduleName] = lookupRes } metadata.Status[status]++ metadata.Lookups++ } + if len(res.Results) > 0 { + v, _ := version.NewVersion("0.0.0") + o := &sheriff.Options{ + Groups: gc.OutputGroups, + ApiVersion: v, + } + data, err := sheriff.Marshal(o, res) + if err != nil { + log.Fatalf("unable to marshal result to JSON: %v", err) + } + jsonRes, err := json.Marshal(data) + if err != nil { + log.Fatalf("unable to marshal JSON result: %v", err) + } + output <- string(jsonRes) + } metadata.Names++ } metaChan <- metadata diff --git a/src/zdns/qa.go b/src/zdns/qa.go index 6bcb5972..1523c65b 100644 --- a/src/zdns/qa.go +++ b/src/zdns/qa.go @@ -46,21 +46,25 @@ type TraceStep struct { Try int `json:"try" groups:"trace"` } -// Result contains all the metadata from a complete lookup, potentailly after following many CNAMEs/etc. +// Result contains all the metadata from a complete lookup(s) for a domain. Results is keyed with the ModuleName. type Result struct { - AlteredName string `json:"altered_name,omitempty" groups:"short,normal,long,trace"` - Name string `json:"name,omitempty" groups:"short,normal,long,trace"` - Nameserver string `json:"nameserver,omitempty" groups:"normal,long,trace"` - Class string `json:"class,omitempty" groups:"long,trace"` - AlexaRank int `json:"alexa_rank,omitempty" groups:"short,normal,long,trace"` - Metadata string `json:"metadata,omitempty" groups:"short,normal,long,trace"` - Module string `json:"lookup_module,omitempty" groups:"short,normal,long,trace"` - Status string `json:"status,omitempty" groups:"short,normal,long,trace"` - Error string `json:"error,omitempty" groups:"short,normal,long,trace"` - Timestamp string `json:"timestamp,omitempty" groups:"short,normal,long,trace"` - Duration float64 `json:"duration,omitempty" groups:"short,normal,long,trace"` // in seconds - Data interface{} `json:"data,omitempty" groups:"short,normal,long,trace"` - Trace Trace `json:"trace,omitempty" groups:"trace"` + AlteredName string `json:"altered_name,omitempty" groups:"short,normal,long,trace"` + Name string `json:"name,omitempty" groups:"short,normal,long,trace"` + Nameserver string `json:"nameserver,omitempty" groups:"normal,long,trace"` + Class string `json:"class,omitempty" groups:"long,trace"` + AlexaRank int `json:"alexa_rank,omitempty" groups:"short,normal,long,trace"` + Metadata string `json:"metadata,omitempty" groups:"short,normal,long,trace"` + Results map[string]SingleModuleResult `json:"results,omitempty" groups:"short,normal,long,trace"` +} + +// SingleModuleResult contains all the metadata from a complete lookup for a domain, potentially after following many CNAMEs/etc. +type SingleModuleResult struct { + Status string `json:"status,omitempty" groups:"short,normal,long,trace"` + Error string `json:"error,omitempty" groups:"short,normal,long,trace"` + Timestamp string `json:"timestamp,omitempty" groups:"short,normal,long,trace"` + Duration float64 `json:"duration,omitempty" groups:"short,normal,long,trace"` // in seconds + Data interface{} `json:"data,omitempty" groups:"short,normal,long,trace"` + Trace Trace `json:"trace,omitempty" groups:"trace"` } // SingleQueryResult contains the results of a single DNS query From 2e5eae412dbc5dd20d468c112c667a566e313861 Mon Sep 17 00:00:00 2001 From: phillip-stephens Date: Fri, 23 Aug 2024 10:36:42 -0400 Subject: [PATCH 3/6] sort imports --- benchmark/stats.go | 11 +++++++++-- src/cli/worker_manager.go | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/benchmark/stats.go b/benchmark/stats.go index e5225d6a..5a09e475 100644 --- a/benchmark/stats.go +++ b/benchmark/stats.go @@ -135,7 +135,15 @@ func updateStats(line string, s *Stats) { log.Panicf("failed to unmarshal JSON (%s): %v", line, err) } domainName := res.Name - resolveTime := time.Duration(res.Duration * float64(time.Second)) + // Assuming we only run a single module + // TODO - this will only work for a single module + var duration float64 + var status zdns.Status + for _, moduleResult := range res.Results { + duration = moduleResult.Duration + status = zdns.Status(moduleResult.Status) + } + resolveTime := time.Duration(duration * float64(time.Second)) if resolveTime < s.MinResolveTime || s.MinResolveTime == 0 { s.MinResolveTime = resolveTime @@ -173,7 +181,6 @@ func updateStats(line string, s *Stats) { } s.numberOfResolutions++ - status := zdns.Status(res.Status) if status == zdns.StatusNoError { s.SuccessfulResolutions++ } else if status == zdns.StatusTimeout || status == zdns.StatusIterTimeout { diff --git a/src/cli/worker_manager.go b/src/cli/worker_manager.go index 231826ed..5d44f88f 100644 --- a/src/cli/worker_manager.go +++ b/src/cli/worker_manager.go @@ -17,8 +17,6 @@ import ( "encoding/csv" "encoding/json" "fmt" - "github.com/hashicorp/go-version" - "github.com/liip/sheriff" "net" "os" "runtime" @@ -27,6 +25,8 @@ import ( "sync" "time" + "github.com/hashicorp/go-version" + "github.com/liip/sheriff" "github.com/pkg/errors" log "github.com/sirupsen/logrus" "github.com/zmap/dns" From 92a2bc703b1c5c724e7b8f56c3a68cf4a7ec844c Mon Sep 17 00:00:00 2001 From: phillip-stephens Date: Fri, 23 Aug 2024 12:49:29 -0400 Subject: [PATCH 4/6] fixed up integration tests to match new schema --- testing/integration_tests.py | 587 ++++++++++++++++++----------------- 1 file changed, 294 insertions(+), 293 deletions(-) diff --git a/testing/integration_tests.py b/testing/integration_tests.py index 28c57a05..c6ee4f40 100755 --- a/testing/integration_tests.py +++ b/testing/integration_tests.py @@ -113,151 +113,171 @@ def run_zdns_multiline_output(self, flags, name, executable=ZDNS_EXECUTABLE): MX_LOOKUP_ANSWER = { "name": "zdns-testing.com", - "class": "IN", - "status": "NOERROR", - "data": { - "exchanges": [ - { - "name": "mx1.zdns-testing.com", - "type": "MX", - "class": "IN", - "preference": 1, - "ipv4_addresses": [ - "1.2.3.4", - "2.3.4.5" - ], - "ipv6_addresses": [ - "fdb3:ac76:a577::4", - "fdb3:ac76:a577::5" - ], - - }, - { - "name": "mx2.zdns-testing.com", - "type": "MX", - "class": "IN", - "preference": 5, - "ipv4_addresses": [ - "5.6.7.8" - ], - }, - { - "name": "mx1.censys.io", - "type": "MX", - "class": "IN", - "preference": 10, + "results": { + "MXLOOKUP": { + "class": "IN", + "status": "NOERROR", + "data": { + "exchanges": [ + { + "name": "mx1.zdns-testing.com", + "type": "MX", + "class": "IN", + "preference": 1, + "ipv4_addresses": [ + "1.2.3.4", + "2.3.4.5" + ], + "ipv6_addresses": [ + "fdb3:ac76:a577::4", + "fdb3:ac76:a577::5" + ], + + }, + { + "name": "mx2.zdns-testing.com", + "type": "MX", + "class": "IN", + "preference": 5, + "ipv4_addresses": [ + "5.6.7.8" + ], + }, + { + "name": "mx1.censys.io", + "type": "MX", + "class": "IN", + "preference": 10, + } + ] } - ] + } } } MX_LOOKUP_ANSWER_IPV4 = copy.deepcopy(MX_LOOKUP_ANSWER) - del MX_LOOKUP_ANSWER_IPV4["data"]["exchanges"][0]["ipv6_addresses"] + del MX_LOOKUP_ANSWER_IPV4["results"]["MXLOOKUP"]["data"]["exchanges"][0]["ipv6_addresses"] MX_LOOKUP_ANSWER_IPV6 = copy.deepcopy(MX_LOOKUP_ANSWER) - del MX_LOOKUP_ANSWER_IPV6["data"]["exchanges"][0]["ipv4_addresses"] - del MX_LOOKUP_ANSWER_IPV6["data"]["exchanges"][1]["ipv4_addresses"] + del MX_LOOKUP_ANSWER_IPV6["results"]["MXLOOKUP"]["data"]["exchanges"][0]["ipv4_addresses"] + del MX_LOOKUP_ANSWER_IPV6["results"]["MXLOOKUP"]["data"]["exchanges"][1]["ipv4_addresses"] A_LOOKUP_WWW_ZDNS_TESTING = { "name": "www.zdns-testing.com", - "class": "IN", - "status": "NOERROR", - "data": { - "ipv4_addresses": [ - "1.2.3.4", - "2.3.4.5", - "3.4.5.6" - ], - "ipv6_addresses": [ - "fde6:9bb3:dbd6::2", - "fd5a:3bce:8713::1", - "fdb3:ac76:a577::3" - ] + "results": { + "ALOOKUP": { + "class": "IN", + "status": "NOERROR", + "data": { + "ipv4_addresses": [ + "1.2.3.4", + "2.3.4.5", + "3.4.5.6" + ], + "ipv6_addresses": [ + "fde6:9bb3:dbd6::2", + "fd5a:3bce:8713::1", + "fdb3:ac76:a577::3" + ] + } + } } } A_LOOKUP_WWW_ZDNS_TESTING_IPv6 = { "name": "www.zdns-testing.com", - "class": "IN", - "status": "NOERROR", - "data": { - "ipv6_addresses": [ - "fde6:9bb3:dbd6::2", - "fd5a:3bce:8713::1", - "fdb3:ac76:a577::3" - ] + "results": { + "ALOOKUP": { + "status": "NOERROR", + "class": "IN", + "data": { + "ipv6_addresses": [ + "fde6:9bb3:dbd6::2", + "fd5a:3bce:8713::1", + "fdb3:ac76:a577::3" + ] + } + } } } A_LOOKUP_CNAME_CHAIN_03 = { "name": "cname-chain-03.esrg.stanford.edu", - "class": "IN", - "status": "NOERROR", - "data": { - "ipv4_addresses": [ - "1.2.3.4", - ], + "results": { + "ALOOKUP": { + "status": "NOERROR", + "class": "IN", + "data": { + "ipv4_addresses": [ + "1.2.3.4", + ] + } + } } } A_LOOKUP_IPV4_WWW_ZDNS_TESTING = copy.deepcopy(A_LOOKUP_WWW_ZDNS_TESTING) - del A_LOOKUP_IPV4_WWW_ZDNS_TESTING["data"]["ipv6_addresses"] + del A_LOOKUP_IPV4_WWW_ZDNS_TESTING["results"]["ALOOKUP"]["data"]["ipv6_addresses"] A_LOOKUP_IPV6_WWW_ZDNS_TESTING = copy.deepcopy(A_LOOKUP_WWW_ZDNS_TESTING) - del A_LOOKUP_IPV6_WWW_ZDNS_TESTING["data"]["ipv4_addresses"] + del A_LOOKUP_IPV6_WWW_ZDNS_TESTING["results"]["ALOOKUP"]["data"]["ipv4_addresses"] NS_LOOKUP_WWW_ZDNS_TESTING = { "name": "www.zdns-testing.com", - "status": "NOERROR", - "data": { - "servers": [ - { - "ipv4_addresses": [ - "216.239.34.108" - ], - "ipv6_addresses": [ - "2001:4860:4802:34::6c" - ], - "name": "ns-cloud-c2.googledomains.com", - "type": "NS" - }, - { - "ipv4_addresses": [ - "216.239.32.108" - ], - "ipv6_addresses": [ - "2001:4860:4802:32::6c" - ], - "name": "ns-cloud-c1.googledomains.com", - "type": "NS" - }, - { - "ipv4_addresses": [ - "216.239.38.108" - ], - "ipv6_addresses": [ - "2001:4860:4802:38::6c" - ], - "name": "ns-cloud-c4.googledomains.com", - "type": "NS" - }, - { - "ipv4_addresses": [ - "216.239.36.108" - ], - "ipv6_addresses": [ - "2001:4860:4802:36::6c" - ], - "name": "ns-cloud-c3.googledomains.com", - "type": "NS" + "results": { + "NSLOOKUP": { + "status": "NOERROR", + "data": { + "servers": [ + { + "ipv4_addresses": [ + "216.239.34.108" + ], + "ipv6_addresses": [ + "2001:4860:4802:34::6c" + ], + "name": "ns-cloud-c2.googledomains.com", + "type": "NS" + }, + { + "ipv4_addresses": [ + "216.239.32.108" + ], + "ipv6_addresses": [ + "2001:4860:4802:32::6c" + ], + "name": "ns-cloud-c1.googledomains.com", + "type": "NS" + }, + { + "ipv4_addresses": [ + "216.239.38.108" + ], + "ipv6_addresses": [ + "2001:4860:4802:38::6c" + ], + "name": "ns-cloud-c4.googledomains.com", + "type": "NS" + }, + { + "ipv4_addresses": [ + "216.239.36.108" + ], + "ipv6_addresses": [ + "2001:4860:4802:36::6c" + ], + "name": "ns-cloud-c3.googledomains.com", + "type": "NS" + } + ] } - ] + } } } NS_LOOKUP_IPV4_WWW_ZDNS_TESTING = copy.deepcopy(NS_LOOKUP_WWW_ZDNS_TESTING) - for server in NS_LOOKUP_IPV4_WWW_ZDNS_TESTING["data"]["servers"]: + for server in NS_LOOKUP_IPV4_WWW_ZDNS_TESTING["results"]["NSLOOKUP"]["data"]["servers"]: del server["ipv6_addresses"] NS_LOOKUP_IPV6_WWW_ZDNS_TESTING = copy.deepcopy(NS_LOOKUP_WWW_ZDNS_TESTING) - for server in NS_LOOKUP_IPV6_WWW_ZDNS_TESTING["data"]["servers"]: + for server in NS_LOOKUP_IPV6_WWW_ZDNS_TESTING["results"]["NSLOOKUP"]["data"]["servers"]: del server["ipv4_addresses"] PTR_LOOKUP_GOOGLE_PUB = [ @@ -559,17 +579,17 @@ def run_zdns_multiline_output(self, flags, name, executable=ZDNS_EXECUTABLE): "129.127.149.0/24": "1.2.3.4" } - def assertSuccess(self, res, cmd): - self.assertEqual(res["status"], "NOERROR", cmd) + def assertSuccess(self, res, cmd, query_type): + self.assertEqual(res["results"][query_type]["status"], "NOERROR", cmd) - def assertServFail(self, res, cmd): - self.assertEqual(res["status"], "SERVFAIL", cmd) + def assertServFail(self, res, cmd, query_type): + self.assertEqual(res["results"][query_type]["status"], "SERVFAIL", cmd) - def assertEqualAnswers(self, res, correct, cmd, key="answer"): - self.assertIn("answers", res["data"]) - for answer in res["data"]["answers"]: + def assertEqualAnswers(self, res, correct, cmd, query_type, key="answer"): + self.assertIn("answers", res["results"][query_type]["data"]) + for answer in res["results"][query_type]["data"]["answers"]: del answer["ttl"] - a = sorted(res["data"]["answers"], key=lambda x: x[key]) + a = sorted(res["results"][query_type]["data"]["answers"], key=lambda x: x[key]) b = sorted(correct, key=lambda x: x[key]) helptext = "%s\nExpected:\n%s\n\nActual:\n%s" % (cmd, json.dumps(b, indent=4), json.dumps(a, indent=4)) @@ -587,37 +607,39 @@ def _lowercase(obj): _lowercase(b) self.assertEqual(a, b, helptext) - def assertEqualNXDOMAIN(self, res, correct): + def assertEqualNXDOMAIN(self, res, correct, query_type): self.assertEqual(res["name"], correct["name"]) - self.assertEqual(res["status"], correct["status"]) + self.assertEqual(res["results"][query_type]["status"], correct["status"]) def assertEqualMXLookup(self, res, correct): self.assertEqual(res["name"], correct["name"]) - self.assertEqual(res["status"], correct["status"]) - for exchange in res["data"]["exchanges"]: + self.assertEqual(res["results"]["MXLOOKUP"]["status"], correct["results"]["MXLOOKUP"]["status"]) + for exchange in res["results"]["MXLOOKUP"]["data"]["exchanges"]: del exchange["ttl"] - self.assertEqual(recursiveSort(res["data"]["exchanges"]), recursiveSort(correct["data"]["exchanges"])) + self.assertEqual(recursiveSort(res["results"]["MXLOOKUP"]["data"]["exchanges"]), recursiveSort(correct["results"]["MXLOOKUP"]["data"]["exchanges"])) - def assertEqualALookup(self, res, correct): + def assertEqualALookup(self, res, correct, query_type): self.assertEqual(res["name"], correct["name"]) - self.assertEqual(res["status"], correct["status"]) - if "ipv4_addresses" in correct["data"]: + res = res["results"][query_type] + correct_A_lookup = correct["results"][query_type] + self.assertEqual(res["status"], correct_A_lookup["status"]) + if "ipv4_addresses" in correct_A_lookup["data"]: self.assertIn("ipv4_addresses", res["data"]) - self.assertEqual(sorted(res["data"]["ipv4_addresses"]), sorted(correct["data"]["ipv4_addresses"])) + self.assertEqual(sorted(res["data"]["ipv4_addresses"]), sorted(correct_A_lookup["data"]["ipv4_addresses"])) else: self.assertNotIn("ipv4_addresses", res["data"]) - if "ipv6_addresses" in correct["data"]: + if "ipv6_addresses" in correct_A_lookup["data"]: self.assertIn("ipv6_addresses", res["data"]) - self.assertEqual(sorted(res["data"]["ipv6_addresses"]), sorted(correct["data"]["ipv6_addresses"])) + self.assertEqual(sorted(res["data"]["ipv6_addresses"]), sorted(correct_A_lookup["data"]["ipv6_addresses"])) else: self.assertNotIn("ipv6_addresses", res["data"]) def assertEqualNSLookup(self, res, correct): self.assertEqual(res["name"], correct["name"]) - self.assertEqual(res["status"], correct["status"]) - for server in res["data"]["servers"]: + self.assertEqual(res["results"]["NSLOOKUP"]["status"], correct["results"]["NSLOOKUP"]["status"]) + for server in res["results"]["NSLOOKUP"]["data"]["servers"]: del server["ttl"] - self.assertEqual(recursiveSort(res["data"]["servers"]), recursiveSort(correct["data"]["servers"])) + self.assertEqual(recursiveSort(res["results"]["NSLOOKUP"]["data"]["servers"]), recursiveSort(correct["results"]["NSLOOKUP"]["data"]["servers"])) def assertEqualTypes(self, res, list): res_types = set() @@ -663,28 +685,28 @@ def test_a(self): c = "A" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.ROOT_A_ANSWERS, cmd) + self.assertSuccess(res, cmd, "A") + self.assertEqualAnswers(res, self.ROOT_A_ANSWERS, cmd, "A") def test_a_dig_style_args(self): c = "A zdns-testing.com" name = "" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.ROOT_A_ANSWERS, cmd) + self.assertSuccess(res, cmd, "A") + self.assertEqualAnswers(res, self.ROOT_A_ANSWERS, cmd, "A") def test_a_multiple_domains_dig_style(self): c = "A zdns-testing.com a.zdns-testing.com --iterative" name = "" cmd, res = self.run_zdns_multiline_output(c, name) - self.assertSuccess(res[0], cmd) - self.assertSuccess(res[1], cmd) + self.assertSuccess(res[0], cmd, "A") + self.assertSuccess(res[1], cmd, "A") if res[0]["name"] == "zdns-testing.com": - self.assertEqualAnswers(res[0], self.ROOT_A_ANSWERS, cmd) - self.assertEqualAnswers(res[1], self.ROOT_A_A_ZDNS_TESTING_COM_ANSWERS, cmd) + self.assertEqualAnswers(res[0], self.ROOT_A_ANSWERS, cmd, "A") + self.assertEqualAnswers(res[1], self.ROOT_A_A_ZDNS_TESTING_COM_ANSWERS, cmd, "A") else: - self.assertEqualAnswers(res[0], self.ROOT_A_A_ZDNS_TESTING_COM_ANSWERS, cmd) - self.assertEqualAnswers(res[1], self.ROOT_A_ANSWERS, cmd) + self.assertEqualAnswers(res[0], self.ROOT_A_A_ZDNS_TESTING_COM_ANSWERS, cmd, "A") + self.assertEqualAnswers(res[1], self.ROOT_A_ANSWERS, cmd, "A") def test_multiple_modules(self): iniFileContents = """ @@ -698,15 +720,11 @@ def test_multiple_modules(self): f.write(iniFileContents) c = "MULTIPLE -c " + file_name name = "zdns-testing.com" - cmd, res = self.run_zdns_multiline_output(c, name) - self.assertSuccess(res[0], cmd) - self.assertSuccess(res[1], cmd) - if res[0]["lookup_module"] == "A": - self.assertEqualAnswers(res[0], self.ROOT_A_ANSWERS, cmd) - self.assertEqualAnswers(res[1], self.ROOT_AAAA_ANSWERS, cmd) - else: - self.assertEqualAnswers(res[0], self.ROOT_AAAA_ANSWERS, cmd) - self.assertEqualAnswers(res[1], self.ROOT_A_ANSWERS, cmd) + cmd, res = self.run_zdns(c, name) + self.assertSuccess(res, cmd, "A") + self.assertSuccess(res, cmd, "AAAA") + self.assertEqualAnswers(res, self.ROOT_A_ANSWERS, cmd, "A") + self.assertEqualAnswers(res, self.ROOT_AAAA_ANSWERS, cmd, "AAAA") # delete file cmd = f"rm {file_name}" subprocess.check_output(cmd, shell=True) @@ -725,21 +743,24 @@ def test_multiple_modules_multiple_domains(self): name = "" cmd, res = self.run_zdns_multiline_output(c, name) - self.assertSuccess(res[0], cmd) - self.assertSuccess(res[1], cmd) + self.assertSuccess(res[0], cmd, "A") + self.assertSuccess(res[0], cmd, "AAAA") + self.assertSuccess(res[1], cmd, "A") + self.assertSuccess(res[1], cmd, "AAAA") for r in res: - if r["data"]["resolver"] != "1.1.1.1:53": - self.fail("Unexpected resolver") - if r["name"] == "zdns-testing.com" and r["lookup_module"] == "A": - self.assertEqualAnswers(r, self.ROOT_A_ANSWERS, cmd) - elif r["name"] == "zdns-testing.com" and r["lookup_module"] == "AAAA": - self.assertEqualAnswers(r, self.ROOT_AAAA_ANSWERS, cmd) - elif r["name"] == "mx1.zdns-testing.com" and r["lookup_module"] == "A": - self.assertEqualAnswers(r, self.A_MX1_ZDNS_TESTING_COM_ANSWERS, cmd) - elif r["name"] == "mx1.zdns-testing.com" and r["lookup_module"] == "AAAA": - self.assertEqualAnswers(r, self.AAAA_MX1_ZDNS_TESTING_COM_ANSWERS, cmd) - else: - self.fail("Unexpected response") + for query_type, query_res in r["results"].items(): + if query_res["data"]["resolver"] != "1.1.1.1:53": + self.fail("Unexpected resolver") + if r["name"] == "zdns-testing.com" and query_type == "A": + self.assertEqualAnswers(r, self.ROOT_A_ANSWERS, cmd, "A") + elif r["name"] == "zdns-testing.com" and query_type == "AAAA": + self.assertEqualAnswers(r, self.ROOT_AAAA_ANSWERS, cmd, "AAAA") + elif r["name"] == "mx1.zdns-testing.com" and query_type == "A": + self.assertEqualAnswers(r, self.A_MX1_ZDNS_TESTING_COM_ANSWERS, cmd, "A") + elif r["name"] == "mx1.zdns-testing.com" and query_type == "AAAA": + self.assertEqualAnswers(r, self.AAAA_MX1_ZDNS_TESTING_COM_ANSWERS, cmd, "AAAA") + else: + self.fail("Unexpected response") # delete file cmd = f"rm {file_name}" subprocess.check_output(cmd, shell=True) @@ -758,8 +779,8 @@ def test_multiple_modules_with_special_modules(self): c = "MULTIPLE -c " + file_name name = "www.zdns-testing.com" cmd, res = self.run_zdns_multiline_output(c, name) - self.assertSuccess(res[0], cmd) - self.assertEqualALookup(res[0], self.A_LOOKUP_WWW_ZDNS_TESTING_IPv6) + self.assertSuccess(res[0], cmd, "ALOOKUP") + self.assertEqualALookup(res[0], self.A_LOOKUP_WWW_ZDNS_TESTING_IPv6, "ALOOKUP") # delete file cmd = f"rm {file_name}" subprocess.check_output(cmd, shell=True) @@ -769,175 +790,175 @@ def test_cname(self): c = "CNAME" name = "www.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.WWW_CNAME_ANSWERS, cmd) + self.assertSuccess(res, cmd, "CNAME") + self.assertEqualAnswers(res, self.WWW_CNAME_ANSWERS, cmd, "CNAME") def test_cname_loop_iterative(self): c = "A --iterative" name = "cname-loop.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.CNAME_LOOP_ANSWERS, cmd) + self.assertSuccess(res, cmd, "A") + self.assertEqualAnswers(res, self.CNAME_LOOP_ANSWERS, cmd, "A") def test_a_behind_cname(self): c = "A" name = "www.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.WWW_CNAME_AND_A_ANSWERS, cmd) + self.assertSuccess(res, cmd, "A") + self.assertEqualAnswers(res, self.WWW_CNAME_AND_A_ANSWERS, cmd, "A") def test_aaaa_behind_cname(self): c = "AAAA" name = "www.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.WWW_CNAME_AND_AAAA_ANSWERS, cmd) + self.assertSuccess(res, cmd, "AAAA") + self.assertEqualAnswers(res, self.WWW_CNAME_AND_AAAA_ANSWERS, cmd, "AAAA") def test_caa(self): c = "CAA" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.CAA_RECORD, cmd, key="name") + self.assertSuccess(res, cmd, "CAA") + self.assertEqualAnswers(res, self.CAA_RECORD, cmd, key="name", query_type="CAA") def test_txt(self): c = "TXT" name = "test_txt.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.TXT_RECORD, cmd) + self.assertSuccess(res, cmd, "TXT") + self.assertEqualAnswers(res, self.TXT_RECORD, cmd, "TXT") def test_a_iterative(self): c = "A --iterative" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.ROOT_A_ANSWERS, cmd) + self.assertSuccess(res, cmd, "A") + self.assertEqualAnswers(res, self.ROOT_A_ANSWERS, cmd, "A") def test_a_iterative_nxdomain(self): c = "A --iterative" name = "zdns-testing-nxdomain.com" cmd, res = self.run_zdns(c, name) - self.assertEqualNXDOMAIN(res, self.NXDOMAIN_ANSWER) + self.assertEqualNXDOMAIN(res, self.NXDOMAIN_ANSWER, "A") def test_aaaa(self): c = "AAAA" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.ROOT_AAAA_ANSWERS, cmd) + self.assertSuccess(res, cmd, "AAAA") + self.assertEqualAnswers(res, self.ROOT_AAAA_ANSWERS, cmd, "AAAA") def test_aaaa_iterative(self): c = "AAAA --iterative" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.ROOT_AAAA_ANSWERS, cmd) + self.assertSuccess(res, cmd, "AAAA") + self.assertEqualAnswers(res, self.ROOT_AAAA_ANSWERS, cmd, "AAAA") def test_mx(self): c = "MX" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.MX_SERVERS, cmd) + self.assertSuccess(res, cmd, "MX") + self.assertEqualAnswers(res, self.MX_SERVERS, cmd, "MX") def test_mx_iterative(self): c = "MX --iterative" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.MX_SERVERS, cmd) + self.assertSuccess(res, cmd, "MX") + self.assertEqualAnswers(res, self.MX_SERVERS, cmd, "MX") def test_ns(self): c = "NS" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.NS_SERVERS, cmd) + self.assertSuccess(res, cmd, "NS") + self.assertEqualAnswers(res, self.NS_SERVERS, cmd, "NS") def test_ns_iterative(self): c = "NS --iterative" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.NS_SERVERS, cmd) + self.assertSuccess(res, cmd, "NS") + self.assertEqualAnswers(res, self.NS_SERVERS, cmd, "NS") def test_mx_lookup(self): c = "mxlookup --ipv4-lookup --ipv6-lookup" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "MXLOOKUP") self.assertEqualMXLookup(res, self.MX_LOOKUP_ANSWER) def test_mx_lookup_iterative(self): c = "mxlookup --ipv4-lookup --ipv6-lookup --iterative" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "MXLOOKUP") self.assertEqualMXLookup(res, self.MX_LOOKUP_ANSWER) def test_mx_lookup_ipv4(self): c = "mxlookup --ipv4-lookup" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "MXLOOKUP") self.assertEqualMXLookup(res, self.MX_LOOKUP_ANSWER_IPV4) def test_mx_lookup_ipv6(self): c = "mxlookup --ipv6-lookup" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "MXLOOKUP") self.assertEqualMXLookup(res, self.MX_LOOKUP_ANSWER_IPV6) def test_mx_lookup_default(self): c = "mxlookup" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "MXLOOKUP") self.assertEqualMXLookup(res, self.MX_LOOKUP_ANSWER_IPV4) def test_a_lookup(self): c = "alookup --ipv4-lookup --ipv6-lookup" name = "www.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualALookup(res, self.A_LOOKUP_WWW_ZDNS_TESTING) + self.assertSuccess(res, cmd, "ALOOKUP") + self.assertEqualALookup(res, self.A_LOOKUP_WWW_ZDNS_TESTING, "ALOOKUP") def test_a_lookup_iterative(self): c = "alookup --ipv4-lookup --ipv6-lookup --iterative" name = "www.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualALookup(res, self.A_LOOKUP_WWW_ZDNS_TESTING) + self.assertSuccess(res, cmd, "ALOOKUP") + self.assertEqualALookup(res, self.A_LOOKUP_WWW_ZDNS_TESTING, "ALOOKUP") def test_a_lookup_ipv4(self): c = "alookup --ipv4-lookup" name = "www.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualALookup(res, self.A_LOOKUP_IPV4_WWW_ZDNS_TESTING) + self.assertSuccess(res, cmd, "ALOOKUP") + self.assertEqualALookup(res, self.A_LOOKUP_IPV4_WWW_ZDNS_TESTING, "ALOOKUP") def test_a_lookup_ipv6(self): c = "alookup --ipv6-lookup" name = "www.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualALookup(res, self.A_LOOKUP_IPV6_WWW_ZDNS_TESTING) + self.assertSuccess(res, cmd, "ALOOKUP") + self.assertEqualALookup(res, self.A_LOOKUP_IPV6_WWW_ZDNS_TESTING, "ALOOKUP") def test_a_lookup_default(self): c = "alookup" name = "www.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualALookup(res, self.A_LOOKUP_IPV4_WWW_ZDNS_TESTING) + self.assertSuccess(res, cmd, "ALOOKUP") + self.assertEqualALookup(res, self.A_LOOKUP_IPV4_WWW_ZDNS_TESTING, "ALOOKUP") def test_a_lookup_iterative_cname_loop(self): c = "alookup --iterative" name = "cname-loop.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - assert len(res["data"]) == 0 + self.assertSuccess(res, cmd, "ALOOKUP") + assert len(res["results"]["ALOOKUP"]["data"]) == 0 # There exists DNS records in esrg.stanford.edu and zdns-testing.com of the form: # cname-chain-01.esrg.stanford.edu CNAME cname-chain-02.zdns-testing.com. @@ -950,133 +971,105 @@ def test_a_lookup_cname_chain_too_long(self): c = "alookup --iterative --ipv4-lookup" name = "cname-chain-01.esrg.stanford.edu" cmd, res = self.run_zdns(c, name) - self.assertServFail(res, cmd) + self.assertServFail(res, cmd, "ALOOKUP") def test_a_lookup_cname_chain(self): c = "alookup --iterative --ipv4-lookup" name = "cname-chain-03.esrg.stanford.edu" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualALookup(res, self.A_LOOKUP_CNAME_CHAIN_03) + self.assertSuccess(res, cmd, "ALOOKUP") + self.assertEqualALookup(res, self.A_LOOKUP_CNAME_CHAIN_03, "ALOOKUP") def test_type_option_server_mode_a_lookup_ipv4(self): c = "A --override-name=www.zdns-testing.com --name-server-mode" name = "8.8.8.8" cmd, res = self.run_zdns(c, name) - self.assertEqual(res["data"]["resolver"], "8.8.8.8:53") - self.assertEqualAnswers(res, self.WWW_CNAME_AND_A_ANSWERS, cmd) + self.assertEqual(res["results"]["A"]["data"]["resolver"], "8.8.8.8:53") + self.assertEqualAnswers(res, self.WWW_CNAME_AND_A_ANSWERS, cmd, "A") def test_dig_style_type_option_server_mode_a_lookup_ipv4(self): c = "A 8.8.8.8 --override-name=www.zdns-testing.com --name-server-mode" name = "" cmd, res = self.run_zdns(c, name) - self.assertEqual(res["data"]["resolver"], "8.8.8.8:53") - self.assertEqualAnswers(res, self.WWW_CNAME_AND_A_ANSWERS, cmd) + self.assertEqual(res["results"]["A"]["data"]["resolver"], "8.8.8.8:53") + self.assertEqualAnswers(res, self.WWW_CNAME_AND_A_ANSWERS, cmd, "A") def test_ns_lookup(self): c = "nslookup --ipv4-lookup --ipv6-lookup" name = "www.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "NSLOOKUP") self.assertEqualNSLookup(res, self.NS_LOOKUP_WWW_ZDNS_TESTING) def test_ns_lookup_iterative(self): c = "nslookup --ipv4-lookup --ipv6-lookup --iterative" name = "www.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualALookup(res, self.NS_LOOKUP_WWW_ZDNS_TESTING) + self.assertSuccess(res, cmd, "NSLOOKUP") + self.assertEqualALookup(res, self.NS_LOOKUP_WWW_ZDNS_TESTING, "NSLOOKUP") def test_ns_lookup_default(self): c = "nslookup" name = "www.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "NSLOOKUP") self.assertEqualNSLookup(res, self.NS_LOOKUP_IPV4_WWW_ZDNS_TESTING) def test_ns_lookup_ipv4(self): c = "nslookup --ipv4-lookup" name = "www.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "NSLOOKUP") self.assertEqualNSLookup(res, self.NS_LOOKUP_IPV4_WWW_ZDNS_TESTING) def test_ns_lookup_ipv6(self): c = "nslookup --ipv6-lookup" name = "www.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "NSLOOKUP") self.assertEqualNSLookup(res, self.NS_LOOKUP_IPV6_WWW_ZDNS_TESTING) def test_spf_lookup(self): c = "spf" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqual(res["data"], self.SPF_ANSWER["data"]) + self.assertSuccess(res, cmd, "SPF") + self.assertEqual(res["results"]["SPF"]["data"], self.SPF_ANSWER["data"]) def test_spf_lookup_iterative(self): c = "spf --iterative" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqual(res["data"], self.SPF_ANSWER["data"]) + self.assertSuccess(res, cmd, "SPF") + self.assertEqual(res["results"]["SPF"]["data"], self.SPF_ANSWER["data"]) def test_dmarc_lookup(self): c = "dmarc" name = "_dmarc.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqual(res["data"], self.DMARC_ANSWER["data"]) + self.assertSuccess(res, cmd, "DMARC") + self.assertEqual(res["results"]["DMARC"]["data"], self.DMARC_ANSWER["data"]) def test_dmarc_lookup_iterative(self): c = "dmarc --iterative" name = "_dmarc.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqual(res["data"], self.DMARC_ANSWER["data"]) + self.assertSuccess(res, cmd, "DMARC") + self.assertEqual(res["results"]["DMARC"]["data"], self.DMARC_ANSWER["data"]) def test_ptr(self): c = "PTR" name = "8.8.8.8" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.PTR_LOOKUP_GOOGLE_PUB, cmd) + self.assertSuccess(res, cmd, "PTR") + self.assertEqualAnswers(res, self.PTR_LOOKUP_GOOGLE_PUB, cmd, "PTR") def test_ptr_iterative(self): c = "PTR --iterative" name = "8.8.8.8" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.PTR_LOOKUP_GOOGLE_PUB, cmd) - - def test_spf(self): - c = "SPF" - name = "zdns-testing.com" - cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqual(res["data"], self.SPF_ANSWER["data"]) - - def test_spf_iterative(self): - c = "SPF --iterative" - name = "zdns-testing.com" - cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqual(res["data"], self.SPF_ANSWER["data"]) - - def test_dmarc(self): - c = "DMARC" - name = "_dmarc.zdns-testing.com" - cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqual(res["data"], self.DMARC_ANSWER["data"]) - - def test_dmarc_iterative(self): - c = "DMARC --iterative" - name = "_dmarc.zdns-testing.com" - cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqual(res["data"], self.DMARC_ANSWER["data"]) + self.assertSuccess(res, cmd, "PTR") + self.assertEqualAnswers(res, self.PTR_LOOKUP_GOOGLE_PUB, cmd, "PTR") def test_axfr(self): # In this test, we just check for few specific records @@ -1086,72 +1079,72 @@ def test_axfr(self): c = "axfr" name = "zonetransfer.me" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "AXFR") f = open("testing/axfr.json") axfr_answer = json.load(f) - self.assertEqualAxfrLookup(res["data"]["servers"][0]["records"], axfr_answer["data"]["servers"][0]["records"]) + self.assertEqualAxfrLookup(res["results"]["AXFR"]["data"]["servers"][0]["records"], axfr_answer["data"]["servers"][0]["records"]) f.close() def test_soa(self): c = "SOA" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.SOA_ANSWERS, cmd, key="serial") + self.assertSuccess(res, cmd, c) + self.assertEqualAnswers(res, self.SOA_ANSWERS, cmd, c, key="serial") def test_srv(self): c = "SRV" name = "_sip._udp.sip.voice.google.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.SRV_ANSWERS, cmd, key="target") + self.assertSuccess(res, cmd, c) + self.assertEqualAnswers(res, self.SRV_ANSWERS, cmd,c, key="target") def test_tlsa(self): c = "TLSA" name = "_25._tcp.mail.ietf.org" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) - self.assertEqualAnswers(res, self.TLSA_ANSWERS, cmd, key="certificate") + self.assertSuccess(res, cmd, c) + self.assertEqualAnswers(res, self.TLSA_ANSWERS, cmd, c, key="certificate") def test_too_big_txt_udp(self): c = "TXT --udp-only --name-servers=8.8.8.8:53" name = "large-text.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertEqual(res["status"], "TRUNCATED") - self.assertEqual(res["data"]["protocol"], "udp") + self.assertEqual(res["results"]["TXT"]["status"], "TRUNCATED") + self.assertEqual(res["results"]["TXT"]["data"]["protocol"], "udp") def test_too_big_txt_tcp(self): c = "TXT --tcp-only --name-servers=8.8.8.8:53" # Azure DNS does not provide results. name = "large-text.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertEqualAnswers(res, self.TCP_LARGE_TXT_ANSWERS, cmd, key="answer") + self.assertEqualAnswers(res, self.TCP_LARGE_TXT_ANSWERS, cmd, "TXT", key="answer") def test_too_big_txt_all(self): c = "TXT --name-servers=8.8.8.8:53" name = "large-text.zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertEqual(res["data"]["protocol"], "tcp") - self.assertEqualAnswers(res, self.TCP_LARGE_TXT_ANSWERS, cmd, key="answer") + self.assertEqual(res["results"]["TXT"]["data"]["protocol"], "tcp") + self.assertEqualAnswers(res, self.TCP_LARGE_TXT_ANSWERS, cmd, "TXT", key="answer") def test_override_name(self): c = "A --override-name=zdns-testing.com" name = "notrealname.com" cmd, res = self.run_zdns(c, name) - self.assertEqualAnswers(res, self.ROOT_A_ANSWERS, cmd) + self.assertEqualAnswers(res, self.ROOT_A_ANSWERS, cmd, "A") def test_server_mode_a_lookup_ipv4(self): c = "A --override-name=zdns-testing.com --name-server-mode" name = "8.8.8.8:53" cmd, res = self.run_zdns(c, name) - self.assertEqual(res["data"]["resolver"], "8.8.8.8:53") - self.assertEqualAnswers(res, self.ROOT_A_ANSWERS, cmd) + self.assertEqual(res["results"]["A"]["data"]["resolver"], "8.8.8.8:53") + self.assertEqualAnswers(res, self.ROOT_A_ANSWERS, cmd, "A") def test_mixed_mode_a_lookup_ipv4(self): c = "A --name-servers=0.0.0.0" name = "zdns-testing.com,8.8.8.8:53" cmd, res = self.run_zdns(c, name) - self.assertEqual(res["data"]["resolver"], "8.8.8.8:53") - self.assertEqualAnswers(res, self.ROOT_A_ANSWERS, cmd) + self.assertEqual(res["results"]["A"]["data"]["resolver"], "8.8.8.8:53") + self.assertEqualAnswers(res, self.ROOT_A_ANSWERS, cmd, "A") def test_local_addr_interface_warning(self): c = "A --local-addr 192.168.1.5 --local-interface en0" @@ -1164,22 +1157,25 @@ def test_edns0_client_subnet(self): # Hardcoding a name server that supports ECS; Github's default recursive does not. c = f"A --client-subnet {subnet} --name-servers=8.8.8.8:53" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "A") address, netmask = tuple(subnet.split("/")) family = 1 if ip_address(address).version == 4 else 2 + original_res = res + res = res["results"]["A"] self.assertEqual(address, res["data"]['additionals'][0]['csubnet']['address']) self.assertEqual(int(netmask), res["data"]['additionals'][0]['csubnet']["source_netmask"]) self.assertEqual(family, res["data"]['additionals'][0]['csubnet']['family']) self.assertTrue("source_scope" in res["data"]['additionals'][0]['csubnet']) correct = [{"type": "A", "class": "IN", "answer": ip_addr, "name": "ecs-geo.zdns-testing.com"}] - self.assertEqualAnswers(res, correct, cmd) + self.assertEqualAnswers(original_res, correct, cmd, "A") def test_edns0_nsid(self): name = "google.com" # using Google Public DNS for testing as its NSID always follows format 'gpdns-' c = f"A --nsid --name-servers=8.8.8.8:53" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "A") + res = res["results"]["A"] self.assertTrue("nsid" in res["data"]['additionals'][0]) self.assertTrue(res["data"]['additionals'][0]['nsid']['nsid'].startswith("gpdns-")) @@ -1188,7 +1184,8 @@ def test_edns0_ede_1(self): # using Cloudflare Public DNS (1.1.1.1) that implements EDE c = f"A --name-servers=1.1.1.1:53" cmd, res = self.run_zdns(c, name) - self.assertServFail(res, cmd) + self.assertServFail(res, cmd, 'A') + res = res["results"]["A"] self.assertTrue("ede" in res["data"]['additionals'][0]) ede_obj = res["data"]['additionals'][0]["ede"][0] self.assertEqual("DNSKEY Missing", ede_obj["error_text"]) @@ -1200,7 +1197,8 @@ def test_edns0_ede_2_cd(self): # using Cloudflare Public DNS (1.1.1.1) that implements EDE, checking disabled resulting in NOERROR c = f"A --name-servers=1.1.1.1:53 --checking-disabled" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "A") + res = res["results"]["A"] self.assertTrue("ede" in res["data"]['additionals'][0]) ede_obj = res["data"]['additionals'][0]["ede"][0] self.assertEqual("DNSKEY Missing", ede_obj["error_text"]) @@ -1212,7 +1210,8 @@ def test_dnssec_response(self): c = f"SOA --dnssec --name-servers=8.8.8.8:53" name = "." cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "SOA") + res = res["results"]["SOA"] self.assertEqual('do', res["data"]['additionals'][0]['flags']) self.assertEqualTypes(res, ["SOA", "RRSIG"]) @@ -1220,19 +1219,20 @@ def test_cd_bit_not_set(self): c = "A --name-servers=8.8.8.8:53" name = "dnssec-failed.org" cmd, res = self.run_zdns(c, name) - self.assertServFail(res, cmd) + self.assertServFail(res, cmd, "A") def test_cd_bit_set(self): c = "A --name-servers=8.8.8.8:53 --checking-disabled" name = "dnssec-failed.org" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "A") def test_timetamps(self): c = "A" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "A") + res = res["results"]["A"] assert "timestamp" in res date = datetime.datetime.strptime(res["timestamp"], "%Y-%m-%dT%H:%M:%S%z") self.assertTrue(date.microsecond == 0) # microseconds should be 0 since we didn't call with --nanoseconds @@ -1241,7 +1241,8 @@ def test_timetamps_nanoseconds(self): c = "A --nanoseconds" name = "zdns-testing.com" cmd, res = self.run_zdns(c, name) - self.assertSuccess(res, cmd) + self.assertSuccess(res, cmd, "A") + res = res["results"]["A"] assert "timestamp" in res date = parser.parse(res["timestamp"]) self.assertTrue(date.microsecond != 0) From 7febad6fdb2ce88d5bcb6c78132adefb6449e883 Mon Sep 17 00:00:00 2001 From: phillip-stephens Date: Fri, 23 Aug 2024 13:04:25 -0400 Subject: [PATCH 5/6] edit todo --- benchmark/stats.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/benchmark/stats.go b/benchmark/stats.go index 5a09e475..d9cdaa71 100644 --- a/benchmark/stats.go +++ b/benchmark/stats.go @@ -135,8 +135,7 @@ func updateStats(line string, s *Stats) { log.Panicf("failed to unmarshal JSON (%s): %v", line, err) } domainName := res.Name - // Assuming we only run a single module - // TODO - this will only work for a single module + // TODO - this will only work for a single module benchmark, we'll need to adjust this if we want to benchmark multi-module var duration float64 var status zdns.Status for _, moduleResult := range res.Results { From 30ca109446bd49a13a0ad35efa885ca0f2acef7a Mon Sep 17 00:00:00 2001 From: phillip-stephens Date: Fri, 23 Aug 2024 13:13:14 -0400 Subject: [PATCH 6/6] update README.md --- README.md | 124 +++++++++++++++++++++++++++++------------------------- 1 file changed, 66 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index 07e8d39d..adc32d8a 100644 --- a/README.md +++ b/README.md @@ -71,40 +71,42 @@ For example, the command: returns: ```json { - "name": "censys.io", - "class": "IN", - "status": "NOERROR", - "data": { - "answers": [ - { - "ttl": 300, - "type": "A", - "class": "IN", - "name": "censys.io", - "data": "216.239.38.21" + "name": "censys.io", + "results": { + "A": { + "data": { + "additionals": [ + { + "flags": "", + "type": "EDNS0", + "udpsize": 512, + "version": 0 + } + ], + "answers": [ + { + "answer": "104.18.10.85", + "class": "IN", + "name": "censys.io", + "ttl": 300, + "type": "A" + }, + { + "answer": "104.18.11.85", + "class": "IN", + "name": "censys.io", + "ttl": 300, + "type": "A" + } + ], + "protocol": "udp", + "resolver": "[2603:6013:9d00:3302::1]:53" + }, + "duration": 0.285295416, + "status": "NOERROR", + "timestamp": "2024-08-23T13:12:43-04:00" } - ], - "additionals": [ - { - "ttl": 34563, - "type": "A", - "class": "IN", - "name": "ns-cloud-e1.googledomains.com", - "data": "216.239.32.110" - }, - ], - "authorities": [ - { - "ttl": 53110, - "type": "NS", - "class": "IN", - "name": "censys.io", - "data": "ns-cloud-e1.googledomains.com." - }, - ], - "protocol": "udp", - "resolver": "30.128.52.190:53" - } + } } ``` @@ -128,32 +130,38 @@ For example, returns: ```json { - "name": "censys.io", - "status": "NOERROR", - "data": { - "exchanges": [ - { - "name": "aspmx.l.google.com", - "type": "MX", - "class": "IN", - "preference": 1, - "ipv4_addresses": [ - "74.125.28.26" - ], - "ttl": 288 - }, - { - "name": "alt1.aspmx.l.google.com", - "type": "MX", - "class": "IN", - "preference": 5, - "ipv4_addresses": [ - "64.233.182.26" - ], - "ttl": 288 + "name": "censys.io", + "results": { + "MXLOOKUP": { + "data": { + "exchanges": [ + { + "class": "IN", + "ipv4_addresses": [ + "209.85.202.27" + ], + "name": "alt1.aspmx.l.google.com", + "preference": 5, + "ttl": 300, + "type": "MX" + }, + { + "class": "IN", + "ipv4_addresses": [ + "142.250.31.26" + ], + "name": "aspmx.l.google.com", + "preference": 1, + "ttl": 300, + "type": "MX" + } + ] + }, + "duration": 0.154786958, + "status": "NOERROR", + "timestamp": "2024-08-23T13:10:11-04:00" } - ] - } + } } ```