func TestDNSNoServers(t *testing.T) { obj := NewTestDNSResolverImpl(time.Hour, []string{}, testStats, clock.NewFake(), 1) _, err := obj.LookupHost(context.Background(), "letsencrypt.org") test.AssertError(t, err, "No servers") }
func setup(t *testing.T) (OCSPUpdater, core.StorageAuthority, *gorp.DbMap, clock.FakeClock, func()) { dbMap, err := sa.NewDbMap(dbConnStr) test.AssertNotError(t, err, "Failed to create dbMap") fc := clock.NewFake() fc.Add(1 * time.Hour) sa, err := sa.NewSQLStorageAuthority(dbMap, fc) test.AssertNotError(t, err, "Failed to create SA") cleanUp := test.ResetSATestDatabase(t) stats, _ := statsd.NewNoopClient(nil) updater := OCSPUpdater{ dbMap: dbMap, clk: fc, cac: &mockCA{}, pubc: &mockPub{sa}, sac: sa, stats: stats, log: blog.GetAuditLogger(), } return updater, sa, dbMap, fc, cleanUp }
func TestDNSLookupHost(t *testing.T) { obj := NewTestDNSResolverImpl(time.Second*10, []string{dnsLoopbackAddr}, testStats, clock.NewFake(), 1) ip, err := obj.LookupHost(context.Background(), "servfail.com") t.Logf("servfail.com - IP: %s, Err: %s", ip, err) test.AssertError(t, err, "Server failure") test.Assert(t, len(ip) == 0, "Should not have IPs") ip, err = obj.LookupHost(context.Background(), "nonexistent.letsencrypt.org") t.Logf("nonexistent.letsencrypt.org - IP: %s, Err: %s", ip, err) test.AssertNotError(t, err, "Not an error to not exist") test.Assert(t, len(ip) == 0, "Should not have IPs") // Single IPv4 address ip, err = obj.LookupHost(context.Background(), "cps.letsencrypt.org") t.Logf("cps.letsencrypt.org - IP: %s, Err: %s", ip, err) test.AssertNotError(t, err, "Not an error to exist") test.Assert(t, len(ip) == 1, "Should have IP") ip, err = obj.LookupHost(context.Background(), "cps.letsencrypt.org") t.Logf("cps.letsencrypt.org - IP: %s, Err: %s", ip, err) test.AssertNotError(t, err, "Not an error to exist") test.Assert(t, len(ip) == 1, "Should have IP") // No IPv6 ip, err = obj.LookupHost(context.Background(), "v6.letsencrypt.org") t.Logf("v6.letsencrypt.org - IP: %s, Err: %s", ip, err) test.AssertNotError(t, err, "Not an error to exist") test.Assert(t, len(ip) == 0, "Should not have IPs") }
func TestDNSOneServer(t *testing.T) { obj := NewTestDNSResolverImpl(time.Second*10, []string{dnsLoopbackAddr}, testStats, clock.NewFake(), 1) _, err := obj.LookupHost(context.Background(), "letsencrypt.org") test.AssertNotError(t, err, "No message") }
func setup(t *testing.T, nagTimes []time.Duration) *testCtx { dbMap, err := sa.NewDbMap(dbConnStr) if err != nil { t.Fatalf("Couldn't connect the database: %s", err) } fc := clock.NewFake() ssa, err := sa.NewSQLStorageAuthority(dbMap, fc) if err != nil { t.Fatalf("unable to create SQLStorageAuthority: %s", err) } cleanUp := test.ResetTestDatabase(t, dbMap.Db) stats, _ := statsd.NewNoopClient(nil) mc := &mockMail{} m := &mailer{ log: blog.GetAuditLogger(), stats: stats, mailer: mc, emailTemplate: tmpl, dbMap: dbMap, rs: ssa, nagTimes: nagTimes, limit: 100, clk: fc, } return &testCtx{ dbMap: dbMap, ssa: ssa, mc: mc, fc: fc, m: m, cleanUp: cleanUp, } }
func TestParseLine(t *testing.T) { dbMap, err := sa.NewDbMap(vars.DBConnSA) if err != nil { t.Fatalf("Failed to create dbMap: %s", err) } fc := clock.NewFake() fc.Set(time.Date(2015, 3, 4, 5, 0, 0, 0, time.UTC)) sa, err := sa.NewSQLStorageAuthority(dbMap, fc) if err != nil { t.Fatalf("Failed to create SA: %s", err) } defer test.ResetSATestDatabase(t)() logger := blog.GetAuditLogger() found, added := parseLogLine(sa, logger, "") test.AssertEquals(t, found, false) test.AssertEquals(t, added, false) found, added = parseLogLine(sa, logger, "0000-00-00T00:00:00+00:00 hostname boulder-ca[pid]: [AUDIT] Failed RPC to store at SA, orphaning certificate: b64der=[] err=[AMQP-RPC timeout], regID=[1337]") test.AssertEquals(t, found, true) test.AssertEquals(t, added, false) found, added = parseLogLine(sa, logger, "0000-00-00T00:00:00+00:00 hostname boulder-ca[pid]: [AUDIT] Failed RPC to store at SA, orphaning certificate: b64der=[deadbeef] err=[AMQP-RPC timeout], regID=[]") test.AssertEquals(t, found, true) test.AssertEquals(t, added, false) reg := satest.CreateWorkingRegistration(t, sa) found, added = parseLogLine(sa, logger, fmt.Sprintf("0000-00-00T00:00:00+00:00 hostname boulder-ca[pid]: [AUDIT] Failed RPC to store at SA, orphaning certificate: b64der=[MIIEWzCCA0OgAwIBAgITAP+gFgYw1hiy61wFEIJLFCdIVjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRoYXBweSBoYWNrZXIgZmFrZSBDQTAeFw0xNTEwMDMwNTIxMDBaFw0xNjAxMDEwNTIxMDBaMBgxFjAUBgNVBAMTDWV4YW1wbGUuY28uYm4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCeo/HSH63lWW42pqdwlalHWOS3JGa3REraT3xM9v3psdRwuTtlwf3YlpF/JIzK5JtXyA3CHGSwEGmUMhMNBZ0tg5I0booXnHyUeDVUnGSnpWgMUY+vCly+pI5oT8pjBHdcj6kjnDTx1cstBjsJi9HBcYPHUh78iEZBsvC0FAKsh8cHaEjUNHzvWd1anBdK0lRn25M8le9IxXi6di9SeyFmahmPteH+LYKZtNzrF5HpatB14+ywV8d212T62PCCnUPDLd+YWjo2+t5pZs7IlGhyGh7EerOOrI2kUUBg3tUdKDp4e3xplxvaAfSfdrqkGx+bQ0iqQnng+lVkXWYWRB8NAgMBAAGjggGVMIIBkTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFDadDBAEUrnrP/566FLp6DmjrlrbMB8GA1UdIwQYMBaAFPt4TxL5YBWDLJ8XfzQZsy426kGJMGoGCCsGAQUFBwEBBF4wXDAmBggrBgEFBQcwAYYaaHR0cDovL2xvY2FsaG9zdDo0MDAyL29jc3AwMgYIKwYBBQUHMAKGJmh0dHA6Ly9sb2NhbGhvc3Q6NDAwMC9hY21lL2lzc3Vlci1jZXJ0MBgGA1UdEQQRMA+CDWV4YW1wbGUuY28uYm4wJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL2V4YW1wbGUuY29tL2NybDBjBgNVHSAEXDBaMAoGBmeBDAECATAAMEwGAyoDBDBFMCIGCCsGAQUFBwIBFhZodHRwOi8vZXhhbXBsZS5jb20vY3BzMB8GCCsGAQUFBwICMBMMEURvIFdoYXQgVGhvdSBXaWx0MA0GCSqGSIb3DQEBCwUAA4IBAQC7tLmUlxyvouVuIljbRtiL+zYdi/zXVSHAMXTkceqp8/8ucZBZu1fMBkB5SW2FUFd8EnuqhKGOeS3dNr9Pe4dLbUDR0UKIwV045Na+Jet4BbHDdWs3NXAutFhdGIa8ivLBQIbTzlBuVRhJE8g6qqjf5hYL0DXkLNptl2l+0+4xJMm/liCp/mYCGRwbdGUzwdSjACO76QLLSqZhkBF37ZJOuDbJTMBi3QzkOcTs6e4d/gSZpCy7yy6nJDxZ9N9P3XBYIpus+aZAYy29d2shYzE3st8cQfB2Wmb0SHd67sftTAzeudiiNW/4E4IKKH4R1S794apUO07y7pkqep1cz32k] err=[AMQP-RPC timeout], regID=[%d]", reg.ID)) test.AssertEquals(t, found, true) test.AssertEquals(t, added, true) }
func TestReconnect(t *testing.T) { ac, mockChannel, finish := setup(t) defer finish() // Override the clock so the sleep calls are instantaneous, regardless of what // the retry calls say. ac.clk = clock.NewFake() ac.retryTimeoutBase = time.Second ac.retryTimeoutMax = time.Second mockChannel.EXPECT().QueueDeclare( "fooqueue", AmqpDurable, AmqpDeleteUnused, AmqpExclusive, AmqpNoWait, nil).AnyTimes() mockChannel.EXPECT().QueueBind("fooqueue", "fooqueue", AmqpExchange, false, nil).Times(3).Return(errors.New("fail")) mockChannel.EXPECT().QueueBind("fooqueue", "fooqueue", AmqpExchange, false, nil).Return(nil) mockChannel.EXPECT().Consume("fooqueue", consumerName, AmqpAutoAck, AmqpExclusive, AmqpNoLocal, AmqpNoWait, nil).Return(make(<-chan amqp.Delivery), nil) mockChannel.EXPECT().NotifyClose(gomock.Any()).Return(make(chan *amqp.Error)) log = mocks.UseMockLog() ac.reconnect(&cmd.AMQPConfig{}, log) if ac.channel != mockChannel { t.Errorf("ac.channel was not equal to mockChannel") } if ac.msgs == nil { t.Errorf("ac.msgs was not initialized") } if ac.closeChan == nil { t.Errorf("ac.closeChan was not initialized") } }
func setup(t *testing.T) (*OCSPUpdater, core.StorageAuthority, *gorp.DbMap, clock.FakeClock, func()) { dbMap, err := sa.NewDbMap(vars.DBConnSA) test.AssertNotError(t, err, "Failed to create dbMap") fc := clock.NewFake() fc.Add(1 * time.Hour) sa, err := sa.NewSQLStorageAuthority(dbMap, fc) test.AssertNotError(t, err, "Failed to create SA") cleanUp := test.ResetSATestDatabase(t) stats, _ := statsd.NewNoopClient(nil) updater, err := newUpdater( stats, fc, dbMap, &mockCA{}, &mockPub{sa}, sa, cmd.OCSPUpdaterConfig{ NewCertificateBatchSize: 1, OldOCSPBatchSize: 1, MissingSCTBatchSize: 1, NewCertificateWindow: cmd.ConfigDuration{Duration: time.Second}, OldOCSPWindow: cmd.ConfigDuration{Duration: time.Second}, MissingSCTWindow: cmd.ConfigDuration{Duration: time.Second}, }, 0, "", ) return updater, sa, dbMap, fc, cleanUp }
func TestDNSTXTAuthorities(t *testing.T) { obj := NewTestDNSResolverImpl(time.Second*10, []string{dnsLoopbackAddr}, testStats, clock.NewFake(), 1) _, auths, err := obj.LookupTXT(context.Background(), "letsencrypt.org") test.AssertNotError(t, err, "TXT lookup failed") test.AssertEquals(t, len(auths), 1) test.AssertEquals(t, auths[0], "letsencrypt.org. 0 IN SOA ns.letsencrypt.org. master.letsencrypt.org. 1 1 1 1 1") }
func TestCheckCert(t *testing.T) { testKey, _ := rsa.GenerateKey(rand.Reader, 1024) checker := newChecker(nil) fc := clock.NewFake() fc.Add(time.Hour * 24 * 90) checker.clock = fc issued := checker.clock.Now().Add(-time.Hour * 24 * 45) goodExpiry := issued.Add(checkPeriod) serial := big.NewInt(1337) // Problems // Blacklsited common name // Expiry period is too long // Basic Constraints aren't set // Wrong key usage (none) rawCert := x509.Certificate{ Subject: pkix.Name{ CommonName: "example.com", }, NotAfter: goodExpiry.AddDate(0, 0, 1), // Period too long DNSNames: []string{"example-a.com"}, SerialNumber: serial, BasicConstraintsValid: false, } brokenCertDer, err := x509.CreateCertificate(rand.Reader, &rawCert, &rawCert, &testKey.PublicKey, testKey) test.AssertNotError(t, err, "Couldn't create certificate") // Problems // Digest doesn't match // Serial doesn't match // Expiry doesn't match cert := core.Certificate{ Status: core.StatusValid, DER: brokenCertDer, Issued: issued, Expires: goodExpiry.AddDate(0, 0, 2), // Expiration doesn't match } problems := checker.checkCert(cert) test.AssertEquals(t, len(problems), 7) // Fix the problems rawCert.Subject.CommonName = "example-a.com" rawCert.NotAfter = goodExpiry rawCert.BasicConstraintsValid = true rawCert.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth} goodCertDer, err := x509.CreateCertificate(rand.Reader, &rawCert, &rawCert, &testKey.PublicKey, testKey) test.AssertNotError(t, err, "Couldn't create certificate") parsed, err := x509.ParseCertificate(goodCertDer) test.AssertNotError(t, err, "Couldn't parse created certificate") cert.Serial = core.SerialToString(serial) cert.Digest = core.Fingerprint256(goodCertDer) cert.DER = goodCertDer cert.Expires = parsed.NotAfter problems = checker.checkCert(cert) test.AssertEquals(t, len(problems), 0) }
func newFakeClock(t *testing.T) clock.FakeClock { const fakeTimeFormat = "2006-01-02T15:04:05.999999999Z" ft, err := time.Parse(fakeTimeFormat, fakeTimeFormat) if err != nil { t.Fatal(err) } fc := clock.NewFake() fc.Set(ft.UTC()) return fc }
func TestDNSLookupTXT(t *testing.T) { obj := NewTestDNSResolverImpl(time.Second*10, []string{dnsLoopbackAddr}, testStats, clock.NewFake(), 1) a, _, err := obj.LookupTXT(context.Background(), "letsencrypt.org") t.Logf("A: %v", a) test.AssertNotError(t, err, "No message") a, _, err = obj.LookupTXT(context.Background(), "split-txt.letsencrypt.org") t.Logf("A: %v ", a) test.AssertNotError(t, err, "No message") test.AssertEquals(t, len(a), 1) test.AssertEquals(t, a[0], "abc") }
func TestAllowNilInIsSafeDomain(t *testing.T) { stats, _ := statsd.NewNoopClient() va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.NewFake()) // Be cool with a nil SafeBrowsing. This will happen in prod when we have // flag mismatch between the VA and RA. resp, err := va.IsSafeDomain(&core.IsSafeDomainRequest{Domain: "example.com"}) if err != nil { t.Errorf("nil SafeBrowsing, unexpected error: %s", err) } else if !resp.IsSafe { t.Errorf("nil Safebrowsing, should fail open but failed closed") } }
func setup(t *testing.T) (*amqpConnector, *MockamqpChannel, func()) { mockCtrl := gomock.NewController(t) mockChannel := NewMockamqpChannel(mockCtrl) ac := amqpConnector{ chMaker: mockChannelMaker{ channel: mockChannel, }, queueName: "fooqueue", retryTimeoutBase: time.Second, clk: clock.NewFake(), } return &ac, mockChannel, func() { mockCtrl.Finish() } }
func TestDNSLookupCAA(t *testing.T) { obj := NewTestDNSResolverImpl(time.Second*10, []string{dnsLoopbackAddr}, testStats, clock.NewFake(), 1) caas, err := obj.LookupCAA(context.Background(), "bracewel.net") test.AssertNotError(t, err, "CAA lookup failed") test.Assert(t, len(caas) > 0, "Should have CAA records") caas, err = obj.LookupCAA(context.Background(), "nonexistent.letsencrypt.org") test.AssertNotError(t, err, "CAA lookup failed") test.Assert(t, len(caas) == 0, "Shouldn't have CAA records") caas, err = obj.LookupCAA(context.Background(), "cname.example.com") test.AssertNotError(t, err, "CAA lookup failed") test.Assert(t, len(caas) > 0, "Should follow CNAME to find CAA") }
func TestGetAndProcessCerts(t *testing.T) { saDbMap, err := sa.NewDbMap(saDbConnStr) test.AssertNotError(t, err, "Couldn't connect to database") paDbMap, err := sa.NewDbMap(paDbConnStr) test.AssertNotError(t, err, "Couldn't connect to policy database") fc := clock.NewFake() checker := newChecker(saDbMap, paDbMap, fc, false) sa, err := sa.NewSQLStorageAuthority(saDbMap, fc) test.AssertNotError(t, err, "Couldn't create SA to insert certificates") saCleanUp := test.ResetTestDatabase(t, saDbMap.Db) paCleanUp := test.ResetTestDatabase(t, paDbMap.Db) defer func() { saCleanUp() paCleanUp() }() testKey, _ := rsa.GenerateKey(rand.Reader, 1024) // Problems // Expiry period is too long rawCert := x509.Certificate{ Subject: pkix.Name{ CommonName: "not-blacklisted.com", }, BasicConstraintsValid: true, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, } reg, err := sa.NewRegistration(core.Registration{ Key: satest.GoodJWK(), }) test.AssertNotError(t, err, "Couldn't create registration") for i := int64(0); i < 5; i++ { rawCert.SerialNumber = big.NewInt(i) certDER, err := x509.CreateCertificate(rand.Reader, &rawCert, &rawCert, &testKey.PublicKey, testKey) test.AssertNotError(t, err, "Couldn't create certificate") _, err = sa.AddCertificate(certDER, reg.ID) test.AssertNotError(t, err, "Couldn't add certificate") } err = checker.getCerts() test.AssertNotError(t, err, "Failed to retrieve certificates") test.AssertEquals(t, len(checker.certs), 5) wg := new(sync.WaitGroup) wg.Add(1) checker.processCerts(wg) test.AssertEquals(t, checker.issuedReport.BadCerts, int64(5)) test.AssertEquals(t, len(checker.issuedReport.Entries), 5) }
func TestDNSNXDOMAIN(t *testing.T) { obj := NewTestDNSResolverImpl(time.Second*10, []string{dnsLoopbackAddr}, testStats, clock.NewFake(), 1) hostname := "nxdomain.letsencrypt.org" _, err := obj.LookupHost(context.Background(), 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(context.Background(), 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 setup(t *testing.T) (*PublisherImpl, *x509.Certificate, *ecdsa.PrivateKey) { intermediatePEM, _ := pem.Decode([]byte(testIntermediate)) pub := NewPublisherImpl(nil, nil) pub.issuerBundle = append(pub.issuerBundle, ct.ASN1Cert(intermediatePEM.Bytes)) pub.SA = mocks.NewStorageAuthority(clock.NewFake()) 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 TestDNSServFail(t *testing.T) { obj := NewTestDNSResolverImpl(time.Second*10, []string{dnsLoopbackAddr}, testStats, clock.NewFake(), 1) bad := "servfail.com" _, _, err := obj.LookupTXT(context.Background(), bad) test.AssertError(t, err, "LookupTXT didn't return an error") _, err = obj.LookupHost(context.Background(), bad) test.AssertError(t, err, "LookupHost didn't return an error") // CAA lookup ignores validation failures from the resolver for now // and returns an empty list of CAA records. emptyCaa, err := obj.LookupCAA(context.Background(), bad) test.Assert(t, len(emptyCaa) == 0, "Query returned non-empty list of CAA records") test.AssertNotError(t, err, "LookupCAA returned an error") }
// initSA constructs a SQLStorageAuthority and a clean up function // that should be defer'ed to the end of the test. func initSA(t *testing.T) (*SQLStorageAuthority, clock.FakeClock, func()) { dbMap, err := NewDbMap(dbConnStr) if err != nil { t.Fatalf("Failed to create dbMap: %s", err) } fc := clock.NewFake() fc.Add(1 * time.Hour) sa, err := NewSQLStorageAuthority(dbMap, fc) if err != nil { t.Fatalf("Failed to create SA: %s", err) } cleanUp := test.ResetTestDatabase(t, dbMap.Db) return sa, fc, cleanUp }
// initSA constructs a SQLStorageAuthority and a clean up function // that should be defer'ed to the end of the test. func initSA(t *testing.T) (*SQLStorageAuthority, clock.FakeClock, func()) { dbMap, err := NewDbMap(vars.DBConnSA) if err != nil { t.Fatalf("Failed to create dbMap: %s", err) } dbMap.TraceOn("SQL: ", &SQLLogger{log}) fc := clock.NewFake() fc.Set(time.Date(2015, 3, 4, 5, 0, 0, 0, time.UTC)) sa, err := NewSQLStorageAuthority(dbMap, fc) if err != nil { t.Fatalf("Failed to create SA: %s", err) } cleanUp := test.ResetSATestDatabase(t) return sa, fc, cleanUp }
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, _ := statsd.NewNoopClient() 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(&PortConfig{}, sbc, stats, clock.NewFake()) resp, err := va.IsSafeDomain(&core.IsSafeDomainRequest{Domain: "good.com"}) if err != nil { t.Errorf("good.com: want no error, got '%s'", err) } if !resp.IsSafe { t.Errorf("good.com: want true, got %t", resp.IsSafe) } resp, err = va.IsSafeDomain(&core.IsSafeDomainRequest{Domain: "bad.com"}) if err != nil { t.Errorf("bad.com: want no error, got '%s'", err) } if resp.IsSafe { t.Errorf("bad.com: want false, got %t", resp.IsSafe) } _, err = va.IsSafeDomain(&core.IsSafeDomainRequest{Domain: "errorful.com"}) if err == nil { t.Errorf("errorful.com: want error, got none") } resp, err = va.IsSafeDomain(&core.IsSafeDomainRequest{Domain: "outofdate.com"}) if err != nil { t.Errorf("outofdate.com: want no error, got '%s'", err) } if !resp.IsSafe { t.Errorf("outofdate.com: IsSafeDomain should fail open on out of date hashes") } }
func TestSendNags(t *testing.T) { stats, _ := statsd.NewNoopClient(nil) mc := mockMail{} rs := newFakeRegStore() fc := clock.NewFake() fc.Add(7 * 24 * time.Hour) m := mailer{ stats: stats, mailer: &mc, emailTemplate: tmpl, rs: rs, clk: fc, } cert := &x509.Certificate{ Subject: pkix.Name{ CommonName: "happy", }, NotAfter: fc.Now().AddDate(0, 0, 2), DNSNames: []string{"example.com"}, } email, _ := core.ParseAcmeURL("mailto:[email protected]") emailB, _ := core.ParseAcmeURL("mailto:[email protected]") err := m.sendNags(cert, []*core.AcmeURL{email}) test.AssertNotError(t, err, "Failed to send warning messages") test.AssertEquals(t, len(mc.Messages), 1) test.AssertEquals(t, fmt.Sprintf(`hi, cert for DNS names example.com is going to expire in 3 days (%s)`, cert.NotAfter), mc.Messages[0]) mc.Clear() err = m.sendNags(cert, []*core.AcmeURL{email, emailB}) test.AssertNotError(t, err, "Failed to send warning messages") test.AssertEquals(t, len(mc.Messages), 2) test.AssertEquals(t, fmt.Sprintf(`hi, cert for DNS names example.com is going to expire in 3 days (%s)`, cert.NotAfter), mc.Messages[0]) test.AssertEquals(t, fmt.Sprintf(`hi, cert for DNS names example.com is going to expire in 3 days (%s)`, cert.NotAfter), mc.Messages[1]) mc.Clear() err = m.sendNags(cert, []*core.AcmeURL{}) test.AssertNotError(t, err, "Not an error to pass no email contacts") test.AssertEquals(t, len(mc.Messages), 0) }
func setup(t *testing.T, port, retries int) (PublisherImpl, *x509.Certificate) { intermediatePEM, _ := pem.Decode([]byte(testIntermediate)) pub, err := NewPublisherImpl(CTConfig{ Logs: []LogDescription{LogDescription{URI: fmt.Sprintf("http://localhost:%d", port)}}, SubmissionBackoffString: "0s", IntermediateBundleFilename: issuerPath, SubmissionRetries: retries, }) test.AssertNotError(t, err, "Couldn't create new Publisher") pub.issuerBundle = append(pub.issuerBundle, base64.StdEncoding.EncodeToString(intermediatePEM.Bytes)) pub.SA = mocks.NewStorageAuthority(clock.NewFake()) leafPEM, _ := pem.Decode([]byte(testLeaf)) leaf, err := x509.ParseCertificate(leafPEM.Bytes) test.AssertNotError(t, err, "Couldn't parse leafPEM.Bytes") return pub, leaf }
func TestLoopTickBackoff(t *testing.T) { fc := clock.NewFake() stats, _ := statsd.NewNoopClient(nil) l := looper{ clk: fc, stats: stats, failureBackoffFactor: 1.5, failureBackoffMax: 10 * time.Minute, tickDur: time.Minute, tickFunc: func(_ int) error { return core.ServiceUnavailableError("sad HSM") }, } start := l.clk.Now() l.tick() // Expected to sleep for 1m backoff := float64(60000000000) maxJittered := backoff * 1.2 test.AssertBetween(t, l.clk.Now().Sub(start).Nanoseconds(), int64(backoff), int64(maxJittered)) start = l.clk.Now() l.tick() // Expected to sleep for 1m30s backoff = 90000000000 maxJittered = backoff * 1.2 test.AssertBetween(t, l.clk.Now().Sub(start).Nanoseconds(), int64(backoff), int64(maxJittered)) l.failures = 6 start = l.clk.Now() l.tick() // Expected to sleep for 11m23.4375s, should be truncated to 10m backoff = 600000000000 maxJittered = backoff * 1.2 test.AssertBetween(t, l.clk.Now().Sub(start).Nanoseconds(), int64(backoff), int64(maxJittered)) l.tickFunc = func(_ int) error { return nil } start = l.clk.Now() l.tick() test.AssertEquals(t, l.failures, 0) test.AssertEquals(t, l.clk.Now(), start) }
func TestGenerateMessage(t *testing.T) { fc := clock.NewFake() m := New("", "", "", "", "*****@*****.**") 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: [email protected]") 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 setup(t *testing.T, nagTimes []time.Duration) *testCtx { // We use the test_setup user (which has full permissions to everything) // because the SA we return is used for inserting data to set up the test. dbMap, err := sa.NewDbMap("mysql+tcp://test_setup@localhost:3306/boulder_sa_test") if err != nil { t.Fatalf("Couldn't connect the database: %s", err) } fc := clock.NewFake() ssa, err := sa.NewSQLStorageAuthority(dbMap, fc) if err != nil { t.Fatalf("unable to create SQLStorageAuthority: %s", err) } cleanUp := test.ResetSATestDatabase(t) stats, _ := statsd.NewNoopClient(nil) mc := &mockMail{} m := &mailer{ log: blog.GetAuditLogger(), stats: stats, mailer: mc, emailTemplate: tmpl, dbMap: dbMap, rs: ssa, nagTimes: nagTimes, limit: 100, clk: fc, } return &testCtx{ dbMap: dbMap, ssa: ssa, mc: mc, fc: fc, m: m, cleanUp: cleanUp, } }
func TestConstructAuthHeader(t *testing.T) { stats, _ := statsd.NewNoopClient(nil) 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 initAuthorities(t *testing.T) (*DummyValidationAuthority, *sa.SQLStorageAuthority, *RegistrationAuthorityImpl, clock.FakeClock, func()) { err := json.Unmarshal(AccountKeyJSONA, &AccountKeyA) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountKeyJSONB, &AccountKeyB) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountKeyJSONC, &AccountKeyC) test.AssertNotError(t, err, "Failed to unmarshal public JWK") err = json.Unmarshal(AccountPrivateKeyJSON, &AccountPrivateKey) test.AssertNotError(t, err, "Failed to unmarshal private JWK") err = json.Unmarshal(ShortKeyJSON, &ShortKey) test.AssertNotError(t, err, "Failed to unmarshal JWK") fc := clock.NewFake() dbMap, err := sa.NewDbMap(vars.DBConnSA) if err != nil { t.Fatalf("Failed to create dbMap: %s", err) } ssa, err := sa.NewSQLStorageAuthority(dbMap, fc) if err != nil { t.Fatalf("Failed to create SA: %s", err) } saDBCleanUp := test.ResetSATestDatabase(t) va := &DummyValidationAuthority{} // PEM files in certificate-authority_test.go caKeyPEM, _ := pem.Decode([]byte(CAkeyPEM)) caKey, _ := x509.ParsePKCS1PrivateKey(caKeyPEM.Bytes) caCertPEM, _ := pem.Decode([]byte(CAcertPEM)) caCert, _ := x509.ParseCertificate(caCertPEM.Bytes) basicPolicy := &cfsslConfig.Signing{ Default: &cfsslConfig.SigningProfile{ Usage: []string{"server auth", "client auth"}, Expiry: 1 * time.Hour, CSRWhitelist: &cfsslConfig.CSRWhitelist{ PublicKey: true, PublicKeyAlgorithm: true, SignatureAlgorithm: true, DNSNames: true, }, }, } signer, _ := local.NewSigner(caKey, caCert, x509.SHA256WithRSA, basicPolicy) ocspSigner, _ := ocsp.NewSigner(caCert, caCert, caKey, time.Hour) paDbMap, err := sa.NewDbMap(vars.DBConnPolicy) if err != nil { t.Fatalf("Failed to create dbMap: %s", err) } policyDBCleanUp := test.ResetPolicyTestDatabase(t) pa, err := policy.NewPolicyAuthorityImpl(paDbMap, false, SupportedChallenges) test.AssertNotError(t, err, "Couldn't create PA") ca := ca.CertificateAuthorityImpl{ Signer: signer, OCSPSigner: ocspSigner, SA: ssa, PA: pa, ValidityPeriod: time.Hour * 2190, NotAfter: time.Now().Add(time.Hour * 8761), Clk: fc, Publisher: &mocks.Publisher{}, } cleanUp := func() { saDBCleanUp() policyDBCleanUp() } csrDER, _ := hex.DecodeString(CSRhex) ExampleCSR, _ = x509.ParseCertificateRequest(csrDER) Registration, _ = ssa.NewRegistration(core.Registration{ Key: AccountKeyA, InitialIP: net.ParseIP("3.2.3.3"), }) stats, _ := statsd.NewNoopClient() ra := NewRegistrationAuthorityImpl(fc, blog.GetAuditLogger(), stats, &DomainCheck{va}, cmd.RateLimitConfig{ TotalCertificates: cmd.RateLimitPolicy{ Threshold: 100, Window: cmd.ConfigDuration{Duration: 24 * 90 * time.Hour}, }, }, 1) ra.SA = ssa ra.VA = va ra.CA = &ca ra.PA = pa ra.DNSResolver = &mocks.DNSResolver{} AuthzInitial.RegistrationID = Registration.ID challenges, combinations, err := pa.ChallengesFor(AuthzInitial.Identifier, &Registration.Key) AuthzInitial.Challenges = challenges AuthzInitial.Combinations = combinations AuthzFinal = AuthzInitial AuthzFinal.Status = "valid" exp := time.Now().Add(365 * 24 * time.Hour) AuthzFinal.Expires = &exp AuthzFinal.Challenges[0].Status = "valid" return va, ssa, ra, fc, cleanUp }
func TestRetry(t *testing.T) { isTempErr := &net.OpError{Op: "read", Err: tempError(true)} nonTempErr := &net.OpError{Op: "read", Err: tempError(false)} servFailError := errors.New("DNS problem: server failure at resolver looking up TXT for example.com") netError := errors.New("DNS problem: networking error looking up TXT for example.com") type testCase struct { maxTries int te *testExchanger expected error expectedCount int } tests := []*testCase{ // The success on first try case { maxTries: 3, te: &testExchanger{ errs: []error{nil}, }, expected: nil, expectedCount: 1, }, // Immediate non-OpError, error returns immediately { maxTries: 3, te: &testExchanger{ errs: []error{errors.New("nope")}, }, expected: servFailError, expectedCount: 1, }, // Temporary err, then non-OpError stops at two tries { maxTries: 3, te: &testExchanger{ errs: []error{isTempErr, errors.New("nope")}, }, expected: servFailError, expectedCount: 2, }, // Temporary error given always { maxTries: 3, te: &testExchanger{ errs: []error{ isTempErr, isTempErr, isTempErr, }, }, expected: netError, expectedCount: 3, }, // Even with maxTries at 0, we should still let a single request go // through { maxTries: 0, te: &testExchanger{ errs: []error{nil}, }, expected: nil, expectedCount: 1, }, // Temporary error given just once causes two tries { maxTries: 3, te: &testExchanger{ errs: []error{ isTempErr, nil, }, }, expected: nil, expectedCount: 2, }, // Temporary error given twice causes three tries { maxTries: 3, te: &testExchanger{ errs: []error{ isTempErr, isTempErr, nil, }, }, expected: nil, expectedCount: 3, }, // Temporary error given thrice causes three tries and fails { maxTries: 3, te: &testExchanger{ errs: []error{ isTempErr, isTempErr, isTempErr, }, }, expected: netError, expectedCount: 3, }, // temporary then non-Temporary error causes two retries { maxTries: 3, te: &testExchanger{ errs: []error{ isTempErr, nonTempErr, }, }, expected: netError, expectedCount: 2, }, } for i, tc := range tests { dr := NewTestDNSResolverImpl(time.Second*10, []string{dnsLoopbackAddr}, testStats, clock.NewFake(), tc.maxTries) dr.DNSClient = tc.te _, _, err := dr.LookupTXT(context.Background(), "example.com") if err == errTooManyRequests { t.Errorf("#%d, sent more requests than the test case handles", i) } expectedErr := tc.expected if (expectedErr == nil && err != nil) || (expectedErr != nil && err == nil) || (expectedErr != nil && expectedErr.Error() != err.Error()) { t.Errorf("#%d, error, expected %v, got %v", i, expectedErr, err) } if tc.expectedCount != tc.te.count { t.Errorf("#%d, error, expectedCount %v, got %v", i, tc.expectedCount, tc.te.count) } } dr := NewTestDNSResolverImpl(time.Second*10, []string{dnsLoopbackAddr}, testStats, clock.NewFake(), 3) dr.DNSClient = &testExchanger{errs: []error{isTempErr, isTempErr, nil}} ctx, cancel := context.WithCancel(context.Background()) cancel() _, _, err := dr.LookupTXT(ctx, "example.com") if err == nil || err.Error() != "DNS problem: query timed out looking up TXT for example.com" { t.Errorf("expected %s, got %s", context.Canceled, err) } dr.DNSClient = &testExchanger{errs: []error{isTempErr, isTempErr, nil}} ctx, _ = context.WithTimeout(context.Background(), -10*time.Hour) _, _, err = dr.LookupTXT(ctx, "example.com") if err == nil || err.Error() != "DNS problem: query timed out looking up TXT for example.com" { t.Errorf("expected %s, got %s", context.DeadlineExceeded, err) } dr.DNSClient = &testExchanger{errs: []error{isTempErr, isTempErr, nil}} ctx, deadlineCancel := context.WithTimeout(context.Background(), -10*time.Hour) deadlineCancel() _, _, err = dr.LookupTXT(ctx, "example.com") if err == nil || err.Error() != "DNS problem: query timed out looking up TXT for example.com" { t.Errorf("expected %s, got %s", context.DeadlineExceeded, err) } }