266 lines
6.9 KiB
Go
266 lines
6.9 KiB
Go
package certmagic
|
|
|
|
// Code in this file adapted from go-acme/lego, July 2020:
|
|
// https://github.com/go-acme/lego
|
|
// by Ludovic Fernandez and Dominik Menke
|
|
//
|
|
// It has been modified.
|
|
|
|
import (
|
|
"net"
|
|
"reflect"
|
|
"runtime"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func TestLookupNameserversOK(t *testing.T) {
|
|
testCases := []struct {
|
|
fqdn string
|
|
nss []string
|
|
}{
|
|
{
|
|
fqdn: "physics.georgetown.edu.",
|
|
nss: []string{"ns4.georgetown.edu.", "ns5.georgetown.edu.", "ns6.georgetown.edu."},
|
|
},
|
|
}
|
|
|
|
for i, test := range testCases {
|
|
test := test
|
|
i := i
|
|
t.Run(test.fqdn, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
nss, err := lookupNameservers(zap.NewNop(), test.fqdn, recursiveNameservers(nil))
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
sort.Strings(nss)
|
|
sort.Strings(test.nss)
|
|
|
|
if !reflect.DeepEqual(test.nss, nss) {
|
|
t.Errorf("Test %d: expected %+v but got %+v", i, test.nss, nss)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLookupNameserversErr(t *testing.T) {
|
|
testCases := []struct {
|
|
desc string
|
|
fqdn string
|
|
error string
|
|
}{
|
|
{
|
|
desc: "invalid tld",
|
|
fqdn: "_null.n0n0.",
|
|
error: "could not determine the zone",
|
|
},
|
|
}
|
|
|
|
for i, test := range testCases {
|
|
test := test
|
|
i := i
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
_, err := lookupNameservers(zap.NewNop(), test.fqdn, nil)
|
|
if err == nil {
|
|
t.Errorf("expected error, got none")
|
|
}
|
|
if !strings.Contains(err.Error(), test.error) {
|
|
t.Errorf("Test %d: Expected error to contain '%s' but got '%s'", i, test.error, err.Error())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
var findXByFqdnTestCases = []struct {
|
|
desc string
|
|
fqdn string
|
|
zone string
|
|
primaryNs string
|
|
nameservers []string
|
|
expectedError string
|
|
skipTest bool
|
|
}{
|
|
{
|
|
desc: "domain is a CNAME",
|
|
fqdn: "scholar.google.com.",
|
|
zone: "google.com.",
|
|
primaryNs: "ns1.google.com.",
|
|
nameservers: recursiveNameservers(nil),
|
|
},
|
|
{
|
|
desc: "domain is a non-existent subdomain",
|
|
fqdn: "foo.google.com.",
|
|
zone: "google.com.",
|
|
primaryNs: "ns1.google.com.",
|
|
nameservers: recursiveNameservers(nil),
|
|
},
|
|
{
|
|
desc: "domain is a eTLD",
|
|
fqdn: "example.com.ac.",
|
|
zone: "ac.",
|
|
primaryNs: "a0.nic.ac.",
|
|
nameservers: recursiveNameservers(nil),
|
|
},
|
|
{
|
|
desc: "domain is a cross-zone CNAME",
|
|
fqdn: "cross-zone-example.assets.sh.",
|
|
zone: "assets.sh.",
|
|
primaryNs: "gina.ns.cloudflare.com.",
|
|
nameservers: recursiveNameservers(nil),
|
|
},
|
|
{
|
|
desc: "NXDOMAIN",
|
|
fqdn: "test.loho.jkl.",
|
|
zone: "loho.jkl.",
|
|
nameservers: []string{"1.1.1.1:53"},
|
|
expectedError: "could not find the start of authority for test.loho.jkl.: NXDOMAIN",
|
|
},
|
|
{
|
|
desc: "several non existent nameservers",
|
|
fqdn: "scholar.google.com.",
|
|
zone: "google.com.",
|
|
primaryNs: "ns1.google.com.",
|
|
nameservers: []string{":7053", ":8053", "1.1.1.1:53"},
|
|
// Windows takes a super long time to timeout and this negatively impacts CI.
|
|
// Essentially, we know this works, but Windows is just slow to give up.
|
|
skipTest: runtime.GOOS == "windows",
|
|
},
|
|
{
|
|
desc: "only non existent nameservers",
|
|
fqdn: "scholar.google.com.",
|
|
zone: "google.com.",
|
|
nameservers: []string{":7053", ":8053", ":9053"},
|
|
expectedError: "could not find the start of authority for scholar.google.com.:",
|
|
// Windows takes a super long time to timeout and this negatively impacts CI.
|
|
// Essentially, we know this works, but Windows is just slow to give up.
|
|
skipTest: runtime.GOOS == "windows",
|
|
},
|
|
{
|
|
desc: "no nameservers",
|
|
fqdn: "test.ldez.com.",
|
|
zone: "ldez.com.",
|
|
nameservers: []string{},
|
|
expectedError: "could not find the start of authority for test.ldez.com.",
|
|
},
|
|
}
|
|
|
|
func TestFindZoneByFqdn(t *testing.T) {
|
|
for i, test := range findXByFqdnTestCases {
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
if test.skipTest {
|
|
t.Skip("skipping test")
|
|
}
|
|
clearFqdnCache()
|
|
|
|
zone, err := findZoneByFQDN(zap.NewNop(), test.fqdn, test.nameservers)
|
|
if test.expectedError != "" {
|
|
if err == nil {
|
|
t.Errorf("test %d: expected error, got none", i)
|
|
return
|
|
}
|
|
if !strings.Contains(err.Error(), test.expectedError) {
|
|
t.Errorf("test %d: expected error to contain '%s' but got '%s'", i, test.expectedError, err.Error())
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Errorf("test %d: expected no error, but got: %v", i, err)
|
|
}
|
|
if zone != test.zone {
|
|
t.Errorf("test %d: expected zone '%s' but got '%s'", i, zone, test.zone)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestResolveConfServers(t *testing.T) {
|
|
var testCases = []struct {
|
|
fixture string
|
|
expected []string
|
|
defaults []string
|
|
}{
|
|
{
|
|
fixture: "testdata/resolv.conf.1",
|
|
defaults: []string{"127.0.0.1:53"},
|
|
expected: []string{"10.200.3.249", "10.200.3.250:5353", "2001:4860:4860::8844", "[10.0.0.1]:5353"},
|
|
},
|
|
{
|
|
fixture: "testdata/resolv.conf.nonexistant",
|
|
defaults: []string{"127.0.0.1:53"},
|
|
expected: []string{"127.0.0.1:53"},
|
|
},
|
|
}
|
|
|
|
for i, test := range testCases {
|
|
t.Run(test.fixture, func(t *testing.T) {
|
|
result := systemOrDefaultNameservers(test.fixture, test.defaults)
|
|
|
|
sort.Strings(result)
|
|
sort.Strings(test.expected)
|
|
|
|
if !reflect.DeepEqual(test.expected, result) {
|
|
t.Errorf("Test %d: Expected %v but got %v", i, test.expected, result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRecursiveNameserversAddsPort(t *testing.T) {
|
|
type want struct {
|
|
port string
|
|
}
|
|
custom := []string{"127.0.0.1", "ns1.google.com:43"}
|
|
expectations := []want{{port: "53"}, {port: "43"}}
|
|
results := recursiveNameservers(custom)
|
|
|
|
if !reflect.DeepEqual(custom, []string{"127.0.0.1", "ns1.google.com:43"}) {
|
|
t.Errorf("Expected custom nameservers to be unmodified. got %v", custom)
|
|
}
|
|
|
|
if len(results) != len(expectations) {
|
|
t.Errorf("%v wrong results length. got %d, want %d", results, len(results), len(expectations))
|
|
}
|
|
|
|
var hasCustom bool
|
|
for i, res := range results {
|
|
hasCustom = hasCustom || strings.HasPrefix(res, custom[0])
|
|
if _, port, err := net.SplitHostPort(res); err != nil {
|
|
t.Errorf("%v Error splitting result %d into host and port: %v", results, i, err)
|
|
} else {
|
|
if port != expectations[i].port {
|
|
t.Errorf("%v Expected result %d to have port %s but got %s", results, i, expectations[i].port, port)
|
|
}
|
|
}
|
|
}
|
|
if !hasCustom {
|
|
t.Errorf("%v Expected custom resolvers to be included, but they weren't: %v", results, custom)
|
|
}
|
|
|
|
}
|
|
|
|
func TestRecursiveNameserversDefaults(t *testing.T) {
|
|
results := recursiveNameservers(nil)
|
|
if len(results) < 1 {
|
|
t.Errorf("%v Expected at least 1 records as default when nil custom", results)
|
|
}
|
|
|
|
results = recursiveNameservers([]string{})
|
|
if len(results) < 1 {
|
|
t.Errorf("%v Expected at least 1 records as default when empty custom", results)
|
|
}
|
|
}
|
|
|
|
func clearFqdnCache() {
|
|
fqdnSOACacheMu.Lock()
|
|
fqdnSOACache = make(map[string]*soaCacheEntry)
|
|
fqdnSOACacheMu.Unlock()
|
|
}
|