1
0
mirror of https://github.com/ribbybibby/ssl_exporter.git synced 2025-07-15 23:54:18 +02:00

Improve tests and remove reliance on external websites

This commit is contained in:
Rob Best
2019-03-27 18:10:35 +00:00
parent 30c8ffb7c3
commit 215029534e
3 changed files with 486 additions and 140 deletions

View File

@ -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
}