func TestGenerateMessage(t *testing.T) { fc := clock.NewFake() stats := metrics.NewNoopScope() fromAddress, _ := mail.ParseAddress("happy sender <*****@*****.**>") log := blog.UseMock() m := New("", "", "", "", *fromAddress, log, stats, 0, 0) m.clk = fc m.csprgSource = fakeSource{} messageBytes, err := m.generateMessage([]string{"*****@*****.**"}, "test subject", "this is the body\n") test.AssertNotError(t, err, "Failed to generate email body") message := string(messageBytes) fields := strings.Split(message, "\r\n") test.AssertEquals(t, len(fields), 12) fmt.Println(message) test.AssertEquals(t, fields[0], "To: \"[email protected]\"") test.AssertEquals(t, fields[1], "From: \"happy sender\" <*****@*****.**>") test.AssertEquals(t, fields[2], "Subject: test subject") test.AssertEquals(t, fields[3], "Date: 01 Jan 70 00:00 UTC") test.AssertEquals(t, fields[4], "Message-Id: <*****@*****.**>") test.AssertEquals(t, fields[5], "MIME-Version: 1.0") test.AssertEquals(t, fields[6], "Content-Type: text/plain; charset=UTF-8") test.AssertEquals(t, fields[7], "Content-Transfer-Encoding: quoted-printable") test.AssertEquals(t, fields[8], "") test.AssertEquals(t, fields[9], "this is the body") }
func TestCheckCAAFallback(t *testing.T) { testSrv := httptest.NewServer(http.HandlerFunc(mocks.GPDNSHandler)) defer testSrv.Close() stats := mocks.NewStatter() scope := metrics.NewStatsdScope(stats, "VA") logger := blog.NewMock() caaDR, err := cdr.New(metrics.NewNoopScope(), time.Second, 1, nil, blog.NewMock()) test.AssertNotError(t, err, "Failed to create CAADistributedResolver") caaDR.URI = testSrv.URL caaDR.Clients["1.1.1.1"] = new(http.Client) va := NewValidationAuthorityImpl( &cmd.PortConfig{}, nil, caaDR, &bdns.MockDNSResolver{}, "user agent 1.0", "ca.com", scope, clock.Default(), logger) prob := va.checkCAA(ctx, core.AcmeIdentifier{Value: "bad-local-resolver.com", Type: "dns"}) test.Assert(t, prob == nil, fmt.Sprintf("returned ProblemDetails was non-nil: %#v", prob)) va.caaDR = nil prob = va.checkCAA(ctx, core.AcmeIdentifier{Value: "bad-local-resolver.com", Type: "dns"}) test.Assert(t, prob != nil, "returned ProblemDetails was nil") test.AssertEquals(t, prob.Type, probs.ConnectionProblem) test.AssertEquals(t, prob.Detail, "server failure at resolver") }
func setup(t *testing.T) (*MailerImpl, net.Listener, func()) { stats := metrics.NewNoopScope() fromAddress, _ := mail.ParseAddress("*****@*****.**") log := blog.UseMock() // Listen on port 0 to get any free available port l, err := net.Listen("tcp", ":0") if err != nil { t.Fatalf("listen: %s", err) } cleanUp := func() { err := l.Close() if err != nil { t.Errorf("listen.Close: %s", err) } } // We can look at the listener Addr() to figure out which free port was // assigned by the operating system addr := l.Addr().(*net.TCPAddr) port := addr.Port m := New( "localhost", fmt.Sprintf("%d", port), "*****@*****.**", "paswd", *fromAddress, log, stats, time.Second*2, time.Second*10) return m, l, cleanUp }
func TestFailNonASCIIAddress(t *testing.T) { log := blog.UseMock() stats := metrics.NewNoopScope() fromAddress, _ := mail.ParseAddress("*****@*****.**") m := New("", "", "", "", *fromAddress, log, stats, 0, 0) _, err := m.generateMessage([]string{"遗憾@email.com"}, "test subject", "this is the body\n") test.AssertError(t, err, "Allowed a non-ASCII to address incorrectly") }
// New constructs a Mailer suitable for doing a dry run. It simply logs each // command that would have been run, at debug level. func NewDryRun(from mail.Address, logger blog.Logger) *MailerImpl { stats := metrics.NewNoopScope() return &MailerImpl{ dialer: dryRunClient{logger}, from: from, clk: clock.Default(), csprgSource: realSource{}, stats: stats, } }
func TestDNSValidationNoServer(t *testing.T) { va, _, _ := setup() va.dnsResolver = bdns.NewTestDNSResolverImpl( time.Second*5, nil, metrics.NewNoopScope(), clock.Default(), 1) chalDNS := createChallenge(core.ChallengeTypeDNS01) _, prob := va.validateChallenge(ctx, ident, chalDNS) test.AssertEquals(t, prob.Type, probs.ConnectionProblem) }
func TestGetCAASetFallback(t *testing.T) { testSrv := httptest.NewServer(http.HandlerFunc(mocks.GPDNSHandler)) defer testSrv.Close() caaDR, err := cdr.New(metrics.NewNoopScope(), time.Second, 1, nil, blog.NewMock()) test.AssertNotError(t, err, "Failed to create CAADistributedResolver") caaDR.URI = testSrv.URL caaDR.Clients["1.1.1.1"] = new(http.Client) va, _, _ := setup() va.caaDR = caaDR set, err := va.getCAASet(ctx, "bad-local-resolver.com") test.AssertNotError(t, err, "getCAASet failed to fail back to cdr on timeout") test.AssertEquals(t, len(set.Issue), 1) }
func setup(t *testing.T) (*Impl, *x509.Certificate, *ecdsa.PrivateKey) { intermediatePEM, _ := pem.Decode([]byte(testIntermediate)) pub := New(nil, nil, 0, log, metrics.NewNoopScope(), mocks.NewStorageAuthority(clock.NewFake())) pub.issuerBundle = append(pub.issuerBundle, ct.ASN1Cert(intermediatePEM.Bytes)) leafPEM, _ := pem.Decode([]byte(testLeaf)) leaf, err := x509.ParseCertificate(leafPEM.Bytes) test.AssertNotError(t, err, "Couldn't parse leafPEM.Bytes") k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) test.AssertNotError(t, err, "Couldn't generate test key") return pub, leaf, k }
func TestHTTPQuorum(t *testing.T) { sbh := &slightlyBrokenHandler{} testSrv := httptest.NewServer(http.HandlerFunc(sbh.Handler)) defer testSrv.Close() cpr := CAADistributedResolver{ logger: log, Clients: map[string]*http.Client{ "1.1.1.1": new(http.Client), "2.2.2.2": new(http.Client), "3.3.3.3": new(http.Client), }, stats: metrics.NewNoopScope(), maxFailures: 1, timeout: time.Second, URI: testSrv.URL, } set, err := cpr.LookupCAA(context.Background(), "test-domain") test.AssertError(t, err, "LookupCAA should've failed") test.Assert(t, set == nil, "LookupCAA returned non-nil CAA set") }
func TestPurgeAuthzs(t *testing.T) { dbMap, err := sa.NewDbMap(vars.DBConnSAFullPerms, 0) if err != nil { t.Fatalf("Couldn't connect the database: %s", err) } log := blog.UseMock() fc := clock.NewFake() fc.Add(time.Hour) ssa, err := sa.NewSQLStorageAuthority(dbMap, fc, log) if err != nil { t.Fatalf("unable to create SQLStorageAuthority: %s", err) } cleanUp := test.ResetSATestDatabase(t) defer cleanUp() stats := metrics.NewNoopScope() p := expiredAuthzPurger{stats, log, fc, dbMap, 1} rows, err := p.purgeAuthzs(time.Time{}, true) test.AssertNotError(t, err, "purgeAuthzs failed") test.AssertEquals(t, rows, int64(0)) old, new := fc.Now().Add(-time.Hour), fc.Now().Add(time.Hour) reg := satest.CreateWorkingRegistration(t, ssa) _, err = ssa.NewPendingAuthorization(context.Background(), core.Authorization{RegistrationID: reg.ID, Expires: &old}) test.AssertNotError(t, err, "NewPendingAuthorization failed") _, err = ssa.NewPendingAuthorization(context.Background(), core.Authorization{RegistrationID: reg.ID, Expires: &old}) test.AssertNotError(t, err, "NewPendingAuthorization failed") _, err = ssa.NewPendingAuthorization(context.Background(), core.Authorization{RegistrationID: reg.ID, Expires: &new}) test.AssertNotError(t, err, "NewPendingAuthorization failed") rows, err = p.purgeAuthzs(fc.Now(), true) test.AssertNotError(t, err, "purgeAuthzs failed") test.AssertEquals(t, rows, int64(2)) rows, err = p.purgeAuthzs(fc.Now().Add(time.Hour), true) test.AssertNotError(t, err, "purgeAuthzs failed") test.AssertEquals(t, rows, int64(1)) }
func TestDNSValidationNoServer(t *testing.T) { c, _ := statsd.NewNoopClient() stats := metrics.NewNoopScope() va := NewValidationAuthorityImpl(&PortConfig{}, nil, c, clock.Default()) va.DNSResolver = bdns.NewTestDNSResolverImpl(time.Second*5, []string{}, stats, clock.Default(), 1) mockRA := &MockRegistrationAuthority{} va.RA = mockRA chalDNS := createChallenge(core.ChallengeTypeDNS01) var authz = core.Authorization{ ID: core.NewToken(), RegistrationID: 1, Identifier: ident, Challenges: []core.Challenge{chalDNS}, } va.validate(context.Background(), authz, 0) test.AssertNotNil(t, mockRA.lastAuthz, "Should have gotten an authorization") test.Assert(t, authz.Challenges[0].Status == core.StatusInvalid, "Should be invalid.") test.AssertEquals(t, authz.Challenges[0].Error.Type, probs.ConnectionProblem) }
func TestLookupCAA(t *testing.T) { testSrv := httptest.NewServer(http.HandlerFunc(mocks.GPDNSHandler)) defer testSrv.Close() cpr := CAADistributedResolver{ logger: log, Clients: map[string]*http.Client{ "1.1.1.1": new(http.Client), "2.2.2.2": new(http.Client), "3.3.3.3": new(http.Client), }, stats: metrics.NewNoopScope(), maxFailures: 1, timeout: time.Second, URI: testSrv.URL, } set, err := cpr.LookupCAA(context.Background(), "test-domain") test.AssertNotError(t, err, "LookupCAA method failed") test.AssertEquals(t, len(set), 1) test.AssertEquals(t, set[0].Hdr.Name, "test-domain.") test.AssertEquals(t, set[0].Hdr.Ttl, uint32(10)) test.AssertEquals(t, set[0].Flag, uint8(0)) test.AssertEquals(t, set[0].Tag, "issue") test.AssertEquals(t, set[0].Value, "ca.com") set, err = cpr.LookupCAA(context.Background(), "break") test.AssertError(t, err, "LookupCAA should've failed") test.Assert(t, set == nil, "LookupCAA returned non-nil CAA set") set, err = cpr.LookupCAA(context.Background(), "break-rcode") test.AssertError(t, err, "LookupCAA should've failed") test.Assert(t, set == nil, "LookupCAA returned non-nil CAA set") set, err = cpr.LookupCAA(context.Background(), "break-dns-quorum") test.AssertError(t, err, "LookupCAA should've failed") test.Assert(t, set == nil, "LookupCAA returned non-nil CAA set") }
func TestAllowNilInIsSafeDomain(t *testing.T) { stats := metrics.NewNoopScope() va := NewValidationAuthorityImpl( &cmd.PortConfig{}, nil, nil, nil, "user agent 1.0", "letsencrypt.org", stats, clock.NewFake(), blog.NewMock()) // Be cool with a nil SafeBrowsing. This will happen in prod when we have // flag mismatch between the VA and RA. domain := "example.com" resp, err := va.IsSafeDomain(ctx, &vaPB.IsSafeDomainRequest{Domain: &domain}) if err != nil { t.Errorf("nil SafeBrowsing, unexpected error: %s", err) } if !resp.GetIsSafe() { t.Errorf("nil Safebrowsing, should fail open but failed closed") } }
func TestConstructAuthHeader(t *testing.T) { stats := metrics.NewNoopScope() cpc, err := NewCachePurgeClient( "https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net", "akab-client-token-xxx-xxxxxxxxxxxxxxxx", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", "akab-access-token-xxx-xxxxxxxxxxxxxxxx", 0, time.Second, nil, stats, ) test.AssertNotError(t, err, "Failed to create cache purge client") fc := clock.NewFake() cpc.clk = fc wantedTimestamp, err := time.Parse(timestampFormat, "20140321T19:34:21+0000") test.AssertNotError(t, err, "Failed to parse timestamp") fc.Add(wantedTimestamp.Sub(fc.Now())) req, err := http.NewRequest( "POST", fmt.Sprintf("%s%s", cpc.apiEndpoint, purgePath), bytes.NewBuffer([]byte{0}), ) test.AssertNotError(t, err, "Failed to create request") expectedHeader := "EG1-HMAC-SHA256 client_token=akab-client-token-xxx-xxxxxxxxxxxxxxxx;access_token=akab-access-token-xxx-xxxxxxxxxxxxxxxx;timestamp=20140321T19:34:21+0000;nonce=nonce-xx-xxxx-xxxx-xxxx-xxxxxxxxxxxx;signature=hXm4iCxtpN22m4cbZb4lVLW5rhX8Ca82vCFqXzSTPe4=" authHeader, err := cpc.constructAuthHeader( req, []byte("datadatadatadatadatadatadatadata"), "/testapi/v1/t3", "nonce-xx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", ) test.AssertNotError(t, err, "Failed to create authorization header") test.AssertEquals(t, authHeader, expectedHeader) }
func newTestStats() metrics.Scope { return metrics.NewNoopScope() }
func setup(t *testing.T) *testCtx { fc := clock.NewFake() fc.Add(1 * time.Hour) pa, err := policy.New(nil) test.AssertNotError(t, err, "Couldn't create PA") err = pa.SetHostnamePolicyFile("../test/hostname-policy.json") test.AssertNotError(t, err, "Couldn't set hostname policy") // Create a CA caConfig := cmd.CAConfig{ RSAProfile: rsaProfileName, ECDSAProfile: ecdsaProfileName, SerialPrefix: 17, Expiry: "8760h", LifespanOCSP: cmd.ConfigDuration{Duration: 45 * time.Minute}, MaxNames: 2, CFSSL: cfsslConfig.Config{ Signing: &cfsslConfig.Signing{ Profiles: map[string]*cfsslConfig.SigningProfile{ rsaProfileName: { Usage: []string{"digital signature", "key encipherment", "server auth"}, CA: false, IssuerURL: []string{"http://not-example.com/issuer-url"}, OCSP: "http://not-example.com/ocsp", CRL: "http://not-example.com/crl", Policies: []cfsslConfig.CertificatePolicy{ { ID: cfsslConfig.OID(asn1.ObjectIdentifier{2, 23, 140, 1, 2, 1}), }, }, ExpiryString: "8760h", Backdate: time.Hour, CSRWhitelist: &cfsslConfig.CSRWhitelist{ PublicKeyAlgorithm: true, PublicKey: true, SignatureAlgorithm: true, }, ClientProvidesSerialNumbers: true, AllowedExtensions: []cfsslConfig.OID{ cfsslConfig.OID(oidTLSFeature), }, }, ecdsaProfileName: { Usage: []string{"digital signature", "server auth"}, CA: false, IssuerURL: []string{"http://not-example.com/issuer-url"}, OCSP: "http://not-example.com/ocsp", CRL: "http://not-example.com/crl", Policies: []cfsslConfig.CertificatePolicy{ { ID: cfsslConfig.OID(asn1.ObjectIdentifier{2, 23, 140, 1, 2, 1}), }, }, ExpiryString: "8760h", Backdate: time.Hour, CSRWhitelist: &cfsslConfig.CSRWhitelist{ PublicKeyAlgorithm: true, PublicKey: true, SignatureAlgorithm: true, }, ClientProvidesSerialNumbers: true, }, }, Default: &cfsslConfig.SigningProfile{ ExpiryString: "8760h", }, }, }, } issuers := []Issuer{{caKey, caCert}} keyPolicy := goodkey.KeyPolicy{ AllowRSA: true, AllowECDSANISTP256: true, AllowECDSANISTP384: true, } logger := blog.NewMock() return &testCtx{ caConfig, pa, issuers, keyPolicy, fc, metrics.NewNoopScope(), logger, } }
func TestIsSafeDomain(t *testing.T) { // TODO(jmhodges): use more of the GSB lib by teaching it how to not make // http requests // This test is mocked out at the wrong level (SafeBrowsing) because the gsb lib // we rely on is a little funny and overcomplicated, but still hasn't // learned out how not make HTTP requests in tests. stats := metrics.NewNoopScope() ctrl := gomock.NewController(t) defer ctrl.Finish() sbc := NewMockSafeBrowsing(ctrl) sbc.EXPECT().IsListed("good.com").Return("", nil) sbc.EXPECT().IsListed("bad.com").Return("bad", nil) sbc.EXPECT().IsListed("errorful.com").Return("", errors.New("welp")) sbc.EXPECT().IsListed("outofdate.com").Return("", safebrowsing.ErrOutOfDateHashes) va := NewValidationAuthorityImpl( &cmd.PortConfig{}, sbc, nil, nil, "user agent 1.0", "letsencrypt.org", stats, clock.NewFake(), blog.NewMock()) domain := "good.com" resp, err := va.IsSafeDomain(ctx, &vaPB.IsSafeDomainRequest{Domain: &domain}) if err != nil { t.Errorf("good.com: want no error, got '%s'", err) } if !resp.GetIsSafe() { t.Errorf("good.com: want true, got %t", resp.GetIsSafe()) } domain = "bad.com" resp, err = va.IsSafeDomain(ctx, &vaPB.IsSafeDomainRequest{Domain: &domain}) if err != nil { t.Errorf("bad.com: want no error, got '%s'", err) } if resp.GetIsSafe() { t.Errorf("bad.com: want false, got %t", resp.GetIsSafe()) } domain = "errorful.com" resp, err = va.IsSafeDomain(ctx, &vaPB.IsSafeDomainRequest{Domain: &domain}) if err == nil { t.Errorf("errorful.com: want error, got none") } if resp != nil { t.Errorf("errorful.com: want resp == nil, got %v", resp) } domain = "outofdate.com" resp, err = va.IsSafeDomain(ctx, &vaPB.IsSafeDomainRequest{Domain: &domain}) if err != nil { t.Errorf("outofdate.com: want no error, got '%s'", err) } if !resp.GetIsSafe() { t.Errorf("outofdate.com: IsSafeDomain should fail open on out of date hashes") } }
func TestChecking(t *testing.T) { type CAATest struct { Domain string Present bool Valid bool } tests := []CAATest{ // Reserved {"reserved.com", true, false}, // Critical {"critical.com", true, false}, {"nx.critical.com", true, false}, // Good (absent) {"absent.com", false, true}, {"example.co.uk", false, true}, // Good (present) {"present.com", true, true}, {"present.servfail.com", true, true}, // Good (multiple critical, one matching) {"multi-crit-present.com", true, true}, // Bad (unknown critical) {"unknown-critical.com", true, false}, {"unknown-critical2.com", true, false}, // Good (unknown noncritical, no issue/issuewild records) {"unknown-noncritical.com", true, true}, // Good (issue record with unknown parameters) {"present-with-parameter.com", true, true}, // Bad (unsatisfiable issue record) {"unsatisfiable.com", true, false}, } stats := metrics.NewNoopScope() ccs := &caaCheckerServer{&bdns.MockDNSResolver{}, stats} issuerDomain := "letsencrypt.org" ctx := context.Background() for _, caaTest := range tests { result, err := ccs.ValidForIssuance(ctx, &pb.Check{Name: &caaTest.Domain, IssuerDomain: &issuerDomain}) if err != nil { t.Errorf("CheckCAARecords error for %s: %s", caaTest.Domain, err) } if *result.Present != caaTest.Present { t.Errorf("CheckCAARecords presence mismatch for %s: got %t expected %t", caaTest.Domain, *result.Present, caaTest.Present) } if *result.Valid != caaTest.Valid { t.Errorf("CheckCAARecords presence mismatch for %s: got %t expected %t", caaTest.Domain, *result.Valid, caaTest.Valid) } } servfail := "servfail.com" servfailPresent := "servfail.present.com" result, err := ccs.ValidForIssuance(ctx, &pb.Check{Name: &servfail, IssuerDomain: &issuerDomain}) test.AssertError(t, err, "servfail.com") test.Assert(t, result == nil, "result should be nil") test.AssertEquals(t, grpc.Code(err), bgrpc.DNSError) result, err = ccs.ValidForIssuance(ctx, &pb.Check{Name: &servfailPresent, IssuerDomain: &issuerDomain}) test.AssertError(t, err, "servfail.present.com") test.Assert(t, result == nil, "result should be nil") test.AssertEquals(t, grpc.Code(err), bgrpc.DNSError) timeout := "caa-timeout.com" result, err = ccs.ValidForIssuance(ctx, &pb.Check{Name: &timeout, IssuerDomain: &issuerDomain}) test.AssertError(t, err, "timeout.com") test.Assert(t, result == nil, "result should be nil") test.AssertEquals(t, grpc.Code(err), bgrpc.DNSQueryTimeout) }