CA: Use Prometheus for counting issued certificates. (#2690)
Prepare for counting precertificates by paramaterizing the counter on "purpose".
This commit is contained in:
parent
cc5ee3906b
commit
2781549618
18
ca/ca.go
18
ca/ca.go
|
@ -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")
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue