Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: allow TemplateAdmin to delete prebuilds via auth layer (POC)#18333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Draft
ssncferreira wants to merge4 commits intomain
base:main
Choose a base branch
Loading
fromssncferreira/poc-prebuild-rbac-authz
Draft
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletionscoderd/apidoc/docs.go
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

2 changes: 2 additions & 0 deletionscoderd/apidoc/swagger.json
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

25 changes: 23 additions & 2 deletionscoderd/database/dbauthz/dbauthz.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -412,6 +412,12 @@ var (
policy.ActionCreate, policy.ActionDelete, policy.ActionRead, policy.ActionUpdate,
policy.ActionWorkspaceStart, policy.ActionWorkspaceStop,
},
// PrebuiltWorkspaces are a subset of Workspaces.
// Explicitly setting PrebuiltWorkspace permissions for clarity.
// Note: even without PrebuiltWorkspace permissions, access is still granted via Workspace permissions.
rbac.ResourcePrebuiltWorkspace.Type: {
policy.ActionRead, policy.ActionUpdate, policy.ActionDelete,
},
// Should be able to add the prebuilds system user as a member to any organization that needs prebuilds.
rbac.ResourceOrganizationMember.Type: {
policy.ActionCreate,
Expand DownExpand Up@@ -3909,7 +3915,14 @@ func (q *querier) InsertWorkspaceBuild(ctx context.Context, arg database.InsertW
action = policy.ActionWorkspaceStop
}

if err = q.authorizeContext(ctx, action, w); err != nil {
if action == policy.ActionDelete && w.IsPrebuild() {
if err := q.authorizeContext(ctx, action, w.PrebuildRBAC()); err != nil {
// Fallback to normal workspace auth check
if err = q.authorizeContext(ctx, action, w); err != nil {
return xerrors.Errorf("authorize context: %w", err)
}
}
} else if err = q.authorizeContext(ctx, action, w); err != nil {
return xerrors.Errorf("authorize context: %w", err)
}

Expand DownExpand Up@@ -3949,7 +3962,15 @@ func (q *querier) InsertWorkspaceBuildParameters(ctx context.Context, arg databa
return err
}

err = q.authorizeContext(ctx, policy.ActionUpdate, workspace)
if workspace.IsPrebuild() {
err = q.authorizeContext(ctx, policy.ActionUpdate, workspace.PrebuildRBAC())
// Fallback to normal workspace auth check
if err != nil {
err = q.authorizeContext(ctx, policy.ActionUpdate, workspace)
}
} else {
err = q.authorizeContext(ctx, policy.ActionUpdate, workspace)
}
if err != nil {
return err
}
Expand Down
17 changes: 17 additions & 0 deletionscoderd/database/modelmethods.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -226,9 +226,26 @@ func (w Workspace) WorkspaceTable() WorkspaceTable {
}

func (w Workspace) RBACObject() rbac.Object {
// if w.IsPrebuild() {
//return w.PrebuildRBAC()
//}
return w.WorkspaceTable().RBACObject()
}

func (w Workspace) IsPrebuild() bool {
// TODO: avoid import cycle
return w.OwnerID == uuid.MustParse("c42fdf75-3097-471c-8c33-fb52454d81c0")
}

func (w Workspace) PrebuildRBAC() rbac.Object {
if w.IsPrebuild() {
return rbac.ResourcePrebuiltWorkspace.WithID(w.ID).
InOrg(w.OrganizationID).
WithOwner(w.OwnerID.String())
}
return w.RBACObject()
}
Comment on lines +235 to +247
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

🤔 what about

func (w Workspace) AsPrebuild (rbac.Object, bool) {}if pb, ok := obj.AsPrebuild(); ok {  ...}


func (w WorkspaceTable) RBACObject() rbac.Object {
if w.DormantAt.Valid {
return w.DormantRBAC()
Expand Down
10 changes: 10 additions & 0 deletionscoderd/rbac/object_gen.go
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

7 changes: 7 additions & 0 deletionscoderd/rbac/policy/policy.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -102,6 +102,13 @@ var RBACPermissions = map[string]PermissionDefinition{
"workspace_dormant": {
Actions:workspaceActions,
},
"prebuilt_workspace": {
Actions:map[Action]ActionDefinition{
ActionRead:actDef("read prebuilt workspace"),
ActionUpdate:actDef("update prebuilt workspace"),
ActionDelete:actDef("delete prebuilt workspace"),
},
},
"workspace_proxy": {
Actions:map[Action]ActionDefinition{
ActionCreate:actDef("create a workspace proxy"),
Expand Down
26 changes: 18 additions & 8 deletionscoderd/rbac/roles.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -270,11 +270,15 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
Site: append(
// Workspace dormancy and workspace are omitted.
// Workspace is specifically handled based on the opts.NoOwnerWorkspaceExec
allPermsExcept(ResourceWorkspaceDormant, ResourceWorkspace),
allPermsExcept(ResourceWorkspaceDormant,ResourcePrebuiltWorkspace,ResourceWorkspace),
// This adds back in the Workspace permissions.
Permissions(map[string][]policy.Action{
ResourceWorkspace.Type: ownerWorkspaceActions,
ResourceWorkspaceDormant.Type: {policy.ActionRead, policy.ActionDelete, policy.ActionCreate, policy.ActionUpdate, policy.ActionWorkspaceStop, policy.ActionCreateAgent, policy.ActionDeleteAgent},
// PrebuiltWorkspaces are a subset of Workspaces.
// Explicitly setting PrebuiltWorkspace permissions for clarity.
// Note: even without PrebuiltWorkspace permissions, access is still granted via Workspace permissions.
ResourcePrebuiltWorkspace.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
})...),
Org: map[string][]Permission{},
User: []Permission{},
Expand All@@ -290,7 +294,7 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
ResourceWorkspaceProxy.Type: {policy.ActionRead},
}),
Org: map[string][]Permission{},
User: append(allPermsExcept(ResourceWorkspaceDormant, ResourceUser, ResourceOrganizationMember),
User: append(allPermsExcept(ResourceWorkspaceDormant,ResourcePrebuiltWorkspace,ResourceUser, ResourceOrganizationMember),
Permissions(map[string][]policy.Action{
// Reduced permission set on dormant workspaces. No build, ssh, or exec
ResourceWorkspaceDormant.Type: {policy.ActionRead, policy.ActionDelete, policy.ActionCreate, policy.ActionUpdate, policy.ActionWorkspaceStop, policy.ActionCreateAgent, policy.ActionDeleteAgent},
Expand DownExpand Up@@ -335,8 +339,9 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
ResourceAssignOrgRole.Type: {policy.ActionRead},
ResourceTemplate.Type: ResourceTemplate.AvailableActions(),
// CRUD all files, even those they did not upload.
ResourceFile.Type: {policy.ActionCreate, policy.ActionRead},
ResourceWorkspace.Type: {policy.ActionRead},
ResourceFile.Type: {policy.ActionCreate, policy.ActionRead},
ResourceWorkspace.Type: {policy.ActionRead},
ResourcePrebuiltWorkspace.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
// CRUD to provisioner daemons for now.
ResourceProvisionerDaemon.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
// Needs to read all organizations since
Expand DownExpand Up@@ -413,9 +418,13 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
}),
Org: map[string][]Permission{
// Org admins should not have workspace exec perms.
organizationID.String(): append(allPermsExcept(ResourceWorkspace, ResourceWorkspaceDormant, ResourceAssignRole), Permissions(map[string][]policy.Action{
organizationID.String(): append(allPermsExcept(ResourceWorkspace, ResourceWorkspaceDormant,ResourcePrebuiltWorkspace,ResourceAssignRole), Permissions(map[string][]policy.Action{
ResourceWorkspaceDormant.Type: {policy.ActionRead, policy.ActionDelete, policy.ActionCreate, policy.ActionUpdate, policy.ActionWorkspaceStop, policy.ActionCreateAgent, policy.ActionDeleteAgent},
ResourceWorkspace.Type: slice.Omit(ResourceWorkspace.AvailableActions(), policy.ActionApplicationConnect, policy.ActionSSH),
// PrebuiltWorkspaces are a subset of Workspaces.
// Explicitly setting PrebuiltWorkspace permissions for clarity.
// Note: even without PrebuiltWorkspace permissions, access is still granted via Workspace permissions.
ResourcePrebuiltWorkspace.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
})...),
},
User: []Permission{},
Expand DownExpand Up@@ -493,9 +502,10 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
Site: []Permission{},
Org: map[string][]Permission{
organizationID.String(): Permissions(map[string][]policy.Action{
ResourceTemplate.Type: ResourceTemplate.AvailableActions(),
ResourceFile.Type: {policy.ActionCreate, policy.ActionRead},
ResourceWorkspace.Type: {policy.ActionRead},
ResourceTemplate.Type: ResourceTemplate.AvailableActions(),
ResourceFile.Type: {policy.ActionCreate, policy.ActionRead},
ResourceWorkspace.Type: {policy.ActionRead},
ResourcePrebuiltWorkspace.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
// Assigning template perms requires this permission.
ResourceOrganization.Type: {policy.ActionRead},
ResourceOrganizationMember.Type: {policy.ActionRead},
Expand Down
9 changes: 9 additions & 0 deletionscoderd/rbac/roles_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -496,6 +496,15 @@ func TestRolePermissions(t *testing.T) {
false: {setOtherOrg, userAdmin, templateAdmin, memberMe, orgTemplateAdmin, orgUserAdmin, orgAuditor},
},
},
{
Name: "PrebuiltWorkspace",
Actions: []policy.Action{policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
Resource: rbac.ResourcePrebuiltWorkspace.WithID(uuid.New()).InOrg(orgID).WithOwner(memberMe.Actor.ID),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I thinkWithOwner(memberMe) is what's tripping you up here. It should be owned by the prebuilds user instead, right?

AuthorizeMap: map[bool][]hasAuthSubjects{
true: {owner, orgAdmin, templateAdmin, orgTemplateAdmin},
false: {setOtherOrg, userAdmin, memberMe, orgUserAdmin, orgAuditor, orgMemberMe},
},
},
// Some admin style resources
{
Name: "Licenses",
Expand Down
10 changes: 10 additions & 0 deletionscoderd/workspacebuilds.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -404,6 +404,16 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
ctx,
tx,
func(action policy.Action, object rbac.Objecter) bool {
if object.RBACObject().Type == rbac.ResourceWorkspace.Type && action == policy.ActionDelete {
workspaceObj, ok := object.(database.Workspace)
if ok {
prebuild := workspaceObj.PrebuildRBAC()
// Fallback to normal workspace auth check
if auth := api.Authorize(r, action, prebuild); auth {
return auth
}
}
}
Comment on lines +408 to +416
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggestion: use inline conditional assignment e.g.

if workspaceObj, ok := object.(database.Workspace); ok {  // prebuild auth}

ssncferreira reacted with thumbs up emoji
return api.Authorize(r, action, object)
},
audit.WorkspaceBuildBaggageFromRequest(r),
Expand Down
2 changes: 2 additions & 0 deletionscodersdk/rbacresources_gen.go
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

5 changes: 5 additions & 0 deletionsdocs/reference/api/members.md
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

1 change: 1 addition & 0 deletionsdocs/reference/api/schemas.md
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp