satellite/{consoleweb,consoleapi}: add cross user api tests
This change adds tests to ensure critical endpoints are not able to be called by users for other users. It asserts that if cases like that do happen, a 401 response will be sent. Issue: https://github.com/storj/storj-private/issues/407 Change-Id: I70097a80f691a7d0fcb0bc5dbce8291144177720
This commit is contained in:
parent
5c155752d2
commit
fe9f69a757
@ -67,7 +67,7 @@ func (keys *APIKeys) CreateAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
info, key, err := keys.service.CreateAPIKey(ctx, projectID, name)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
if console.ErrUnauthorized.Has(err) || console.ErrNoMembership.Has(err) {
|
||||
keys.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
@ -262,6 +262,10 @@ func (p *Projects) GetMembersAndInvitations(w http.ResponseWriter, r *http.Reque
|
||||
|
||||
project, err := p.service.GetProject(ctx, publicID)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) || console.ErrNoMembership.Has(err) {
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
@ -424,6 +428,10 @@ func (p *Projects) InviteUsers(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
_, err = p.service.InviteProjectMembers(ctx, id, data.Emails)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) || console.ErrNoMembership.Has(err) {
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
}
|
||||
@ -590,6 +598,10 @@ func (p *Projects) DeleteMembersAndInvitations(w http.ResponseWriter, r *http.Re
|
||||
|
||||
err = p.service.DeleteProjectMembersAndInvitations(ctx, id, emails)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) || console.ErrNoMembership.Has(err) {
|
||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ func (ul *UsageLimits) ProjectUsageLimits(w http.ResponseWriter, r *http.Request
|
||||
usageLimits, err := ul.service.GetProjectUsageLimits(ctx, projectID)
|
||||
if err != nil {
|
||||
switch {
|
||||
case console.ErrUnauthorized.Has(err):
|
||||
case console.ErrUnauthorized.Has(err) || console.ErrNoMembership.Has(err):
|
||||
ul.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
case accounting.ErrInvalidArgument.Has(err):
|
||||
@ -140,7 +140,7 @@ func (ul *UsageLimits) DailyUsage(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
dailyUsage, err := ul.service.GetDailyProjectUsage(ctx, projectID, since, before)
|
||||
if err != nil {
|
||||
if console.ErrUnauthorized.Has(err) {
|
||||
if console.ErrUnauthorized.Has(err) || console.ErrNoMembership.Has(err) {
|
||||
ul.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
@ -500,16 +500,80 @@ func TestWrongUser(t *testing.T) {
|
||||
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 1,
|
||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||
test := newTest(t, ctx, planet)
|
||||
user := test.defaultUser()
|
||||
_ = user
|
||||
user2 := test.registerUser("user@mail.test", "#$Rnkl12i3nkljfds")
|
||||
test.login(user2.email, user2.password)
|
||||
authorizedUser := test.defaultUser()
|
||||
unauthorizedUser := test.registerUser("user@mail.test", "#$Rnkl12i3nkljfds")
|
||||
test.login(unauthorizedUser.email, unauthorizedUser.password)
|
||||
|
||||
{ // Get_ProjectUsageLimitById
|
||||
resp, body := test.request(http.MethodGet, `/projects/`+test.defaultProjectID()+`/usage-limits`, nil)
|
||||
require.Contains(t, body, "not authorized")
|
||||
// TODO: wrong error code
|
||||
require.Equal(t, http.StatusInternalServerError, resp.StatusCode)
|
||||
type endpointTest struct {
|
||||
endpoint string
|
||||
method string
|
||||
body interface{}
|
||||
}
|
||||
|
||||
baseProjectsUrl := "/projects"
|
||||
baseProjectIdUrl := fmt.Sprintf("%s/%s", baseProjectsUrl, test.defaultProjectID())
|
||||
getProjectResourceUrl := func(resource string) string {
|
||||
return fmt.Sprintf("%s/%s", baseProjectIdUrl, resource)
|
||||
}
|
||||
|
||||
testCases := []endpointTest{
|
||||
{
|
||||
endpoint: baseProjectIdUrl,
|
||||
method: http.MethodPatch,
|
||||
body: map[string]interface{}{
|
||||
"name": "new name",
|
||||
},
|
||||
},
|
||||
{
|
||||
endpoint: getProjectResourceUrl("members") + "?emails=" + "some@email.com",
|
||||
method: http.MethodDelete,
|
||||
},
|
||||
{
|
||||
endpoint: getProjectResourceUrl("salt"),
|
||||
method: http.MethodGet,
|
||||
},
|
||||
{
|
||||
endpoint: getProjectResourceUrl("members"),
|
||||
method: http.MethodGet,
|
||||
},
|
||||
{
|
||||
endpoint: getProjectResourceUrl("invite"),
|
||||
method: http.MethodPost,
|
||||
body: map[string]interface{}{
|
||||
"emails": []string{"some@email.com"},
|
||||
},
|
||||
},
|
||||
{
|
||||
endpoint: getProjectResourceUrl("usage-limits"),
|
||||
method: http.MethodGet,
|
||||
},
|
||||
{
|
||||
endpoint: getProjectResourceUrl("daily-usage") + "?from=100000000&to=200000000000",
|
||||
method: http.MethodGet,
|
||||
},
|
||||
{
|
||||
endpoint: "/api-keys/create/" + test.defaultProjectID(),
|
||||
method: http.MethodPost,
|
||||
body: "name",
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(fmt.Sprintf("Unauthorized on %s", testCase.endpoint), func(t *testing.T) {
|
||||
resp, body := test.request(testCase.method, testCase.endpoint, test.toJSON(testCase.body))
|
||||
require.Contains(t, body, "not authorized")
|
||||
require.Equal(t, http.StatusUnauthorized, resp.StatusCode)
|
||||
})
|
||||
}
|
||||
|
||||
// login with correct user to make sure they have access.
|
||||
test.login(authorizedUser.email, authorizedUser.password)
|
||||
for _, testCase := range testCases {
|
||||
t.Run(fmt.Sprintf("Authorized on %s", testCase.endpoint), func(t *testing.T) {
|
||||
resp, body := test.request(testCase.method, testCase.endpoint, test.toJSON(testCase.body))
|
||||
require.NotContains(t, body, "not authorized")
|
||||
require.NotEqual(t, http.StatusUnauthorized, resp.StatusCode)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user