mirror of
https://github.com/ribbybibby/ssl_exporter.git
synced 2024-11-24 08:22:17 +02:00
224 lines
5.7 KiB
Go
224 lines
5.7 KiB
Go
package prober
|
|
|
|
import (
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
dto "github.com/prometheus/client_model/go"
|
|
"golang.org/x/crypto/ocsp"
|
|
)
|
|
|
|
type registryResult struct {
|
|
Name string
|
|
LabelValues map[string]string
|
|
Value float64
|
|
}
|
|
|
|
func (rr *registryResult) String() string {
|
|
var labels []string
|
|
for k, v := range rr.LabelValues {
|
|
labels = append(labels, k+"=\""+v+"\"")
|
|
}
|
|
m := rr.Name
|
|
if len(labels) > 0 {
|
|
m = fmt.Sprintf("%s{%s}", m, strings.Join(labels, ","))
|
|
}
|
|
return fmt.Sprintf("%s %f", m, rr.Value)
|
|
}
|
|
|
|
func checkRegistryResults(expectedResults []*registryResult, mfs []*dto.MetricFamily, t *testing.T) {
|
|
for _, expRes := range expectedResults {
|
|
checkRegistryResult(expRes, mfs, t)
|
|
}
|
|
}
|
|
|
|
func checkRegistryResult(expRes *registryResult, mfs []*dto.MetricFamily, t *testing.T) {
|
|
var results []*registryResult
|
|
for _, mf := range mfs {
|
|
for _, metric := range mf.Metric {
|
|
result := ®istryResult{
|
|
Name: mf.GetName(),
|
|
Value: metric.GetGauge().GetValue(),
|
|
}
|
|
if len(metric.GetLabel()) > 0 {
|
|
labelValues := make(map[string]string)
|
|
for _, l := range metric.GetLabel() {
|
|
labelValues[l.GetName()] = l.GetValue()
|
|
}
|
|
result.LabelValues = labelValues
|
|
}
|
|
results = append(results, result)
|
|
}
|
|
}
|
|
var ok bool
|
|
var resStr string
|
|
for _, res := range results {
|
|
resStr = resStr + "\n" + res.String()
|
|
if reflect.DeepEqual(res, expRes) {
|
|
ok = true
|
|
}
|
|
}
|
|
if !ok {
|
|
t.Fatalf("Expected %s, got: %s", expRes.String(), resStr)
|
|
}
|
|
}
|
|
|
|
func checkCertificateMetrics(cert *x509.Certificate, registry *prometheus.Registry, t *testing.T) {
|
|
mfs, err := registry.Gather()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ips := ","
|
|
for _, ip := range cert.IPAddresses {
|
|
ips = ips + ip.String() + ","
|
|
}
|
|
expectedLabels := map[string]string{
|
|
"serial_no": cert.SerialNumber.String(),
|
|
"issuer_cn": cert.Issuer.CommonName,
|
|
"cn": cert.Subject.CommonName,
|
|
"dnsnames": "," + strings.Join(cert.DNSNames, ",") + ",",
|
|
"ips": ips,
|
|
"emails": "," + strings.Join(cert.EmailAddresses, ",") + ",",
|
|
"ou": "," + strings.Join(cert.Subject.OrganizationalUnit, ",") + ",",
|
|
}
|
|
expectedResults := []*registryResult{
|
|
®istryResult{
|
|
Name: "ssl_cert_not_after",
|
|
LabelValues: expectedLabels,
|
|
Value: float64(cert.NotAfter.Unix()),
|
|
},
|
|
®istryResult{
|
|
Name: "ssl_cert_not_before",
|
|
LabelValues: expectedLabels,
|
|
Value: float64(cert.NotBefore.Unix()),
|
|
},
|
|
}
|
|
checkRegistryResults(expectedResults, mfs, t)
|
|
}
|
|
|
|
func checkVerifiedChainMetrics(verifiedChains [][]*x509.Certificate, registry *prometheus.Registry, t *testing.T) {
|
|
mfs, err := registry.Gather()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for i, chain := range verifiedChains {
|
|
for _, cert := range chain {
|
|
ips := ","
|
|
for _, ip := range cert.IPAddresses {
|
|
ips = ips + ip.String() + ","
|
|
}
|
|
expectedLabels := map[string]string{
|
|
"chain_no": strconv.Itoa(i),
|
|
"serial_no": cert.SerialNumber.String(),
|
|
"issuer_cn": cert.Issuer.CommonName,
|
|
"cn": cert.Subject.CommonName,
|
|
"dnsnames": "," + strings.Join(cert.DNSNames, ",") + ",",
|
|
"ips": ips,
|
|
"emails": "," + strings.Join(cert.EmailAddresses, ",") + ",",
|
|
"ou": "," + strings.Join(cert.Subject.OrganizationalUnit, ",") + ",",
|
|
}
|
|
expectedResults := []*registryResult{
|
|
®istryResult{
|
|
Name: "ssl_verified_cert_not_after",
|
|
LabelValues: expectedLabels,
|
|
Value: float64(cert.NotAfter.Unix()),
|
|
},
|
|
®istryResult{
|
|
Name: "ssl_verified_cert_not_before",
|
|
LabelValues: expectedLabels,
|
|
Value: float64(cert.NotBefore.Unix()),
|
|
},
|
|
}
|
|
checkRegistryResults(expectedResults, mfs, t)
|
|
}
|
|
}
|
|
}
|
|
|
|
func checkOCSPMetrics(resp []byte, registry *prometheus.Registry, t *testing.T) {
|
|
var (
|
|
stapled float64
|
|
status float64
|
|
nextUpdate float64
|
|
thisUpdate float64
|
|
revokedAt float64
|
|
producedAt float64
|
|
)
|
|
mfs, err := registry.Gather()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(resp) > 0 {
|
|
parsedResponse, err := ocsp.ParseResponse(resp, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
stapled = 1
|
|
status = float64(parsedResponse.Status)
|
|
nextUpdate = float64(parsedResponse.NextUpdate.Unix())
|
|
thisUpdate = float64(parsedResponse.ThisUpdate.Unix())
|
|
revokedAt = float64(parsedResponse.RevokedAt.Unix())
|
|
producedAt = float64(parsedResponse.ProducedAt.Unix())
|
|
}
|
|
expectedResults := []*registryResult{
|
|
®istryResult{
|
|
Name: "ssl_ocsp_response_stapled",
|
|
Value: stapled,
|
|
},
|
|
®istryResult{
|
|
Name: "ssl_ocsp_response_status",
|
|
Value: status,
|
|
},
|
|
®istryResult{
|
|
Name: "ssl_ocsp_response_next_update",
|
|
Value: nextUpdate,
|
|
},
|
|
®istryResult{
|
|
Name: "ssl_ocsp_response_this_update",
|
|
Value: thisUpdate,
|
|
},
|
|
®istryResult{
|
|
Name: "ssl_ocsp_response_revoked_at",
|
|
Value: revokedAt,
|
|
},
|
|
®istryResult{
|
|
Name: "ssl_ocsp_response_produced_at",
|
|
Value: producedAt,
|
|
},
|
|
}
|
|
checkRegistryResults(expectedResults, mfs, t)
|
|
}
|
|
|
|
func checkTLSVersionMetrics(version string, registry *prometheus.Registry, t *testing.T) {
|
|
mfs, err := registry.Gather()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expectedResults := []*registryResult{
|
|
®istryResult{
|
|
Name: "ssl_tls_version_info",
|
|
LabelValues: map[string]string{
|
|
"version": version,
|
|
},
|
|
Value: 1,
|
|
},
|
|
}
|
|
checkRegistryResults(expectedResults, mfs, t)
|
|
}
|
|
|
|
func newCertificate(certPEM []byte) (*x509.Certificate, error) {
|
|
block, _ := pem.Decode(certPEM)
|
|
return x509.ParseCertificate(block.Bytes)
|
|
}
|
|
|
|
func newKey(keyPEM []byte) (*rsa.PrivateKey, error) {
|
|
block, _ := pem.Decode([]byte(keyPEM))
|
|
return x509.ParsePKCS1PrivateKey(block.Bytes)
|
|
}
|