From 27bd49322a96510637897073b5e9b4e4125b4ee6 Mon Sep 17 00:00:00 2001 From: Kayra Date: Tue, 14 May 2024 13:14:50 +0300 Subject: [PATCH] metrics tests --- internal/metrics/metrics.go | 9 ++- internal/metrics/metrics_test.go | 112 +++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 3 deletions(-) diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index df73bd8..a79d60f 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -39,9 +39,10 @@ func NewMetricsSubsystem(db *certdb.CertificateRequestsRepository) *PrometheusMe log.Println(errors.Join(errors.New("error generating metrics repository: "), err)) } metricsBackend := newPrometheusMetrics() + metricsBackend.generateMetrics(csrs) go func() { - metricsBackend.generateMetrics(csrs) time.Sleep(120 * ONE_SECOND) + metricsBackend.generateMetrics(csrs) }() metricsBackend.Handler = promhttp.HandlerFor(metricsBackend.registry, promhttp.HandlerOpts{}) return metricsBackend @@ -97,10 +98,12 @@ func (pm *PrometheusMetrics) generateMetrics(csrs []certdb.CertificateRequest) { for _, entry := range csrs { if entry.Certificate == "" { outstandingCSRCount += 1 + continue } - if entry.Certificate != "" && entry.Certificate != "rejected" { - certCount += 1 + if entry.Certificate == "rejected" { + continue } + certCount += 1 expiryDate := certificateExpiryDate(entry.Certificate) daysRemaining := time.Until(expiryDate).Hours() / 24 if daysRemaining < 0 { diff --git a/internal/metrics/metrics_test.go b/internal/metrics/metrics_test.go index b1c4275..0a52acd 100644 --- a/internal/metrics/metrics_test.go +++ b/internal/metrics/metrics_test.go @@ -1,11 +1,19 @@ package metrics_test import ( + "bytes" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "fmt" "log" + "math/big" "net/http" "net/http/httptest" "strings" "testing" + "time" "github.com/canonical/gocert/internal/certdb" metrics "github.com/canonical/gocert/internal/metrics" @@ -41,3 +49,107 @@ func TestPrometheusHandler(t *testing.T) { log.Fatalln(err) } } + +// Generates a CSR and Certificate with the given days remaining +func generateCertPair(daysRemaining int) (string, string) { + NotAfterTime := time.Now().AddDate(0, 0, daysRemaining) + key, _ := rsa.GenerateKey(rand.Reader, 2048) + + csrTemplate := x509.CertificateRequest{} + certTemplate := x509.Certificate{ + SerialNumber: big.NewInt(1), + NotAfter: NotAfterTime, + } + + csrBytes, _ := x509.CreateCertificateRequest(rand.Reader, &csrTemplate, key) + certBytes, _ := x509.CreateCertificate(rand.Reader, &certTemplate, &certTemplate, &key.PublicKey, key) + + var buff bytes.Buffer + pem.Encode(&buff, &pem.Block{ + Type: "CERTIFICATE REQUEST", + Bytes: csrBytes, + }) + csr := buff.String() + buff.Reset() + pem.Encode(&buff, &pem.Block{ + Type: "CERTIFICATE", + Bytes: certBytes, + }) + cert := buff.String() + return csr, cert +} + +func initializeTestDB(db *certdb.CertificateRequestsRepository) { + for i, v := range []int{5, 10, 32} { + csr, cert := generateCertPair(v) + _, err := db.Create(csr) + if err != nil { + log.Fatalf("couldn't create test csr:%s", err) + } + _, err = db.Update(fmt.Sprint(i+1), cert) + if err != nil { + log.Fatalf("couldn't create test cert:%s", err) + } + } +} + +// TestMetrics tests some of the metrics that we currently collect. +func TestMetrics(t *testing.T) { + db, err := certdb.NewCertificateRequestsRepository(":memory:", "CertificateReq") + if err != nil { + log.Fatalln(err) + } + initializeTestDB(db) + m := metrics.NewMetricsSubsystem(db) + + request, _ := http.NewRequest("GET", "/", nil) + recorder := httptest.NewRecorder() + m.Handler.ServeHTTP(recorder, request) + + if status := recorder.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) + } + if recorder.Body.String() == "" { + t.Errorf("handler returned an empty body") + } + for _, line := range strings.Split(recorder.Body.String(), "\n") { + if strings.Contains(line, "outstanding_certificate_requests ") && !strings.HasPrefix(line, "#") { + if !strings.HasSuffix(line, "0") { + t.Errorf("outstanding_certificate_requests expected to receive 0") + } + } else if strings.Contains(line, "certificate_requests ") && !strings.HasPrefix(line, "#") { + if !strings.HasSuffix(line, "3") { + t.Errorf("certificate_requests expected to receive 3") + } + } else if strings.Contains(line, "certificates ") && !strings.HasPrefix(line, "#") { + if !strings.HasSuffix(line, "3") { + t.Errorf("certificates expected to receive 3") + } + } else if strings.Contains(line, "certificates_expired ") && !strings.HasPrefix(line, "#") { + if !strings.HasSuffix(line, "0") { + t.Errorf("certificates_expired expected to receive 0") + } + } else if strings.Contains(line, "certificates_expiring_in_1_day ") && !strings.HasPrefix(line, "#") { + if !strings.HasSuffix(line, "0") { + t.Errorf("certificates_expiring_in_1_day expected to receive 0") + } + } else if strings.Contains(line, "certificates_expiring_in_7_days ") && !strings.HasPrefix(line, "#") { + if !strings.HasSuffix(line, "1") { + t.Errorf("certificates_expiring_in_7_days expected to receive 1") + } + } else if strings.Contains(line, "certificates_expiring_in_30_days ") && !strings.HasPrefix(line, "#") { + if !strings.HasSuffix(line, "2") { + t.Errorf("certificates_expiring_in_30_days expected to receive 2") + } + } else if strings.Contains(line, "certificates_expiring_in_90_days ") && !strings.HasPrefix(line, "#") { + if !strings.HasSuffix(line, "3") { + t.Errorf("certificates_expiring_in_90_days expected to receive 3") + } + } + } + + err = db.Close() + if err != nil { + log.Fatalln(err) + } +}