-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat: add certificate caching for AI Bridge Proxy #21344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: ssncferreira/feat-aiproxy-routing
Are you sure you want to change the base?
feat: add certificate caching for AI Bridge Proxy #21344
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
| targetServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| w.WriteHeader(http.StatusOK) | ||
| })) | ||
| defer targetServer.Close() | ||
|
|
||
| certFile, keyFile := generateTestCA(t) | ||
| logger := slogtest.Make(t, nil) | ||
|
|
||
| // Start the proxy server. | ||
| srv, err := aibridgeproxyd.New(t.Context(), logger, aibridgeproxyd.Options{ | ||
| ListenAddr: "127.0.0.1:0", | ||
| CoderAccessURL: "http://localhost:3000", | ||
| CertFile: certFile, | ||
| KeyFile: keyFile, | ||
| }) | ||
| require.NoError(t, err) | ||
| t.Cleanup(func() { _ = srv.Close() }) | ||
|
|
||
| proxyAddr := srv.Addr() | ||
| require.NotEmpty(t, proxyAddr) | ||
|
|
||
| // Wait for the proxy server to be ready. | ||
| require.Eventually(t, func() bool { | ||
| conn, err := net.Dial("tcp", proxyAddr) | ||
| if err != nil { | ||
| return false | ||
| } | ||
| _ = conn.Close() | ||
| return true | ||
| }, testutil.WaitShort, testutil.IntervalFast) | ||
|
|
||
| // Load the CA certificate so the client trusts the proxy's MITM certificate. | ||
| certPEM, err := os.ReadFile(certFile) | ||
| require.NoError(t, err) | ||
| certPool := x509.NewCertPool() | ||
| certPool.AppendCertsFromPEM(certPEM) | ||
|
|
||
| // Create an HTTP client configured to use the proxy. | ||
| proxyURL, err := url.Parse("http://" + proxyAddr) | ||
| require.NoError(t, err) | ||
|
|
||
| client := &http.Client{ | ||
| Transport: &http.Transport{ | ||
| Proxy: http.ProxyURL(proxyURL), | ||
| ProxyConnectHeader: http.Header{ | ||
| "Proxy-Authorization": []string{makeProxyAuthHeader("test-session-token")}, | ||
| }, | ||
| TLSClientConfig: &tls.Config{ | ||
| MinVersion: tls.VersionTLS12, | ||
| RootCAs: certPool, | ||
| }, | ||
| }, | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: this feels like a repeated pattern that we could move into a test util to make the tests more readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aggree, I will address this in a follow-up PR 👍
9b2593b to
bc4caed
Compare
ecf32ef to
330ccd7
Compare
bc4caed to
97198d5
Compare
330ccd7 to
ee37009
Compare
7e117da to
6e0a054
Compare
77155cc to
b0a0d5d
Compare
6b3a42f to
b82c306
Compare
fd98405 to
42720ba
Compare
b82c306 to
5e6a35c
Compare
dd18dfb to
01151fb
Compare
5a1d2dc to
4196397
Compare
b22bf6c to
32e418d
Compare
4196397 to
64470eb
Compare
32e418d to
bdf6895
Compare
64470eb to
dcda7da
Compare
cd695b9 to
2cecfac
Compare
644e954 to
4654e31
Compare
2cecfac to
ab0b3f6
Compare
4654e31 to
e0906db
Compare

Description
Implements in-memory certificate caching for the AI Bridge MITM proxy. Certificate generation is expensive (RSA key generation + signing), so caching avoids repeated generation for the same hostname.
Changes
certCachestruct implementinggoproxy.CertStoragewith thread-safe double-check lockingproxy.CertStoreCloses coder/internal#1183