Skip to content

Commit

Permalink
Only register grpc TLS metrics on successful handshake (#1338)
Browse files Browse the repository at this point in the history
In the current gRPC implementation, TLS metrics are registered before the handshake is complete. In cases where the probe fails, probeSSLEarliestCertExpiryGauge is set to the default time.Time value (far in the past), resulting in any alerts using probe_ssl_earliest_cert_expiry metric firing.

In the case of the TLS handshake failing, it makes more sense for TLS metrics not to be set. This is the way the http probe is currently configured. This should also solve #1120.

* only register grpc TLS metrics on success

* adds tests

---------

Signed-off-by: mattb18 <[email protected]>
  • Loading branch information
mattb18 authored Dec 31, 2024
1 parent 9f9d483 commit 9cc59c3
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
4 changes: 1 addition & 3 deletions prober/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,6 @@ func ProbeGRPC(ctx context.Context, target string, module config.Module, registr
registry.MustRegister(isSSLGauge)
registry.MustRegister(statusCodeGauge)
registry.MustRegister(healthCheckResponseGaugeVec)
registry.MustRegister(probeSSLEarliestCertExpiryGauge)
registry.MustRegister(probeTLSVersion)
registry.MustRegister(probeSSLLastInformation)

if !strings.HasPrefix(target, "http://") && !strings.HasPrefix(target, "https://") {
target = "http://" + target
Expand Down Expand Up @@ -203,6 +200,7 @@ func ProbeGRPC(ctx context.Context, target string, module config.Module, registr
if serverPeer != nil {
tlsInfo, tlsOk := serverPeer.AuthInfo.(credentials.TLSInfo)
if tlsOk {
registry.MustRegister(probeSSLEarliestCertExpiryGauge, probeTLSVersion, probeSSLLastInformation)
isSSLGauge.Set(float64(1))
probeSSLEarliestCertExpiryGauge.Set(float64(getEarliestCertExpiry(&tlsInfo.State).Unix()))
probeTLSVersion.WithLabelValues(getTLSVersion(&tlsInfo.State)).Set(1)
Expand Down
31 changes: 31 additions & 0 deletions prober/grpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,3 +432,34 @@ func TestGRPCHealthCheckUnimplemented(t *testing.T) {

checkRegistryResults(expectedResults, mfs, t)
}

func TestGRPCAbsentFailedTLS(t *testing.T) {
testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
registry := prometheus.NewRegistry()

// probe and invalid port to trigger TCP/TLS error
result := ProbeGRPC(testCTX, "localhost:0",
config.Module{Timeout: time.Second, GRPC: config.GRPCProbe{
IPProtocolFallback: false,
Service: "NonExistingService",
},
}, registry, promslog.NewNopLogger())

if result {
t.Fatalf("GRPC probe succeeded, should have failed")
}

mfs, err := registry.Gather()
if err != nil {
t.Fatal(err)
}

absentMetrics := []string{
"probe_ssl_earliest_cert_expiry",
"probe_tls_version_info",
"probe_ssl_last_chain_info",
}

checkAbsentMetrics(absentMetrics, mfs, t)
}
10 changes: 10 additions & 0 deletions prober/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"math/big"
"net"
"slices"
"testing"
"time"

Expand Down Expand Up @@ -249,3 +250,12 @@ func checkMetrics(expected map[string]map[string]map[string]struct{}, mfs []*dto
}
}
}

func checkAbsentMetrics(absent []string, mfs []*dto.MetricFamily, t *testing.T) {
for _, v := range mfs {
name := v.GetName()
if slices.Contains(absent, name) {
t.Fatalf("metric %s was found but should be absent", name)
}
}
}

0 comments on commit 9cc59c3

Please sign in to comment.