git » prometheus-expvar-exporter » commit 176c61f

Support insecure https

author Alberto Bertogli
2024-04-19 17:45:53 UTC
committer Alberto Bertogli
2024-04-19 17:45:53 UTC
parent 85df98790c837e161478401a28e6ad5d17c97d4b

Support insecure https

This patch adds an `insecure = true` option that allows users to fetch
expvars from an insecure https server (e.g. one with self-signed certs).

config.toml +3 -0
main.go +19 -1
test/httpd.go +59 -3
test/t-02-insecure.expected +9 -0
test/t-02-insecure.toml +5 -0
test/t-02-insecure.vars +9 -0

diff --git a/config.toml b/config.toml
index 9912b10..d87dcb9 100644
--- a/config.toml
+++ b/config.toml
@@ -12,6 +12,9 @@ url = "http://localhost:20099/debug/vars"
 
 # From here on, everything is optional.
 
+# If you want to disable TLS checking for the URL, set this.
+#insecure = true
+
 # List of variables to export.
 # By default, the exporter will try to auto-convert all expvars.  It is only
 # able to auto-convert float and boolean expvars without labels.
diff --git a/main.go b/main.go
index 4a1db22..2558198 100644
--- a/main.go
+++ b/main.go
@@ -3,6 +3,7 @@
 package main
 
 import (
+	"crypto/tls"
 	"encoding/json"
 	"flag"
 	"fmt"
@@ -43,6 +44,10 @@ func main() {
 			labelName: map[string]string{},
 		}
 
+		if config.Has(t + ".insecure") {
+			c.insecure = config.Get(t + ".insecure").(bool)
+		}
+
 		mnames := config.GetDefault(t+".m", &toml.Tree{}).(*toml.Tree).Keys()
 		for _, name := range mnames {
 			info := config.Get(t + ".m." + name).(*toml.Tree)
@@ -75,6 +80,9 @@ type Collector struct {
 	// URL to collect from.
 	url string
 
+	// Disable TLS checking for this URL.
+	insecure bool
+
 	// expvar -> prometheus name
 	names map[string]string
 
@@ -95,8 +103,18 @@ func (c *Collector) Describe(ch chan<- *prometheus.Desc) {
 	return
 }
 
+func (c *Collector) GetURL() (*http.Response, error) {
+	client := &http.Client{}
+	if c.insecure {
+		client.Transport = &http.Transport{
+			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+		}
+	}
+	return client.Get(c.url)
+}
+
 func (c *Collector) Collect(ch chan<- prometheus.Metric) {
-	resp, err := http.Get(c.url)
+	resp, err := c.GetURL()
 	if err != nil {
 		log.Printf("Error scraping %q: %v", c.url, err)
 		return
diff --git a/test/httpd.go b/test/httpd.go
index 4f7d97d..cde7aa5 100644
--- a/test/httpd.go
+++ b/test/httpd.go
@@ -1,18 +1,74 @@
 package main
 
 import (
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
 	"flag"
+	"math/big"
 	"net/http"
+	"time"
 )
 
 var (
-	addr = flag.String("addr", ":30081", "Address to listen on")
-	path = flag.String("path", ".", "Path to serve")
+	addrHTTP  = flag.String("http", ":30081", "Address to listen on for HTTP")
+	addrHTTPS = flag.String("https", ":30082", "Address to listen on for HTTPS")
+	path      = flag.String("path", ".", "Path to serve")
 )
 
 func main() {
 	flag.Parse()
 
 	http.Handle("/", http.FileServer(http.Dir(*path)))
-	http.ListenAndServe(*addr, nil)
+
+	// HTTP server.
+	go http.ListenAndServe(*addrHTTP, nil)
+
+	// HTTPS server.
+	cert := GenCert()
+	server := &http.Server{
+		Addr:      *addrHTTPS,
+		TLSConfig: &tls.Config{Certificates: []tls.Certificate{*cert}},
+	}
+	server.ListenAndServeTLS("", "")
+}
+
+func GenCert() *tls.Certificate {
+	// Build the certificate template.
+	serial, _ := rand.Int(rand.Reader, big.NewInt(1<<62))
+	tmpl := x509.Certificate{
+		SerialNumber: serial,
+		Subject:      pkix.Name{Organization: []string{"Test Cert Org"}},
+
+		NotBefore: time.Now(),
+		NotAfter:  time.Now().Add(1 * time.Hour),
+
+		KeyUsage: x509.KeyUsageKeyEncipherment |
+			x509.KeyUsageDigitalSignature |
+			x509.KeyUsageCertSign,
+		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+
+		BasicConstraintsValid: true,
+
+		DNSNames: []string{"localhost"},
+	}
+
+	// Generate a private key.
+	privK, err := rsa.GenerateKey(rand.Reader, 1024)
+	if err != nil {
+		panic(err)
+	}
+
+	derBytes, err := x509.CreateCertificate(
+		rand.Reader, &tmpl, &tmpl, privK.Public(), privK)
+	if err != nil {
+		panic(err)
+	}
+
+	return &tls.Certificate{
+		Certificate: [][]byte{derBytes},
+		PrivateKey:  privK,
+	}
 }
diff --git a/test/t-02-insecure.expected b/test/t-02-insecure.expected
new file mode 100644
index 0000000..774e4ad
--- /dev/null
+++ b/test/t-02-insecure.expected
@@ -0,0 +1,9 @@
+# HELP a_float expvar "a-float"
+# TYPE a_float untyped
+a_float 1.2
+# HELP an_int expvar "an-int"
+# TYPE an_int untyped
+an_int 26
+# HELP with_unsupported_characters expvar "with/unsupported-characters"
+# TYPE with_unsupported_characters untyped
+with_unsupported_characters 55
diff --git a/test/t-02-insecure.toml b/test/t-02-insecure.toml
new file mode 100644
index 0000000..054b1a2
--- /dev/null
+++ b/test/t-02-insecure.toml
@@ -0,0 +1,5 @@
+listen_addr = ":30080"
+
+[target]
+url = "https://localhost:30082/t-02-insecure.vars"
+insecure = true
diff --git a/test/t-02-insecure.vars b/test/t-02-insecure.vars
new file mode 100644
index 0000000..fdab564
--- /dev/null
+++ b/test/t-02-insecure.vars
@@ -0,0 +1,9 @@
+{
+"an-int": 26,
+"a-float": 1.2,
+"a-map": {"good": 73.5, "bad": 38.4},
+"a-string": "I am a string",
+"with/unsupported-characters": 55,
+"cmdline": ["/usr/bin/test", "--flag"],
+"memstats": {"Alloc":6702144,"TotalAlloc":36862810952,"Sys":161443112}
+}