refactor: consolidate template and workspace acl validation (#19192)

This commit is contained in:
ケイラ
2025-08-07 10:14:58 -06:00
committed by GitHub
parent 02de067d46
commit 26458cd6f0
14 changed files with 535 additions and 103 deletions
+18 -46
View File
@@ -32,6 +32,7 @@ import (
"github.com/coder/coder/v2/coderd/notifications"
"github.com/coder/coder/v2/coderd/prebuilds"
"github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/coderd/rbac/acl"
"github.com/coder/coder/v2/coderd/rbac/policy"
"github.com/coder/coder/v2/coderd/schedule"
"github.com/coder/coder/v2/coderd/schedule/cron"
@@ -2086,17 +2087,10 @@ func (api *API) patchWorkspaceACL(rw http.ResponseWriter, r *http.Request) {
return
}
validErrs := validateWorkspaceACLPerms(ctx, api.Database, req.UserRoles, "user_roles")
validErrs = append(validErrs, validateWorkspaceACLPerms(
ctx,
api.Database,
req.GroupRoles,
"group_roles",
)...)
validErrs := acl.Validate(ctx, api.Database, WorkspaceACLUpdateValidator(req))
if len(validErrs) > 0 {
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid request to update template metadata!",
Message: "Invalid request to update workspace ACL",
Validations: validErrs,
})
return
@@ -2492,50 +2486,28 @@ func (api *API) publishWorkspaceAgentLogsUpdate(ctx context.Context, workspaceAg
}
}
func validateWorkspaceACLPerms(ctx context.Context, db database.Store, perms map[string]codersdk.WorkspaceRole, field string) []codersdk.ValidationError {
// nolint:gocritic // Validate requires full read access to users and groups
ctx = dbauthz.AsSystemRestricted(ctx)
var validErrs []codersdk.ValidationError
for idStr, role := range perms {
if err := validateWorkspaceRole(role); err != nil {
validErrs = append(validErrs, codersdk.ValidationError{Field: field, Detail: err.Error()})
continue
}
type WorkspaceACLUpdateValidator codersdk.UpdateWorkspaceACL
id, err := uuid.Parse(idStr)
if err != nil {
validErrs = append(validErrs, codersdk.ValidationError{Field: field, Detail: idStr + "is not a valid UUID."})
continue
}
var (
workspaceACLUpdateUsersFieldName = "user_roles"
workspaceACLUpdateGroupsFieldName = "group_roles"
)
switch field {
case "user_roles":
// TODO(lilac): put this back after Kirby button shenanigans are over
// This could get slow if we get a ton of user perm updates.
// _, err = db.GetUserByID(ctx, id)
// if err != nil {
// validErrs = append(validErrs, codersdk.ValidationError{Field: field, Detail: fmt.Sprintf("Failed to find resource with ID %q: %v", idStr, err.Error())})
// continue
// }
case "group_roles":
// This could get slow if we get a ton of group perm updates.
_, err = db.GetGroupByID(ctx, id)
if err != nil {
validErrs = append(validErrs, codersdk.ValidationError{Field: field, Detail: fmt.Sprintf("Failed to find resource with ID %q: %v", idStr, err.Error())})
continue
}
default:
validErrs = append(validErrs, codersdk.ValidationError{Field: field, Detail: "invalid field"})
}
}
// WorkspaceACLUpdateValidator implements acl.UpdateValidator[codersdk.WorkspaceRole]
var _ acl.UpdateValidator[codersdk.WorkspaceRole] = WorkspaceACLUpdateValidator{}
return validErrs
func (w WorkspaceACLUpdateValidator) Users() (map[string]codersdk.WorkspaceRole, string) {
return w.UserRoles, workspaceACLUpdateUsersFieldName
}
func validateWorkspaceRole(role codersdk.WorkspaceRole) error {
func (w WorkspaceACLUpdateValidator) Groups() (map[string]codersdk.WorkspaceRole, string) {
return w.GroupRoles, workspaceACLUpdateGroupsFieldName
}
func (WorkspaceACLUpdateValidator) ValidateRole(role codersdk.WorkspaceRole) error {
actions := db2sdk.WorkspaceRoleActions(role)
if len(actions) == 0 && role != codersdk.WorkspaceRoleDeleted {
return xerrors.Errorf("role %q is not a valid Workspace role", role)
return xerrors.Errorf("role %q is not a valid workspace role", role)
}
return nil