@@ -29,17 +29,23 @@ import (
29
29
30
30
"github.com/elazarl/goproxy"
31
31
"github.com/fluxcd/pkg/gittestserver"
32
+ "github.com/go-logr/logr"
32
33
. "github.com/onsi/gomega"
33
34
34
35
"github.com/fluxcd/source-controller/pkg/git"
35
36
"github.com/fluxcd/source-controller/pkg/git/gogit"
36
37
"github.com/fluxcd/source-controller/pkg/git/libgit2"
38
+ "github.com/fluxcd/source-controller/pkg/git/libgit2/managed"
37
39
"github.com/fluxcd/source-controller/pkg/git/strategy"
38
40
)
39
41
40
42
// These tests are run in a different _test.go file because go-git uses the ProxyFromEnvironment function of the net/http package
41
43
// which caches the Proxy settings, hence not including other tests in the same file ensures a clean proxy setup for the tests to run.
42
44
func TestCheckoutStrategyForImplementation_Proxied (t * testing.T ) {
45
+ // for libgit2 we are only testing for managed transport,
46
+ // as unmanaged is sunsetting.
47
+ // Unmanaged transport does not support HTTP_PROXY.
48
+ managed .InitManagedTransport (logr .Discard ())
43
49
44
50
type cleanupFunc func ()
45
51
@@ -62,8 +68,104 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
62
68
proxyAddr := fmt .Sprintf ("localhost:%d" , l .Addr ().(* net.TCPAddr ).Port )
63
69
g .Expect (l .Close ()).ToNot (HaveOccurred ())
64
70
65
- // Note there is no libgit2 HTTP_PROXY test as libgit2 doesnt support proxied HTTP requests.
66
71
cases := []testCase {
72
+ {
73
+ name : "gogit_HTTP_PROXY" ,
74
+ gitImpl : gogit .Implementation ,
75
+ url : "http://example.com/bar/test-reponame" ,
76
+ branch : "main" ,
77
+ setupGitProxy : func (g * WithT , proxy * goproxy.ProxyHttpServer , proxyGotRequest * bool ) (* git.AuthOptions , cleanupFunc ) {
78
+ // Create the git server.
79
+ gitServer , err := gittestserver .NewTempGitServer ()
80
+ g .Expect (err ).ToNot (HaveOccurred ())
81
+
82
+ username := "test-user"
83
+ password := "test-password"
84
+ gitServer .Auth (username , password )
85
+ gitServer .KeyDir (gitServer .Root ())
86
+
87
+ g .Expect (gitServer .StartHTTP ()).ToNot (HaveOccurred ())
88
+
89
+ // Initialize a git repo.
90
+ err = gitServer .InitRepo ("../testdata/repo1" , "main" , "bar/test-reponame" )
91
+ g .Expect (err ).ToNot (HaveOccurred ())
92
+
93
+ u , err := url .Parse (gitServer .HTTPAddress ())
94
+ g .Expect (err ).ToNot (HaveOccurred ())
95
+
96
+ // The request is being forwarded to the local test git server in this handler.
97
+ var proxyHandler goproxy.FuncReqHandler = func (req * http.Request , ctx * goproxy.ProxyCtx ) (* http.Request , * http.Response ) {
98
+ userAgent := req .Header .Get ("User-Agent" )
99
+ if strings .Contains (req .Host , "example.com" ) && strings .Contains (userAgent , "git" ) {
100
+ * proxyGotRequest = true
101
+ req .Host = u .Host
102
+ req .URL .Host = req .Host
103
+ return req , nil
104
+ }
105
+ // Reject if it isnt our request.
106
+ return req , goproxy .NewResponse (req , goproxy .ContentTypeText , http .StatusForbidden , "" )
107
+ }
108
+ proxy .OnRequest ().Do (proxyHandler )
109
+
110
+ return & git.AuthOptions {
111
+ Transport : git .HTTP ,
112
+ Username : username ,
113
+ Password : password ,
114
+ }, func () {
115
+ os .RemoveAll (gitServer .Root ())
116
+ gitServer .StopHTTP ()
117
+ }
118
+ },
119
+ shortTimeout : false ,
120
+ wantUsedProxy : true ,
121
+ wantError : false ,
122
+ },
123
+ {
124
+ name : "gogit_HTTPS_PROXY" ,
125
+ gitImpl : gogit .Implementation ,
126
+ url : "https://github.com/git-fixtures/basic" ,
127
+ branch : "master" ,
128
+ setupGitProxy : func (g * WithT , proxy * goproxy.ProxyHttpServer , proxyGotRequest * bool ) (* git.AuthOptions , cleanupFunc ) {
129
+ var proxyHandler goproxy.FuncHttpsHandler = func (host string , ctx * goproxy.ProxyCtx ) (* goproxy.ConnectAction , string ) {
130
+ // We don't check for user agent as this handler is only going to process CONNECT requests, and because Go's net/http
131
+ // is the one making such a request on behalf of go-git, adding a check for the go net/http user agent (Go-http-client)
132
+ // would only allow false positives from any request originating from Go's net/http.
133
+ if strings .Contains (host , "github.com" ) {
134
+ * proxyGotRequest = true
135
+ return goproxy .OkConnect , host
136
+ }
137
+ // Reject if it isnt our request.
138
+ return goproxy .RejectConnect , host
139
+ }
140
+ proxy .OnRequest ().HandleConnect (proxyHandler )
141
+
142
+ // go-git does not allow to use an HTTPS proxy and a custom root CA at the same time.
143
+ // See https://github.com/fluxcd/source-controller/pull/524#issuecomment-1006673163.
144
+ return nil , func () {}
145
+ },
146
+ shortTimeout : false ,
147
+ wantUsedProxy : true ,
148
+ wantError : false ,
149
+ },
150
+ {
151
+ name : "gogit_NO_PROXY" ,
152
+ gitImpl : gogit .Implementation ,
153
+ url : "https://192.0.2.1/bar/test-reponame" ,
154
+ branch : "main" ,
155
+ setupGitProxy : func (g * WithT , proxy * goproxy.ProxyHttpServer , proxyGotRequest * bool ) (* git.AuthOptions , cleanupFunc ) {
156
+ var proxyHandler goproxy.FuncHttpsHandler = func (host string , ctx * goproxy.ProxyCtx ) (* goproxy.ConnectAction , string ) {
157
+ // We shouldn't hit the proxy so we just want to check for any interaction, then reject.
158
+ * proxyGotRequest = true
159
+ return goproxy .RejectConnect , host
160
+ }
161
+ proxy .OnRequest ().HandleConnect (proxyHandler )
162
+
163
+ return nil , func () {}
164
+ },
165
+ shortTimeout : true ,
166
+ wantUsedProxy : false ,
167
+ wantError : true ,
168
+ },
67
169
{
68
170
name : "libgit2_HTTPS_PROXY" ,
69
171
gitImpl : libgit2 .Implementation ,
@@ -100,6 +202,7 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
100
202
// The request is being forwarded to the local test git server in this handler.
101
203
// The certificate used here is valid for both example.com and localhost.
102
204
var proxyHandler goproxy.FuncHttpsHandler = func (host string , ctx * goproxy.ProxyCtx ) (* goproxy.ConnectAction , string ) {
205
+ defer managed .RemoveTransportOptions ("https://example.com/bar/test-reponame" )
103
206
// Check if the host matches with the git server address and the user-agent is the expected git client.
104
207
userAgent := ctx .Req .Header .Get ("User-Agent" )
105
208
if strings .Contains (host , "example.com" ) && strings .Contains (userAgent , "libgit2" ) {
@@ -112,10 +215,11 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
112
215
proxy .OnRequest ().HandleConnect (proxyHandler )
113
216
114
217
return & git.AuthOptions {
115
- Transport : git .HTTPS ,
116
- Username : username ,
117
- Password : password ,
118
- CAFile : exampleCA ,
218
+ Transport : git .HTTPS ,
219
+ Username : username ,
220
+ Password : password ,
221
+ CAFile : exampleCA ,
222
+ TransportOptionsURL : "https://proxy-test" ,
119
223
}, func () {
120
224
os .RemoveAll (gitServer .Root ())
121
225
gitServer .StopHTTP ()
@@ -126,33 +230,31 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
126
230
wantError : false ,
127
231
},
128
232
{
129
- name : "gogit_HTTP_PROXY " ,
130
- gitImpl : gogit .Implementation ,
233
+ name : "libgit2_HTTP_PROXY " ,
234
+ gitImpl : libgit2 .Implementation ,
131
235
url : "http://example.com/bar/test-reponame" ,
132
236
branch : "main" ,
133
237
setupGitProxy : func (g * WithT , proxy * goproxy.ProxyHttpServer , proxyGotRequest * bool ) (* git.AuthOptions , cleanupFunc ) {
134
238
// Create the git server.
135
239
gitServer , err := gittestserver .NewTempGitServer ()
136
240
g .Expect (err ).ToNot (HaveOccurred ())
137
241
138
- username := "test-user"
139
- password := "test-password"
140
- gitServer .Auth (username , password )
141
- gitServer .KeyDir (gitServer .Root ())
142
-
143
- g .Expect (gitServer .StartHTTP ()).ToNot (HaveOccurred ())
242
+ err = gitServer .StartHTTP ()
243
+ g .Expect (err ).ToNot (HaveOccurred ())
144
244
145
245
// Initialize a git repo.
146
- err = gitServer .InitRepo ("../testdata/repo1" , "main" , "bar/test-reponame" )
246
+ repoPath := "bar/test-reponame"
247
+ err = gitServer .InitRepo ("../testdata/repo1" , "main" , repoPath )
147
248
g .Expect (err ).ToNot (HaveOccurred ())
148
249
149
250
u , err := url .Parse (gitServer .HTTPAddress ())
150
251
g .Expect (err ).ToNot (HaveOccurred ())
151
252
152
253
// The request is being forwarded to the local test git server in this handler.
254
+ // The certificate used here is valid for both example.com and localhost.
153
255
var proxyHandler goproxy.FuncReqHandler = func (req * http.Request , ctx * goproxy.ProxyCtx ) (* http.Request , * http.Response ) {
154
256
userAgent := req .Header .Get ("User-Agent" )
155
- if strings .Contains (req .Host , "example.com" ) && strings .Contains (userAgent , "git " ) {
257
+ if strings .Contains (req .Host , "example.com" ) && strings .Contains (userAgent , "libgit2 " ) {
156
258
* proxyGotRequest = true
157
259
req .Host = u .Host
158
260
req .URL .Host = req .Host
@@ -164,9 +266,8 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
164
266
proxy .OnRequest ().Do (proxyHandler )
165
267
166
268
return & git.AuthOptions {
167
- Transport : git .HTTP ,
168
- Username : username ,
169
- Password : password ,
269
+ Transport : git .HTTP ,
270
+ TransportOptionsURL : "http://proxy-test" ,
170
271
}, func () {
171
272
os .RemoveAll (gitServer .Root ())
172
273
gitServer .StopHTTP ()
@@ -177,35 +278,8 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
177
278
wantError : false ,
178
279
},
179
280
{
180
- name : "gogit_HTTPS_PROXY" ,
181
- gitImpl : gogit .Implementation ,
182
- url : "https://github.com/git-fixtures/basic" ,
183
- branch : "master" ,
184
- setupGitProxy : func (g * WithT , proxy * goproxy.ProxyHttpServer , proxyGotRequest * bool ) (* git.AuthOptions , cleanupFunc ) {
185
- var proxyHandler goproxy.FuncHttpsHandler = func (host string , ctx * goproxy.ProxyCtx ) (* goproxy.ConnectAction , string ) {
186
- // We don't check for user agent as this handler is only going to process CONNECT requests, and because Go's net/http
187
- // is the one making such a request on behalf of go-git, adding a check for the go net/http user agent (Go-http-client)
188
- // would only allow false positives from any request originating from Go's net/http.
189
- if strings .Contains (host , "github.com" ) {
190
- * proxyGotRequest = true
191
- return goproxy .OkConnect , host
192
- }
193
- // Reject if it isnt our request.
194
- return goproxy .RejectConnect , host
195
- }
196
- proxy .OnRequest ().HandleConnect (proxyHandler )
197
-
198
- // go-git does not allow to use an HTTPS proxy and a custom root CA at the same time.
199
- // See https://github.com/fluxcd/source-controller/pull/524#issuecomment-1006673163.
200
- return nil , func () {}
201
- },
202
- shortTimeout : false ,
203
- wantUsedProxy : true ,
204
- wantError : false ,
205
- },
206
- {
207
- name : "gogit_NO_PROXY" ,
208
- gitImpl : gogit .Implementation ,
281
+ name : "libgit2_NO_PROXY" ,
282
+ gitImpl : libgit2 .Implementation ,
209
283
url : "https://192.0.2.1/bar/test-reponame" ,
210
284
branch : "main" ,
211
285
setupGitProxy : func (g * WithT , proxy * goproxy.ProxyHttpServer , proxyGotRequest * bool ) (* git.AuthOptions , cleanupFunc ) {
@@ -218,13 +292,10 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
218
292
219
293
return nil , func () {}
220
294
},
221
- shortTimeout : true ,
295
+ shortTimeout : false ,
222
296
wantUsedProxy : false ,
223
297
wantError : true ,
224
298
},
225
- // 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
226
- // the NO_PROXY functionality
227
- // This PR introduces the functionality in libgit2: https://github.com/libgit2/libgit2/pull/6026
228
299
}
229
300
230
301
for _ , tt := range cases {
@@ -282,7 +353,6 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
282
353
}
283
354
284
355
g .Expect (proxyGotRequest ).To (Equal (tt .wantUsedProxy ))
285
-
286
356
})
287
357
}
288
358
}
0 commit comments