expand proxy tests to cover managed transport
Signed-off-by: Sanskar Jaiswal <jaiswalsanskar078@gmail.com> Co-authored-by: Paulo Gomes <paulo.gomes@weave.works>
This commit is contained in:
		
							parent
							
								
									7d2bc64f47
								
							
						
					
					
						commit
						90ec1e230c
					
				|  | @ -29,17 +29,23 @@ import ( | ||||||
| 
 | 
 | ||||||
| 	"github.com/elazarl/goproxy" | 	"github.com/elazarl/goproxy" | ||||||
| 	"github.com/fluxcd/pkg/gittestserver" | 	"github.com/fluxcd/pkg/gittestserver" | ||||||
|  | 	"github.com/go-logr/logr" | ||||||
| 	. "github.com/onsi/gomega" | 	. "github.com/onsi/gomega" | ||||||
| 
 | 
 | ||||||
| 	"github.com/fluxcd/source-controller/pkg/git" | 	"github.com/fluxcd/source-controller/pkg/git" | ||||||
| 	"github.com/fluxcd/source-controller/pkg/git/gogit" | 	"github.com/fluxcd/source-controller/pkg/git/gogit" | ||||||
| 	"github.com/fluxcd/source-controller/pkg/git/libgit2" | 	"github.com/fluxcd/source-controller/pkg/git/libgit2" | ||||||
|  | 	"github.com/fluxcd/source-controller/pkg/git/libgit2/managed" | ||||||
| 	"github.com/fluxcd/source-controller/pkg/git/strategy" | 	"github.com/fluxcd/source-controller/pkg/git/strategy" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // These tests are run in a different _test.go file because go-git uses the ProxyFromEnvironment function of the net/http package
 | // These tests are run in a different _test.go file because go-git uses the ProxyFromEnvironment function of the net/http package
 | ||||||
| // which caches the Proxy settings, hence not including other tests in the same file ensures a clean proxy setup for the tests to run.
 | // which caches the Proxy settings, hence not including other tests in the same file ensures a clean proxy setup for the tests to run.
 | ||||||
| func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) { | func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) { | ||||||
|  | 	// for libgit2 we are only testing for managed transport,
 | ||||||
|  | 	// as unmanaged is sunsetting.
 | ||||||
|  | 	// Unmanaged transport does not support HTTP_PROXY.
 | ||||||
|  | 	managed.InitManagedTransport(logr.Discard()) | ||||||
| 
 | 
 | ||||||
| 	type cleanupFunc func() | 	type cleanupFunc func() | ||||||
| 
 | 
 | ||||||
|  | @ -62,69 +68,7 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) { | ||||||
| 	proxyAddr := fmt.Sprintf("localhost:%d", l.Addr().(*net.TCPAddr).Port) | 	proxyAddr := fmt.Sprintf("localhost:%d", l.Addr().(*net.TCPAddr).Port) | ||||||
| 	g.Expect(l.Close()).ToNot(HaveOccurred()) | 	g.Expect(l.Close()).ToNot(HaveOccurred()) | ||||||
| 
 | 
 | ||||||
| 	// Note there is no libgit2 HTTP_PROXY test as libgit2 doesnt support proxied HTTP requests.
 |  | ||||||
| 	cases := []testCase{ | 	cases := []testCase{ | ||||||
| 		{ |  | ||||||
| 			name:    "libgit2_HTTPS_PROXY", |  | ||||||
| 			gitImpl: libgit2.Implementation, |  | ||||||
| 			url:     "https://example.com/bar/test-reponame", |  | ||||||
| 			branch:  "main", |  | ||||||
| 			setupGitProxy: func(g *WithT, proxy *goproxy.ProxyHttpServer, proxyGotRequest *bool) (*git.AuthOptions, cleanupFunc) { |  | ||||||
| 				// Create the git server.
 |  | ||||||
| 				gitServer, err := gittestserver.NewTempGitServer() |  | ||||||
| 				g.Expect(err).ToNot(HaveOccurred()) |  | ||||||
| 
 |  | ||||||
| 				username := "test-user" |  | ||||||
| 				password := "test-password" |  | ||||||
| 				gitServer.Auth(username, password) |  | ||||||
| 				gitServer.KeyDir(gitServer.Root()) |  | ||||||
| 
 |  | ||||||
| 				// Start the HTTPS server.
 |  | ||||||
| 				examplePublicKey, err := os.ReadFile("../testdata/certs/server.pem") |  | ||||||
| 				g.Expect(err).ToNot(HaveOccurred()) |  | ||||||
| 				examplePrivateKey, err := os.ReadFile("../testdata/certs/server-key.pem") |  | ||||||
| 				g.Expect(err).ToNot(HaveOccurred()) |  | ||||||
| 				exampleCA, err := os.ReadFile("../testdata/certs/ca.pem") |  | ||||||
| 				g.Expect(err).ToNot(HaveOccurred()) |  | ||||||
| 				err = gitServer.StartHTTPS(examplePublicKey, examplePrivateKey, exampleCA, "example.com") |  | ||||||
| 				g.Expect(err).ToNot(HaveOccurred()) |  | ||||||
| 
 |  | ||||||
| 				// Initialize a git repo.
 |  | ||||||
| 				repoPath := "bar/test-reponame" |  | ||||||
| 				err = gitServer.InitRepo("../testdata/repo1", "main", repoPath) |  | ||||||
| 				g.Expect(err).ToNot(HaveOccurred()) |  | ||||||
| 
 |  | ||||||
| 				u, err := url.Parse(gitServer.HTTPAddress()) |  | ||||||
| 				g.Expect(err).ToNot(HaveOccurred()) |  | ||||||
| 
 |  | ||||||
| 				// The request is being forwarded to the local test git server in this handler.
 |  | ||||||
| 				// The certificate used here is valid for both example.com and localhost.
 |  | ||||||
| 				var proxyHandler goproxy.FuncHttpsHandler = func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) { |  | ||||||
| 					// Check if the host matches with the git server address and the user-agent is the expected git client.
 |  | ||||||
| 					userAgent := ctx.Req.Header.Get("User-Agent") |  | ||||||
| 					if strings.Contains(host, "example.com") && strings.Contains(userAgent, "libgit2") { |  | ||||||
| 						*proxyGotRequest = true |  | ||||||
| 						return goproxy.OkConnect, u.Host |  | ||||||
| 					} |  | ||||||
| 					// Reject if it isn't our request.
 |  | ||||||
| 					return goproxy.RejectConnect, host |  | ||||||
| 				} |  | ||||||
| 				proxy.OnRequest().HandleConnect(proxyHandler) |  | ||||||
| 
 |  | ||||||
| 				return &git.AuthOptions{ |  | ||||||
| 						Transport: git.HTTPS, |  | ||||||
| 						Username:  username, |  | ||||||
| 						Password:  password, |  | ||||||
| 						CAFile:    exampleCA, |  | ||||||
| 					}, func() { |  | ||||||
| 						os.RemoveAll(gitServer.Root()) |  | ||||||
| 						gitServer.StopHTTP() |  | ||||||
| 					} |  | ||||||
| 			}, |  | ||||||
| 			shortTimeout:  false, |  | ||||||
| 			wantUsedProxy: true, |  | ||||||
| 			wantError:     false, |  | ||||||
| 		}, |  | ||||||
| 		{ | 		{ | ||||||
| 			name:    "gogit_HTTP_PROXY", | 			name:    "gogit_HTTP_PROXY", | ||||||
| 			gitImpl: gogit.Implementation, | 			gitImpl: gogit.Implementation, | ||||||
|  | @ -222,9 +166,136 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) { | ||||||
| 			wantUsedProxy: false, | 			wantUsedProxy: false, | ||||||
| 			wantError:     true, | 			wantError:     true, | ||||||
| 		}, | 		}, | ||||||
| 		// TODO: Add a NO_PROXY test for libgit2 once the version of libgit2 used by the source controller is updated to a version that includes
 | 		{ | ||||||
| 		// the NO_PROXY functionality
 | 			name:    "libgit2_HTTPS_PROXY", | ||||||
| 		// This PR introduces the functionality in libgit2: https://github.com/libgit2/libgit2/pull/6026
 | 			gitImpl: libgit2.Implementation, | ||||||
|  | 			url:     "https://example.com/bar/test-reponame", | ||||||
|  | 			branch:  "main", | ||||||
|  | 			setupGitProxy: func(g *WithT, proxy *goproxy.ProxyHttpServer, proxyGotRequest *bool) (*git.AuthOptions, cleanupFunc) { | ||||||
|  | 				// Create the git server.
 | ||||||
|  | 				gitServer, err := gittestserver.NewTempGitServer() | ||||||
|  | 				g.Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 
 | ||||||
|  | 				username := "test-user" | ||||||
|  | 				password := "test-password" | ||||||
|  | 				gitServer.Auth(username, password) | ||||||
|  | 				gitServer.KeyDir(gitServer.Root()) | ||||||
|  | 
 | ||||||
|  | 				// Start the HTTPS server.
 | ||||||
|  | 				examplePublicKey, err := os.ReadFile("../testdata/certs/server.pem") | ||||||
|  | 				g.Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 				examplePrivateKey, err := os.ReadFile("../testdata/certs/server-key.pem") | ||||||
|  | 				g.Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 				exampleCA, err := os.ReadFile("../testdata/certs/ca.pem") | ||||||
|  | 				g.Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 				err = gitServer.StartHTTPS(examplePublicKey, examplePrivateKey, exampleCA, "example.com") | ||||||
|  | 				g.Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 
 | ||||||
|  | 				// Initialize a git repo.
 | ||||||
|  | 				repoPath := "bar/test-reponame" | ||||||
|  | 				err = gitServer.InitRepo("../testdata/repo1", "main", repoPath) | ||||||
|  | 				g.Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 
 | ||||||
|  | 				u, err := url.Parse(gitServer.HTTPAddress()) | ||||||
|  | 				g.Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 
 | ||||||
|  | 				// The request is being forwarded to the local test git server in this handler.
 | ||||||
|  | 				// The certificate used here is valid for both example.com and localhost.
 | ||||||
|  | 				var proxyHandler goproxy.FuncHttpsHandler = func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) { | ||||||
|  | 					defer managed.RemoveTransportOptions("https://example.com/bar/test-reponame") | ||||||
|  | 					// Check if the host matches with the git server address and the user-agent is the expected git client.
 | ||||||
|  | 					userAgent := ctx.Req.Header.Get("User-Agent") | ||||||
|  | 					if strings.Contains(host, "example.com") && strings.Contains(userAgent, "libgit2") { | ||||||
|  | 						*proxyGotRequest = true | ||||||
|  | 						return goproxy.OkConnect, u.Host | ||||||
|  | 					} | ||||||
|  | 					// Reject if it isn't our request.
 | ||||||
|  | 					return goproxy.RejectConnect, host | ||||||
|  | 				} | ||||||
|  | 				proxy.OnRequest().HandleConnect(proxyHandler) | ||||||
|  | 
 | ||||||
|  | 				return &git.AuthOptions{ | ||||||
|  | 						Transport:           git.HTTPS, | ||||||
|  | 						Username:            username, | ||||||
|  | 						Password:            password, | ||||||
|  | 						CAFile:              exampleCA, | ||||||
|  | 						TransportOptionsURL: "https://proxy-test", | ||||||
|  | 					}, func() { | ||||||
|  | 						os.RemoveAll(gitServer.Root()) | ||||||
|  | 						gitServer.StopHTTP() | ||||||
|  | 					} | ||||||
|  | 			}, | ||||||
|  | 			shortTimeout:  false, | ||||||
|  | 			wantUsedProxy: true, | ||||||
|  | 			wantError:     false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:    "libgit2_HTTP_PROXY", | ||||||
|  | 			gitImpl: libgit2.Implementation, | ||||||
|  | 			url:     "http://example.com/bar/test-reponame", | ||||||
|  | 			branch:  "main", | ||||||
|  | 			setupGitProxy: func(g *WithT, proxy *goproxy.ProxyHttpServer, proxyGotRequest *bool) (*git.AuthOptions, cleanupFunc) { | ||||||
|  | 				// Create the git server.
 | ||||||
|  | 				gitServer, err := gittestserver.NewTempGitServer() | ||||||
|  | 				g.Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 
 | ||||||
|  | 				err = gitServer.StartHTTP() | ||||||
|  | 				g.Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 
 | ||||||
|  | 				// Initialize a git repo.
 | ||||||
|  | 				repoPath := "bar/test-reponame" | ||||||
|  | 				err = gitServer.InitRepo("../testdata/repo1", "main", repoPath) | ||||||
|  | 				g.Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 
 | ||||||
|  | 				u, err := url.Parse(gitServer.HTTPAddress()) | ||||||
|  | 				g.Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 
 | ||||||
|  | 				// The request is being forwarded to the local test git server in this handler.
 | ||||||
|  | 				// The certificate used here is valid for both example.com and localhost.
 | ||||||
|  | 				var proxyHandler goproxy.FuncReqHandler = func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) { | ||||||
|  | 					userAgent := req.Header.Get("User-Agent") | ||||||
|  | 					if strings.Contains(req.Host, "example.com") && strings.Contains(userAgent, "libgit2") { | ||||||
|  | 						*proxyGotRequest = true | ||||||
|  | 						req.Host = u.Host | ||||||
|  | 						req.URL.Host = req.Host | ||||||
|  | 						return req, nil | ||||||
|  | 					} | ||||||
|  | 					// Reject if it isnt our request.
 | ||||||
|  | 					return req, goproxy.NewResponse(req, goproxy.ContentTypeText, http.StatusForbidden, "") | ||||||
|  | 				} | ||||||
|  | 				proxy.OnRequest().Do(proxyHandler) | ||||||
|  | 
 | ||||||
|  | 				return &git.AuthOptions{ | ||||||
|  | 						Transport:           git.HTTP, | ||||||
|  | 						TransportOptionsURL: "http://proxy-test", | ||||||
|  | 					}, func() { | ||||||
|  | 						os.RemoveAll(gitServer.Root()) | ||||||
|  | 						gitServer.StopHTTP() | ||||||
|  | 					} | ||||||
|  | 			}, | ||||||
|  | 			shortTimeout:  false, | ||||||
|  | 			wantUsedProxy: true, | ||||||
|  | 			wantError:     false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:    "libgit2_NO_PROXY", | ||||||
|  | 			gitImpl: libgit2.Implementation, | ||||||
|  | 			url:     "https://192.0.2.1/bar/test-reponame", | ||||||
|  | 			branch:  "main", | ||||||
|  | 			setupGitProxy: func(g *WithT, proxy *goproxy.ProxyHttpServer, proxyGotRequest *bool) (*git.AuthOptions, cleanupFunc) { | ||||||
|  | 				var proxyHandler goproxy.FuncHttpsHandler = func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) { | ||||||
|  | 					// We shouldn't hit the proxy so we just want to check for any interaction, then reject.
 | ||||||
|  | 					*proxyGotRequest = true | ||||||
|  | 					return goproxy.RejectConnect, host | ||||||
|  | 				} | ||||||
|  | 				proxy.OnRequest().HandleConnect(proxyHandler) | ||||||
|  | 
 | ||||||
|  | 				return nil, func() {} | ||||||
|  | 			}, | ||||||
|  | 			shortTimeout:  false, | ||||||
|  | 			wantUsedProxy: false, | ||||||
|  | 			wantError:     true, | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for _, tt := range cases { | 	for _, tt := range cases { | ||||||
|  | @ -282,7 +353,6 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) { | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			g.Expect(proxyGotRequest).To(Equal(tt.wantUsedProxy)) | 			g.Expect(proxyGotRequest).To(Equal(tt.wantUsedProxy)) | ||||||
| 
 |  | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue