CA: Use Prometheus for counting issued certificates. (#2690)

Prepare for counting precertificates by paramaterizing the counter
on "purpose".
This commit is contained in:
Brian Smith 2017-04-19 08:06:04 -10:00 committed by Jacob Hoffman-Andrews
parent cc5ee3906b
commit 2781549618
2 changed files with 34 additions and 6 deletions

View File

@ -34,6 +34,7 @@ import (
"github.com/letsencrypt/boulder/goodkey"
blog "github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/metrics"
"github.com/prometheus/client_golang/prometheus"
)
// Miscellaneous PKIX OIDs that we need to refer to
@ -97,6 +98,19 @@ const (
metricCSRExtensionOther = "CSRExtensions.Other"
)
var (
signatureCount = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "signatures",
Help: "Number of signatures",
},
[]string{"purpose"})
)
func init() {
prometheus.MustRegister(signatureCount)
}
type certificateStorage interface {
AddCertificate(context.Context, []byte, int64, []byte) (string, error)
}
@ -365,7 +379,7 @@ func (ca *CertificateAuthorityImpl) GenerateOCSP(ctx context.Context, xferObj co
ocspResponse, err := issuer.ocspSigner.Sign(signRequest)
ca.noteSignError(err)
if err == nil {
ca.stats.Inc("Signatures.OCSP", 1)
signatureCount.With(prometheus.Labels{"purpose": "ocsp"}).Inc()
}
return ocspResponse, err
}
@ -460,7 +474,7 @@ func (ca *CertificateAuthorityImpl) IssueCertificate(ctx context.Context, csr x5
ca.log.AuditErr(fmt.Sprintf("Signing failed: serial=[%s] err=[%v]", serialHex, err))
return emptyCert, err
}
ca.stats.Inc("Signatures.Certificate", 1)
signatureCount.With(prometheus.Labels{"purpose": "cert"}).Inc()
if len(certPEM) == 0 {
err = berrors.InternalServerError("no certificate returned by server")

View File

@ -28,6 +28,8 @@ import (
"github.com/letsencrypt/boulder/mocks"
"github.com/letsencrypt/boulder/policy"
"github.com/letsencrypt/boulder/test"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_model/go"
)
var (
@ -709,6 +711,7 @@ func TestExtensions(t *testing.T) {
test.AssertNotError(t, err, "Error parsing UnsupportedExtensionCSR")
sign := func(csr *x509.CertificateRequest) *x509.Certificate {
signatureCount.Reset()
coreCert, err := ca.IssueCertificate(ctx, *csr, 1001)
test.AssertNotError(t, err, "Failed to issue")
cert, err := x509.ParseCertificate(coreCert.DER)
@ -719,35 +722,46 @@ func TestExtensions(t *testing.T) {
// With ca.enableMustStaple = false, should issue successfully and not add
// Must Staple.
stats.EXPECT().Inc(metricCSRExtensionTLSFeature, int64(1)).Return(nil)
stats.EXPECT().Inc("Signatures.Certificate", int64(1)).Return(nil)
noStapleCert := sign(mustStapleCSR)
test.AssertEquals(t, signatureCountByPurpose("cert"), 1)
test.AssertEquals(t, countMustStaple(t, noStapleCert), 0)
// With ca.enableMustStaple = true, a TLS feature extension should put a must-staple
// extension into the cert
ca.enableMustStaple = true
stats.EXPECT().Inc(metricCSRExtensionTLSFeature, int64(1)).Return(nil)
stats.EXPECT().Inc("Signatures.Certificate", int64(1)).Return(nil)
singleStapleCert := sign(mustStapleCSR)
test.AssertEquals(t, signatureCountByPurpose("cert"), 1)
test.AssertEquals(t, countMustStaple(t, singleStapleCert), 1)
// Even if there are multiple TLS Feature extensions, only one extension should be included
stats.EXPECT().Inc(metricCSRExtensionTLSFeature, int64(1)).Return(nil)
stats.EXPECT().Inc("Signatures.Certificate", int64(1)).Return(nil)
duplicateMustStapleCert := sign(duplicateMustStapleCSR)
test.AssertEquals(t, signatureCountByPurpose("cert"), 1)
test.AssertEquals(t, countMustStaple(t, duplicateMustStapleCert), 1)
// ... but if it doesn't ask for stapling, there should be an error
stats.EXPECT().Inc(metricCSRExtensionTLSFeature, int64(1)).Return(nil)
stats.EXPECT().Inc(metricCSRExtensionTLSFeatureInvalid, int64(1)).Return(nil)
signatureCount.Reset()
_, err = ca.IssueCertificate(ctx, *tlsFeatureUnknownCSR, 1001)
test.AssertEquals(t, signatureCountByPurpose("cert"), 0)
test.AssertError(t, err, "Allowed a CSR with an empty TLS feature extension")
test.Assert(t, berrors.Is(err, berrors.Malformed), "Wrong error type when rejecting a CSR with empty TLS feature extension")
// Unsupported extensions should be silently ignored, having the same
// extensions as the TLS Feature cert above, minus the TLS Feature Extension
stats.EXPECT().Inc(metricCSRExtensionOther, int64(1)).Return(nil)
stats.EXPECT().Inc("Signatures.Certificate", int64(1)).Return(nil)
unsupportedExtensionCert := sign(unsupportedExtensionCSR)
test.AssertEquals(t, signatureCountByPurpose("cert"), 1)
test.AssertEquals(t, len(unsupportedExtensionCert.Extensions), len(singleStapleCert.Extensions)-1)
}
func signatureCountByPurpose(signatureType string) int {
ch := make(chan prometheus.Metric, 10)
signatureCount.With(prometheus.Labels{"purpose": signatureType}).Collect(ch)
m := <-ch
var iom io_prometheus_client.Metric
_ = m.Write(&iom)
return int(iom.Counter.GetValue())
}