Skip to content

Commit

Permalink
Merge pull request #275 from mitalirawat/mitali/SECENG-7134
Browse files Browse the repository at this point in the history
add certificate expiration metrics for client certificates used in handshake
  • Loading branch information
cbroglie authored Jul 8, 2020
2 parents cdf0b58 + b490db3 commit fbb660d
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 2 deletions.
54 changes: 54 additions & 0 deletions certmetrics/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Package certmetrics will be used to register and emit metrics for certificates in memory
package certmetrics

import (
"crypto/x509"
"sort"
"strings"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)

var certificateExpirationTimes = promauto.NewGaugeVec(
prometheus.GaugeOpts{
Name: "certificate_expiration_timestamp_seconds",
Help: "Expiration times of gokeyless certs",
},
[]string{"serial_no", "cn", "hostnames", "ca", "server", "client"},
)

// Observe takes in a list of certs and emits its expiration times
func Observe(certs ...*x509.Certificate) {
for _, cert := range certs {
certificateExpirationTimes.With(getPrometheusLabels(cert)).Set(float64(cert.NotAfter.Unix()))
}
}

func getPrometheusLabels(cert *x509.Certificate) prometheus.Labels {
hostnames := append([]string(nil), cert.DNSNames...)
sort.Strings(hostnames)
return prometheus.Labels{
"serial_no": cert.SerialNumber.String(),
"cn": cert.Subject.CommonName,
"hostnames": strings.Join(hostnames, ","),
"ca": boolToBinaryString(cert.IsCA),
"server": hasKeyUsageAsBinaryString(cert.ExtKeyUsage, x509.ExtKeyUsageServerAuth),
"client": hasKeyUsageAsBinaryString(cert.ExtKeyUsage, x509.ExtKeyUsageClientAuth)}
}

func boolToBinaryString(val bool) string {
if val {
return "1"
}
return "0"
}

func hasKeyUsageAsBinaryString(a []x509.ExtKeyUsage, x x509.ExtKeyUsage) string {
for _, e := range a {
if e == x || e == x509.ExtKeyUsageAny {
return "1"
}
}
return "0"
}
37 changes: 36 additions & 1 deletion cmd/gokeyless/gokeyless.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/gokeyless/certmetrics"
"github.com/cloudflare/gokeyless/server"
)

Expand Down Expand Up @@ -272,7 +273,8 @@ func main() {
f.Close()
}
}

certs := gatherCerts()
certmetrics.Observe(certs...)
go func() {
log.Critical(s.MetricsListenAndServe(net.JoinHostPort("", strconv.Itoa(config.MetricsPort))))
}()
Expand Down Expand Up @@ -393,3 +395,36 @@ func verifyCSRAndKey() bool {

return true
}

// pemCertsFromFile reads PEM format certificates from a file.
func pemCertsFromFile(path string) []*x509.Certificate {
file, err := os.Open(path)
if err != nil {
log.Fatal(err)
}
pemData, err := ioutil.ReadAll(file)
if err != nil {
log.Fatal(err)
}
certs, err := helpers.ParseCertificatesPEM(pemData)
if err != nil {
log.Fatal(err)
}
return certs
}

func gatherCerts() []*x509.Certificate {
certPaths := []string{
config.CertFile,
config.CACertFile,
}
var allCerts []*x509.Certificate
for _, cPath := range certPaths {
if cPath == "" {
continue
}
pemCerts := pemCertsFromFile(cPath)
allCerts = append(allCerts, pemCerts...)
}
return allCerts
}
6 changes: 5 additions & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
"sync"
"time"

"github.com/cloudflare/gokeyless/certmetrics"

"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/helpers/derhelpers"
"github.com/cloudflare/cfssl/log"
Expand Down Expand Up @@ -644,7 +646,9 @@ func (s *Server) spawn(l net.Listener, c net.Conn) {
tconn.Close()
return
}
limited, err := s.config.isLimited(tconn.ConnectionState())
connState := tconn.ConnectionState()
certmetrics.Observe(connState.PeerCertificates...)
limited, err := s.config.isLimited(connState)
if err != nil {
log.Errorf("connection %v: could not determine if limited: %v", c.RemoteAddr(), err)
tconn.Close()
Expand Down

0 comments on commit fbb660d

Please # to comment.