170 lines
3.2 KiB
Go
170 lines
3.2 KiB
Go
package tlscheck_test
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"net"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"sneak.berlin/go/dnswatcher/internal/tlscheck"
|
|
)
|
|
|
|
func startTLSServer(
|
|
t *testing.T,
|
|
) (*httptest.Server, string, int) {
|
|
t.Helper()
|
|
|
|
srv := httptest.NewTLSServer(
|
|
http.HandlerFunc(
|
|
func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
},
|
|
),
|
|
)
|
|
|
|
addr, ok := srv.Listener.Addr().(*net.TCPAddr)
|
|
if !ok {
|
|
t.Fatal("unexpected address type")
|
|
}
|
|
|
|
return srv, addr.IP.String(), addr.Port
|
|
}
|
|
|
|
func TestCheckCertificateValid(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
srv, ip, port := startTLSServer(t)
|
|
|
|
defer srv.Close()
|
|
|
|
checker := tlscheck.NewStandalone(
|
|
tlscheck.WithTimeout(5 * time.Second),
|
|
tlscheck.WithTLSConfig(&tls.Config{
|
|
//nolint:gosec // test uses self-signed cert
|
|
InsecureSkipVerify: true,
|
|
}),
|
|
tlscheck.WithPort(port),
|
|
)
|
|
|
|
info, err := checker.CheckCertificate(
|
|
context.Background(), ip, "localhost",
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if info == nil {
|
|
t.Fatal("expected non-nil CertificateInfo")
|
|
}
|
|
|
|
if info.NotAfter.IsZero() {
|
|
t.Error("expected non-zero NotAfter")
|
|
}
|
|
|
|
if info.SerialNumber == "" {
|
|
t.Error("expected non-empty SerialNumber")
|
|
}
|
|
}
|
|
|
|
func TestCheckCertificateConnectionRefused(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
lc := &net.ListenConfig{}
|
|
|
|
ln, err := lc.Listen(
|
|
context.Background(), "tcp", "127.0.0.1:0",
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("failed to listen: %v", err)
|
|
}
|
|
|
|
addr, ok := ln.Addr().(*net.TCPAddr)
|
|
if !ok {
|
|
t.Fatal("unexpected address type")
|
|
}
|
|
|
|
port := addr.Port
|
|
|
|
_ = ln.Close()
|
|
|
|
checker := tlscheck.NewStandalone(
|
|
tlscheck.WithTimeout(2*time.Second),
|
|
tlscheck.WithPort(port),
|
|
)
|
|
|
|
_, err = checker.CheckCertificate(
|
|
context.Background(), "127.0.0.1", "localhost",
|
|
)
|
|
if err == nil {
|
|
t.Fatal("expected error for connection refused")
|
|
}
|
|
}
|
|
|
|
func TestCheckCertificateContextCanceled(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
|
|
checker := tlscheck.NewStandalone(
|
|
tlscheck.WithTimeout(2 * time.Second),
|
|
tlscheck.WithPort(1),
|
|
)
|
|
|
|
_, err := checker.CheckCertificate(
|
|
ctx, "127.0.0.1", "localhost",
|
|
)
|
|
if err == nil {
|
|
t.Fatal("expected error for canceled context")
|
|
}
|
|
}
|
|
|
|
func TestCheckCertificateTimeout(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
checker := tlscheck.NewStandalone(
|
|
tlscheck.WithTimeout(1 * time.Millisecond),
|
|
tlscheck.WithPort(1),
|
|
)
|
|
|
|
_, err := checker.CheckCertificate(
|
|
context.Background(),
|
|
"192.0.2.1",
|
|
"example.com",
|
|
)
|
|
if err == nil {
|
|
t.Fatal("expected error for timeout")
|
|
}
|
|
}
|
|
|
|
func TestCheckCertificateSANs(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
srv, ip, port := startTLSServer(t)
|
|
|
|
defer srv.Close()
|
|
|
|
checker := tlscheck.NewStandalone(
|
|
tlscheck.WithTimeout(5*time.Second),
|
|
tlscheck.WithTLSConfig(&tls.Config{
|
|
//nolint:gosec // test uses self-signed cert
|
|
InsecureSkipVerify: true,
|
|
}),
|
|
tlscheck.WithPort(port),
|
|
)
|
|
|
|
info, err := checker.CheckCertificate(
|
|
context.Background(), ip, "localhost",
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if info.CommonName == "" && len(info.SubjectAlternativeNames) == 0 {
|
|
t.Error("expected CN or SANs to be populated")
|
|
}
|
|
}
|