Skip to content

Commit db80b4d

Browse files
committed
feat: POC for allowing TemplateAdmin to delete prebuild workspaces via auth layer
1 parent af4a668 commit db80b4d

File tree

15 files changed

+218
-20
lines changed

15 files changed

+218
-20
lines changed

coderd/apidoc/docs.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbauthz/dbauthz.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,9 @@ var (
412412
policy.ActionCreate, policy.ActionDelete, policy.ActionRead, policy.ActionUpdate,
413413
policy.ActionWorkspaceStart, policy.ActionWorkspaceStop,
414414
},
415+
rbac.ResourcePrebuiltWorkspace.Type: {
416+
policy.ActionRead, policy.ActionUpdate, policy.ActionDelete,
417+
},
415418
// Should be able to add the prebuilds system user as a member to any organization that needs prebuilds.
416419
rbac.ResourceOrganizationMember.Type: {
417420
policy.ActionCreate,
@@ -3909,7 +3912,14 @@ func (q *querier) InsertWorkspaceBuild(ctx context.Context, arg database.InsertW
39093912
action = policy.ActionWorkspaceStop
39103913
}
39113914

3912-
if err = q.authorizeContext(ctx, action, w); err != nil {
3915+
if action == policy.ActionDelete && w.IsPrebuild() {
3916+
if err := q.authorizeContext(ctx, action, w.PrebuildRBAC()); err != nil {
3917+
// Fallback to normal workspace auth check
3918+
if err = q.authorizeContext(ctx, action, w); err != nil {
3919+
return xerrors.Errorf("authorize context: %w", err)
3920+
}
3921+
}
3922+
} else if err = q.authorizeContext(ctx, action, w); err != nil {
39133923
return xerrors.Errorf("authorize context: %w", err)
39143924
}
39153925

@@ -3927,7 +3937,14 @@ func (q *querier) InsertWorkspaceBuild(ctx context.Context, arg database.InsertW
39273937
// to use a non-active version then we must fail the request.
39283938
if accessControl.RequireActiveVersion {
39293939
if arg.TemplateVersionID != t.ActiveVersionID {
3930-
if err = q.authorizeContext(ctx, policy.ActionUpdate, t); err != nil {
3940+
if w.IsPrebuild() {
3941+
if err := q.authorizeContext(ctx, policy.ActionUpdate, w.PrebuildRBAC()); err != nil {
3942+
// Fallback to normal workspace auth check
3943+
if err = q.authorizeContext(ctx, policy.ActionUpdate, t); err != nil {
3944+
return xerrors.Errorf("cannot use non-active version: %w", err)
3945+
}
3946+
}
3947+
} else if err = q.authorizeContext(ctx, policy.ActionUpdate, t); err != nil {
39313948
return xerrors.Errorf("cannot use non-active version: %w", err)
39323949
}
39333950
}
@@ -3949,7 +3966,15 @@ func (q *querier) InsertWorkspaceBuildParameters(ctx context.Context, arg databa
39493966
return err
39503967
}
39513968

3952-
err = q.authorizeContext(ctx, policy.ActionUpdate, workspace)
3969+
if workspace.IsPrebuild() {
3970+
err = q.authorizeContext(ctx, policy.ActionUpdate, workspace.PrebuildRBAC())
3971+
// Fallback to normal workspace auth check
3972+
if err != nil {
3973+
err = q.authorizeContext(ctx, policy.ActionUpdate, workspace)
3974+
}
3975+
} else {
3976+
err = q.authorizeContext(ctx, policy.ActionUpdate, workspace)
3977+
}
39533978
if err != nil {
39543979
return err
39553980
}

coderd/database/modelmethods.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,26 @@ func (w Workspace) WorkspaceTable() WorkspaceTable {
226226
}
227227

228228
func (w Workspace) RBACObject() rbac.Object {
229+
// if w.IsPrebuild() {
230+
// return w.PrebuildRBAC()
231+
//}
229232
return w.WorkspaceTable().RBACObject()
230233
}
231234

235+
func (w Workspace) IsPrebuild() bool {
236+
// TODO: avoid import cycle
237+
return w.OwnerID == uuid.MustParse("c42fdf75-3097-471c-8c33-fb52454d81c0")
238+
}
239+
240+
func (w Workspace) PrebuildRBAC() rbac.Object {
241+
if w.IsPrebuild() {
242+
return rbac.ResourcePrebuiltWorkspace.WithID(w.ID).
243+
InOrg(w.OrganizationID).
244+
WithOwner(w.OwnerID.String())
245+
}
246+
return w.RBACObject()
247+
}
248+
232249
func (w WorkspaceTable) RBACObject() rbac.Object {
233250
if w.DormantAt.Valid {
234251
return w.DormantRBAC()

coderd/rbac/object_gen.go

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/rbac/policy/policy.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ var RBACPermissions = map[string]PermissionDefinition{
102102
"workspace_dormant": {
103103
Actions: workspaceActions,
104104
},
105+
"prebuilt_workspace": {
106+
Actions: map[Action]ActionDefinition{
107+
ActionRead: actDef("read prebuilt workspace"),
108+
ActionUpdate: actDef("update prebuilt workspace"),
109+
ActionDelete: actDef("delete prebuilt workspace"),
110+
},
111+
},
105112
"workspace_proxy": {
106113
Actions: map[Action]ActionDefinition{
107114
ActionCreate: actDef("create a workspace proxy"),

coderd/rbac/roles.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,9 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
335335
ResourceAssignOrgRole.Type: {policy.ActionRead},
336336
ResourceTemplate.Type: ResourceTemplate.AvailableActions(),
337337
// CRUD all files, even those they did not upload.
338-
ResourceFile.Type: {policy.ActionCreate, policy.ActionRead},
339-
ResourceWorkspace.Type: {policy.ActionRead},
338+
ResourceFile.Type: {policy.ActionCreate, policy.ActionRead},
339+
ResourceWorkspace.Type: {policy.ActionRead},
340+
ResourcePrebuiltWorkspace.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
340341
// CRUD to provisioner daemons for now.
341342
ResourceProvisionerDaemon.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
342343
// Needs to read all organizations since
@@ -493,9 +494,10 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
493494
Site: []Permission{},
494495
Org: map[string][]Permission{
495496
organizationID.String(): Permissions(map[string][]policy.Action{
496-
ResourceTemplate.Type: ResourceTemplate.AvailableActions(),
497-
ResourceFile.Type: {policy.ActionCreate, policy.ActionRead},
498-
ResourceWorkspace.Type: {policy.ActionRead},
497+
ResourceTemplate.Type: ResourceTemplate.AvailableActions(),
498+
ResourceFile.Type: {policy.ActionCreate, policy.ActionRead},
499+
ResourceWorkspace.Type: {policy.ActionRead},
500+
ResourcePrebuiltWorkspace.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
499501
// Assigning template perms requires this permission.
500502
ResourceOrganization.Type: {policy.ActionRead},
501503
ResourceOrganizationMember.Type: {policy.ActionRead},

coderd/workspacebuilds.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,16 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
404404
ctx,
405405
tx,
406406
func(action policy.Action, object rbac.Objecter) bool {
407+
if object.RBACObject().Type == rbac.ResourceWorkspace.Type && action == policy.ActionDelete {
408+
workspaceObj, ok := object.(database.Workspace)
409+
if ok {
410+
prebuild := workspaceObj.PrebuildRBAC()
411+
// Fallback to normal workspace auth check
412+
if auth := api.Authorize(r, action, prebuild); auth {
413+
return auth
414+
}
415+
}
416+
}
407417
return api.Authorize(r, action, object)
408418
},
409419
audit.WorkspaceBuildBaggageFromRequest(r),

codersdk/rbacresources_gen.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/api/members.md

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy