-
Notifications
You must be signed in to change notification settings - Fork 928
feat: allow TemplateAdmin to delete prebuilds via auth layer #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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2ba15c5
a043f92
6cae769
afc5359
b2c7bdd
f24e4ab
98576c6
9d2bf8b
d461a3d
5f896f0
f4ae6bc
998fa3b
007f3fd
f811778
ed8af65
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package database | ||
|
||
import "github.com/google/uuid" | ||
|
||
var PrebuildsSystemUserID = uuid.MustParse("c42fdf75-3097-471c-8c33-fb52454d81c0") |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,6 @@ import ( | |
"github.com/coder/coder/v2/coderd/database/dbtime" | ||
"github.com/coder/coder/v2/coderd/httpapi/httpapiconstraints" | ||
"github.com/coder/coder/v2/coderd/httpmw/loggermw" | ||
"github.com/coder/coder/v2/coderd/prebuilds" | ||
"github.com/coder/coder/v2/coderd/rbac" | ||
"github.com/coder/coder/v2/coderd/rbac/policy" | ||
"github.com/coder/coder/v2/coderd/rbac/rolestore" | ||
|
@@ -150,6 +149,30 @@ func (q *querier) authorizeContext(ctx context.Context, action policy.Action, ob | |
return nil | ||
} | ||
|
||
// authorizePrebuiltWorkspace handles authorization for workspace resource types. | ||
// prebuilt_workspaces are a subset of workspaces, currently limited to | ||
// supporting delete operations. Therefore, if the action is delete or | ||
// update and the workspace is a prebuild, a prebuilt-specific authorization | ||
// is attempted first. If that fails, it falls back to normal workspace | ||
// authorization. | ||
// Note: Delete operations of workspaces requires both update and delete | ||
// permissions. | ||
func (q *querier) authorizePrebuiltWorkspace(ctx context.Context, action policy.Action, workspace database.Workspace) error { | ||
var prebuiltErr error | ||
// Special handling for prebuilt_workspace deletion authorization check | ||
if (action == policy.ActionUpdate || action == policy.ActionDelete) && workspace.IsPrebuild() { | ||
// Try prebuilt-specific authorization first | ||
if prebuiltErr = q.authorizeContext(ctx, action, workspace.AsPrebuild()); prebuiltErr == nil { | ||
return nil | ||
} | ||
} | ||
// Fallback to normal workspace authorization check | ||
if err := q.authorizeContext(ctx, action, workspace); err != nil { | ||
return xerrors.Errorf("authorize context: %w", errors.Join(prebuiltErr, err)) | ||
} | ||
Comment on lines
+163
to
+172
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the normal workspace check is more likely to succeed then the prebuild. So it might be a slight optimization to flip these checks. But that will probably break some of the unit tests? No need to change this, just a thought. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point, I had considered that optimization as well. I believe it might require some test updates, so I'd prefer to merge this PR and address the optimization in a follow-up PR. |
||
return nil | ||
} | ||
|
||
type authContextKey struct{} | ||
|
||
// ActorFromContext returns the authorization subject from the context. | ||
|
@@ -399,7 +422,7 @@ var ( | |
subjectPrebuildsOrchestrator = rbac.Subject{ | ||
Type: rbac.SubjectTypePrebuildsOrchestrator, | ||
FriendlyName: "Prebuilds Orchestrator", | ||
ID: prebuilds.SystemUserID.String(), | ||
ID: database.PrebuildsSystemUserID.String(), | ||
Roles: rbac.Roles([]rbac.Role{ | ||
{ | ||
Identifier: rbac.RoleIdentifier{Name: "prebuilds-orchestrator"}, | ||
|
@@ -412,6 +435,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.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, | ||
|
@@ -3953,8 +3982,9 @@ func (q *querier) InsertWorkspaceBuild(ctx context.Context, arg database.InsertW | |
action = policy.ActionWorkspaceStop | ||
} | ||
|
||
if err = q.authorizeContext(ctx, action, w); err != nil { | ||
return xerrors.Errorf("authorize context: %w", err) | ||
// Special handling for prebuilt workspace deletion | ||
if err := q.authorizePrebuiltWorkspace(ctx, action, w); err != nil { | ||
return err | ||
} | ||
|
||
// If we're starting a workspace we need to check the template. | ||
|
@@ -3993,8 +4023,8 @@ func (q *querier) InsertWorkspaceBuildParameters(ctx context.Context, arg databa | |
return err | ||
} | ||
|
||
err = q.authorizeContext(ctx, policy.ActionUpdate, workspace) | ||
if err != nil { | ||
// Special handling for prebuilt workspace deletion | ||
if err := q.authorizePrebuiltWorkspace(ctx, policy.ActionUpdate, workspace); err != nil { | ||
return err | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.