Skip to content

Commit 1c7ef96

Browse files
committed
tests: rework tests for proxy controller
1 parent 134befe commit 1c7ef96

2 files changed

Lines changed: 200 additions & 77 deletions

File tree

internal/controller/proxy_controller.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,11 @@ func (controller *ProxyController) getExtAuthzContext(c *gin.Context) (ProxyCont
388388
}
389389

390390
// It sets the host to the original host, not the forwarded host
391-
host := c.Request.URL.Host
391+
host := c.Request.Host
392+
393+
if strings.TrimSpace(host) == "" {
394+
return ProxyContext{}, errors.New("host not found")
395+
}
392396

393397
// We get the path from the query string
394398
path := c.Query("path")
Lines changed: 195 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package controller_test
22

33
import (
4+
"net/http"
45
"net/http/httptest"
56
"testing"
67

@@ -9,21 +10,26 @@ import (
910
"github.com/steveiliop56/tinyauth/internal/controller"
1011
"github.com/steveiliop56/tinyauth/internal/repository"
1112
"github.com/steveiliop56/tinyauth/internal/service"
12-
"github.com/steveiliop56/tinyauth/internal/utils/tlog"
1313

1414
"github.com/gin-gonic/gin"
1515
"gotest.tools/v3/assert"
1616
)
1717

18-
func setupProxyController(t *testing.T, middlewares *[]gin.HandlerFunc) (*gin.Engine, *httptest.ResponseRecorder, *service.AuthService) {
19-
tlog.NewSimpleLogger().Init()
18+
var loggedInCtx = config.UserContext{
19+
Username: "test",
20+
Name: "Test",
21+
22+
IsLoggedIn: true,
23+
Provider: "local",
24+
}
2025

26+
func setupProxyController(t *testing.T, middlewares []gin.HandlerFunc) (*gin.Engine, *httptest.ResponseRecorder) {
2127
// Setup
2228
gin.SetMode(gin.TestMode)
2329
router := gin.Default()
2430

25-
if middlewares != nil {
26-
for _, m := range *middlewares {
31+
if len(middlewares) > 0 {
32+
for _, m := range middlewares {
2733
router.Use(m)
2834
}
2935
}
@@ -48,7 +54,13 @@ func setupProxyController(t *testing.T, middlewares *[]gin.HandlerFunc) (*gin.En
4854
assert.NilError(t, dockerService.Init())
4955

5056
// Access controls
51-
accessControlsService := service.NewAccessControlsService(dockerService, map[string]config.App{})
57+
accessControlsService := service.NewAccessControlsService(dockerService, map[string]config.App{
58+
"whoami": {
59+
Path: config.AppPath{
60+
Allow: "/allow",
61+
},
62+
},
63+
})
5264

5365
assert.NilError(t, accessControlsService.Init())
5466

@@ -77,107 +89,214 @@ func setupProxyController(t *testing.T, middlewares *[]gin.HandlerFunc) (*gin.En
7789

7890
// Controller
7991
ctrl := controller.NewProxyController(controller.ProxyControllerConfig{
80-
AppURL: "http://localhost:8080",
92+
AppURL: "http://tinyauth.example.com",
8193
}, group, accessControlsService, authService)
8294
ctrl.SetupRoutes()
8395

84-
return router, recorder, authService
96+
return router, recorder
8597
}
8698

8799
// TODO: Needs tests for context middleware
88100

89101
func TestProxyHandler(t *testing.T) {
90-
// Setup
91-
router, recorder, _ := setupProxyController(t, nil)
102+
// Test logged out user traefik/caddy (forward_auth)
103+
router, recorder := setupProxyController(t, nil)
92104

93-
// Test invalid proxy
94-
req := httptest.NewRequest("GET", "/api/auth/invalidproxy", nil)
95-
router.ServeHTTP(recorder, req)
105+
req, err := http.NewRequest("GET", "/api/auth/traefik", nil)
106+
assert.NilError(t, err)
96107

97-
assert.Equal(t, 400, recorder.Code)
108+
req.Header.Set("x-forwarded-host", "whoami.example.com")
109+
req.Header.Set("x-forwarded-proto", "http")
110+
req.Header.Set("x-forwarded-uri", "/")
98111

99-
// Test invalid method for non-envoy proxy
100-
recorder = httptest.NewRecorder()
101-
req = httptest.NewRequest("POST", "/api/auth/traefik", nil)
102112
router.ServeHTTP(recorder, req)
113+
assert.Equal(t, recorder.Code, http.StatusUnauthorized)
103114

104-
assert.Equal(t, 405, recorder.Code)
105-
assert.Equal(t, "GET", recorder.Header().Get("Allow"))
115+
// Test logged out user nginx (auth_request)
116+
router, recorder = setupProxyController(t, nil)
106117

107-
// Test logged out user (traefik/caddy)
108-
recorder = httptest.NewRecorder()
109-
req = httptest.NewRequest("GET", "/api/auth/traefik", nil)
110-
req.Header.Set("X-Forwarded-Proto", "https")
111-
req.Header.Set("X-Forwarded-Host", "example.com")
112-
req.Header.Set("X-Forwarded-Uri", "/somepath")
113-
req.Header.Set("Accept", "text/html")
114-
router.ServeHTTP(recorder, req)
118+
req, err = http.NewRequest("GET", "/api/auth/nginx", nil)
119+
assert.NilError(t, err)
115120

116-
assert.Equal(t, 307, recorder.Code)
117-
assert.Equal(t, "http://localhost:8080/login?redirect_uri=https%3A%2F%2Fexample.com%2Fsomepath", recorder.Header().Get("Location"))
121+
req.Header.Set("x-original-url", "http://whoami.example.com/")
118122

119-
// Test logged out user (envoy - POST method)
120-
recorder = httptest.NewRecorder()
121-
req = httptest.NewRequest("POST", "/api/auth/envoy", nil)
122-
req.Header.Set("X-Forwarded-Proto", "https")
123-
req.Header.Set("X-Forwarded-Host", "example.com")
124-
req.Header.Set("X-Forwarded-Uri", "/somepath")
125-
req.Header.Set("Accept", "text/html")
126123
router.ServeHTTP(recorder, req)
124+
assert.Equal(t, recorder.Code, http.StatusUnauthorized)
125+
126+
// Test logged out user envoy (ext_authz)
127+
router, recorder = setupProxyController(t, nil)
128+
129+
req, err = http.NewRequest("GET", "/api/auth/envoy?path=/", nil)
130+
assert.NilError(t, err)
127131

128-
assert.Equal(t, 307, recorder.Code)
129-
assert.Equal(t, "http://localhost:8080/login?redirect_uri=https%3A%2F%2Fexample.com%2Fsomepath", recorder.Header().Get("Location"))
132+
req.Host = "whoami.example.com"
133+
req.Header.Set("x-forwarded-proto", "http")
130134

131-
// Test logged out user (envoy - DELETE method)
132-
recorder = httptest.NewRecorder()
133-
req = httptest.NewRequest("DELETE", "/api/auth/envoy", nil)
134-
req.Header.Set("X-Forwarded-Proto", "https")
135-
req.Header.Set("X-Forwarded-Host", "example.com")
136-
req.Header.Set("X-Forwarded-Uri", "/somepath")
137-
req.Header.Set("Accept", "text/html")
138135
router.ServeHTTP(recorder, req)
136+
assert.Equal(t, recorder.Code, http.StatusUnauthorized)
139137

140-
assert.Equal(t, 307, recorder.Code)
141-
assert.Equal(t, "http://localhost:8080/login?redirect_uri=https%3A%2F%2Fexample.com%2Fsomepath", recorder.Header().Get("Location"))
138+
// Test logged in user traefik/caddy (forward_auth)
139+
router, recorder = setupProxyController(t, []gin.HandlerFunc{
140+
func(c *gin.Context) {
141+
c.Set("context", &loggedInCtx)
142+
c.Next()
143+
},
144+
})
145+
146+
req, err = http.NewRequest("GET", "/api/auth/traefik", nil)
147+
assert.NilError(t, err)
148+
149+
req.Header.Set("x-forwarded-host", "whoami.example.com")
150+
req.Header.Set("x-forwarded-proto", "http")
151+
req.Header.Set("x-forwarded-uri", "/")
142152

143-
// Test logged out user (nginx)
144-
recorder = httptest.NewRecorder()
145-
req = httptest.NewRequest("GET", "/api/auth/nginx", nil)
146-
req.Header.Set("X-Forwarded-Proto", "https")
147-
req.Header.Set("X-Forwarded-Host", "example.com")
148-
// we won't set X-Forwarded-Uri to test that the controller can work without it
149153
router.ServeHTTP(recorder, req)
154+
assert.Equal(t, recorder.Code, http.StatusOK)
150155

151-
assert.Equal(t, 401, recorder.Code)
156+
// Test logged in user nginx (auth_request)
157+
router, recorder = setupProxyController(t, []gin.HandlerFunc{
158+
func(c *gin.Context) {
159+
c.Set("context", &loggedInCtx)
160+
c.Next()
161+
},
162+
})
163+
164+
req, err = http.NewRequest("GET", "/api/auth/nginx", nil)
165+
assert.NilError(t, err)
166+
167+
req.Header.Set("x-original-url", "http://whoami.example.com/")
168+
169+
router.ServeHTTP(recorder, req)
170+
assert.Equal(t, recorder.Code, http.StatusOK)
152171

153-
// Test logged in user
154-
router, recorder, _ = setupProxyController(t, &[]gin.HandlerFunc{
172+
// Test logged in user envoy (ext_authz)
173+
router, recorder = setupProxyController(t, []gin.HandlerFunc{
155174
func(c *gin.Context) {
156-
c.Set("context", &config.UserContext{
157-
Username: "testuser",
158-
Name: "testuser",
159-
160-
IsLoggedIn: true,
161-
OAuth: false,
162-
Provider: "local",
163-
TotpPending: false,
164-
OAuthGroups: "",
165-
TotpEnabled: false,
166-
})
175+
c.Set("context", &loggedInCtx)
167176
c.Next()
168177
},
169178
})
170179

171-
req = httptest.NewRequest("GET", "/api/auth/traefik", nil)
172-
req.Header.Set("X-Forwarded-Proto", "https")
173-
req.Header.Set("X-Forwarded-Host", "example.com")
174-
req.Header.Set("X-Original-Uri", "/somepath") // Test with original URI for kubernetes ingress
175-
req.Header.Set("Accept", "text/html")
180+
req, err = http.NewRequest("GET", "/api/auth/envoy?path=/", nil)
181+
assert.NilError(t, err)
182+
183+
req.Host = "whoami.example.com"
184+
req.Header.Set("x-forwarded-proto", "http")
185+
186+
router.ServeHTTP(recorder, req)
187+
assert.Equal(t, recorder.Code, http.StatusOK)
188+
189+
// Test ACL allow caddy/traefik (forward_auth)
190+
router, recorder = setupProxyController(t, nil)
191+
192+
req, err = http.NewRequest("GET", "/api/auth/traefik", nil)
193+
assert.NilError(t, err)
194+
195+
req.Header.Set("x-forwarded-host", "whoami.example.com")
196+
req.Header.Set("x-forwarded-proto", "http")
197+
req.Header.Set("x-forwarded-uri", "/allow")
198+
199+
router.ServeHTTP(recorder, req)
200+
assert.Equal(t, recorder.Code, http.StatusOK)
201+
202+
// Test ACL allow nginx
203+
router, recorder = setupProxyController(t, nil)
204+
205+
req, err = http.NewRequest("GET", "/api/auth/nginx", nil)
206+
assert.NilError(t, err)
207+
208+
req.Header.Set("x-original-url", "http://whoami.example.com/allow")
209+
210+
router.ServeHTTP(recorder, req)
211+
assert.Equal(t, recorder.Code, http.StatusOK)
212+
213+
// Test ACL allow envoy
214+
router, recorder = setupProxyController(t, nil)
215+
216+
req, err = http.NewRequest("GET", "/api/auth/envoy?path=/allow", nil)
217+
assert.NilError(t, err)
218+
219+
req.Host = "whoami.example.com"
220+
req.Header.Set("x-forwarded-proto", "http")
221+
222+
router.ServeHTTP(recorder, req)
223+
assert.Equal(t, recorder.Code, http.StatusOK)
224+
225+
// Test traefik/caddy (forward_auth) without required headers
226+
router, recorder = setupProxyController(t, nil)
227+
228+
req, err = http.NewRequest("GET", "/api/auth/traefik", nil)
229+
assert.NilError(t, err)
230+
231+
router.ServeHTTP(recorder, req)
232+
assert.Equal(t, recorder.Code, http.StatusBadRequest)
233+
234+
// Test nginx (forward_auth) without required headers
235+
router, recorder = setupProxyController(t, nil)
236+
237+
req, err = http.NewRequest("GET", "/api/auth/nginx", nil)
238+
assert.NilError(t, err)
176239

177240
router.ServeHTTP(recorder, req)
178-
assert.Equal(t, 200, recorder.Code)
241+
assert.Equal(t, recorder.Code, http.StatusBadRequest)
242+
243+
// Test envoy (forward_auth) without required headers
244+
router, recorder = setupProxyController(t, nil)
179245

180-
assert.Equal(t, "testuser", recorder.Header().Get("Remote-User"))
181-
assert.Equal(t, "testuser", recorder.Header().Get("Remote-Name"))
182-
assert.Equal(t, "[email protected]", recorder.Header().Get("Remote-Email"))
246+
req, err = http.NewRequest("GET", "/api/auth/envoy", nil)
247+
assert.NilError(t, err)
248+
249+
router.ServeHTTP(recorder, req)
250+
assert.Equal(t, recorder.Code, http.StatusBadRequest)
251+
252+
// Test nginx (auth_request) with forward_auth fallback with ACLs
253+
router, recorder = setupProxyController(t, nil)
254+
255+
req, err = http.NewRequest("GET", "/api/auth/nginx", nil)
256+
assert.NilError(t, err)
257+
258+
req.Header.Set("x-forwarded-host", "whoami.example.com")
259+
req.Header.Set("x-forwarded-proto", "http")
260+
req.Header.Set("x-forwarded-uri", "/allow")
261+
262+
router.ServeHTTP(recorder, req)
263+
assert.Equal(t, recorder.Code, http.StatusOK)
264+
265+
// Test envoy (ext_authz) with forward_auth fallback with ACLs
266+
router, recorder = setupProxyController(t, nil)
267+
268+
req, err = http.NewRequest("GET", "/api/auth/envoy", nil)
269+
assert.NilError(t, err)
270+
271+
req.Header.Set("x-forwarded-host", "whoami.example.com")
272+
req.Header.Set("x-forwarded-proto", "http")
273+
req.Header.Set("x-forwarded-uri", "/allow")
274+
275+
router.ServeHTTP(recorder, req)
276+
assert.Equal(t, recorder.Code, http.StatusOK)
277+
278+
// Test envoy (ext_authz) with empty path
279+
router, recorder = setupProxyController(t, nil)
280+
281+
req, err = http.NewRequest("GET", "/api/auth/envoy", nil)
282+
assert.NilError(t, err)
283+
284+
req.Host = "whoami.example.com"
285+
req.Header.Set("x-forwarded-proto", "http")
286+
287+
router.ServeHTTP(recorder, req)
288+
assert.Equal(t, recorder.Code, http.StatusUnauthorized)
289+
290+
// Ensure forward_auth fallback works with path (should ignore)
291+
router, recorder = setupProxyController(t, nil)
292+
293+
req, err = http.NewRequest("GET", "/api/auth/traefik?path=/allow", nil)
294+
assert.NilError(t, err)
295+
296+
req.Header.Set("x-forwarded-proto", "http")
297+
req.Header.Set("x-forwarded-host", "whoami.example.com")
298+
req.Header.Set("x-forwarded-uri", "/allow")
299+
300+
router.ServeHTTP(recorder, req)
301+
assert.Equal(t, recorder.Code, http.StatusOK)
183302
}

0 commit comments

Comments
 (0)