...

Source file src/github.com/letsencrypt/boulder/va/dns_test.go

Documentation: github.com/letsencrypt/boulder/va

     1  package va
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"strings"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/jmhodges/clock"
    12  	"github.com/letsencrypt/boulder/bdns"
    13  	"github.com/letsencrypt/boulder/core"
    14  	"github.com/letsencrypt/boulder/identifier"
    15  	"github.com/letsencrypt/boulder/metrics"
    16  	"github.com/letsencrypt/boulder/probs"
    17  	"github.com/letsencrypt/boulder/test"
    18  	"github.com/prometheus/client_golang/prometheus"
    19  )
    20  
    21  func dnsChallenge() core.Challenge {
    22  	return createChallenge(core.ChallengeTypeDNS01)
    23  }
    24  
    25  func TestDNSValidationEmpty(t *testing.T) {
    26  	va, _ := setup(nil, 0, "", nil)
    27  
    28  	// This test calls PerformValidation directly, because that is where the
    29  	// metrics checked below are incremented.
    30  	req := createValidationRequest("empty-txts.com", core.ChallengeTypeDNS01)
    31  	res, _ := va.PerformValidation(context.Background(), req)
    32  	test.AssertEquals(t, res.Problems.ProblemType, "unauthorized")
    33  	test.AssertEquals(t, res.Problems.Detail, "No TXT record found at _acme-challenge.empty-txts.com")
    34  
    35  	test.AssertMetricWithLabelsEquals(t, va.metrics.validationTime, prometheus.Labels{
    36  		"type":         "dns-01",
    37  		"result":       "invalid",
    38  		"problem_type": "unauthorized",
    39  	}, 1)
    40  }
    41  
    42  func TestDNSValidationWrong(t *testing.T) {
    43  	va, _ := setup(nil, 0, "", nil)
    44  
    45  	_, prob := va.validateDNS01(context.Background(), dnsi("wrong-dns01.com"), dnsChallenge())
    46  	if prob == nil {
    47  		t.Fatalf("Successful DNS validation with wrong TXT record")
    48  	}
    49  	test.AssertEquals(t, prob.Error(), "unauthorized :: Incorrect TXT record \"a\" found at _acme-challenge.wrong-dns01.com")
    50  }
    51  
    52  func TestDNSValidationWrongMany(t *testing.T) {
    53  	va, _ := setup(nil, 0, "", nil)
    54  
    55  	_, prob := va.validateDNS01(context.Background(), dnsi("wrong-many-dns01.com"), dnsChallenge())
    56  	if prob == nil {
    57  		t.Fatalf("Successful DNS validation with wrong TXT record")
    58  	}
    59  	test.AssertEquals(t, prob.Error(), "unauthorized :: Incorrect TXT record \"a\" (and 4 more) found at _acme-challenge.wrong-many-dns01.com")
    60  }
    61  
    62  func TestDNSValidationWrongLong(t *testing.T) {
    63  	va, _ := setup(nil, 0, "", nil)
    64  
    65  	_, prob := va.validateDNS01(context.Background(), dnsi("long-dns01.com"), dnsChallenge())
    66  	if prob == nil {
    67  		t.Fatalf("Successful DNS validation with wrong TXT record")
    68  	}
    69  	test.AssertEquals(t, prob.Error(), "unauthorized :: Incorrect TXT record \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...\" found at _acme-challenge.long-dns01.com")
    70  }
    71  
    72  func TestDNSValidationFailure(t *testing.T) {
    73  	va, _ := setup(nil, 0, "", nil)
    74  
    75  	_, prob := va.validateDNS01(ctx, dnsi("localhost"), dnsChallenge())
    76  
    77  	test.AssertEquals(t, prob.Type, probs.UnauthorizedProblem)
    78  }
    79  
    80  func TestDNSValidationInvalid(t *testing.T) {
    81  	var notDNS = identifier.ACMEIdentifier{
    82  		Type:  identifier.IdentifierType("iris"),
    83  		Value: "790DB180-A274-47A4-855F-31C428CB1072",
    84  	}
    85  
    86  	va, _ := setup(nil, 0, "", nil)
    87  
    88  	_, prob := va.validateDNS01(ctx, notDNS, dnsChallenge())
    89  
    90  	test.AssertEquals(t, prob.Type, probs.MalformedProblem)
    91  }
    92  
    93  func TestDNSValidationNotSane(t *testing.T) {
    94  	va, _ := setup(nil, 0, "", nil)
    95  
    96  	chall := dnsChallenge()
    97  	chall.Token = ""
    98  	_, prob := va.validateChallenge(ctx, dnsi("localhost"), chall)
    99  	if prob.Type != probs.MalformedProblem {
   100  		t.Errorf("Got wrong error type: expected %s, got %s",
   101  			prob.Type, probs.MalformedProblem)
   102  	}
   103  	if !strings.Contains(prob.Error(), "Challenge failed consistency check:") {
   104  		t.Errorf("Got wrong error: %s", prob.Error())
   105  	}
   106  
   107  	chall.Token = "yfCBb-bRTLz8Wd1C0lTUQK3qlKj3-t2tYGwx5Hj7r_"
   108  	_, prob = va.validateChallenge(ctx, dnsi("localhost"), chall)
   109  	if prob.Type != probs.MalformedProblem {
   110  		t.Errorf("Got wrong error type: expected %s, got %s",
   111  			prob.Type, probs.MalformedProblem)
   112  	}
   113  	if !strings.Contains(prob.Error(), "Challenge failed consistency check:") {
   114  		t.Errorf("Got wrong error: %s", prob.Error())
   115  	}
   116  
   117  	chall.ProvidedKeyAuthorization = "a"
   118  	_, prob = va.validateChallenge(ctx, dnsi("localhost"), chall)
   119  	if prob.Type != probs.MalformedProblem {
   120  		t.Errorf("Got wrong error type: expected %s, got %s",
   121  			prob.Type, probs.MalformedProblem)
   122  	}
   123  	if !strings.Contains(prob.Error(), "Challenge failed consistency check:") {
   124  		t.Errorf("Got wrong error: %s", prob.Error())
   125  	}
   126  
   127  }
   128  
   129  func TestDNSValidationServFail(t *testing.T) {
   130  	va, _ := setup(nil, 0, "", nil)
   131  
   132  	_, prob := va.validateChallenge(ctx, dnsi("servfail.com"), dnsChallenge())
   133  
   134  	test.AssertEquals(t, prob.Type, probs.DNSProblem)
   135  }
   136  
   137  func TestDNSValidationNoServer(t *testing.T) {
   138  	va, log := setup(nil, 0, "", nil)
   139  	staticProvider, err := bdns.NewStaticProvider([]string{})
   140  	test.AssertNotError(t, err, "Couldn't make new static provider")
   141  
   142  	va.dnsClient = bdns.NewTest(
   143  		time.Second*5,
   144  		staticProvider,
   145  		metrics.NoopRegisterer,
   146  		clock.New(),
   147  		1,
   148  		log)
   149  
   150  	_, prob := va.validateChallenge(ctx, dnsi("localhost"), dnsChallenge())
   151  
   152  	test.AssertEquals(t, prob.Type, probs.DNSProblem)
   153  }
   154  
   155  func TestDNSValidationOK(t *testing.T) {
   156  	va, _ := setup(nil, 0, "", nil)
   157  
   158  	_, prob := va.validateChallenge(ctx, dnsi("good-dns01.com"), dnsChallenge())
   159  
   160  	test.Assert(t, prob == nil, "Should be valid.")
   161  }
   162  
   163  func TestDNSValidationNoAuthorityOK(t *testing.T) {
   164  	va, _ := setup(nil, 0, "", nil)
   165  
   166  	_, prob := va.validateChallenge(ctx, dnsi("no-authority-dns01.com"), dnsChallenge())
   167  
   168  	test.Assert(t, prob == nil, "Should be valid.")
   169  }
   170  
   171  func TestAvailableAddresses(t *testing.T) {
   172  	v6a := net.ParseIP("::1")
   173  	v6b := net.ParseIP("2001:db8::2:1") // 2001:DB8 is reserved for docs (RFC 3849)
   174  	v4a := net.ParseIP("127.0.0.1")
   175  	v4b := net.ParseIP("192.0.2.1") // 192.0.2.0/24 is reserved for docs (RFC 5737)
   176  
   177  	testcases := []struct {
   178  		input []net.IP
   179  		v4    []net.IP
   180  		v6    []net.IP
   181  	}{
   182  		// An empty validation record
   183  		{
   184  			[]net.IP{},
   185  			[]net.IP{},
   186  			[]net.IP{},
   187  		},
   188  		// A validation record with one IPv4 address
   189  		{
   190  			[]net.IP{v4a},
   191  			[]net.IP{v4a},
   192  			[]net.IP{},
   193  		},
   194  		// A dual homed record with an IPv4 and IPv6 address
   195  		{
   196  			[]net.IP{v4a, v6a},
   197  			[]net.IP{v4a},
   198  			[]net.IP{v6a},
   199  		},
   200  		// The same as above but with the v4/v6 order flipped
   201  		{
   202  			[]net.IP{v6a, v4a},
   203  			[]net.IP{v4a},
   204  			[]net.IP{v6a},
   205  		},
   206  		// A validation record with just IPv6 addresses
   207  		{
   208  			[]net.IP{v6a, v6b},
   209  			[]net.IP{},
   210  			[]net.IP{v6a, v6b},
   211  		},
   212  		// A validation record with interleaved IPv4/IPv6 records
   213  		{
   214  			[]net.IP{v6a, v4a, v6b, v4b},
   215  			[]net.IP{v4a, v4b},
   216  			[]net.IP{v6a, v6b},
   217  		},
   218  	}
   219  
   220  	for _, tc := range testcases {
   221  		// Split the input record into v4/v6 addresses
   222  		v4result, v6result := availableAddresses(tc.input)
   223  
   224  		// Test that we got the right number of v4 results
   225  		test.Assert(t, len(tc.v4) == len(v4result),
   226  			fmt.Sprintf("Wrong # of IPv4 results: expected %d, got %d", len(tc.v4), len(v4result)))
   227  
   228  		// Check that all of the v4 results match expected values
   229  		for i, v4addr := range tc.v4 {
   230  			test.Assert(t, v4addr.String() == v4result[i].String(),
   231  				fmt.Sprintf("Wrong v4 result index %d: expected %q got %q", i, v4addr.String(), v4result[i].String()))
   232  		}
   233  
   234  		// Test that we got the right number of v6 results
   235  		test.Assert(t, len(tc.v6) == len(v6result),
   236  			fmt.Sprintf("Wrong # of IPv6 results: expected %d, got %d", len(tc.v6), len(v6result)))
   237  
   238  		// Check that all of the v6 results match expected values
   239  		for i, v6addr := range tc.v6 {
   240  			test.Assert(t, v6addr.String() == v6result[i].String(),
   241  				fmt.Sprintf("Wrong v6 result index %d: expected %q got %q", i, v6addr.String(), v6result[i].String()))
   242  		}
   243  	}
   244  }
   245  

View as plain text