|
4 | 4 | "bytes" |
5 | 5 | "context" |
6 | 6 | "crypto/tls" |
| 7 | + "crypto/x509" |
7 | 8 | "errors" |
8 | 9 | "fmt" |
9 | 10 | "io" |
@@ -110,6 +111,22 @@ func NewInjector(provider vault.Provider, resolver *atomic.Pointer[vault.Binding |
110 | 111 | proxy := goproxy.NewProxyHttpServer() |
111 | 112 | proxy.Verbose = false |
112 | 113 |
|
| 114 | + // Build a root CA pool for the outbound transport. Start with system |
| 115 | + // roots and add the sluice MITM CA cert. Adding the MITM CA is |
| 116 | + // necessary because in containerized deployments, upstream test |
| 117 | + // servers may present certificates signed by the same CA that sluice |
| 118 | + // uses for interception. In production, no real server will present a |
| 119 | + // cert signed by sluice's CA, so this addition is harmless. |
| 120 | + rootCAs, _ := x509.SystemCertPool() |
| 121 | + if rootCAs == nil { |
| 122 | + rootCAs = x509.NewCertPool() |
| 123 | + } |
| 124 | + if len(caCert.Certificate) > 0 { |
| 125 | + if parsed, err := x509.ParseCertificate(caCert.Certificate[0]); err == nil { |
| 126 | + rootCAs.AddCert(parsed) |
| 127 | + } |
| 128 | + } |
| 129 | + |
113 | 130 | // Use a transport that dials pinned IPs (set by the SOCKS5 dial |
114 | 131 | // function) instead of re-resolving DNS. This prevents DNS rebinding |
115 | 132 | // attacks where the hostname resolves to a different IP between |
@@ -138,6 +155,7 @@ func NewInjector(provider vault.Provider, resolver *atomic.Pointer[vault.Binding |
138 | 155 | } |
139 | 156 | return (&net.Dialer{Timeout: connectTimeout}).DialContext(ctx, network, addr) |
140 | 157 | }, |
| 158 | + TLSClientConfig: &tls.Config{RootCAs: rootCAs}, |
141 | 159 | ForceAttemptHTTP2: true, |
142 | 160 | TLSHandshakeTimeout: 10 * time.Second, |
143 | 161 | } |
|
0 commit comments