Add hostname parameter for TCP probe (#981)
authorLyas Spiehler <lspiehler@gmail.com>
Wed, 1 Feb 2023 13:35:13 +0000 (07:35 -0600)
committerGitHub <noreply@github.com>
Wed, 1 Feb 2023 13:35:13 +0000 (19:05 +0530)
This adds the ability to set the TLS server name for TCP probes using the hostname parameter,
just like #823 did for HTTP probes

* add hostname parameter for tcp probe
* only add servername if TLS is true
* add even if TLS isn't true in case of STARTTLS
* added test hostname parameter with TCP probe
* remove unnecessary function and inline assignment

---------

Signed-off-by: Lyas Spiehler <lspiehler@gmail.com>
Co-authored-by: Lyas Spiehler <lyas.spiehler@sapphirehealth.org>
prober/handler.go
prober/handler_test.go

index f449cace287fb92510d1fdf0c9aeb46e63697474..2a8a1d9c5a16e286a55698bbf311c1bbbc220dce 100644 (file)
@@ -107,6 +107,12 @@ func Handler(w http.ResponseWriter, r *http.Request, c *config.Config, logger lo
                }
        }
 
+       if module.Prober == "tcp" && hostname != "" {
+               if module.TCP.TLSConfig.ServerName == "" {
+                       module.TCP.TLSConfig.ServerName = hostname
+               }
+       }
+
        sl := newScrapeLogger(logger, moduleName, target)
        level.Info(sl).Log("msg", "Beginning probe", "probe", module.Prober, "timeout_seconds", timeoutSeconds)
 
index a144fb955a3bef15ce39421a40ce9872f9801e0e..40039d48df327c763fba041495fe0e09da9235d9 100644 (file)
@@ -16,8 +16,10 @@ package prober
 import (
        "bytes"
        "fmt"
+       "net"
        "net/http"
        "net/http/httptest"
+       "strconv"
        "strings"
        "testing"
        "time"
@@ -203,3 +205,55 @@ func TestHostnameParam(t *testing.T) {
                t.Errorf("probe request handler returned wrong status code: %v, want %v", status, http.StatusBadRequest)
        }
 }
+
+func TestTCPHostnameParam(t *testing.T) {
+       c := &config.Config{
+               Modules: map[string]config.Module{
+                       "tls_connect": {
+                               Prober:  "tcp",
+                               Timeout: 10 * time.Second,
+                               TCP: config.TCPProbe{
+                                       TLS:        true,
+                                       IPProtocol: "ip4",
+                                       TLSConfig:  pconfig.TLSConfig{InsecureSkipVerify: true},
+                               },
+                       },
+               },
+       }
+
+       // check that 'hostname' parameter make its way to server_name in the tls_config
+       hostname := "foo.example.com"
+
+       ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+               if r.Host != hostname {
+                       t.Errorf("Unexpected Host: expected %q, got %q.", hostname, r.Host)
+               }
+               w.WriteHeader(http.StatusOK)
+       }))
+       defer ts.Close()
+
+       requrl := fmt.Sprintf("?module=tls_connect&debug=true&hostname=%s&target=%s", hostname, ts.Listener.Addr().(*net.TCPAddr).IP.String()+":"+strconv.Itoa(ts.Listener.Addr().(*net.TCPAddr).Port))
+
+       req, err := http.NewRequest("GET", requrl, nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       rr := httptest.NewRecorder()
+
+       handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+               Handler(w, r, c, log.NewNopLogger(), &ResultHistory{}, 0.5, nil)
+       })
+
+       handler.ServeHTTP(rr, req)
+
+       if status := rr.Code; status != http.StatusOK {
+               t.Errorf("probe request handler returned wrong status code: %v, want %v", status, http.StatusOK)
+       }
+
+       // check debug output to confirm the server_name is set in tls_config and matches supplied hostname
+       if !strings.Contains(rr.Body.String(), "server_name: "+hostname) {
+               t.Errorf("probe failed, response body: %v", rr.Body.String())
+       }
+
+}