mirror of
https://github.com/ribbybibby/ssl_exporter.git
synced 2025-02-19 19:59:47 +02:00
Improve tests and remove reliance on external websites
This commit is contained in:
parent
30c8ffb7c3
commit
215029534e
@ -3,115 +3,518 @@ package main
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestProbeHandler(t *testing.T) {
|
||||
certContent, err := ioutil.ReadFile("test/badssl.com-client.pem")
|
||||
if err != nil {
|
||||
t.Fatalf("Can't read test client certificate from disk")
|
||||
}
|
||||
var clientCert = `-----BEGIN CERTIFICATE-----
|
||||
MIIC6jCCApCgAwIBAgIQPbn1oJJ0lvHOxk3BbnhGMTAKBggqhkjOPQQDAjCBhTEL
|
||||
MAkGA1UEBhMCR0IxEDAOBgNVBAgTB0VuZ2xhbmQxDzANBgNVBAcTBkxvbmRvbjEU
|
||||
MBIGA1UECRMLMTIzIEZha2UgU3QxEDAOBgNVBBETB1NXMThYWFgxEzARBgNVBAoT
|
||||
CnJpYmJ5YmliYnkxFjAUBgNVBAMTDXJpYmJ5YmliYnkubWUwHhcNMTkwMzI5MDc1
|
||||
MjI5WhcNMjAwMzI4MDc1MjI5WjAdMRswGQYDVQQDExJjZXJ0LnJpYmJ5YmliYnku
|
||||
bWUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASlHGGsAAEMpyBVkgSZazMcYmHH
|
||||
4K8+m9VI9nSnD4t1b01jYuNAsJjvnRI2iGLOxQ1i8KgzgeZz6ud1mJLIudTzo4IB
|
||||
RzCCAUMwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF
|
||||
BQcDAjAMBgNVHRMBAf8EAjAAMGgGA1UdDgRhBF9mNzphMzo4NDo0ZDo0NjowOTpl
|
||||
Nzo5ZDpiNzo3MjphMTo5ZTpkOTpjMDoxYTpmYzpjMzplODplZDozOTozMTo5Mzox
|
||||
MjpmMDplZTowODo2YTo2Mzo3NzphNjplMDoyMjBqBgNVHSMEYzBhgF8xNTpkZDo0
|
||||
MTo4ODoxODo0YjoxOTo2NToyYjo2ZTo0Njo1NTozZTo3MTo0MzpjYjphMjo3Nzpk
|
||||
YzpiNTpjZToxMTpiZTo2NDo3ODo3Zjo1OTo2NzpiYTpmMDo0YTowNTAuBgNVHREE
|
||||
JzAlghJjZXJ0LnJpYmJ5YmliYnkubWWCCWxvY2FsaG9zdIcEfwAAATAKBggqhkjO
|
||||
PQQDAgNIADBFAiEAq5AUjiAQxMy0g0f2KyFshTu5QPXXSPo+VTBSQcYuEzICIAWr
|
||||
JxpZXB4hH2+sEZ4z+bH6l47wbYqOT02d/VNbk3vw
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
keyContent, err := ioutil.ReadFile("test/badssl.com-client-key.pem")
|
||||
if err != nil {
|
||||
t.Fatalf("Can't read test client certificate key from disk")
|
||||
}
|
||||
var clientKey = `-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIPfP8yJatMwUfCyNdIQiQANO2vd3QQIoHJ6g+o8kb7PJoAoGCCqGSM49
|
||||
AwEHoUQDQgAEpRxhrAABDKcgVZIEmWszHGJhx+CvPpvVSPZ0pw+LdW9NY2LjQLCY
|
||||
750SNohizsUNYvCoM4Hmc+rndZiSyLnU8w==
|
||||
-----END EC PRIVATE KEY-----`
|
||||
|
||||
keyBlock, _ := pem.Decode(keyContent)
|
||||
var clientCertWrong = `-----BEGIN CERTIFICATE-----
|
||||
MIIC7zCCApWgAwIBAgIRAPx4XNhgs5QfvE6FHnYa3uQwCgYIKoZIzj0EAwIwgYUx
|
||||
CzAJBgNVBAYTAkdCMRAwDgYDVQQIEwdFbmdsYW5kMQ8wDQYDVQQHEwZMb25kb24x
|
||||
FDASBgNVBAkTCzEyMyBGYWtlIFN0MRAwDgYDVQQREwdTVzE4WFhYMRMwEQYDVQQK
|
||||
EwpyaWJieWJpYmJ5MRYwFAYDVQQDEw1yaWJieWJpYmJ5Lm1lMB4XDTE5MDMyNzE2
|
||||
MTgzOVoXDTIwMDMyNjE2MTgzOVowHzEdMBsGA1UEAxMUY2xpZW50LnJpYmJ5Ymli
|
||||
YnkubWUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQtlqtCTzZNCdDiMHKD/p1F
|
||||
97/I1MnkRK+QdUxEDnRhHAuMOhypxJ6NruZz+wXLnJEmUYmTsHkz1a4tKz2YJCUp
|
||||
o4IBSTCCAUUwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr
|
||||
BgEFBQcDATAMBgNVHRMBAf8EAjAAMGgGA1UdDgRhBF9kYzowNDozMjo0ZTpkOTo4
|
||||
YjphNTplMDpmNjo5MjpkYzpiYzoxOTo1NTo0ZDo0YjpiNTo5YTo5OTpjYjo4Zjoz
|
||||
ZjplMTpkNzo3MDoyMTo2MzpmZDo4YTo4MDpjMzpiNzBqBgNVHSMEYzBhgF82YTo0
|
||||
MDozNTowZjpmZTowMjpkNzo0Zjo5ODozZTo3ODoyMTpjMDo0YTo5YzpjZTo2Nzoz
|
||||
NDpiZDo4MjowYTo3MjpkMzpjOTo3Njo5MDo3Nzo5ODpmMDo2NTpmYzpkMDAwBgNV
|
||||
HREEKTAnghRjbGllbnQucmliYnliaWJieS5tZYIJbG9jYWxob3N0hwR/AAABMAoG
|
||||
CCqGSM49BAMCA0gAMEUCIQCa7ru0f0/HVoGa7aBJqACMBfiXWCI159WGt2B7Mxvf
|
||||
VAIgX9O8fOl6qmsJyfMkfdmv6lo9oAWIecDLpVtqEj5i2Qc=
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
keyBlockDecrypted, err := x509.DecryptPEMBlock(keyBlock, []byte("badssl.com"))
|
||||
if err != nil {
|
||||
t.Fatalf("Issue decrypting test client key")
|
||||
}
|
||||
var clientKeyWrong = `-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEILnEJttULi+2cupO4ta6IB9bEeul6rMGFSpPMB7kPuSwoAoGCCqGSM49
|
||||
AwEHoUQDQgAELZarQk82TQnQ4jByg/6dRfe/yNTJ5ESvkHVMRA50YRwLjDocqcSe
|
||||
ja7mc/sFy5yRJlGJk7B5M9WuLSs9mCQlKQ==
|
||||
-----END EC PRIVATE KEY-----`
|
||||
|
||||
keyContent = pem.EncodeToMemory(&pem.Block{Type: keyBlock.Type, Bytes: keyBlockDecrypted})
|
||||
var serverCert = `-----BEGIN CERTIFICATE-----
|
||||
MIIC6jCCApGgAwIBAgIRAO+sgyd/vcnDgfmafkgALKwwCgYIKoZIzj0EAwIwgYUx
|
||||
CzAJBgNVBAYTAkdCMRAwDgYDVQQIEwdFbmdsYW5kMQ8wDQYDVQQHEwZMb25kb24x
|
||||
FDASBgNVBAkTCzEyMyBGYWtlIFN0MRAwDgYDVQQREwdTVzE4WFhYMRMwEQYDVQQK
|
||||
EwpyaWJieWJpYmJ5MRYwFAYDVQQDEw1yaWJieWJpYmJ5Lm1lMB4XDTE5MDMyOTA3
|
||||
NTIyN1oXDTIwMDMyODA3NTIyN1owHTEbMBkGA1UEAxMSY2VydC5yaWJieWJpYmJ5
|
||||
Lm1lMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEY5nQFSmpZnFvjbAicuElYlT2
|
||||
xQvO+LgYt+5bcGfemT5HRq63tljiGlsyNXAysAmMwT9+blu8sLqkyh6PMFesJ6OC
|
||||
AUcwggFDMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB
|
||||
BQUHAwIwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfZmI6NDM6NWY6M2Y6NTE6NGI6
|
||||
NjA6YTI6YzQ6NzI6ZjE6MGQ6OTM6ZDA6YjQ6ODA6N2Y6Mjc6NjM6Yjk6NWI6NTQ6
|
||||
ZGQ6NzI6NzU6N2Q6MDU6N2U6ZTc6Y2U6OTM6YTMwagYDVR0jBGMwYYBfMTU6ZGQ6
|
||||
NDE6ODg6MTg6NGI6MTk6NjU6MmI6NmU6NDY6NTU6M2U6NzE6NDM6Y2I6YTI6Nzc6
|
||||
ZGM6YjU6Y2U6MTE6YmU6NjQ6Nzg6N2Y6NTk6Njc6YmE6ZjA6NGE6MDUwLgYDVR0R
|
||||
BCcwJYISY2VydC5yaWJieWJpYmJ5Lm1lgglsb2NhbGhvc3SHBH8AAAEwCgYIKoZI
|
||||
zj0EAwIDRwAwRAIgI6w7Px0UnI3AAP4n9ApO1gNIhY+ECEb0EZvKopmNUn0CIHN4
|
||||
MEaXLzEfNdNi7E521qIR+bhV/mu8nubZIsG4K383
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
emptyRootCAs := x509.NewCertPool()
|
||||
var serverKey = `-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIAeLgH2jonGdCgdG1MpEy9wAgxvCSC4N7sK3hC0GZM7MoAoGCCqGSM49
|
||||
AwEHoUQDQgAEY5nQFSmpZnFvjbAicuElYlT2xQvO+LgYt+5bcGfemT5HRq63tlji
|
||||
GlsyNXAysAmMwT9+blu8sLqkyh6PMFesJw==
|
||||
-----END EC PRIVATE KEY-----`
|
||||
|
||||
certificate, err := tls.X509KeyPair(certContent, keyContent)
|
||||
var expiredCert = `-----BEGIN CERTIFICATE-----
|
||||
MIIC2DCCAn6gAwIBAgIQeP4wyiBMCZ5TLpM40Ho6UzAKBggqhkjOPQQDAjCBhTEL
|
||||
MAkGA1UEBhMCR0IxEDAOBgNVBAgTB0VuZ2xhbmQxDzANBgNVBAcTBkxvbmRvbjEU
|
||||
MBIGA1UECRMLMTIzIEZha2UgU3QxEDAOBgNVBBETB1NXMThYWFgxEzARBgNVBAoT
|
||||
CnJpYmJ5YmliYnkxFjAUBgNVBAMTDXJpYmJ5YmliYnkubWUwHhcNMTkwMzI5MDgw
|
||||
MTM4WhcNMTkwMzI4MDgwMTM4WjAdMRswGQYDVQQDExJjZXJ0LnJpYmJ5YmliYnku
|
||||
bWUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjDs0ehi0miAKmDnuCmRyWaKOY
|
||||
+h0MugoFngChyygYCY+mOb/+HV5AYUEf1NFJLz4DtYnNKyWNHnX7vUPEh+Ico4IB
|
||||
NTCCATEwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF
|
||||
BQcDAjAMBgNVHRMBAf8EAjAAMGgGA1UdDgRhBF9mNTo1NDpmYzphNTo1ZjplMzo5
|
||||
YTo3MzplNzo1YTo0ZDowNzo0MTo4YjoyOTo2ZDpiNzpiNTpjMDpiZjowMzpkZTo5
|
||||
Zjo5NTozNzphMjphNDo4MDo2YTo3MDozNDpmNjBqBgNVHSMEYzBhgF9iOTpjMDo2
|
||||
NzoyYjo2YTpiNzowMToyMjo2Zjo1NTplMjpiMDphNDoyNDo1YTo5NzplMzpjYzpi
|
||||
MTo3Yjo4ZjoyNDpiNTo1NToxYzpiMDo3NTozMDplNToxZDo3OTpmZDAcBgNVHREE
|
||||
FTATggCCCWxvY2FsaG9zdIcEfwAAATAKBggqhkjOPQQDAgNIADBFAiB+ZGtScM5Y
|
||||
QHra5d+lqFRJOd7WXkoU03QHWOP3pSqbCAIhAJreqVQ3dUME4j9LYbQWmD96agdL
|
||||
2uxG31qfCa/T5TCq
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
var expiredKey = `-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIFDlw65IF8NLdgIWU1ipkMffcE6MgZ5DHTGzf0WN09EJoAoGCCqGSM49
|
||||
AwEHoUQDQgAEow7NHoYtJogCpg57gpkclmijmPodDLoKBZ4AocsoGAmPpjm//h1e
|
||||
QGFBH9TRSS8+A7WJzSsljR51+71DxIfiHA==
|
||||
-----END EC PRIVATE KEY-----`
|
||||
|
||||
var caCert = `-----BEGIN CERTIFICATE-----
|
||||
MIIDBjCCAqygAwIBAgIRAJxzFmvhp8ef68W7SQrt5KwwCgYIKoZIzj0EAwIwgYUx
|
||||
CzAJBgNVBAYTAkdCMRAwDgYDVQQIEwdFbmdsYW5kMQ8wDQYDVQQHEwZMb25kb24x
|
||||
FDASBgNVBAkTCzEyMyBGYWtlIFN0MRAwDgYDVQQREwdTVzE4WFhYMRMwEQYDVQQK
|
||||
EwpyaWJieWJpYmJ5MRYwFAYDVQQDEw1yaWJieWJpYmJ5Lm1lMB4XDTE5MDMyOTA3
|
||||
NTIyMloXDTI0MDMyNzA3NTIyMlowgYUxCzAJBgNVBAYTAkdCMRAwDgYDVQQIEwdF
|
||||
bmdsYW5kMQ8wDQYDVQQHEwZMb25kb24xFDASBgNVBAkTCzEyMyBGYWtlIFN0MRAw
|
||||
DgYDVQQREwdTVzE4WFhYMRMwEQYDVQQKEwpyaWJieWJpYmJ5MRYwFAYDVQQDEw1y
|
||||
aWJieWJpYmJ5Lm1lMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE94APL4adMA7A
|
||||
tSSfxcHzzxdVBCwJju6jVCf5qRqG4Qz0neXlde6jIXocZvoboZJiA2e7BadnjoPN
|
||||
2sTB8mgg4KOB+jCB9zAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zBo
|
||||
BgNVHQ4EYQRfMTU6ZGQ6NDE6ODg6MTg6NGI6MTk6NjU6MmI6NmU6NDY6NTU6M2U6
|
||||
NzE6NDM6Y2I6YTI6Nzc6ZGM6YjU6Y2U6MTE6YmU6NjQ6Nzg6N2Y6NTk6Njc6YmE6
|
||||
ZjA6NGE6MDUwagYDVR0jBGMwYYBfMTU6ZGQ6NDE6ODg6MTg6NGI6MTk6NjU6MmI6
|
||||
NmU6NDY6NTU6M2U6NzE6NDM6Y2I6YTI6Nzc6ZGM6YjU6Y2U6MTE6YmU6NjQ6Nzg6
|
||||
N2Y6NTk6Njc6YmE6ZjA6NGE6MDUwCgYIKoZIzj0EAwIDSAAwRQIhANycTcKTH1DU
|
||||
eu3Xuz8CdtgT67yqUTxDy0O5kS8fFPUVAiAV0u1M7dQYV+buY8oOLYnZxondrb7/
|
||||
BNltD7A8Y0S0hw==
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
// Test the basic case: a typical HTTPS server
|
||||
func TestProbeHandlerConnectSuccess(t *testing.T) {
|
||||
server, err := server()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
// Test the behaviour of various target URIs
|
||||
// 'ok' denotes whether we expect a succesful tls connection
|
||||
cases := []struct {
|
||||
uri string
|
||||
ok bool
|
||||
tlsConfig *tls.Config
|
||||
}{
|
||||
// Test against an assumed valid, reachable and functioning HTTPS address
|
||||
{uri: "google.com:443", ok: true, tlsConfig: &tls.Config{}},
|
||||
// Test against a HTTP address
|
||||
{uri: "google.com:80", ok: false, tlsConfig: &tls.Config{}},
|
||||
// Test against an expired certificate when we're rejecting invalid certs
|
||||
{uri: "expired.badssl.com:443", ok: false, tlsConfig: &tls.Config{}},
|
||||
// Test against an expired certificate when we're accepting invalid certs
|
||||
{uri: "expired.badssl.com:443", ok: true, tlsConfig: &tls.Config{InsecureSkipVerify: true}},
|
||||
// Test against a target with no port
|
||||
{uri: "google.com", ok: true, tlsConfig: &tls.Config{}},
|
||||
// Test against a string with spaces
|
||||
{uri: "with spaces", ok: false, tlsConfig: &tls.Config{}},
|
||||
// Test against nothing
|
||||
{uri: "", ok: false, tlsConfig: &tls.Config{}},
|
||||
// Test with client authentication
|
||||
{uri: "client.badssl.com:443", ok: true, tlsConfig: &tls.Config{Certificates: []tls.Certificate{certificate}}},
|
||||
// Test with an empty root CA bundle
|
||||
{uri: "google.com:443", ok: false, tlsConfig: &tls.Config{RootCAs: emptyRootCAs}},
|
||||
// Test with a https scheme
|
||||
{uri: "https://google.com", ok: true, tlsConfig: &tls.Config{}},
|
||||
// Test with a https scheme and port
|
||||
{uri: "https://google.com:443", ok: true, tlsConfig: &tls.Config{}},
|
||||
}
|
||||
|
||||
fmt.Println("Note: The error logs in these tests are expected. One of the important tests is that we return the expected body, even in the face of errors.")
|
||||
|
||||
successMetricRegexp, err := regexp.Compile("(ssl_tls_connect_success [0-1])")
|
||||
rr, err := probe(server.URL)
|
||||
if err != nil {
|
||||
t.Fatalf("Error compiling success metric: " + err.Error())
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
ok := strings.Contains(rr.Body.String(), "ssl_tls_connect_success 1")
|
||||
if !ok {
|
||||
t.Errorf("expected `ssl_tls_connect_success 1`")
|
||||
}
|
||||
|
||||
uri := "/probe?target=" + test.uri
|
||||
req, err := http.NewRequest("GET", uri, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
server.Close()
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
probeHandler(w, r, test.tlsConfig)
|
||||
})
|
||||
// Test against a non-existent server
|
||||
func TestProbeHandlerConnectSuccessFalse(t *testing.T) {
|
||||
rr, err := probe("localhost:6666")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
ok := strings.Contains(rr.Body.String(), "ssl_tls_connect_success 0")
|
||||
if !ok {
|
||||
t.Errorf("expected `ssl_tls_connect_success 0`")
|
||||
}
|
||||
|
||||
// We should always return a 200, no matter what
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v",
|
||||
status, http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we're getting the ssl_tls_connect_success metric back
|
||||
if !successMetricRegexp.MatchString(rr.Body.String()) {
|
||||
t.Errorf("can't find ssl_tls_connect_success metric in response body w/ %q", uri)
|
||||
}
|
||||
// Test with an empty target
|
||||
func TestProbeHandlerEmptyTarget(t *testing.T) {
|
||||
rr, err := probe("")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
// Make sure we're getting the result we expect from ssl_tls_connect_success
|
||||
ok := strings.Contains(rr.Body.String(), "ssl_tls_connect_success 1")
|
||||
if test.ok && !ok {
|
||||
t.Errorf("expected tls connection to succeed but it failed w/ %q", uri)
|
||||
}
|
||||
if !test.ok && ok {
|
||||
t.Errorf("expected tls connection to fail but it succeeded w/ %q", uri)
|
||||
}
|
||||
ok := strings.Contains(rr.Body.String(), "ssl_tls_connect_success 0")
|
||||
if !ok {
|
||||
t.Errorf("expected `ssl_tls_connect_success 0`")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Test with spaces in the target
|
||||
func TestProbeHandlerSpaces(t *testing.T) {
|
||||
rr, err := probe("with spaces")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
ok := strings.Contains(rr.Body.String(), "ssl_tls_connect_success 0")
|
||||
if !ok {
|
||||
t.Errorf("expected `ssl_tls_connect_success 0`")
|
||||
}
|
||||
}
|
||||
|
||||
// Test against a HTTP server
|
||||
func TestProbeHandlerHTTP(t *testing.T) {
|
||||
server, err := serverHTTP()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
rr, err := probe(server.URL)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
ok := strings.Contains(rr.Body.String(), "ssl_tls_connect_success 0")
|
||||
if !ok {
|
||||
t.Errorf("expected `ssl_tls_connect_success 0`")
|
||||
}
|
||||
|
||||
server.Close()
|
||||
}
|
||||
|
||||
// Test that the exporter returns the correct list of IPs
|
||||
func TestProbeHandlerIPs(t *testing.T) {
|
||||
server, err := server()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
rr, err := probe(server.URL)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
ok := strings.Contains(rr.Body.String(), "ssl_cert_subject_alternative_ips{ips=\",127.0.0.1,\"")
|
||||
if !ok {
|
||||
t.Errorf("expected `ssl_cert_subject_alternative_ips{ips=\",127.0.0.1,\"`")
|
||||
}
|
||||
|
||||
server.Close()
|
||||
}
|
||||
|
||||
// Test that the exporter returns the correct CN
|
||||
func TestProbeHandlerCommonName(t *testing.T) {
|
||||
server, err := server()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
rr, err := probe(server.URL)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
log.Println(rr.Body.String())
|
||||
ok := strings.Contains(rr.Body.String(), "ssl_cert_subject_common_name{issuer_cn=\"ribbybibby.me\",serial_no=\"318581226177353336430613662595136105644\",subject_cn=\"cert.ribbybibby.me\"} 1")
|
||||
if !ok {
|
||||
t.Errorf("expected `ssl_cert_subject_common_name{issuer_cn=\"ribbybibby.me\",serial_no=\"318581226177353336430613662595136105644\",subject_cn=\"cert.ribbybibby.me\"} 1`")
|
||||
}
|
||||
|
||||
server.Close()
|
||||
}
|
||||
|
||||
// Test that the exporter returns the correct list of DNS names
|
||||
func TestProbeHandlerDNSNames(t *testing.T) {
|
||||
server, err := server()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
rr, err := probe(server.URL)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
ok := strings.Contains(rr.Body.String(), "ssl_cert_subject_alternative_dnsnames{dnsnames=\",cert.ribbybibby.me,localhost,\"")
|
||||
if !ok {
|
||||
t.Errorf("expected `ssl_cert_subject_alternative_dnsnames{dnsnames=\",cert.ribbybibby.me,localhost,\"`")
|
||||
}
|
||||
|
||||
server.Close()
|
||||
}
|
||||
|
||||
// Test client authentication
|
||||
func TestProbeHandlerClientAuth(t *testing.T) {
|
||||
server, err := serverClientAuth()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
rr, err := probeClientAuth(server.URL)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
ok := strings.Contains(rr.Body.String(), "ssl_tls_connect_success 1")
|
||||
if !ok {
|
||||
t.Errorf("expected `ssl_tls_connect_success 1`")
|
||||
}
|
||||
|
||||
server.Close()
|
||||
}
|
||||
|
||||
// Test client authentication with a bad client certificate
|
||||
func TestProbeHandlerClientAuthWrongClientCert(t *testing.T) {
|
||||
server, err := serverClientAuth()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
rr, err := probeClientAuthBad(server.URL)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
ok := strings.Contains(rr.Body.String(), "ssl_tls_connect_success 0")
|
||||
if !ok {
|
||||
t.Errorf("expected `ssl_tls_connect_success 0`")
|
||||
}
|
||||
|
||||
server.Close()
|
||||
}
|
||||
|
||||
// Test against a server with an expired certificate
|
||||
func TestProbeHandlerExpired(t *testing.T) {
|
||||
server, err := serverExpired()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
rr, err := probe(server.URL)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
ok := strings.Contains(rr.Body.String(), "ssl_tls_connect_success 0")
|
||||
if !ok {
|
||||
t.Errorf("expected `ssl_tls_connect_success 0`")
|
||||
}
|
||||
|
||||
server.Close()
|
||||
}
|
||||
|
||||
// Test against a server with an expired certificate with an insecure probe
|
||||
func TestProbeHandlerExpiredInsecure(t *testing.T) {
|
||||
server, err := serverExpired()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
rr, err := probeInsecure(server.URL)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
ok := strings.Contains(rr.Body.String(), "ssl_tls_connect_success 1")
|
||||
if !ok {
|
||||
t.Errorf("expected `ssl_tls_connect_success 1`")
|
||||
}
|
||||
|
||||
server.Close()
|
||||
}
|
||||
|
||||
func probe(url string) (*httptest.ResponseRecorder, error) {
|
||||
uri := "/probe?target=" + url
|
||||
req, err := http.NewRequest("GET", uri, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
probeHandler(w, r, &tls.Config{
|
||||
RootCAs: certPool(),
|
||||
})
|
||||
})
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
return rr, nil
|
||||
}
|
||||
|
||||
func probeInsecure(url string) (*httptest.ResponseRecorder, error) {
|
||||
uri := "/probe?target=" + url
|
||||
req, err := http.NewRequest("GET", uri, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
probeHandler(w, r, &tls.Config{
|
||||
RootCAs: certPool(),
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
})
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
return rr, nil
|
||||
}
|
||||
|
||||
func probeClientAuth(url string) (*httptest.ResponseRecorder, error) {
|
||||
clientCertificate, err := tls.X509KeyPair([]byte(clientCert), []byte(clientKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
uri := "/probe?target=" + url
|
||||
req, err := http.NewRequest("GET", uri, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
probeHandler(w, r, &tls.Config{
|
||||
Certificates: []tls.Certificate{clientCertificate},
|
||||
RootCAs: certPool(),
|
||||
})
|
||||
})
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
return rr, nil
|
||||
}
|
||||
|
||||
func probeClientAuthBad(url string) (*httptest.ResponseRecorder, error) {
|
||||
clientCertificate, err := tls.X509KeyPair([]byte(clientCertWrong), []byte(clientKeyWrong))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
uri := "/probe?target=" + url
|
||||
req, err := http.NewRequest("GET", uri, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
probeHandler(w, r, &tls.Config{
|
||||
Certificates: []tls.Certificate{clientCertificate},
|
||||
RootCAs: certPool(),
|
||||
})
|
||||
})
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
return rr, nil
|
||||
}
|
||||
|
||||
func server() (*httptest.Server, error) {
|
||||
serverCertificate, err := tls.X509KeyPair([]byte(serverCert), []byte(serverKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, "Hello world")
|
||||
}))
|
||||
|
||||
server.TLS = &tls.Config{
|
||||
Certificates: []tls.Certificate{serverCertificate},
|
||||
}
|
||||
|
||||
server.StartTLS()
|
||||
return server, nil
|
||||
}
|
||||
|
||||
func serverClientAuth() (*httptest.Server, error) {
|
||||
certPool := certPool()
|
||||
|
||||
serverCertificate, err := tls.X509KeyPair([]byte(serverCert), []byte(serverKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, "Hello world")
|
||||
}))
|
||||
|
||||
server.TLS = &tls.Config{
|
||||
Certificates: []tls.Certificate{serverCertificate},
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
RootCAs: certPool,
|
||||
ClientCAs: certPool,
|
||||
}
|
||||
|
||||
server.StartTLS()
|
||||
return server, nil
|
||||
}
|
||||
|
||||
func serverExpired() (*httptest.Server, error) {
|
||||
certPool := certPool()
|
||||
|
||||
serverCertificate, err := tls.X509KeyPair([]byte(expiredCert), []byte(expiredKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, "Hello world")
|
||||
}))
|
||||
|
||||
server.TLS = &tls.Config{
|
||||
Certificates: []tls.Certificate{serverCertificate},
|
||||
RootCAs: certPool,
|
||||
ClientCAs: certPool,
|
||||
}
|
||||
|
||||
server.StartTLS()
|
||||
return server, nil
|
||||
}
|
||||
|
||||
func serverHTTP() (*httptest.Server, error) {
|
||||
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, "Hello world")
|
||||
}))
|
||||
|
||||
server.Start()
|
||||
return server, nil
|
||||
}
|
||||
|
||||
func certPool() *x509.CertPool {
|
||||
certPool := x509.NewCertPool()
|
||||
certPool.AppendCertsFromPEM([]byte(caCert))
|
||||
return certPool
|
||||
}
|
||||
|
@ -1,30 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,8906E5B87ECB8682
|
||||
|
||||
cY/EOwDILOiCPzyqZanlrhrb5h+fCnS/mHhsNme0Zyrk9udaBZKwxkPtUC6rJZ9/
|
||||
rX4HQch9tuVy992CDe1bl4l+3EfqshUhxtivG8GHiFj7TNo5Ia9LaE+KwugB2rdX
|
||||
J8odwWmwE8Y9TX09WyPKHikjg2nAOgN3Gf+GeJW6fL9xcEVmIgDyX6kBusQYWIQ3
|
||||
PMYqyaBhL8UCZVRpiUINTrJXCnNAI4t6K0i4J+hjyekRnA5PQ+A/0+C9J+kQW+wj
|
||||
uDWkQtyyBNsscGhXrL9ita7/UtJa+/aS99FLTnxD+fqyU4svzNIQWmZBcIxb9Lxq
|
||||
LHcxNaQCtFycD1iU8Tsq9HY1apKrdPBjaaYne6qCg8nIPWpo3gWoffu+R3EfVcdZ
|
||||
lNgKL3Cd1oCJy/Vcz+u0iayCPT0zfP1dLlGpL2U7L7+8pJ88FbXt/F1th9QEUp5z
|
||||
dISg/6ukHyIkfXwoxYXkin9fW2clo99+fuXkJaVPEOnRmr0+kf+1S0Uw8fkete4v
|
||||
f0IUxUwydxCXFN2ZFZ6o/LFLMLRfNAqGSGjqGeY1L0ILkJPo3KBqlmUhl2FIROOW
|
||||
4rSrfpujjsOqlPncJ9apW04RnqhY7t0YOtp0rMK+gIDteKD+utCyh+UAetiiqTiB
|
||||
ZDup/kzPNDClSDU6cgRbZUf/Nt8RiBcVeX4TfDb1eEhqV0BTHrLOBo8yp6ETDlJM
|
||||
CKO5i9kb5fUaFPFD5VTc5rnY4qV/hUj/uyAVK757A+m9nn7fYOMeaRAgOEvChYSf
|
||||
Qam0VPgpJxfjsaw0BFOMyfsHNJqvTbPXA+hIKD3fhP6jNcgpKTLHJp89J4XUOeIR
|
||||
tvh/u7vljhVygP7ZQOpCoX1xSMdJMO7Qhrh3O/2fq/EJertJD2PQ0Zgqb8wosHn/
|
||||
Aw9VWT6849jL55Xd5l3zXmI9vU0Le4HP3NstV9jjpcp91dU9yfQpcuIo8U26u+4r
|
||||
LR1VmhZJjo7FBOpyJZ1Jb3vyp+nPI+tH214DhM9LuXvMbf3ORhXTMOlqSABUmo/+
|
||||
t+QjVfcEuhFR9CTVWZUIXflJk/euvzqTQdm8iz7JuFzQOhoXjiPIq0GqtCk10SeL
|
||||
zqHz1s0TZNcrZyzkmiHuWjGVwHN/XZA3dW67uj522hD7EzucKE9CoCdJ3f4JEWmS
|
||||
CQwEbba6SKAR6iBlouIYLVdkOBgimGiF13rCwvdN234hQeJT8Wc87iG+uDw73PJL
|
||||
+amDglATH4wIpBk4xmjh/GTRDK0yH9jp7Dv9iwShbjk0yOuoz5yDn8VPqRIREn8d
|
||||
9sAaiFUUQ/9XrdlA5F+49OznClDWLKHK8sSAAFyrzvoCcqseSKbvLyrlHGT0fiot
|
||||
obgDu/W+K2xEOjQeaIyVI5J1qOi6k78fyv1vutjEs6mcTRtDAIxi+V5y5lXUEj0v
|
||||
OWYsbp9yb8Yq602vV8UYSROd+1xdE+7Td3ENLYE7MnVqju7a5NRfnZYgAU03NgIf
|
||||
nHGFZC6/tMz/PXS+D0dqzXxwEjH5JQzGBjvSQHK09gHtCfcyshMQQWtXZGQViZX8
|
||||
QdYXiaq67nJex0DjWTt56a4EgsdYC1J28bJ3GAkrWNkDFRmlx49zvA==
|
||||
-----END RSA PRIVATE KEY-----
|
@ -1,27 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEnTCCAoWgAwIBAgIJAPC7KMFjfslXMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
|
||||
BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNp
|
||||
c2NvMQ8wDQYDVQQKDAZCYWRTU0wxMTAvBgNVBAMMKEJhZFNTTCBDbGllbnQgUm9v
|
||||
dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMTcxMTE2MDUzNjMzWhcNMTkxMTE2
|
||||
MDUzNjMzWjBvMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG
|
||||
A1UEBwwNU2FuIEZyYW5jaXNjbzEPMA0GA1UECgwGQmFkU1NMMSIwIAYDVQQDDBlC
|
||||
YWRTU0wgQ2xpZW50IENlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEAxzdfEeseTs/rukjly6MSLHM+Rh0enA3Ai4Mj2sdl31x3SbPoen08
|
||||
utVhjPmlxIUdkiMG4+ffe7N+JtDLG75CaxZp9CxytX7kywooRBJsRnQhmQPca8MR
|
||||
WAJBIz+w/L+3AFkTIqWBfyT+1VO8TVKPkEpGdLDovZOmzZAASi9/sj+j6gM7AaCi
|
||||
DeZTf2ES66abA5pOp60Q6OEdwg/vCUJfarhKDpi9tj3P6qToy9Y4DiBUhOct4MG8
|
||||
w5XwmKAC+Vfm8tb7tMiUoU0yvKKOcL6YXBXxB2kPcOYxYNobXavfVBEdwSrjQ7i/
|
||||
s3o6hkGQlm9F7JPEuVgbl/Jdwa64OYIqjQIDAQABoy0wKzAJBgNVHRMEAjAAMBEG
|
||||
CWCGSAGG+EIBAQQEAwIHgDALBgNVHQ8EBAMCBeAwDQYJKoZIhvcNAQELBQADggIB
|
||||
AKpzk1ZTunWuof3DIer2Abq7IV3STGeFaoH4TuHdSbmXwC0KuPkv7wVPgPekyRaH
|
||||
b9CBnsreRF7eleD1M63kakhdnA1XIbdJw8sfSDlKdI4emmb4fzdaaPxbrkQ5IxOB
|
||||
QDw5rTUFVPPqFWw1bGP2zrKD1/i1pxUtGM0xem1jR7UZYpsSPs0JCOHKZOmk8OEW
|
||||
Uy+Jp4gRzbMLZ0TrvajGEZXRepjOkXObR81xZGtvTNP2wl1zm13ffwIYdqJUrf1H
|
||||
H4miU9lVX+3/Z+2mVHBWhzBgbTmo06s3uwUE6JsxUGm2/w4NNblRit0uQcGw7ba8
|
||||
kl2d5rZQscFsqNFz2vRjj1G0dO8S3owmuF0izZO9Fqvq0jB6oaUkxcAcTKFSjs2z
|
||||
wy1oy+cu8iO3GRbfAW7U0xzGp9MnkdPS5dHzvhod3/DK0YVskfxZF7M8GhkjT7Qm
|
||||
2EUBQNNMNXC3g/GXTdXOgqqjW5GXahI8Z6Q4OYN6xZwuEhizwKkgojwaww2YgYT9
|
||||
MJXciJZWr3QXvFdBH7m0zwpKgQ1wm6j3yeyuRphq2lEtU3OQl55A3tXtvqyMXsxk
|
||||
xMCCNQdmKQt0WYmMS3Xj/AfAY2sjCWziDflvW5mGCUjSYdZ+r3JIIF4m/FNCIO1d
|
||||
Ioacp9qb0qL9duFlVHtFiPgoKrEdJaNVUL7NG9ppF8pR
|
||||
-----END CERTIFICATE-----
|
Loading…
x
Reference in New Issue
Block a user