You've already forked ssl_exporter
mirror of
https://github.com/ribbybibby/ssl_exporter.git
synced 2025-07-15 23:54:18 +02:00
feat: add http_file prober
This commit is contained in:
83
prober/http_file.go
Normal file
83
prober/http_file.go
Normal file
@ -0,0 +1,83 @@
|
||||
package prober
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/ribbybibby/ssl_exporter/v2/config"
|
||||
)
|
||||
|
||||
// ProbeHTTPFile performs a http_file probe
|
||||
func ProbeHTTPFile(ctx context.Context, logger log.Logger, target string, module config.Module, registry *prometheus.Registry) error {
|
||||
tlsConfig, err := config.NewTLSConfig(&module.TLSConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
targetURL, err := url.Parse(target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If server name isn't set, then use the target hostname
|
||||
if tlsConfig.ServerName == "" {
|
||||
tlsConfig.ServerName = targetURL.Hostname()
|
||||
}
|
||||
|
||||
proxy := http.ProxyFromEnvironment
|
||||
if module.HTTPS.ProxyURL.URL != nil {
|
||||
proxy = http.ProxyURL(module.HTTPS.ProxyURL.URL)
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
Proxy: proxy,
|
||||
DisableKeepAlives: true,
|
||||
},
|
||||
}
|
||||
|
||||
// Issue a GET request to the target
|
||||
request, err := http.NewRequest(http.MethodGet, targetURL.String(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
request = request.WithContext(ctx)
|
||||
resp, err := client.Do(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_, err := io.Copy(ioutil.Discard, resp.Body)
|
||||
if err != nil {
|
||||
level.Error(logger).Log("msg", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
}()
|
||||
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
certs, err := decodeCertificates(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(certs) == 0 {
|
||||
return fmt.Errorf("no certificates in response body")
|
||||
}
|
||||
|
||||
return collectCertificateMetrics(certs, registry)
|
||||
}
|
81
prober/http_file_test.go
Normal file
81
prober/http_file_test.go
Normal file
@ -0,0 +1,81 @@
|
||||
package prober
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/ribbybibby/ssl_exporter/v2/config"
|
||||
"github.com/ribbybibby/ssl_exporter/v2/test"
|
||||
)
|
||||
|
||||
func TestProbeHTTPFile(t *testing.T) {
|
||||
certPEM, _ := test.GenerateTestCertificate(time.Now().Add(time.Hour * 1))
|
||||
block, _ := pem.Decode([]byte(certPEM))
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
t.Fatalf("parsing cert: %s", err)
|
||||
}
|
||||
|
||||
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(certPEM)
|
||||
}))
|
||||
|
||||
server.Start()
|
||||
defer server.Close()
|
||||
|
||||
registry := prometheus.NewRegistry()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := ProbeHTTPFile(ctx, newTestLogger(), server.URL+"/file", config.Module{}, registry); err != nil {
|
||||
t.Fatalf("error: %s", err)
|
||||
}
|
||||
|
||||
checkCertificateMetrics(cert, registry, t)
|
||||
}
|
||||
|
||||
func TestProbeHTTPFile_HTTPS(t *testing.T) {
|
||||
server, certPEM, _, caFile, teardown, err := test.SetupHTTPSServer()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
defer teardown()
|
||||
|
||||
block, _ := pem.Decode([]byte(certPEM))
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
t.Fatalf("parsing cert: %s", err)
|
||||
}
|
||||
|
||||
server.Config.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(certPEM)
|
||||
})
|
||||
|
||||
server.StartTLS()
|
||||
defer server.Close()
|
||||
|
||||
module := config.Module{
|
||||
TLSConfig: config.TLSConfig{
|
||||
CAFile: caFile,
|
||||
InsecureSkipVerify: false,
|
||||
},
|
||||
}
|
||||
|
||||
registry := prometheus.NewRegistry()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := ProbeHTTPFile(ctx, newTestLogger(), server.URL+"/file", module, registry); err != nil {
|
||||
t.Fatalf("error: %s", err)
|
||||
}
|
||||
|
||||
checkCertificateMetrics(cert, registry, t)
|
||||
}
|
@ -13,6 +13,7 @@ var (
|
||||
Probers = map[string]ProbeFn{
|
||||
"https": ProbeHTTPS,
|
||||
"http": ProbeHTTPS,
|
||||
"http_file": ProbeHTTPFile,
|
||||
"tcp": ProbeTCP,
|
||||
"file": ProbeFile,
|
||||
"kubernetes": ProbeKubernetes,
|
||||
|
Reference in New Issue
Block a user