You've already forked ssl_exporter
mirror of
https://github.com/ribbybibby/ssl_exporter.git
synced 2025-07-12 23:50:14 +02:00
Support TLS renegotiation (#83)
* Support TLS renegotiation * Bump version * Revert version bump * Extend TLSConfig with renegotiation support * Update config/config.go - comment formatting Co-authored-by: Rob Best <robertbest89@gmail.com> * add dedicated renegotiation example * Create local NewTLSConfig in order to incorporate local extentions * go mod tidy * Move TLS renegotiation parsing into UnmarshalYAML Co-authored-by: Rob Best <robertbest89@gmail.com>
This commit is contained in:
@ -277,6 +277,10 @@ prober: <prober_string>
|
|||||||
# Disable target certificate validation.
|
# Disable target certificate validation.
|
||||||
[ insecure_skip_verify: <boolean> | default = false ]
|
[ insecure_skip_verify: <boolean> | default = false ]
|
||||||
|
|
||||||
|
# Configure TLS renegotiation support.
|
||||||
|
# Valid options: never, once, freely
|
||||||
|
[ renegotiation: <string> | default = never ]
|
||||||
|
|
||||||
# The CA cert to use for the targets.
|
# The CA cert to use for the targets.
|
||||||
[ ca_file: <filename> ]
|
[ ca_file: <filename> ]
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/common/config"
|
pconfig "github.com/prometheus/common/config"
|
||||||
yaml "gopkg.in/yaml.v3"
|
yaml "gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -63,12 +64,64 @@ type Config struct {
|
|||||||
|
|
||||||
// Module configures a prober
|
// Module configures a prober
|
||||||
type Module struct {
|
type Module struct {
|
||||||
Prober string `yaml:"prober,omitempty"`
|
Prober string `yaml:"prober,omitempty"`
|
||||||
Timeout time.Duration `yaml:"timeout,omitempty"`
|
Timeout time.Duration `yaml:"timeout,omitempty"`
|
||||||
TLSConfig config.TLSConfig `yaml:"tls_config,omitempty"`
|
TLSConfig TLSConfig `yaml:"tls_config,omitempty"`
|
||||||
HTTPS HTTPSProbe `yaml:"https,omitempty"`
|
HTTPS HTTPSProbe `yaml:"https,omitempty"`
|
||||||
TCP TCPProbe `yaml:"tcp,omitempty"`
|
TCP TCPProbe `yaml:"tcp,omitempty"`
|
||||||
Kubernetes KubernetesProbe `yaml:"kubernetes,omitempty"`
|
Kubernetes KubernetesProbe `yaml:"kubernetes,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TLSConfig is a superset of config.TLSConfig that supports TLS renegotiation
|
||||||
|
type TLSConfig struct {
|
||||||
|
CAFile string `yaml:"ca_file,omitempty"`
|
||||||
|
CertFile string `yaml:"cert_file,omitempty"`
|
||||||
|
KeyFile string `yaml:"key_file,omitempty"`
|
||||||
|
ServerName string `yaml:"server_name,omitempty"`
|
||||||
|
InsecureSkipVerify bool `yaml:"insecure_skip_verify"`
|
||||||
|
// Renegotiation controls what types of TLS renegotiation are supported.
|
||||||
|
// Supported values: never (default), once, freely.
|
||||||
|
Renegotiation renegotiation `yaml:"renegotiation,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type renegotiation tls.RenegotiationSupport
|
||||||
|
|
||||||
|
func (r *renegotiation) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
var v string
|
||||||
|
if err := unmarshal(&v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch v {
|
||||||
|
case "", "never":
|
||||||
|
*r = renegotiation(tls.RenegotiateNever)
|
||||||
|
case "once":
|
||||||
|
*r = renegotiation(tls.RenegotiateOnceAsClient)
|
||||||
|
case "freely":
|
||||||
|
*r = renegotiation(tls.RenegotiateFreelyAsClient)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported TLS renegotiation type %s", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTLSConfig creates a new tls.Config from the given TLSConfig,
|
||||||
|
// plus our local extensions
|
||||||
|
func NewTLSConfig(cfg *TLSConfig) (*tls.Config, error) {
|
||||||
|
tlsConfig, err := pconfig.NewTLSConfig(&pconfig.TLSConfig{
|
||||||
|
CAFile: cfg.CAFile,
|
||||||
|
CertFile: cfg.CertFile,
|
||||||
|
KeyFile: cfg.KeyFile,
|
||||||
|
ServerName: cfg.ServerName,
|
||||||
|
InsecureSkipVerify: cfg.InsecureSkipVerify,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfig.Renegotiation = tls.RenegotiationSupport(cfg.Renegotiation)
|
||||||
|
|
||||||
|
return tlsConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TCPProbe configures a tcp probe
|
// TCPProbe configures a tcp probe
|
||||||
|
@ -5,6 +5,10 @@ modules:
|
|||||||
prober: https
|
prober: https
|
||||||
tls_config:
|
tls_config:
|
||||||
insecure_skip_verify: true
|
insecure_skip_verify: true
|
||||||
|
https_renegotiation:
|
||||||
|
prober: https
|
||||||
|
tls_config:
|
||||||
|
renegotiation: freely
|
||||||
https_proxy:
|
https_proxy:
|
||||||
prober: https
|
prober: https
|
||||||
https:
|
https:
|
||||||
|
@ -17,7 +17,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
pconfig "github.com/prometheus/common/config"
|
|
||||||
"github.com/ribbybibby/ssl_exporter/config"
|
"github.com/ribbybibby/ssl_exporter/config"
|
||||||
"github.com/ribbybibby/ssl_exporter/test"
|
"github.com/ribbybibby/ssl_exporter/test"
|
||||||
"golang.org/x/crypto/ocsp"
|
"golang.org/x/crypto/ocsp"
|
||||||
@ -35,7 +34,7 @@ func TestProbeHTTPS(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -77,7 +76,7 @@ func TestProbeHTTPSTimeout(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -105,7 +104,7 @@ func TestProbeHTTPSInvalidName(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -139,7 +138,7 @@ func TestProbeHTTPSNoScheme(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -186,7 +185,7 @@ func TestProbeHTTPSServerName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
ServerName: u.Hostname(),
|
ServerName: u.Hostname(),
|
||||||
@ -263,7 +262,7 @@ func TestProbeHTTPSClientAuth(t *testing.T) {
|
|||||||
defer os.Remove(keyFile)
|
defer os.Remove(keyFile)
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
CertFile: certFile,
|
CertFile: certFile,
|
||||||
KeyFile: keyFile,
|
KeyFile: keyFile,
|
||||||
@ -327,7 +326,7 @@ func TestProbeHTTPSClientAuthWrongClientCert(t *testing.T) {
|
|||||||
defer os.Remove(keyFile)
|
defer os.Remove(keyFile)
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
CertFile: certFile,
|
CertFile: certFile,
|
||||||
KeyFile: keyFile,
|
KeyFile: keyFile,
|
||||||
@ -365,7 +364,7 @@ func TestProbeHTTPSExpired(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -402,7 +401,7 @@ func TestProbeHTTPSExpiredInsecure(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
},
|
},
|
||||||
@ -455,7 +454,7 @@ func TestProbeHTTPSProxy(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -517,7 +516,7 @@ func TestProbeHTTPSOCSP(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -598,7 +597,7 @@ func TestProbeHTTPSVerifiedChains(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ import (
|
|||||||
"golang.org/x/crypto/ocsp"
|
"golang.org/x/crypto/ocsp"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
pconfig "github.com/prometheus/common/config"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestProbeTCP tests the typical case
|
// TestProbeTCP tests the typical case
|
||||||
@ -32,7 +31,7 @@ func TestProbeTCP(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -69,7 +68,7 @@ func TestProbeTCPInvalidName(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -102,7 +101,7 @@ func TestProbeTCPServerName(t *testing.T) {
|
|||||||
host, listenPort, _ := net.SplitHostPort(server.Listener.Addr().String())
|
host, listenPort, _ := net.SplitHostPort(server.Listener.Addr().String())
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
ServerName: host,
|
ServerName: host,
|
||||||
@ -147,7 +146,7 @@ func TestProbeTCPExpired(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -184,7 +183,7 @@ func TestProbeTCPExpiredInsecure(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
},
|
},
|
||||||
@ -223,7 +222,7 @@ func TestProbeTCPStartTLSSMTP(t *testing.T) {
|
|||||||
TCP: config.TCPProbe{
|
TCP: config.TCPProbe{
|
||||||
StartTLS: "smtp",
|
StartTLS: "smtp",
|
||||||
},
|
},
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -262,7 +261,7 @@ func TestProbeTCPStartTLSFTP(t *testing.T) {
|
|||||||
TCP: config.TCPProbe{
|
TCP: config.TCPProbe{
|
||||||
StartTLS: "ftp",
|
StartTLS: "ftp",
|
||||||
},
|
},
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -301,7 +300,7 @@ func TestProbeTCPStartTLSIMAP(t *testing.T) {
|
|||||||
TCP: config.TCPProbe{
|
TCP: config.TCPProbe{
|
||||||
StartTLS: "imap",
|
StartTLS: "imap",
|
||||||
},
|
},
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -340,7 +339,7 @@ func TestProbeTCPStartTLSPostgreSQL(t *testing.T) {
|
|||||||
TCP: config.TCPProbe{
|
TCP: config.TCPProbe{
|
||||||
StartTLS: "postgres",
|
StartTLS: "postgres",
|
||||||
},
|
},
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -377,7 +376,7 @@ func TestProbeTCPTimeout(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -420,7 +419,7 @@ func TestProbeTCPOCSP(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
},
|
},
|
||||||
@ -502,7 +501,7 @@ func TestProbeTCPVerifiedChains(t *testing.T) {
|
|||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
module := config.Module{
|
module := config.Module{
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,13 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
pconfig "github.com/prometheus/common/config"
|
"github.com/ribbybibby/ssl_exporter/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// newTLSConfig sets up TLS config and instruments it with a function that
|
// newTLSConfig sets up TLS config and instruments it with a function that
|
||||||
// collects metrics for the verified chain
|
// collects metrics for the verified chain
|
||||||
func newTLSConfig(target string, registry *prometheus.Registry, pTLSConfig *pconfig.TLSConfig) (*tls.Config, error) {
|
func newTLSConfig(target string, registry *prometheus.Registry, cfg *config.TLSConfig) (*tls.Config, error) {
|
||||||
tlsConfig, err := pconfig.NewTLSConfig(pTLSConfig)
|
tlsConfig, err := config.NewTLSConfig(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-kit/log"
|
"github.com/go-kit/log"
|
||||||
pconfig "github.com/prometheus/common/config"
|
|
||||||
"github.com/ribbybibby/ssl_exporter/config"
|
"github.com/ribbybibby/ssl_exporter/config"
|
||||||
"github.com/ribbybibby/ssl_exporter/test"
|
"github.com/ribbybibby/ssl_exporter/test"
|
||||||
)
|
)
|
||||||
@ -29,7 +28,7 @@ func TestProbeHandler(t *testing.T) {
|
|||||||
Modules: map[string]config.Module{
|
Modules: map[string]config.Module{
|
||||||
"https": config.Module{
|
"https": config.Module{
|
||||||
Prober: "https",
|
Prober: "https",
|
||||||
TLSConfig: pconfig.TLSConfig{
|
TLSConfig: config.TLSConfig{
|
||||||
CAFile: caFile,
|
CAFile: caFile,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user