87 lines
2.8 KiB
Go
87 lines
2.8 KiB
Go
package bootstrap
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"io"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/http/httputil"
|
|
"net/url"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.pcux.cn/xuans/Scert/backend/internal/config"
|
|
)
|
|
|
|
func TestProxyPreflightStrictTLSAndResponseProof(t *testing.T) {
|
|
for _, mode := range []string{"trusted", "untrusted-upstream", "untrusted-public", "wrong-response", "redirect"} {
|
|
t.Run(mode, func(t *testing.T) {
|
|
material := completionDomainResource("admin.example.test")
|
|
directory := t.TempDir()
|
|
cert := filepath.Join(directory, "chain.pem")
|
|
key := filepath.Join(directory, "key.pem")
|
|
if err := os.WriteFile(cert, material.Certificate, 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(key, material.PrivateKey, 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
reservation, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
port := reservation.Addr().(*net.TCPAddr).Port
|
|
_ = reservation.Close()
|
|
target, _ := url.Parse("https://127.0.0.1:" + strconv.Itoa(port))
|
|
upstreamRoots := x509.NewCertPool()
|
|
if mode != "untrusted-upstream" {
|
|
upstreamRoots.AppendCertsFromPEM(material.Certificate)
|
|
}
|
|
reverse := httputil.NewSingleHostReverseProxy(target)
|
|
reverse.ErrorLog = log.New(io.Discard, "", 0)
|
|
upstream := &http.Transport{TLSClientConfig: &tls.Config{MinVersion: tls.VersionTLS12, RootCAs: upstreamRoots, ServerName: "admin.example.test"}}
|
|
defer upstream.CloseIdleConnections()
|
|
reverse.Transport = upstream
|
|
proxy := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if mode == "wrong-response" {
|
|
_, _ = io.WriteString(w, "unrelated-service")
|
|
return
|
|
}
|
|
if mode == "redirect" {
|
|
http.Redirect(w, r, "/login", http.StatusFound)
|
|
return
|
|
}
|
|
reverse.ServeHTTP(w, r)
|
|
}))
|
|
defer proxy.Close()
|
|
publicRoots := x509.NewCertPool()
|
|
if mode != "untrusted-public" {
|
|
publicRoots.AddCert(proxy.Certificate())
|
|
}
|
|
transport := &http.Transport{TLSClientConfig: &tls.Config{MinVersion: tls.VersionTLS12, RootCAs: publicRoots}, DisableKeepAlives: true}
|
|
candidate := config.Config{
|
|
Server: config.ServerConfig{Host: "127.0.0.1", Port: port, HTTPSMode: "proxy", ProxyHTTPSPort: proxy.Listener.Addr().(*net.TCPAddr).Port, TLSCert: cert, TLSKey: key},
|
|
Web: config.WebConfig{Hostname: "127.0.0.1"},
|
|
}
|
|
ctx, cancel := context.WithTimeout(t.Context(), time.Second)
|
|
defer cancel()
|
|
err = verifySetupProxyTransport(ctx, candidate, transport)
|
|
if (err == nil) != (mode == "trusted") {
|
|
t.Fatalf("代理校验结果不正确:%s %v", mode, err)
|
|
}
|
|
listener, err := net.Listen("tcp", target.Host)
|
|
if err != nil {
|
|
t.Fatalf("预检未释放正式端口:%v", err)
|
|
}
|
|
_ = listener.Close()
|
|
})
|
|
}
|
|
}
|