Beispiel #1
0
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)
}
Beispiel #2
0
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 paImpl(t *testing.T) (*PolicyAuthorityImpl, func()) {
	dbMap, err := sa.NewDbMap(dbConnStr)
	test.AssertNotError(t, err, "Could not construct dbMap")

	pa, err := NewPolicyAuthorityImpl(dbMap, false)
	test.AssertNotError(t, err, "Couldn't create PADB")

	cleanUp := test.ResetTestDatabase(t, dbMap.Db)

	return pa, 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, func()) {
	dbMap, err := NewDbMap(dbConnStr)
	if err != nil {
		t.Fatalf("Failed to create dbMap: %s", err)
	}

	sa, err := NewSQLStorageAuthority(dbMap)
	if err != nil {
		t.Fatalf("Failed to create SA: %s", err)
	}
	cleanUp := test.ResetTestDatabase(t, dbMap.Db)
	return sa, cleanUp
}
// This is an unfortunate bit of tech debt that is being taken on in
// order to get the more important change of using MySQL/MariaDB in
// all of our tests working without SQLite. We already had issues with
// the RA here getting a real CertificateAuthority instead of a
// CertificateAuthorityClient, so this is only marginally worse.
// TODO(Issue #628): use a CAClient fake instead of a CAImpl instance
func caDBImpl(t *testing.T) (core.CertificateAuthorityDatabase, func()) {
	dbMap, err := sa.NewDbMap(caDBConnStr)
	if err != nil {
		t.Fatalf("Could not construct dbMap: %s", err)
	}

	cadb, err := ca.NewCertificateAuthorityDatabaseImpl(dbMap)
	if err != nil {
		t.Fatalf("Could not construct CA DB: %s", err)
	}

	cleanUp := test.ResetTestDatabase(t, dbMap.Db)
	return cadb, 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(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
}
// This is an unfortunate bit of tech debt that is being taken on in
// order to get the more important change of using MySQL/MariaDB in
// all of our tests working without SQLite. We already had issues with
// the RA here getting a real CertificateAuthority instead of a
// CertificateAuthorityClient, so this is only marginally worse.
// TODO(Issue #628): use a CAClient fake instead of a CAImpl instance
func caDBImpl(t *testing.T) (core.CertificateAuthorityDatabase, func()) {
	dbMap, err := sa.NewDbMap(caDBConnStr)
	if err != nil {
		t.Fatalf("Could not construct dbMap: %s", err)
	}

	cadb, err := ca.NewCertificateAuthorityDatabaseImpl(dbMap)
	if err != nil {
		t.Fatalf("Could not construct CA DB: %s", err)
	}

	cleanUp := test.ResetTestDatabase(t, dbMap.Db)

	// This row is required to exist for caDBImpl to work
	// correctly. We can no longer use
	// dbMap.Insert(&SerialNumber{...}) for this because gorp will
	// ignore the ID and insert a new row at a new autoincrement id.
	// TODO(jmhodges): gen ids flickr-style, no row needed a head of time
	_, err = dbMap.Db.Exec("insert into serialNumber (id, number, lastUpdated) VALUES (?, ?, ?)", 1, 1, time.Now())
	if err != nil {
		t.Fatalf("unable to create the serial number row: %s", err)
	}
	return cadb, cleanUp
}
Beispiel #8
0
func TestFindExpiringCertificates(t *testing.T) {
	dbMap, err := sa.NewDbMap(dbConnStr)
	if err != nil {
		t.Fatalf("Couldn't connect the database: %s", err)
	}
	cleanUp := test.ResetTestDatabase(t, dbMap.Db)
	ssa, err := sa.NewSQLStorageAuthority(dbMap)
	if err != nil {
		t.Fatalf("unable to create SQLStorageAuthority: %s", err)
	}
	defer cleanUp()
	tmpl, err := template.New("expiry-email").Parse(testTmpl)
	test.AssertNotError(t, err, "Couldn't parse test email template")
	stats, _ := statsd.NewNoopClient(nil)
	mc := mockMail{}
	m := mailer{
		log:           blog.GetAuditLogger(),
		stats:         stats,
		mailer:        &mc,
		emailTemplate: tmpl,
		dbMap:         dbMap,
		rs:            ssa,
		nagTimes:      []time.Duration{time.Hour * 24, time.Hour * 24 * 4, time.Hour * 24 * 7},
		limit:         100,
	}

	log.Clear()
	err = m.findExpiringCertificates()
	test.AssertNotError(t, err, "Failed on no certificates")
	test.AssertEquals(t, len(log.GetAllMatching("Searching for certificates that expire between.*")), 3)

	// Add some expiring certificates and registrations
	emailA, _ := core.ParseAcmeURL("mailto:[email protected]")
	emailB, _ := core.ParseAcmeURL("mailto:[email protected]")
	var keyA jose.JsonWebKey
	var keyB jose.JsonWebKey
	err = json.Unmarshal(jsonKeyA, &keyA)
	test.AssertNotError(t, err, "Failed to unmarshal public JWK")
	err = json.Unmarshal(jsonKeyB, &keyB)
	test.AssertNotError(t, err, "Failed to unmarshal public JWK")
	regA := core.Registration{
		ID: 1,
		Contact: []*core.AcmeURL{
			emailA,
		},
		Key: keyA,
	}
	regB := core.Registration{
		ID: 2,
		Contact: []*core.AcmeURL{
			emailB,
		},
		Key: keyB,
	}
	regA, err = ssa.NewRegistration(regA)
	if err != nil {
		t.Fatalf("Couldn't store regA: %s", err)
	}
	regB, err = ssa.NewRegistration(regB)
	if err != nil {
		t.Fatalf("Couldn't store regB: %s", err)
	}

	rawCertA := x509.Certificate{
		Subject: pkix.Name{
			CommonName: "happy A",
		},
		NotAfter:     time.Now().AddDate(0, 0, 1),
		DNSNames:     []string{"example-a.com"},
		SerialNumber: big.NewInt(1337),
	}
	certDerA, _ := x509.CreateCertificate(rand.Reader, &rawCertA, &rawCertA, &testKey.PublicKey, &testKey)
	certA := &core.Certificate{
		RegistrationID: regA.ID,
		Status:         core.StatusValid,
		Serial:         "001",
		Expires:        time.Now().AddDate(0, 0, 1),
		DER:            certDerA,
	}
	// Already sent a nag but too long ago
	certStatusA := &core.CertificateStatus{Serial: "001", LastExpirationNagSent: time.Now().Add(-time.Hour * 24 * 3)}
	rawCertB := x509.Certificate{
		Subject: pkix.Name{
			CommonName: "happy B",
		},
		NotAfter:     time.Now().AddDate(0, 0, 3),
		DNSNames:     []string{"example-b.com"},
		SerialNumber: big.NewInt(1337),
	}
	certDerB, _ := x509.CreateCertificate(rand.Reader, &rawCertB, &rawCertB, &testKey.PublicKey, &testKey)
	certB := &core.Certificate{
		RegistrationID: regA.ID,
		Status:         core.StatusValid,
		Serial:         "002",
		Expires:        time.Now().AddDate(0, 0, 3),
		DER:            certDerB,
	}
	// Already sent a nag for this period
	certStatusB := &core.CertificateStatus{Serial: "002", LastExpirationNagSent: time.Now().Add(-time.Hour * 24 * 3)}
	rawCertC := x509.Certificate{
		Subject: pkix.Name{
			CommonName: "happy C",
		},
		NotAfter:     time.Now().AddDate(0, 0, 7),
		DNSNames:     []string{"example-c.com"},
		SerialNumber: big.NewInt(1337),
	}
	certDerC, _ := x509.CreateCertificate(rand.Reader, &rawCertC, &rawCertC, &testKey.PublicKey, &testKey)
	certC := &core.Certificate{
		RegistrationID: regB.ID,
		Status:         core.StatusValid,
		Serial:         "003",
		Expires:        time.Now().AddDate(0, 0, 7),
		DER:            certDerC,
	}
	certStatusC := &core.CertificateStatus{Serial: "003"}

	err = dbMap.Insert(certA)
	test.AssertNotError(t, err, "Couldn't add certA")
	err = dbMap.Insert(certB)
	test.AssertNotError(t, err, "Couldn't add certB")
	err = dbMap.Insert(certC)
	test.AssertNotError(t, err, "Couldn't add certC")
	err = dbMap.Insert(certStatusA)
	test.AssertNotError(t, err, "Couldn't add certStatusA")
	err = dbMap.Insert(certStatusB)
	test.AssertNotError(t, err, "Couldn't add certStatusB")
	err = dbMap.Insert(certStatusC)
	test.AssertNotError(t, err, "Couldn't add certStatusC")

	log.Clear()
	err = m.findExpiringCertificates()
	test.AssertNotError(t, err, "Failed to find expiring certs")
	// Should get 001 and 003
	test.AssertEquals(t, len(mc.Messages), 2)

	test.AssertEquals(t, fmt.Sprintf(`hi, cert for DNS names example-a.com is going to expire in 1 days (%s)`, rawCertA.NotAfter.UTC().Format("2006-01-02 15:04:05 -0700 MST")), mc.Messages[0])
	test.AssertEquals(t, fmt.Sprintf(`hi, cert for DNS names example-c.com is going to expire in 7 days (%s)`, rawCertC.NotAfter.UTC().Format("2006-01-02 15:04:05 -0700 MST")), mc.Messages[1])

	// A consecutive run shouldn't find anything
	mc.Clear()
	log.Clear()
	err = m.findExpiringCertificates()
	test.AssertNotError(t, err, "Failed to find expiring certs")
	test.AssertEquals(t, len(mc.Messages), 0)
}
func setup(t *testing.T) *testCtx {
	// Create an SA
	dbMap, err := sa.NewDbMap(saDBConnStr)
	if err != nil {
		t.Fatalf("Failed to create dbMap: %s", err)
	}
	fc := clock.NewFake()
	fc.Add(1 * time.Hour)
	ssa, err := sa.NewSQLStorageAuthority(dbMap, fc)
	if err != nil {
		t.Fatalf("Failed to create SA: %s", err)
	}
	saDBCleanUp := test.ResetTestDatabase(t, dbMap.Db)
	cadb, caDBCleanUp := caDBImpl(t)

	paDbMap, err := sa.NewDbMap(paDBConnStr)
	test.AssertNotError(t, err, "Could not construct dbMap")
	pa, err := policy.NewPolicyAuthorityImpl(paDbMap, false)
	test.AssertNotError(t, err, "Couldn't create PADB")
	paDBCleanUp := test.ResetTestDatabase(t, paDbMap.Db)

	cleanUp := func() {
		saDBCleanUp()
		caDBCleanUp()
		paDBCleanUp()
	}

	// TODO(jmhodges): use of this pkg here is a bug caused by using a real SA
	reg := satest.CreateWorkingRegistration(t, ssa)

	// Create a CA
	caConfig := cmd.CAConfig{
		Profile:      profileName,
		SerialPrefix: 17,
		Key: cmd.KeyConfig{
			File: caKeyFile,
		},
		Expiry:       "8760h",
		LifespanOCSP: "45m",
		MaxNames:     2,
		CFSSL: cfsslConfig.Config{
			Signing: &cfsslConfig.Signing{
				Profiles: map[string]*cfsslConfig.SigningProfile{
					profileName: &cfsslConfig.SigningProfile{
						Usage:     []string{"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{
							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,
						},
					},
				},
				Default: &cfsslConfig.SigningProfile{
					ExpiryString: "8760h",
				},
			},
			OCSP: &ocspConfig.Config{
				CACertFile:        caCertFile,
				ResponderCertFile: caCertFile,
				KeyFile:           caKeyFile,
			},
		},
	}
	return &testCtx{cadb, ssa, caConfig, reg, pa, fc, cleanUp}
}
func initAuthorities(t *testing.T) (*DummyValidationAuthority, *sa.SQLStorageAuthority, *RegistrationAuthorityImpl, 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 unmarshall JWK")

	dbMap, err := sa.NewDbMap(saDBConnStr)
	if err != nil {
		t.Fatalf("Failed to create dbMap: %s", err)
	}
	ssa, err := sa.NewSQLStorageAuthority(dbMap)
	if err != nil {
		t.Fatalf("Failed to create SA: %s", err)
	}

	saDBCleanUp := test.ResetTestDatabase(t, dbMap.Db)

	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)
	pa := policy.NewPolicyAuthorityImpl()
	cadb, caDBCleanUp := caDBImpl(t)
	ca := ca.CertificateAuthorityImpl{
		Signer:         signer,
		OCSPSigner:     ocspSigner,
		SA:             ssa,
		PA:             pa,
		DB:             cadb,
		ValidityPeriod: time.Hour * 2190,
		NotAfter:       time.Now().Add(time.Hour * 8761),
		MaxKeySize:     4096,
	}
	cleanUp := func() {
		saDBCleanUp()
		caDBCleanUp()
	}

	csrDER, _ := hex.DecodeString(CSRhex)
	ExampleCSR, _ = x509.ParseCertificateRequest(csrDER)

	Registration, _ = ssa.NewRegistration(core.Registration{Key: AccountKeyA})

	ra := NewRegistrationAuthorityImpl()
	ra.SA = ssa
	ra.VA = va
	ra.CA = &ca
	ra.PA = pa
	ra.AuthzBase = "http://acme.invalid/authz/"
	ra.MaxKeySize = 4096
	ra.DNSResolver = &mocks.MockDNS{}

	AuthzInitial.RegistrationID = Registration.ID

	AuthzUpdated = AuthzInitial

	AuthzFinal = AuthzUpdated
	AuthzFinal.Status = "valid"
	exp := time.Now().Add(365 * 24 * time.Hour)
	AuthzFinal.Expires = &exp
	AuthzFinal.Challenges[0].Status = "valid"

	return va, ssa, &ra, cleanUp
}
Beispiel #11
0
func TestCheckCert(t *testing.T) {
	saDbMap, err := sa.NewDbMap(saDbConnStr)
	test.AssertNotError(t, err, "Couldn't connect to database")
	saCleanup := test.ResetTestDatabase(t, saDbMap.Db)
	paDbMap, err := sa.NewDbMap(paDbConnStr)
	test.AssertNotError(t, err, "Couldn't connect to policy database")
	paCleanup := test.ResetTestDatabase(t, paDbMap.Db)
	defer func() {
		saCleanup()
		paCleanup()
	}()

	testKey, _ := rsa.GenerateKey(rand.Reader, 1024)
	fc := clock.NewFake()
	fc.Add(time.Hour * 24 * 90)

	checker := newChecker(saDbMap, paDbMap, fc, false)

	issued := checker.clock.Now().Add(-time.Hour * 24 * 45)
	goodExpiry := issued.Add(checkPeriod)
	serial := big.NewInt(1337)
	// Problems
	//   Expiry period is too long
	//   Basic Constraints aren't set
	//   Wrong key usage (none)
	rawCert := x509.Certificate{
		Subject: pkix.Name{
			CommonName: "example.com",
		},
		NotBefore:             issued,
		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
	//   Issued doesn't match
	cert := core.Certificate{
		DER:     brokenCertDer,
		Issued:  issued.Add(12 * time.Hour),
		Expires: goodExpiry.AddDate(0, 0, 2), // Expiration doesn't match
	}

	problems := checker.checkCert(cert)
	fmt.Println(strings.Join(problems, "\n"))
	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
	cert.Issued = parsed.NotBefore
	problems = checker.checkCert(cert)
	test.AssertEquals(t, len(problems), 0)
}
Beispiel #12
0
func TestCheckCert(t *testing.T) {
	saDbMap, err := sa.NewDbMap(saDbConnStr)
	test.AssertNotError(t, err, "Couldn't connect to database")
	saCleanup := test.ResetTestDatabase(t, saDbMap.Db)
	paDbMap, err := sa.NewDbMap(paDbConnStr)
	test.AssertNotError(t, err, "Couldn't connect to policy database")
	paCleanup := test.ResetTestDatabase(t, paDbMap.Db)
	defer func() {
		saCleanup()
		paCleanup()
	}()

	testKey, _ := rsa.GenerateKey(rand.Reader, 1024)
	fc := clock.NewFake()
	fc.Add(time.Hour * 24 * 90)

	checker := newChecker(saDbMap, paDbMap, fc, false)

	issued := checker.clock.Now().Add(-time.Hour * 24 * 45)
	goodExpiry := issued.Add(checkPeriod)
	serial := big.NewInt(1337)
	// Problems
	//   Expiry period is too long
	//   Basic Constraints aren't set
	//   Wrong key usage (none)
	rawCert := x509.Certificate{
		Subject: pkix.Name{
			CommonName: "example.com",
		},
		NotBefore:             issued,
		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
	//   Issued doesn't match
	cert := core.Certificate{
		Serial:  "8485f2687eba29ad455ae4e31c8679206fec",
		DER:     brokenCertDer,
		Issued:  issued.Add(12 * time.Hour),
		Expires: goodExpiry.AddDate(0, 0, 2), // Expiration doesn't match
	}

	problems := checker.checkCert(cert)

	problemsMap := map[string]int{
		"Stored digest doesn't match certificate digest":                            1,
		"Stored serial doesn't match certificate serial":                            1,
		"Stored expiration doesn't match certificate NotAfter":                      1,
		"Certificate doesn't have basic constraints set":                            1,
		"Certificate has a validity period longer than 2160h0m0s":                   1,
		"Stored issuance date is outside of 6 hour window of certificate NotBefore": 1,
		"Certificate has incorrect key usage extensions":                            1,
	}
	test.AssertEquals(t, len(problems), 7)
	for _, p := range problems {
		_, ok := problemsMap[p]
		if !ok {
			t.Errorf("Expected problem '%s' but didn't find it.", p)
		}
		delete(problemsMap, p)
	}
	for k, _ := range problemsMap {
		t.Errorf("Found unexpected problem '%s'.", k)
	}

	// Same settings as above, but the stored serial number in the DB is invalid.
	cert.Serial = "not valid"
	problems = checker.checkCert(cert)
	foundInvalidSerialProblem := false
	for _, p := range problems {
		if p == "Stored serial is invalid" {
			foundInvalidSerialProblem = true
		}
	}
	test.Assert(t, foundInvalidSerialProblem, "Invalid certificate serial number in DB did not trigger problem.")

	// 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
	cert.Issued = parsed.NotBefore
	problems = checker.checkCert(cert)
	test.AssertEquals(t, len(problems), 0)
}
Beispiel #13
0
func TestLifetimeOfACert(t *testing.T) {
	dbMap, err := sa.NewDbMap(dbConnStr)
	if err != nil {
		t.Fatalf("Couldn't connect the database: %s", err)
	}
	cleanUp := test.ResetTestDatabase(t, dbMap.Db)
	ssa, err := sa.NewSQLStorageAuthority(dbMap)
	if err != nil {
		t.Fatalf("unable to create SQLStorageAuthority: %s", err)
	}
	defer cleanUp()

	stats, _ := statsd.NewNoopClient(nil)
	mc := mockMail{}
	fc := clock.NewFake()

	m := mailer{
		log:           blog.GetAuditLogger(),
		stats:         stats,
		mailer:        &mc,
		emailTemplate: tmpl,
		dbMap:         dbMap,
		rs:            ssa,
		nagTimes:      []time.Duration{time.Hour * 24, time.Hour * 24 * 4, time.Hour * 24 * 7},
		limit:         100,
		clk:           fc,
	}

	var keyA jose.JsonWebKey
	err = json.Unmarshal(jsonKeyA, &keyA)
	test.AssertNotError(t, err, "Failed to unmarshal public JWK")

	emailA, _ := core.ParseAcmeURL("mailto:[email protected]")

	regA := core.Registration{
		ID: 1,
		Contact: []*core.AcmeURL{
			emailA,
		},
		Key: keyA,
	}
	regA, err = ssa.NewRegistration(regA)
	if err != nil {
		t.Fatalf("Couldn't store regA: %s", err)
	}
	rawCertA := x509.Certificate{
		Subject: pkix.Name{
			CommonName: "happy A",
		},

		NotAfter:     fc.Now(),
		DNSNames:     []string{"example-a.com"},
		SerialNumber: big.NewInt(1337),
	}
	certDerA, _ := x509.CreateCertificate(rand.Reader, &rawCertA, &rawCertA, &testKey.PublicKey, &testKey)
	certA := &core.Certificate{
		RegistrationID: regA.ID,
		Status:         core.StatusValid,
		Serial:         "001",
		Expires:        rawCertA.NotAfter,
		DER:            certDerA,
	}

	certStatusA := &core.CertificateStatus{
		Serial: "001",
	}

	err = dbMap.Insert(certA)
	test.AssertNotError(t, err, "unable to insert Certificate")
	err = dbMap.Insert(certStatusA)
	test.AssertNotError(t, err, "unable to insert CertificateStatus")

	type lifeTest struct {
		timeLeft time.Duration
		numMsgs  int
		context  string
	}
	tests := []lifeTest{
		{
			timeLeft: 8 * 24 * time.Hour, // 8 days before expiration

			numMsgs: 0,
			context: "Expected no emails sent because we are more than 7 days out.",
		},
		{
			7 * 24 * time.Hour, // 7 days before
			1,
			"Sent 1 for 7 day notice.",
		},
		{
			5 * 24 * time.Hour,
			1,
			"The 7 day email was already sent.",
		},
		{
			3 * 24 * time.Hour, // 3 days before, the mailer wasn't run the day before
			2,
			"Sent 1 for the 7 day notice, and 1 for the 4 day notice.",
		},
		{
			1 * 24 * time.Hour,
			3,
			"Sent 1 for the 7 day notice, 1 for the 4 day notice, and 1 for the 1 day notice.",
		},
		{
			12 * time.Hour,
			3,
			"The 1 day before email was already sent.",
		},
		{
			-2 * 24 * time.Hour, // 2 days after expiration
			3,
			"No expiration warning emails are sent after expiration",
		},
	}

	for _, tt := range tests {
		fc.Add(-tt.timeLeft)
		err = m.findExpiringCertificates()
		test.AssertNotError(t, err, "error calling findExpiringCertificates")
		if len(mc.Messages) != tt.numMsgs {
			t.Errorf(tt.context+" number of messages: expected %d, got %d", tt.numMsgs, len(mc.Messages))
		}
		fc.Add(tt.timeLeft)
	}
}