feat: Add initial AuthzQuerier implementation (#5919)

feat: Add initial AuthzQuerier implementation
- Adds package database/dbauthz that adds a database.Store implementation where each method goes through AuthZ checks
- Implements all database.Store methods on AuthzQuerier
- Updates and fixes unit tests where required
- Updates coderd initialization to use AuthzQuerier if codersdk.ExperimentAuthzQuerier is enabled
This commit is contained in:
Steven Masley
2023-02-14 08:27:06 -06:00
committed by GitHub
parent ebdfdc749d
commit 6fb8aff6d0
59 changed files with 5013 additions and 136 deletions

View File

@ -16,6 +16,7 @@ import (
"github.com/coder/coder/coderd/audit"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/database/dbauthz"
"github.com/coder/coder/coderd/gitsshkey"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/httpmw"
@ -37,7 +38,8 @@ import (
// @Router /users/first [get]
func (api *API) firstUser(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
userCount, err := api.Database.GetUserCount(ctx)
//nolint:gocritic // needed for first user check
userCount, err := api.Database.GetUserCount(dbauthz.AsSystem(ctx))
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user count.",
@ -70,6 +72,7 @@ func (api *API) firstUser(rw http.ResponseWriter, r *http.Request) {
// @Success 201 {object} codersdk.CreateFirstUserResponse
// @Router /users/first [post]
func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
// TODO: Should this admin system context be in a middleware?
ctx := r.Context()
var createUser codersdk.CreateFirstUserRequest
if !httpapi.Read(ctx, rw, r, &createUser) {
@ -77,7 +80,8 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
}
// This should only function for the first user.
userCount, err := api.Database.GetUserCount(ctx)
//nolint:gocritic // needed to create first user
userCount, err := api.Database.GetUserCount(dbauthz.AsSystem(ctx))
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user count.",
@ -117,7 +121,8 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
return
}
user, organizationID, err := api.CreateUser(ctx, api.Database, CreateUserRequest{
//nolint:gocritic // needed to create first user
user, organizationID, err := api.CreateUser(dbauthz.AsSystem(ctx), api.Database, CreateUserRequest{
CreateUserRequest: codersdk.CreateUserRequest{
Email: createUser.Email,
Username: createUser.Username,
@ -146,7 +151,8 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
// the user. Maybe I add this ability to grant roles in the createUser api
// and add some rbac bypass when calling api functions this way??
// Add the admin role to this first user.
_, err = api.Database.UpdateUserRoles(ctx, database.UpdateUserRolesParams{
//nolint:gocritic // needed to create first user
_, err = api.Database.UpdateUserRoles(dbauthz.AsSystem(ctx), database.UpdateUserRolesParams{
GrantedRoles: []string{rbac.RoleOwner()},
ID: user.ID,
})
@ -987,7 +993,7 @@ func (api *API) organizationByUserAndName(rw http.ResponseWriter, r *http.Reques
ctx := r.Context()
organizationName := chi.URLParam(r, "organizationname")
organization, err := api.Database.GetOrganizationByName(ctx, organizationName)
if errors.Is(err, sql.ErrNoRows) {
if errors.Is(err, sql.ErrNoRows) || rbac.IsUnauthorizedError(err) {
httpapi.ResourceNotFound(rw)
return
}