coder/coderd/httpmw/authz_test.go

98 lines
2.7 KiB
Go

package httpmw_test
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/go-chi/chi/v5"
"github.com/stretchr/testify/assert"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database/dbauthz"
"github.com/coder/coder/v2/coderd/httpmw"
)
func TestAsAuthzSystem(t *testing.T) {
t.Parallel()
userActor := coderdtest.RandomRBACSubject()
base := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
actor, ok := dbauthz.ActorFromContext(r.Context())
assert.True(t, ok, "actor should exist")
assert.True(t, userActor.Equal(actor), "actor should be the user actor")
})
mwSetUser := func(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
r = r.WithContext(dbauthz.As(r.Context(), userActor))
next.ServeHTTP(rw, r)
})
}
mwAssertSystem := mwAssert(func(req *http.Request) {
actor, ok := dbauthz.ActorFromContext(req.Context())
assert.True(t, ok, "actor should exist")
assert.False(t, userActor.Equal(actor), "systemActor should not be the user actor")
assert.Contains(t, actor.Roles.Names(), "system", "should have system role")
})
mwAssertUser := mwAssert(func(req *http.Request) {
actor, ok := dbauthz.ActorFromContext(req.Context())
assert.True(t, ok, "actor should exist")
assert.True(t, userActor.Equal(actor), "should be the useractor")
})
mwAssertNoUser := mwAssert(func(req *http.Request) {
_, ok := dbauthz.ActorFromContext(req.Context())
assert.False(t, ok, "actor should not exist")
})
// Request as the user actor
const pattern = "/"
req := httptest.NewRequest("GET", pattern, nil)
res := httptest.NewRecorder()
handler := chi.NewRouter()
handler.Route(pattern, func(r chi.Router) {
r.Use(
// First assert there is no actor context
mwAssertNoUser,
httpmw.AsAuthzSystem(
// Assert the system actor
mwAssertSystem,
mwAssertSystem,
),
// Assert no user present outside of the AsAuthzSystem chain
mwAssertNoUser,
// ----
// Set to the user actor
mwSetUser,
// Assert the user actor
mwAssertUser,
httpmw.AsAuthzSystem(
// Assert the system actor
mwAssertSystem,
mwAssertSystem,
),
// Check the user actor was returned to the context
mwAssertUser,
)
r.Handle("/", base)
r.NotFound(func(writer http.ResponseWriter, request *http.Request) {
assert.Fail(t, "should not hit not found, the route should be correct")
})
})
handler.ServeHTTP(res, req)
}
func mwAssert(assertF func(req *http.Request)) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
assertF(r)
next.ServeHTTP(rw, r)
})
}
}