mirror of
https://github.com/ribbybibby/ssl_exporter.git
synced 2026-02-16 10:39:54 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6037c98a77 | ||
|
|
ad237243c4 | ||
|
|
1b8a0c3b93 | ||
|
|
dd2a9a2e71 | ||
|
|
1ec0cd6dc7 | ||
|
|
515b990f52 | ||
|
|
4cb38cb268 |
8
.github/workflows/test-and-snapshot.yaml
vendored
8
.github/workflows/test-and-snapshot.yaml
vendored
@@ -1,6 +1,12 @@
|
||||
name: test-and-snapshot
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
test:
|
||||
|
||||
49
README.md
49
README.md
@@ -4,6 +4,7 @@ Exports metrics for certificates collected from various sources:
|
||||
- [TCP probes](#tcp)
|
||||
- [HTTPS probes](#https)
|
||||
- [PEM files](#file)
|
||||
- [Remote PEM files](#http_file)
|
||||
- [Kubernetes secrets](#kubernetes)
|
||||
- [Kubeconfig files](#kubeconfig)
|
||||
|
||||
@@ -130,7 +131,7 @@ scrape_configs:
|
||||
```
|
||||
|
||||
This will use proxy servers discovered by the environment variables `HTTP_PROXY`,
|
||||
`HTTPS_PROXY` and `ALL_PROXY`. Or, you can set the `proxy_url` option in the module
|
||||
`HTTPS_PROXY` and `ALL_PROXY`. Or, you can set the `https.proxy_url` option in the module
|
||||
configuration.
|
||||
|
||||
The latter takes precedence.
|
||||
@@ -175,6 +176,44 @@ scrape_configs:
|
||||
replacement: ${1}:9219
|
||||
```
|
||||
|
||||
### HTTP File
|
||||
|
||||
The `http_file` prober exports `ssl_cert_not_after` and
|
||||
`ssl_cert_not_before` for PEM encoded certificates found at the
|
||||
specified URL.
|
||||
|
||||
```
|
||||
curl "localhost:9219/probe?module=http_file&target=https://www.paypalobjects.com/marketing/web/logos/paypal_com.pem"
|
||||
```
|
||||
|
||||
Here's a sample Prometheus configuration:
|
||||
|
||||
```yml
|
||||
scrape_configs:
|
||||
- job_name: 'ssl-http-files'
|
||||
metrics_path: /probe
|
||||
params:
|
||||
module: ["http_file"]
|
||||
static_configs:
|
||||
- targets:
|
||||
- 'https://www.paypalobjects.com/marketing/web/logos/paypal_com.pem'
|
||||
- 'https://d3frv9g52qce38.cloudfront.net/amazondefault/amazon_web_services_inc_2024.pem'
|
||||
relabel_configs:
|
||||
- source_labels: [__address__]
|
||||
target_label: __param_target
|
||||
- source_labels: [__param_target]
|
||||
target_label: instance
|
||||
- target_label: __address__
|
||||
replacement: 127.0.0.1:9219
|
||||
```
|
||||
|
||||
For proxying to the target resource, this prober will use proxy servers
|
||||
discovered in the environment variables `HTTP_PROXY`, `HTTPS_PROXY` and
|
||||
`ALL_PROXY`. Or, you can set the `http_file.proxy_url` option in the module
|
||||
configuration.
|
||||
|
||||
The latter takes precedence.
|
||||
|
||||
### Kubernetes
|
||||
|
||||
The `kubernetes` prober exports `ssl_kubernetes_cert_not_after` and
|
||||
@@ -293,6 +332,7 @@ target: <string>
|
||||
[ https: <https_probe> ]
|
||||
[ tcp: <tcp_probe> ]
|
||||
[ kubernetes: <kubernetes_probe> ]
|
||||
[ http_file: <http_file_probe> ]
|
||||
```
|
||||
|
||||
### <tls_config>
|
||||
@@ -339,6 +379,13 @@ target: <string>
|
||||
[ kubeconfig: <string> ]
|
||||
```
|
||||
|
||||
### <http_file_probe>
|
||||
|
||||
```
|
||||
# HTTP proxy server to use to connect to the targets.
|
||||
[ proxy_url: <string> ]
|
||||
```
|
||||
|
||||
## Example Queries
|
||||
|
||||
Certificates that expire within 7 days:
|
||||
|
||||
@@ -17,22 +17,25 @@ var (
|
||||
DefaultConfig = &Config{
|
||||
DefaultModule: "tcp",
|
||||
Modules: map[string]Module{
|
||||
"tcp": Module{
|
||||
"tcp": {
|
||||
Prober: "tcp",
|
||||
},
|
||||
"http": Module{
|
||||
"http": {
|
||||
Prober: "https",
|
||||
},
|
||||
"https": Module{
|
||||
"https": {
|
||||
Prober: "https",
|
||||
},
|
||||
"file": Module{
|
||||
"file": {
|
||||
Prober: "file",
|
||||
},
|
||||
"kubernetes": Module{
|
||||
"http_file": {
|
||||
Prober: "http_file",
|
||||
},
|
||||
"kubernetes": {
|
||||
Prober: "kubernetes",
|
||||
},
|
||||
"kubeconfig": Module{
|
||||
"kubeconfig": {
|
||||
Prober: "kubeconfig",
|
||||
},
|
||||
},
|
||||
@@ -73,6 +76,7 @@ type Module struct {
|
||||
HTTPS HTTPSProbe `yaml:"https,omitempty"`
|
||||
TCP TCPProbe `yaml:"tcp,omitempty"`
|
||||
Kubernetes KubernetesProbe `yaml:"kubernetes,omitempty"`
|
||||
HTTPFile HTTPFileProbe `yaml:"http_file,omitempty"`
|
||||
}
|
||||
|
||||
// TLSConfig is a superset of config.TLSConfig that supports TLS renegotiation
|
||||
@@ -142,6 +146,11 @@ type KubernetesProbe struct {
|
||||
Kubeconfig string `yaml:"kubeconfig,omitempty"`
|
||||
}
|
||||
|
||||
// HTTPFileProbe configures a http_file probe
|
||||
type HTTPFileProbe struct {
|
||||
ProxyURL URL `yaml:"proxy_url,omitempty"`
|
||||
}
|
||||
|
||||
// URL is a custom URL type that allows validation at configuration load time
|
||||
type URL struct {
|
||||
*url.URL
|
||||
|
||||
@@ -34,3 +34,18 @@ scrape_configs:
|
||||
static_configs:
|
||||
- targets:
|
||||
- 127.0.0.1:9219
|
||||
- job_name: 'ssl-http-files'
|
||||
metrics_path: /probe
|
||||
params:
|
||||
module: ["http_file"]
|
||||
static_configs:
|
||||
- targets:
|
||||
- 'https://www.paypalobjects.com/marketing/web/logos/paypal_com.pem'
|
||||
- 'https://d3frv9g52qce38.cloudfront.net/amazondefault/amazon_web_services_inc_2024.pem'
|
||||
relabel_configs:
|
||||
- source_labels: [__address__]
|
||||
target_label: __param_target
|
||||
- source_labels: [__param_target]
|
||||
target_label: instance
|
||||
- target_label: __address__
|
||||
replacement: 127.0.0.1:9219
|
||||
|
||||
@@ -38,6 +38,12 @@ modules:
|
||||
file_ca_certificates:
|
||||
prober: file
|
||||
target: /etc/ssl/certs/ca-certificates.crt
|
||||
http_file:
|
||||
prober: http_file
|
||||
http_file_proxy:
|
||||
prober: http_file
|
||||
http_file:
|
||||
proxy_url: "socks5://localhost:8123"
|
||||
kubernetes:
|
||||
prober: kubernetes
|
||||
kubernetes_kubeconfig:
|
||||
|
||||
10
go.mod
10
go.mod
@@ -4,10 +4,10 @@ require (
|
||||
github.com/alecthomas/kingpin/v2 v2.4.0
|
||||
github.com/bmatcuk/doublestar/v2 v2.0.4
|
||||
github.com/go-kit/log v0.2.1
|
||||
github.com/prometheus/client_golang v1.19.0
|
||||
github.com/prometheus/client_golang v1.19.1
|
||||
github.com/prometheus/client_model v0.6.1
|
||||
github.com/prometheus/common v0.53.0
|
||||
golang.org/x/crypto v0.22.0
|
||||
golang.org/x/crypto v0.25.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/api v0.30.0
|
||||
k8s.io/apimachinery v0.30.0
|
||||
@@ -46,9 +46,9 @@ require (
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||
golang.org/x/net v0.24.0 // indirect
|
||||
golang.org/x/oauth2 v0.19.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/term v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/term v0.22.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
|
||||
24
go.sum
24
go.sum
@@ -78,8 +78,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
|
||||
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE=
|
||||
@@ -102,8 +102,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -120,22 +120,22 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
|
||||
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
60
prober/http_file.go
Normal file
60
prober/http_file.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package prober
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/ribbybibby/ssl_exporter/v2/config"
|
||||
)
|
||||
|
||||
// ProbeHTTPFile collects certificate metrics from a remote file via http
|
||||
func ProbeHTTPFile(ctx context.Context, logger log.Logger, target string, module config.Module, registry *prometheus.Registry) error {
|
||||
proxy := http.ProxyFromEnvironment
|
||||
if module.HTTPFile.ProxyURL.URL != nil {
|
||||
proxy = http.ProxyURL(module.HTTPFile.ProxyURL.URL)
|
||||
}
|
||||
|
||||
tlsConfig, err := config.NewTLSConfig(&module.TLSConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating TLS config: %w", err)
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
Proxy: proxy,
|
||||
DisableKeepAlives: true,
|
||||
},
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, target, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating http request: %w", err)
|
||||
}
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("making http request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("unexpected response code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading response body: %w", err)
|
||||
}
|
||||
|
||||
certs, err := decodeCertificates(body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("decoding certificates from response body: %w", err)
|
||||
}
|
||||
|
||||
return collectCertificateMetrics(certs, registry)
|
||||
}
|
||||
112
prober/http_file_test.go
Normal file
112
prober/http_file_test.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package prober
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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) {
|
||||
testcertPEM, _ := test.GenerateTestCertificate(time.Now().AddDate(0, 0, 1))
|
||||
|
||||
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(testcertPEM)
|
||||
}))
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
cert, err := newCertificate(testcertPEM)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
checkCertificateMetrics(cert, registry, t)
|
||||
}
|
||||
|
||||
func TestProbeHTTPFile_NotCertificate(t *testing.T) {
|
||||
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("foobar"))
|
||||
}))
|
||||
|
||||
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.Errorf("expected error but got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestProbeHTTPFile_NotFound(t *testing.T) {
|
||||
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}))
|
||||
|
||||
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.Errorf("expected error but got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestProbeHTTPFileHTTPS(t *testing.T) {
|
||||
server, certPEM, _, caFile, teardown, err := test.SetupHTTPSServer()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
defer teardown()
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
cert, err := newCertificate(certPEM)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
checkCertificateMetrics(cert, registry, t)
|
||||
}
|
||||
@@ -12,9 +12,12 @@ import (
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/version"
|
||||
"github.com/ribbybibby/ssl_exporter/v2/config"
|
||||
)
|
||||
|
||||
var userAgent = fmt.Sprintf("SSLExporter/%s", version.Version)
|
||||
|
||||
// ProbeHTTPS performs a https probe
|
||||
func ProbeHTTPS(ctx context.Context, logger log.Logger, target string, module config.Module, registry *prometheus.Registry) error {
|
||||
tlsConfig, err := newTLSConfig("", registry, &module.TLSConfig)
|
||||
@@ -57,6 +60,7 @@ func ProbeHTTPS(ctx context.Context, logger log.Logger, target string, module co
|
||||
return err
|
||||
}
|
||||
request = request.WithContext(ctx)
|
||||
request.Header.Set("User-Agent", userAgent)
|
||||
resp, err := client.Do(request)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -15,6 +15,7 @@ var (
|
||||
"http": ProbeHTTPS,
|
||||
"tcp": ProbeTCP,
|
||||
"file": ProbeFile,
|
||||
"http_file": ProbeHTTPFile,
|
||||
"kubernetes": ProbeKubernetes,
|
||||
"kubeconfig": ProbeKubeconfig,
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ func contains(certs []*x509.Certificate, cert *x509.Certificate) bool {
|
||||
func decodeCertificates(data []byte) ([]*x509.Certificate, error) {
|
||||
var certs []*x509.Certificate
|
||||
for block, rest := pem.Decode(data); block != nil; block, rest = pem.Decode(rest) {
|
||||
if block.Type == "CERTIFICATE" {
|
||||
if block.Type == "CERTIFICATE" || block.Type == "TRUSTED CERTIFICATE" {
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return certs, err
|
||||
|
||||
86
prober/tls_test.go
Normal file
86
prober/tls_test.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package prober
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDecodeCertificates(t *testing.T) {
|
||||
data := []byte(`
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
v5KXxrGlqibeNjyc3Wng6S0Kpg6YNqU=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN TRUSTED CERTIFICATE-----
|
||||
MIIF7zCCA9egAwIBAgIUZXsnB0gxoPSFaUjnQeLwTW+sqbYwDQYJKoZIhvcNAQEL
|
||||
BQAwgYYxCzAJBgNVBAYTAlhYMRIwEAYDVQQIDAlTdGF0ZU5hbWUxETAPBgNVBAcM
|
||||
CENpdHlOYW1lMRQwEgYDVQQKDAtDb21wYW55TmFtZTEbMBkGA1UECwwSQ29tcGFu
|
||||
eVNlY3Rpb25OYW1lMR0wGwYDVQQDDBRDb21tb25OYW1lT3JIb3N0bmFtZTAeFw0y
|
||||
NDA0MjgxNjE3MzZaFw0zNDA0MjYxNjE3MzZaMIGGMQswCQYDVQQGEwJYWDESMBAG
|
||||
A1UECAwJU3RhdGVOYW1lMREwDwYDVQQHDAhDaXR5TmFtZTEUMBIGA1UECgwLQ29t
|
||||
cGFueU5hbWUxGzAZBgNVBAsMEkNvbXBhbnlTZWN0aW9uTmFtZTEdMBsGA1UEAwwU
|
||||
Q29tbW9uTmFtZU9ySG9zdG5hbWUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
|
||||
AoICAQDJ+g1z+nZFj0DFc+wV1AH4giAqDFhwx25yziaQJnHkoXpllN0bRpr50Fhx
|
||||
QsMuMqjMCM0eFPo7kDWSrAUusdh3j1jdF7KidZRZdyUgioQvbmNtqtwdU/38Gq0s
|
||||
yTspOTZTWziIMFsLYxvFb0Ia8dwQFvyDB3pM1/eXFJMr2Cz/nF4/g4IUFEtPY2pe
|
||||
4sQDMhszvROMfI5LB4SmGiim/zUS7+ZDEQigf10/CrbLntjXHiFy+V0hcrDQXkuY
|
||||
gXU9HsiwRpCx+GRqcI6SWPIZ2rYa7goAVBENv5KWFXdWaOFCpi55XldYYzDeaXWa
|
||||
On9EOjyylLbJ2pv/yhpt/VYDC6Lsqki1XcU/zeETcBRlqzCwZhMqFErSPRBGxaTN
|
||||
lEGKNS2qQnE7I7bmUksRcCxA0WIn4V2xxxGHkLFnEsCipFGgMm7LaGSukYZGQ2MF
|
||||
0ELqaaRMaTBfvPhFRtolkFChm7JQlCrk9j47b07OTMj4KUoBkhYPNoK26sHjvKue
|
||||
Iks7BTGy8NdZk3jVDNEgGwngj+bNyJcjDvq+cHhWhS/N8c8Tg2tFb3ZOnwbyFPLf
|
||||
1DdsP/SW6TybMc6NtpWvmSCFMvxqRpr+7LscpBGThepAUaoPkATnT6UdYGqr+l5N
|
||||
z1+cZEuHBF7Jk5xThXCCFwuBC/KREvRuU2LyAhm9RV1ci8XyYwIDAQABo1MwUTAd
|
||||
BgNVHQ4EFgQUa1FF7jssOpGY0UY1qbFQH83rxOQwHwYDVR0jBBgwFoAUa1FF7jss
|
||||
OpGY0UY1qbFQH83rxOQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
|
||||
AgEAhRPDPmVetjE5w/igfnGiNUKhQiqB3E6yT1wMwF5LbNIC+h8E8WqF0mzF3XQC
|
||||
t9+Eib+mFptHGfRGdA8JmJ79xBgch6JLagw8Ot6hA1oEqWy/PAzcFLemccvhonhZ
|
||||
+N7umRO27agIYVJ71mxlS7rD1SItBKZ+g4/Lt3sr/iDM0kIhWjWdQiYgJMNhH2Mt
|
||||
XAd53tmPSom1Vsca1ZorB0HJNIw8RB7QYwceAi0xk0Tui7Z6pHg8p99XHCK/2vD+
|
||||
+u5a1nHjtrAvLdNti8o82EUScK4j91CODCm5bv2KDMIUUv+1O83UMicK8DLSIi0P
|
||||
1acuIdbRrY5JiYewCC+NFCfODZT6y00QL7aF9cbT+ZySiYtpBUiLFlIZCw4dcJ6r
|
||||
yYJca1gv+kqZugdgLD7nXWIzXgfreQ+Q/BiVouXroXaWqU/9dqzGw4LlPSpyqI9o
|
||||
nFdu970j4BvVc809i1aNo3odGz9yRx7wOOMyiyHoRpYenlf3hFbqJHS2FUgJ/Ajl
|
||||
TC1joWDPdwdqQY56WOpk2LMK1KJuMYQEEHb3Ib0ZaxXAT6Nd12VashG5gYhw9vGn
|
||||
aZ3nCnZFahgB2tB5DtkK+p0PQVpZOv6/0CKSsfQkBFLTjeVIRnlL/UlK3VlwHH9h
|
||||
0LfsLFabedOS9R1XIaQ7aKXPK4tKmNb5H/ONzH2zxU5Oqoo=
|
||||
-----END TRUSTED CERTIFICATE-----
|
||||
`)
|
||||
|
||||
certs, err := decodeCertificates(data)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if len(certs) != 2 {
|
||||
t.Errorf("unexpected number of certs: %d", len(certs))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user