Skip to content

Commit

Permalink
Export TLS version (#538)
Browse files Browse the repository at this point in the history
* Add a metric for the TLS version used

Signed-off-by: Silke Hofstra <[email protected]>
  • Loading branch information
silkeh authored and brian-brazil committed Oct 14, 2019
1 parent 713b4ad commit 93a48d8
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 3 deletions.
11 changes: 10 additions & 1 deletion prober/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,14 @@ func ProbeHTTP(ctx context.Context, target string, module config.Module, registr
Help: "Returns earliest SSL cert expiry in unixtime",
})

probeTLSVersion = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "probe_tls_version_info",
Help: "Contains the TLS version used",
},
[]string{"version"},
)

probeHTTPVersionGauge = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "probe_http_version",
Help: "Returns the version of HTTP of the probe response",
Expand Down Expand Up @@ -538,8 +546,9 @@ func ProbeHTTP(ctx context.Context, target string, module config.Module, registr

if resp.TLS != nil {
isSSLGauge.Set(float64(1))
registry.MustRegister(probeSSLEarliestCertExpiryGauge)
registry.MustRegister(probeSSLEarliestCertExpiryGauge, probeTLSVersion)
probeSSLEarliestCertExpiryGauge.Set(float64(getEarliestCertExpiry(resp.TLS).Unix()))
probeTLSVersion.WithLabelValues(getTLSVersion(resp.TLS)).Set(1)
if httpConfig.FailIfSSL {
level.Error(logger).Log("msg", "Final request was over SSL")
success = false
Expand Down
11 changes: 10 additions & 1 deletion prober/tcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ func ProbeTCP(ctx context.Context, target string, module config.Module, registry
Name: "probe_ssl_earliest_cert_expiry",
Help: "Returns earliest SSL cert expiry date",
})
probeTLSVersion := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "probe_tls_version_info",
Help: "Returns the TLS version used, or NaN when unknown",
},
[]string{"version"},
)
probeFailedDueToRegex := prometheus.NewGauge(prometheus.GaugeOpts{
Name: "probe_failed_due_to_regex",
Help: "Indicates if probe failed due to regex",
Expand All @@ -118,8 +125,9 @@ func ProbeTCP(ctx context.Context, target string, module config.Module, registry
}
if module.TCP.TLS {
state := conn.(*tls.Conn).ConnectionState()
registry.MustRegister(probeSSLEarliestCertExpiry)
registry.MustRegister(probeSSLEarliestCertExpiry, probeTLSVersion)
probeSSLEarliestCertExpiry.Set(float64(getEarliestCertExpiry(&state).Unix()))
probeTLSVersion.WithLabelValues(getTLSVersion(&state)).Set(1)
}
scanner := bufio.NewScanner(conn)
for i, qr := range module.TCP.QueryResponse {
Expand Down Expand Up @@ -188,6 +196,7 @@ func ProbeTCP(ctx context.Context, target string, module config.Module, registry
state := tlsConn.ConnectionState()
registry.MustRegister(probeSSLEarliestCertExpiry)
probeSSLEarliestCertExpiry.Set(float64(getEarliestCertExpiry(&state).Unix()))
probeTLSVersion.WithLabelValues(getTLSVersion(&state)).Set(1)
}
}
return true
Expand Down
15 changes: 14 additions & 1 deletion prober/tcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ func TestTCPConnectionWithTLS(t *testing.T) {
tlsConfig := &tls.Config{
ServerName: "localhost",
Certificates: []tls.Certificate{testcert},
MinVersion: tls.VersionTLS12,
MaxVersion: tls.VersionTLS12,
}
tlsConn := tls.Server(conn, tlsConfig)
defer tlsConn.Close()
Expand Down Expand Up @@ -168,13 +170,24 @@ func TestTCPConnectionWithTLS(t *testing.T) {
}
<-ch

// Check the probe_ssl_earliest_cert_expiry.
// Check the resulting metrics.
mfs, err := registry.Gather()
if err != nil {
t.Fatal(err)
}

// Check labels
expectedLabels := map[string]map[string]string{
"probe_tls_version_info": {
"version": "TLS 1.2",
},
}
checkRegistryLabels(expectedLabels, mfs, t)

// Check values
expectedResults := map[string]float64{
"probe_ssl_earliest_cert_expiry": float64(certExpiry.Unix()),
"probe_tls_version_info": 1,
}
checkRegistryResults(expectedResults, mfs, t)
}
Expand Down
15 changes: 15 additions & 0 deletions prober/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,18 @@ func getEarliestCertExpiry(state *tls.ConnectionState) time.Time {
}
return earliest
}

func getTLSVersion(state *tls.ConnectionState) string {
switch state.Version {
case tls.VersionTLS10:
return "TLS 1.0"
case tls.VersionTLS11:
return "TLS 1.1"
case tls.VersionTLS12:
return "TLS 1.2"
case tls.VersionTLS13:
return "TLS 1.3"
default:
return "unknown"
}
}
29 changes: 29 additions & 0 deletions prober/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,35 @@ func checkRegistryResults(expRes map[string]float64, mfs []*dto.MetricFamily, t
}
}

// Check if expected labels are in the registry
func checkRegistryLabels(expRes map[string]map[string]string, mfs []*dto.MetricFamily, t *testing.T) {
results := make(map[string]map[string]string)
for _, mf := range mfs {
result := make(map[string]string)
for _, metric := range mf.Metric {
for _, l := range metric.GetLabel() {
result[l.GetName()] = l.GetValue()
}
}
results[mf.GetName()] = result
}

for metric, labelValues := range expRes {
if _, ok := results[metric]; !ok {
t.Fatalf("Expected metric %v not found in returned metrics", metric)
}
for name, exp := range labelValues {
val, ok := results[metric][name]
if !ok {
t.Fatalf("Expected label %v for metric %v not found in returned metrics", val, name)
}
if val != exp {
t.Fatalf("Expected: %v{%q=%q}, got: %v{%q=%q}", metric, name, exp, metric, name, val)
}
}
}
}

// Create test certificate with specified expiry date
// Certificate will be self-signed and use localhost/127.0.0.1
// Generated certificate and key are returned in PEM encoding
Expand Down

0 comments on commit 93a48d8

Please sign in to comment.