Skip to content

Commit 1404861

Browse files
authored
test: add regression tests for API.Authorizations (#11060)
1 parent c7eda21 commit 1404861

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed

test/cli/rpc_auth_test.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,127 @@ func TestRPCAuth(t *testing.T) {
159159

160160
node.StopDaemon()
161161
})
162+
163+
t.Run("Requests without Authorization header are rejected when auth is enabled", func(t *testing.T) {
164+
t.Parallel()
165+
166+
node := makeAndStartProtectedNode(t, map[string]*config.RPCAuthScope{
167+
"userA": {
168+
AuthSecret: "bearer:mytoken",
169+
AllowedPaths: []string{"/api/v0"},
170+
},
171+
})
172+
173+
// Create client with NO auth
174+
apiClient := node.APIClient() // Uses http.DefaultClient with no auth headers
175+
176+
// Should be denied without auth header
177+
resp := apiClient.Post("/api/v0/id", nil)
178+
assert.Equal(t, 403, resp.StatusCode)
179+
180+
// Should contain denial message
181+
assert.Contains(t, resp.Body, rpcDeniedMsg)
182+
183+
node.StopDaemon()
184+
})
185+
186+
t.Run("Version endpoint is always accessible even with limited AllowedPaths", func(t *testing.T) {
187+
t.Parallel()
188+
189+
node := makeAndStartProtectedNode(t, map[string]*config.RPCAuthScope{
190+
"userA": {
191+
AuthSecret: "bearer:mytoken",
192+
AllowedPaths: []string{"/api/v0/id"}, // Only /id allowed
193+
},
194+
})
195+
196+
apiClient := node.APIClient()
197+
apiClient.Client = &http.Client{
198+
Transport: auth.NewAuthorizedRoundTripper("Bearer mytoken", http.DefaultTransport),
199+
}
200+
201+
// Can access /version even though not in AllowedPaths
202+
resp := apiClient.Post("/api/v0/version", nil)
203+
assert.Equal(t, 200, resp.StatusCode)
204+
205+
node.StopDaemon()
206+
})
207+
208+
t.Run("User cannot access API with another user's secret", func(t *testing.T) {
209+
t.Parallel()
210+
211+
node := makeAndStartProtectedNode(t, map[string]*config.RPCAuthScope{
212+
"alice": {
213+
AuthSecret: "bearer:alice-secret",
214+
AllowedPaths: []string{"/api/v0/id"},
215+
},
216+
"bob": {
217+
AuthSecret: "bearer:bob-secret",
218+
AllowedPaths: []string{"/api/v0/config"},
219+
},
220+
})
221+
222+
// Alice tries to use Bob's secret
223+
apiClient := node.APIClient()
224+
apiClient.Client = &http.Client{
225+
Transport: auth.NewAuthorizedRoundTripper("Bearer bob-secret", http.DefaultTransport),
226+
}
227+
228+
// Bob's secret should work for Bob's paths
229+
resp := apiClient.Post("/api/v0/config/show", nil)
230+
assert.Equal(t, 200, resp.StatusCode)
231+
232+
// But not for Alice's paths (Bob doesn't have access to /id)
233+
resp = apiClient.Post("/api/v0/id", nil)
234+
assert.Equal(t, 403, resp.StatusCode)
235+
236+
node.StopDaemon()
237+
})
238+
239+
t.Run("Empty AllowedPaths denies all access except version", func(t *testing.T) {
240+
t.Parallel()
241+
242+
node := makeAndStartProtectedNode(t, map[string]*config.RPCAuthScope{
243+
"userA": {
244+
AuthSecret: "bearer:mytoken",
245+
AllowedPaths: []string{}, // Empty!
246+
},
247+
})
248+
249+
apiClient := node.APIClient()
250+
apiClient.Client = &http.Client{
251+
Transport: auth.NewAuthorizedRoundTripper("Bearer mytoken", http.DefaultTransport),
252+
}
253+
254+
// Should deny everything
255+
resp := apiClient.Post("/api/v0/id", nil)
256+
assert.Equal(t, 403, resp.StatusCode)
257+
258+
resp = apiClient.Post("/api/v0/config/show", nil)
259+
assert.Equal(t, 403, resp.StatusCode)
260+
261+
// Except version
262+
resp = apiClient.Post("/api/v0/version", nil)
263+
assert.Equal(t, 200, resp.StatusCode)
264+
265+
node.StopDaemon()
266+
})
267+
268+
t.Run("CLI commands fail without --api-auth when auth is enabled", func(t *testing.T) {
269+
t.Parallel()
270+
271+
node := makeAndStartProtectedNode(t, map[string]*config.RPCAuthScope{
272+
"userA": {
273+
AuthSecret: "bearer:mytoken",
274+
AllowedPaths: []string{"/api/v0"},
275+
},
276+
})
277+
278+
// Try to run command without --api-auth flag
279+
resp := node.RunIPFS("id") // No --api-auth flag
280+
require.Error(t, resp.Err)
281+
require.Contains(t, resp.Stderr.String(), rpcDeniedMsg)
282+
283+
node.StopDaemon()
284+
})
162285
}

0 commit comments

Comments
 (0)