Skip to content

Commit

Permalink
Check role permissions based on the resource, not the role
Browse files Browse the repository at this point in the history
One of the quirks of our current role model is that roles don't belong
to a resource outright - instead, their binding to a resource is
inferred by the actions that can be performed. This means that we
can't use the role itself to make authorization decisions. This commit
updates permissions checks for roles to use the role's resource rather
than the role itself for checking permissions.

Signed-off-by: John Schaeffer <[email protected]>
  • Loading branch information
jnschaeffer committed Sep 6, 2023
1 parent a1071c8 commit 5baa948
Showing 1 changed file with 24 additions and 6 deletions.
30 changes: 24 additions & 6 deletions internal/api/roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,16 @@ func (r *Router) roleGet(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, "error getting resource").SetInternal(err)
}

if err := r.checkActionWithResponse(ctx, subjectResource, actionRoleGet, roleResource); err != nil {
// Roles belong to resources by way of the actions they can perform; do the permissions
// check on the role resource.
resource, err := r.engine.GetRoleResource(ctx, roleResource, "")
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "error getting resource").SetInternal(err)
}

// TODO: This shows an error for the role's resource, not the role. Determine if that
// matters.
if err := r.checkActionWithResponse(ctx, subjectResource, actionRoleGet, resource); err != nil {
return err
}

Expand Down Expand Up @@ -167,7 +176,14 @@ func (r *Router) roleDelete(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, "error deleting resource").SetInternal(err)
}

if err := r.checkActionWithResponse(ctx, subjectResource, actionRoleDelete, roleResource); err != nil {
// Roles belong to resources by way of the actions they can perform; do the permissions
// check on the role resource.
resource, err := r.engine.GetRoleResource(ctx, roleResource, "")
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "error getting resource").SetInternal(err)
}

if err := r.checkActionWithResponse(ctx, subjectResource, actionRoleDelete, resource); err != nil {
return err
}

Expand Down Expand Up @@ -204,15 +220,17 @@ func (r *Router) roleGetResource(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, "error getting resource").SetInternal(err)
}

if err := r.checkActionWithResponse(ctx, subjectResource, actionRoleGet, roleResource); err != nil {
return err
}

// There's a little irony here in that getting a role's resource here is required to actually
// do the permissions check.
resource, err := r.engine.GetRoleResource(ctx, roleResource, "")
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "error getting resource").SetInternal(err)
}

if err := r.checkActionWithResponse(ctx, subjectResource, actionRoleGet, resource); err != nil {
return err
}

resp := resourceResponse{
ID: resource.ID,
}
Expand Down

0 comments on commit 5baa948

Please sign in to comment.