Report DNS errors properly.

Previously we would return a detailed errorString, which ProblemDetailsFromDNSError
would turn into a generic, uninformative "Server failure at resolver".

Now we return a new internal dnsError type, which ProblemDetailsFromDNSError can
turn into a more informative message to be shown to the user.
This commit is contained in:
Jacob Hoffman-Andrews 2015-12-24 15:33:07 -08:00
parent 2b15b6cc33
commit df4ba7aaa8
10 changed files with 237 additions and 179 deletions

View File

@ -201,24 +201,24 @@ func (dnsResolver *DNSResolverImpl) exchangeOne(hostname string, qtype uint16, m
// the provided hostname.
func (dnsResolver *DNSResolverImpl) LookupTXT(hostname string) ([]string, error) {
var txt []string
r, err := dnsResolver.exchangeOne(hostname, dns.TypeTXT, dnsResolver.txtStats)
dnsType := dns.TypeTXT
r, err := dnsResolver.exchangeOne(hostname, dnsType, dnsResolver.txtStats)
if err != nil {
return nil, err
return nil, &dnsError{dnsType, hostname, err, -1}
}
if r.Rcode != dns.RcodeSuccess {
err = fmt.Errorf("DNS failure: %d-%s for TXT query", r.Rcode, dns.RcodeToString[r.Rcode])
return nil, err
return nil, &dnsError{dnsType, hostname, nil, r.Rcode}
}
for _, answer := range r.Answer {
if answer.Header().Rrtype == dns.TypeTXT {
if answer.Header().Rrtype == dnsType {
if txtRec, ok := answer.(*dns.TXT); ok {
txt = append(txt, strings.Join(txtRec.Txt, ""))
}
}
}
return txt, err
return txt, nil
}
func isPrivateV4(ip net.IP) bool {
@ -235,18 +235,17 @@ func isPrivateV4(ip net.IP) bool {
// aliases and return relevant A records.
func (dnsResolver *DNSResolverImpl) LookupHost(hostname string) ([]net.IP, error) {
var addrs []net.IP
r, err := dnsResolver.exchangeOne(hostname, dns.TypeA, dnsResolver.aStats)
dnsType := dns.TypeA
r, err := dnsResolver.exchangeOne(hostname, dnsType, dnsResolver.aStats)
if err != nil {
return addrs, err
return addrs, &dnsError{dnsType, hostname, err, -1}
}
if r.Rcode != dns.RcodeSuccess {
err = fmt.Errorf("DNS failure: %d-%s for A query", r.Rcode, dns.RcodeToString[r.Rcode])
return nil, err
return nil, &dnsError{dnsType, hostname, nil, r.Rcode}
}
for _, answer := range r.Answer {
if answer.Header().Rrtype == dns.TypeA {
if answer.Header().Rrtype == dnsType {
if a, ok := answer.(*dns.A); ok && a.A.To4() != nil && (!isPrivateV4(a.A) || dnsResolver.allowRestrictedAddresses) {
addrs = append(addrs, a.A)
}
@ -260,9 +259,10 @@ func (dnsResolver *DNSResolverImpl) LookupHost(hostname string) ([]net.IP, error
// the provided hostname. If the response code from the resolver is
// SERVFAIL an empty slice of CAA records is returned.
func (dnsResolver *DNSResolverImpl) LookupCAA(hostname string) ([]*dns.CAA, error) {
r, err := dnsResolver.exchangeOne(hostname, dns.TypeCAA, dnsResolver.caaStats)
dnsType := dns.TypeCAA
r, err := dnsResolver.exchangeOne(hostname, dnsType, dnsResolver.caaStats)
if err != nil {
return nil, err
return nil, &dnsError{dnsType, hostname, err, -1}
}
// On resolver validation failure, or other server failures, return empty an
@ -273,7 +273,7 @@ func (dnsResolver *DNSResolverImpl) LookupCAA(hostname string) ([]*dns.CAA, erro
}
for _, answer := range r.Answer {
if answer.Header().Rrtype == dns.TypeCAA {
if answer.Header().Rrtype == dnsType {
if caaR, ok := answer.(*dns.CAA); ok {
CAAs = append(CAAs, caaR)
}
@ -285,13 +285,13 @@ func (dnsResolver *DNSResolverImpl) LookupCAA(hostname string) ([]*dns.CAA, erro
// LookupMX sends a DNS query to find a MX record associated hostname and returns the
// record target.
func (dnsResolver *DNSResolverImpl) LookupMX(hostname string) ([]string, error) {
r, err := dnsResolver.exchangeOne(hostname, dns.TypeMX, dnsResolver.mxStats)
dnsType := dns.TypeMX
r, err := dnsResolver.exchangeOne(hostname, dnsType, dnsResolver.mxStats)
if err != nil {
return nil, err
return nil, &dnsError{dnsType, hostname, err, -1}
}
if r.Rcode != dns.RcodeSuccess {
err = fmt.Errorf("DNS failure: %d-%s for MX query", r.Rcode, dns.RcodeToString[r.Rcode])
return nil, err
return nil, &dnsError{dnsType, hostname, nil, r.Rcode}
}
var results []string

View File

@ -61,6 +61,9 @@ func mockDNSQuery(w dns.ResponseWriter, r *dns.Msg) {
record.A = net.ParseIP("127.0.0.1")
appendAnswer(record)
}
if q.Name == "nxdomain.letsencrypt.org." {
m.SetRcode(r, dns.RcodeNameError)
}
case dns.TypeCNAME:
if q.Name == "cname.letsencrypt.org." {
record := new(dns.CNAME)
@ -105,6 +108,9 @@ func mockDNSQuery(w dns.ResponseWriter, r *dns.Msg) {
record.Txt = []string{"a", "b", "c"}
appendAnswer(record)
}
if q.Name == "nxdomain.letsencrypt.org." {
m.SetRcode(r, dns.RcodeNameError)
}
}
}
@ -248,6 +254,23 @@ func TestDNSLookupHost(t *testing.T) {
test.Assert(t, len(ip) == 0, "Should not have IPs")
}
func TestDNSNXDOMAIN(t *testing.T) {
obj := NewTestDNSResolverImpl(time.Second*10, []string{dnsLoopbackAddr}, testStats)
hostname := "nxdomain.letsencrypt.org"
_, err := obj.LookupHost(hostname)
expected := dnsError{dns.TypeA, hostname, nil, dns.RcodeNameError}
if err, ok := err.(*dnsError); !ok || *err != expected {
t.Errorf("Looking up %s, got %#v, expected %#v", hostname, err, expected)
}
_, err = obj.LookupTXT(hostname)
expected.recordType = dns.TypeTXT
if err, ok := err.(*dnsError); !ok || *err != expected {
t.Errorf("Looking up %s, got %#v, expected %#v", hostname, err, expected)
}
}
func TestDNSLookupCAA(t *testing.T) {
obj := NewTestDNSResolverImpl(time.Second*10, []string{dnsLoopbackAddr}, testStats)

116
bdns/mocks.go Normal file
View File

@ -0,0 +1,116 @@
package bdns
import (
"errors"
"fmt"
"net"
"os"
"strings"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
)
// MockDNSResolver is a mock
type MockDNSResolver struct {
}
// LookupTXT is a mock
func (mock *MockDNSResolver) LookupTXT(hostname string) ([]string, error) {
if hostname == "_acme-challenge.servfail.com" {
return nil, fmt.Errorf("SERVFAIL")
}
if hostname == "_acme-challenge.good-dns01.com" {
// base64(sha256("LoqXcYV8q5ONbJQxbmR7SCTNo3tiAXDfowyjxAjEuX0"
// + "." + "9jg46WB3rR_AHD-EBXdN7cBkH1WOu0tA3M9fm21mqTI"))
// expected token + test account jwk thumbprint
return []string{"LPsIwTo7o8BoG0-vjCyGQGBWSVIPxI-i_X336eUOQZo"}, nil
}
return []string{"hostname"}, nil
}
// MockTimeoutError returns a a net.OpError for which Timeout() returns true.
func MockTimeoutError() *net.OpError {
return &net.OpError{
Err: os.NewSyscallError("ugh timeout", timeoutError{}),
}
}
type timeoutError struct{}
func (t timeoutError) Error() string {
return "so sloooow"
}
func (t timeoutError) Timeout() bool {
return true
}
// LookupHost is a mock
//
// Note: see comments on LookupMX regarding email.only
//
func (mock *MockDNSResolver) LookupHost(hostname string) ([]net.IP, error) {
if hostname == "always.invalid" ||
hostname == "invalid.invalid" ||
hostname == "email.only" {
return []net.IP{}, nil
}
if hostname == "always.timeout" {
return []net.IP{}, &dnsError{dns.TypeA, "always.timeout", MockTimeoutError(), -1}
}
if hostname == "always.error" {
return []net.IP{}, &dnsError{dns.TypeA, "always.error", &net.OpError{
Err: errors.New("some net error"),
}, -1}
}
ip := net.ParseIP("127.0.0.1")
return []net.IP{ip}, nil
}
// LookupCAA is a mock
func (mock *MockDNSResolver) LookupCAA(domain string) ([]*dns.CAA, error) {
var results []*dns.CAA
var record dns.CAA
switch strings.TrimRight(domain, ".") {
case "caa-timeout.com":
return nil, &dnsError{dns.TypeCAA, "always.timeout", MockTimeoutError(), -1}
case "reserved.com":
record.Tag = "issue"
record.Value = "symantec.com"
results = append(results, &record)
case "critical.com":
record.Flag = 1
record.Tag = "issue"
record.Value = "symantec.com"
results = append(results, &record)
case "present.com":
record.Tag = "issue"
record.Value = "letsencrypt.org"
results = append(results, &record)
case "com":
// Nothing should ever call this, since CAA checking should stop when it
// reaches a public suffix.
fallthrough
case "servfail.com":
return results, fmt.Errorf("SERVFAIL")
}
return results, nil
}
// LookupMX is a mock
//
// Note: the email.only domain must have an MX but no A or AAAA
// records. The mock LookupHost returns an address of 127.0.0.1 for
// all domains except for special cases, so MX-only domains must be
// handled in both LookupHost and LookupMX.
//
func (mock *MockDNSResolver) LookupMX(domain string) ([]string, error) {
switch strings.TrimRight(domain, ".") {
case "letsencrypt.org":
fallthrough
case "email.only":
fallthrough
case "email.com":
return []string{"mail.email.com"}, nil
}
return nil, nil
}

View File

@ -9,30 +9,55 @@ import (
"fmt"
"net"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
"github.com/letsencrypt/boulder/probs"
)
const detailDNSTimeout = "DNS query timed out"
const detailDNSNetFailure = "DNS networking error"
const detailServerFailure = "Server failure at resolver"
type dnsError struct {
recordType uint16
hostname string
// Exactly one of rCode or underlying should be set.
underlying error
rCode int
}
func (d dnsError) Error() string {
var detail string
if d.underlying != nil {
if netErr, ok := d.underlying.(*net.OpError); ok {
if netErr.Timeout() {
detail = detailDNSTimeout
} else {
detail = detailDNSNetFailure
}
}
} else if d.rCode != dns.RcodeSuccess {
detail = dns.RcodeToString[d.rCode]
} else {
detail = detailServerFailure
}
return fmt.Sprintf("DNS problem: %s looking up %s for %s", detail,
dns.TypeToString[d.recordType], d.hostname)
}
const detailDNSTimeout = "query timed out"
const detailDNSNetFailure = "networking error"
const detailServerFailure = "server failure at resolver"
// ProblemDetailsFromDNSError checks the error returned from Lookup... methods
// and tests if the error was an underlying net.OpError or an error caused by
// resolver returning SERVFAIL or other invalid Rcodes and returns the relevant
// core.ProblemDetails. The detail string will contain a mention of the DNS
// record type and domain given.
func ProblemDetailsFromDNSError(recordType, domain string, err error) *probs.ProblemDetails {
detail := detailServerFailure
if netErr, ok := err.(*net.OpError); ok {
if netErr.Timeout() {
detail = detailDNSTimeout
} else {
detail = detailDNSNetFailure
func ProblemDetailsFromDNSError(err error) *probs.ProblemDetails {
if dnsErr, ok := err.(*dnsError); ok {
return &probs.ProblemDetails{
Type: probs.ConnectionProblem,
Detail: dnsErr.Error(),
}
}
detail = fmt.Sprintf("%s during %s-record lookup of %s", detail, recordType, domain)
return &probs.ProblemDetails{
Type: probs.ConnectionProblem,
Detail: detail,
Detail: detailServerFailure,
}
}

View File

@ -10,7 +10,8 @@ import (
"net"
"testing"
"github.com/letsencrypt/boulder/mocks"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
"github.com/letsencrypt/boulder/probs"
)
@ -20,23 +21,25 @@ func TestProblemDetailsFromDNSError(t *testing.T) {
expected string
}{
{
mocks.TimeoutError(),
detailDNSTimeout,
&dnsError{dns.TypeA, "hostname", MockTimeoutError(), -1},
"DNS problem: query timed out looking up A for hostname",
}, {
errors.New("other failure"),
detailServerFailure,
}, {
&net.OpError{Err: errors.New("some net error")},
detailDNSNetFailure,
&dnsError{dns.TypeMX, "hostname", &net.OpError{Err: errors.New("some net error")}, -1},
"DNS problem: networking error looking up MX for hostname",
}, {
&dnsError{dns.TypeTXT, "hostname", nil, dns.RcodeNameError},
"DNS problem: NXDOMAIN looking up TXT for hostname",
},
}
for _, tc := range testCases {
err := ProblemDetailsFromDNSError("TXT", "example.com", tc.err)
err := ProblemDetailsFromDNSError(tc.err)
if err.Type != probs.ConnectionProblem {
t.Errorf("ProblemDetailsFromDNSError(%q).Type = %q, expected %q", tc.err, err.Type, probs.ConnectionProblem)
}
exp := tc.expected + " during TXT-record lookup of example.com"
if err.Detail != exp {
if err.Detail != tc.expected {
t.Errorf("ProblemDetailsFromDNSError(%q).Detail = %q, expected %q", tc.err, err.Detail, tc.expected)
}
}

View File

@ -12,8 +12,6 @@ import (
"fmt"
"io/ioutil"
"net"
"os"
"strings"
"time"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
@ -23,116 +21,10 @@ import (
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/letsencrypt/go-jose"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
"github.com/letsencrypt/boulder/core"
)
// DNSResolver is a mock
type DNSResolver struct {
}
// LookupTXT is a mock
func (mock *DNSResolver) LookupTXT(hostname string) ([]string, error) {
if hostname == "_acme-challenge.servfail.com" {
return nil, fmt.Errorf("SERVFAIL")
}
if hostname == "_acme-challenge.good-dns01.com" {
// base64(sha256("LoqXcYV8q5ONbJQxbmR7SCTNo3tiAXDfowyjxAjEuX0"
// + "." + "9jg46WB3rR_AHD-EBXdN7cBkH1WOu0tA3M9fm21mqTI"))
// expected token + test account jwk thumbprint
return []string{"LPsIwTo7o8BoG0-vjCyGQGBWSVIPxI-i_X336eUOQZo"}, nil
}
return []string{"hostname"}, nil
}
// TimeoutError returns a a net.OpError for which Timeout() returns true.
func TimeoutError() *net.OpError {
return &net.OpError{
Err: os.NewSyscallError("ugh timeout", timeoutError{}),
}
}
type timeoutError struct{}
func (t timeoutError) Error() string {
return "so sloooow"
}
func (t timeoutError) Timeout() bool {
return true
}
// LookupHost is a mock
//
// Note: see comments on LookupMX regarding email.only
//
func (mock *DNSResolver) LookupHost(hostname string) ([]net.IP, error) {
if hostname == "always.invalid" ||
hostname == "invalid.invalid" ||
hostname == "email.only" {
return []net.IP{}, nil
}
if hostname == "always.timeout" {
return []net.IP{}, TimeoutError()
}
if hostname == "always.error" {
return []net.IP{}, &net.OpError{
Err: errors.New("some net error"),
}
}
ip := net.ParseIP("127.0.0.1")
return []net.IP{ip}, nil
}
// LookupCAA is a mock
func (mock *DNSResolver) LookupCAA(domain string) ([]*dns.CAA, error) {
var results []*dns.CAA
var record dns.CAA
switch strings.TrimRight(domain, ".") {
case "caa-timeout.com":
return nil, TimeoutError()
case "reserved.com":
record.Tag = "issue"
record.Value = "symantec.com"
results = append(results, &record)
case "critical.com":
record.Flag = 1
record.Tag = "issue"
record.Value = "symantec.com"
results = append(results, &record)
case "present.com":
record.Tag = "issue"
record.Value = "letsencrypt.org"
results = append(results, &record)
case "com":
// Nothing should ever call this, since CAA checking should stop when it
// reaches a public suffix.
fallthrough
case "servfail.com":
return results, fmt.Errorf("SERVFAIL")
}
return results, nil
}
// LookupMX is a mock
//
// Note: the email.only domain must have an MX but no A or AAAA
// records. The mock LookupHost returns an address of 127.0.0.1 for
// all domains except for special cases, so MX-only domains must be
// handled in both LookupHost and LookupMX.
//
func (mock *DNSResolver) LookupMX(domain string) ([]string, error) {
switch strings.TrimRight(domain, ".") {
case "letsencrypt.org":
fallthrough
case "email.only":
fallthrough
case "email.com":
return []string{"mail.email.com"}, nil
}
return nil, nil
}
// StorageAuthority is a mock
type StorageAuthority struct {
clk clock.Clock

View File

@ -97,10 +97,8 @@ func validateEmail(address string, resolver bdns.DNSResolver) (prob *probs.Probl
var resultMX []string
var resultA []net.IP
resultMX, err = resolver.LookupMX(domain)
recQ := "MX"
if err == nil && len(resultMX) == 0 {
resultA, err = resolver.LookupHost(domain)
recQ = "A"
if err == nil && len(resultA) == 0 {
return &probs.ProblemDetails{
Type: probs.InvalidEmailProblem,
@ -109,7 +107,7 @@ func validateEmail(address string, resolver bdns.DNSResolver) (prob *probs.Probl
}
}
if err != nil {
prob := bdns.ProblemDetailsFromDNSError(recQ, domain, err)
prob := bdns.ProblemDetailsFromDNSError(err)
prob.Type = probs.InvalidEmailProblem
return prob
}

View File

@ -22,6 +22,7 @@ import (
cfsslConfig "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
jose "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/letsencrypt/go-jose"
"github.com/letsencrypt/boulder/bdns"
"github.com/letsencrypt/boulder/ca"
"github.com/letsencrypt/boulder/cmd"
"github.com/letsencrypt/boulder/core"
@ -246,7 +247,7 @@ func initAuthorities(t *testing.T) (*DummyValidationAuthority, *sa.SQLStorageAut
ra.VA = va
ra.CA = ca
ra.PA = pa
ra.DNSResolver = &mocks.DNSResolver{}
ra.DNSResolver = &bdns.MockDNSResolver{}
AuthzInitial.RegistrationID = Registration.ID
@ -317,15 +318,15 @@ func TestValidateEmail(t *testing.T) {
}{
{"an email`", unparseableEmailDetail},
{"a@always.invalid", emptyDNSResponseDetail},
{"a@always.timeout", "DNS query timed out during A-record lookup of always.timeout"},
{"a@always.error", "DNS networking error during A-record lookup of always.error"},
{"a@always.timeout", "DNS problem: query timed out looking up A for always.timeout"},
{"a@always.error", "DNS problem: networking error looking up A for always.error"},
}
testSuccesses := []string{
"a@email.com",
"b@email.only",
}
for _, tc := range testFailures {
problem := validateEmail(tc.input, &mocks.DNSResolver{})
problem := validateEmail(tc.input, &bdns.MockDNSResolver{})
if problem.Type != probs.InvalidEmailProblem {
t.Errorf("validateEmail(%q): got problem type %#v, expected %#v", tc.input, problem.Type, probs.InvalidEmailProblem)
}
@ -336,7 +337,7 @@ func TestValidateEmail(t *testing.T) {
}
for _, addr := range testSuccesses {
if prob := validateEmail(addr, &mocks.DNSResolver{}); prob != nil {
if prob := validateEmail(addr, &bdns.MockDNSResolver{}); prob != nil {
t.Errorf("validateEmail(%q): expected success, but it failed: %s",
addr, prob)
}

View File

@ -93,7 +93,7 @@ func (va ValidationAuthorityImpl) getAddr(hostname string) (net.IP, []net.IP, *p
addrs, err := va.DNSResolver.LookupHost(hostname)
if err != nil {
va.log.Debug(fmt.Sprintf("%s DNS failure: %s", hostname, err))
problem := bdns.ProblemDetailsFromDNSError("A", hostname, err)
problem := bdns.ProblemDetailsFromDNSError(err)
return net.IP{}, nil, problem
}
@ -435,7 +435,7 @@ func (va *ValidationAuthorityImpl) validateDNS01(identifier core.AcmeIdentifier,
if err != nil {
va.log.Debug(fmt.Sprintf("%s [%s] DNS failure: %s", challenge.Type, identifier, err))
return nil, bdns.ProblemDetailsFromDNSError("TXT", challengeSubdomain, err)
return nil, bdns.ProblemDetailsFromDNSError(err)
}
for _, element := range txts {
@ -456,7 +456,7 @@ func (va *ValidationAuthorityImpl) checkCAA(identifier core.AcmeIdentifier, regI
present, valid, err := va.CheckCAARecords(identifier)
if err != nil {
va.log.Warning(fmt.Sprintf("Problem checking CAA: %s", err))
return bdns.ProblemDetailsFromDNSError("CAA", identifier.Value, err)
return bdns.ProblemDetailsFromDNSError(err)
}
// AUDIT[ Certificate Requests ] 11917fa4-10ef-4e0d-9105-bacbe7836a3c
va.log.Audit(fmt.Sprintf("Checked CAA records for %s, registration ID %d [Present: %t, Valid for issuance: %t]", identifier.Value, regID, present, valid))

View File

@ -221,7 +221,7 @@ func TestHTTP(t *testing.T) {
}
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{HTTPPort: badPort}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
_, prob := va.validateHTTP01(ident, chall)
if prob == nil {
@ -230,7 +230,7 @@ func TestHTTP(t *testing.T) {
test.AssertEquals(t, prob.Type, probs.ConnectionProblem)
va = NewValidationAuthorityImpl(&PortConfig{HTTPPort: goodPort}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
log.Clear()
t.Logf("Trying to validate: %+v\n", chall)
@ -314,7 +314,7 @@ func TestHTTPRedirectLookup(t *testing.T) {
test.AssertNotError(t, err, "failed to get test server port")
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{HTTPPort: port}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
log.Clear()
setChallengeToken(&chall, pathMoved)
@ -372,7 +372,7 @@ func TestHTTPRedirectLoop(t *testing.T) {
test.AssertNotError(t, err, "failed to get test server port")
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{HTTPPort: port}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
log.Clear()
_, prob := va.validateHTTP01(ident, chall)
@ -392,7 +392,7 @@ func TestHTTPRedirectUserAgent(t *testing.T) {
test.AssertNotError(t, err, "failed to get test server port")
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{HTTPPort: port}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
va.UserAgent = rejectUserAgent
setChallengeToken(&chall, pathMoved)
@ -434,7 +434,7 @@ func TestTLSSNI(t *testing.T) {
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{TLSPort: port}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
log.Clear()
_, prob := va.validateTLSSNI01(ident, chall)
@ -506,7 +506,7 @@ func TestTLSError(t *testing.T) {
test.AssertNotError(t, err, "failed to get test server port")
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{TLSPort: port}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
_, prob := va.validateTLSSNI01(ident, chall)
if prob == nil {
@ -525,7 +525,7 @@ func TestValidateHTTP(t *testing.T) {
test.AssertNotError(t, err, "failed to get test server port")
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{HTTPPort: port}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
mockRA := &MockRegistrationAuthority{}
va.RA = mockRA
@ -582,7 +582,7 @@ func TestValidateTLSSNI01(t *testing.T) {
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{TLSPort: port}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
mockRA := &MockRegistrationAuthority{}
va.RA = mockRA
@ -600,7 +600,7 @@ func TestValidateTLSSNI01(t *testing.T) {
func TestValidateTLSSNINotSane(t *testing.T) {
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default()) // no calls made
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
mockRA := &MockRegistrationAuthority{}
va.RA = mockRA
@ -622,7 +622,7 @@ func TestValidateTLSSNINotSane(t *testing.T) {
func TestUpdateValidations(t *testing.T) {
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
mockRA := &MockRegistrationAuthority{}
va.RA = mockRA
@ -649,13 +649,13 @@ func TestUpdateValidations(t *testing.T) {
func TestCAATimeout(t *testing.T) {
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
va.IssuerDomain = "letsencrypt.org"
err := va.checkCAA(core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "caa-timeout.com"}, 101)
if err.Type != probs.ConnectionProblem {
t.Errorf("Expected timeout error type %s, got %s", probs.ConnectionProblem, err.Type)
}
expected := "DNS query timed out during CAA-record lookup of caa-timeout.com"
expected := "DNS problem: query timed out looking up CAA for always.timeout"
if err.Detail != expected {
t.Errorf("checkCAA: got %#v, expected %#v", err.Detail, expected)
}
@ -682,7 +682,7 @@ func TestCAAChecking(t *testing.T) {
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
va.IssuerDomain = "letsencrypt.org"
for _, caaTest := range tests {
present, valid, err := va.CheckCAARecords(core.AcmeIdentifier{Type: "dns", Value: caaTest.Domain})
@ -712,7 +712,7 @@ func TestCAAChecking(t *testing.T) {
func TestDNSValidationFailure(t *testing.T) {
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
mockRA := &MockRegistrationAuthority{}
va.RA = mockRA
@ -749,7 +749,7 @@ func TestDNSValidationInvalid(t *testing.T) {
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
mockRA := &MockRegistrationAuthority{}
va.RA = mockRA
@ -763,7 +763,7 @@ func TestDNSValidationInvalid(t *testing.T) {
func TestDNSValidationNotSane(t *testing.T) {
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
mockRA := &MockRegistrationAuthority{}
va.RA = mockRA
@ -790,7 +790,7 @@ func TestDNSValidationNotSane(t *testing.T) {
func TestDNSValidationServFail(t *testing.T) {
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
mockRA := &MockRegistrationAuthority{}
va.RA = mockRA
@ -839,7 +839,7 @@ func TestDNSValidationNoServer(t *testing.T) {
func TestDNSValidationOK(t *testing.T) {
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
mockRA := &MockRegistrationAuthority{}
va.RA = mockRA
@ -873,7 +873,7 @@ func TestDNSValidationOK(t *testing.T) {
func TestDNSValidationLive(t *testing.T) {
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
mockRA := &MockRegistrationAuthority{}
va.RA = mockRA
@ -932,7 +932,7 @@ func TestCAAFailure(t *testing.T) {
stats, _ := statsd.NewNoopClient()
va := NewValidationAuthorityImpl(&PortConfig{TLSPort: port}, nil, stats, clock.Default())
va.DNSResolver = &mocks.DNSResolver{}
va.DNSResolver = &bdns.MockDNSResolver{}
mockRA := &MockRegistrationAuthority{}
va.RA = mockRA