@@ -18,6 +18,7 @@ import (
1818
1919"cdr.dev/slog"
2020
21+ "github.com/coder/coder/v2/coderd/prebuilds"
2122"github.com/coder/coder/v2/coderd/rbac/policy"
2223"github.com/coder/coder/v2/coderd/rbac/rolestore"
2324
@@ -358,6 +359,27 @@ var (
358359}),
359360Scope :rbac .ScopeAll ,
360361}.WithCachedASTValue ()
362+
363+ subjectPrebuildsOrchestrator = rbac.Subject {
364+ FriendlyName :"Prebuilds Orchestrator" ,
365+ ID :prebuilds .OwnerID .String (),
366+ Roles :rbac .Roles ([]rbac.Role {
367+ {
368+ Identifier : rbac.RoleIdentifier {Name :"prebuilds-orchestrator" },
369+ DisplayName :"Coder" ,
370+ Site :rbac .Permissions (map [string ][]policy.Action {
371+ // May use template, read template-related info, & insert template-related resources (preset prebuilds).
372+ rbac .ResourceTemplate .Type : {policy .ActionRead ,policy .ActionUpdate ,policy .ActionUse },
373+ // May CRUD workspaces, and start/stop them.
374+ rbac .ResourceWorkspace .Type : {
375+ policy .ActionCreate ,policy .ActionDelete ,policy .ActionRead ,policy .ActionUpdate ,
376+ policy .ActionWorkspaceStart ,policy .ActionWorkspaceStop ,
377+ },
378+ }),
379+ },
380+ }),
381+ Scope :rbac .ScopeAll ,
382+ }.WithCachedASTValue ()
361383)
362384
363385// AsProvisionerd returns a context with an actor that has permissions required
@@ -412,6 +434,12 @@ func AsSystemReadProvisionerDaemons(ctx context.Context) context.Context {
412434return context .WithValue (ctx ,authContextKey {},subjectSystemReadProvisionerDaemons )
413435}
414436
437+ // AsPrebuildsOrchestrator returns a context with an actor that has permissions
438+ // to read orchestrator workspace prebuilds.
439+ func AsPrebuildsOrchestrator (ctx context.Context ) context.Context {
440+ return context .WithValue (ctx ,authContextKey {},subjectPrebuildsOrchestrator )
441+ }
442+
415443var AsRemoveActor = rbac.Subject {
416444ID :"remove-actor" ,
417445}
@@ -1106,6 +1134,15 @@ func (q *querier) BulkMarkNotificationMessagesSent(ctx context.Context, arg data
11061134return q .db .BulkMarkNotificationMessagesSent (ctx ,arg )
11071135}
11081136
1137+ func (q * querier )ClaimPrebuild (ctx context.Context ,newOwnerID database.ClaimPrebuildParams ) (database.ClaimPrebuildRow ,error ) {
1138+ if err := q .authorizeContext (ctx ,policy .ActionUpdate ,rbac .ResourceWorkspace );err != nil {
1139+ return database.ClaimPrebuildRow {
1140+ ID :uuid .Nil ,
1141+ },err
1142+ }
1143+ return q .db .ClaimPrebuild (ctx ,newOwnerID )
1144+ }
1145+
11091146func (q * querier )CleanTailnetCoordinators (ctx context.Context )error {
11101147if err := q .authorizeContext (ctx ,policy .ActionDelete ,rbac .ResourceTailnetCoordinator );err != nil {
11111148return err
@@ -2020,6 +2057,20 @@ func (q *querier) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUI
20202057return q .db .GetParameterSchemasByJobID (ctx ,jobID )
20212058}
20222059
2060+ func (q * querier )GetPrebuildMetrics (ctx context.Context ) ([]database.GetPrebuildMetricsRow ,error ) {
2061+ if err := q .authorizeContext (ctx ,policy .ActionRead ,rbac .ResourceTemplate );err != nil {
2062+ return nil ,err
2063+ }
2064+ return q .db .GetPrebuildMetrics (ctx )
2065+ }
2066+
2067+ func (q * querier )GetPrebuildsInProgress (ctx context.Context ) ([]database.GetPrebuildsInProgressRow ,error ) {
2068+ if err := q .authorizeContext (ctx ,policy .ActionRead ,rbac .ResourceTemplate );err != nil {
2069+ return nil ,err
2070+ }
2071+ return q .db .GetPrebuildsInProgress (ctx )
2072+ }
2073+
20232074func (q * querier )GetPresetByWorkspaceBuildID (ctx context.Context ,workspaceID uuid.UUID ) (database.TemplateVersionPreset ,error ) {
20242075if err := q .authorizeContext (ctx ,policy .ActionRead ,rbac .ResourceTemplate );err != nil {
20252076return database.TemplateVersionPreset {},err
@@ -2037,6 +2088,13 @@ func (q *querier) GetPresetParametersByTemplateVersionID(ctx context.Context, te
20372088return q .db .GetPresetParametersByTemplateVersionID (ctx ,templateVersionID )
20382089}
20392090
2091+ func (q * querier )GetPresetsBackoff (ctx context.Context ,lookback time.Time ) ([]database.GetPresetsBackoffRow ,error ) {
2092+ if err := q .authorizeContext (ctx ,policy .ActionRead ,rbac .ResourceTemplate );err != nil {
2093+ return nil ,err
2094+ }
2095+ return q .db .GetPresetsBackoff (ctx ,lookback )
2096+ }
2097+
20402098func (q * querier )GetPresetsByTemplateVersionID (ctx context.Context ,templateVersionID uuid.UUID ) ([]database.TemplateVersionPreset ,error ) {
20412099// An actor can read template version presets if they can read the related template version.
20422100_ ,err := q .GetTemplateVersionByID (ctx ,templateVersionID )
@@ -2088,13 +2146,13 @@ func (q *querier) GetProvisionerJobByID(ctx context.Context, id uuid.UUID) (data
20882146// can read the job.
20892147_ ,err := q .GetWorkspaceBuildByJobID (ctx ,id )
20902148if err != nil {
2091- return database.ProvisionerJob {},err
2149+ return database.ProvisionerJob {},xerrors . Errorf ( "fetch related workspace build: %w" , err )
20922150}
20932151case database .ProvisionerJobTypeTemplateVersionDryRun ,database .ProvisionerJobTypeTemplateVersionImport :
20942152// Authorized call to get template version.
20952153_ ,err := authorizedTemplateVersionFromJob (ctx ,q ,job )
20962154if err != nil {
2097- return database.ProvisionerJob {},err
2155+ return database.ProvisionerJob {},xerrors . Errorf ( "fetch related template version: %w" , err )
20982156}
20992157default :
21002158return database.ProvisionerJob {},xerrors .Errorf ("unknown job type: %q" ,job .Type )
@@ -2187,6 +2245,13 @@ func (q *querier) GetReplicasUpdatedAfter(ctx context.Context, updatedAt time.Ti
21872245return q .db .GetReplicasUpdatedAfter (ctx ,updatedAt )
21882246}
21892247
2248+ func (q * querier )GetRunningPrebuilds (ctx context.Context ) ([]database.GetRunningPrebuildsRow ,error ) {
2249+ if err := q .authorizeContext (ctx ,policy .ActionRead ,rbac .ResourceTemplate );err != nil {
2250+ return nil ,err
2251+ }
2252+ return q .db .GetRunningPrebuilds (ctx )
2253+ }
2254+
21902255func (q * querier )GetRuntimeConfig (ctx context.Context ,key string ) (string ,error ) {
21912256if err := q .authorizeContext (ctx ,policy .ActionRead ,rbac .ResourceSystem );err != nil {
21922257return "" ,err
@@ -2311,6 +2376,16 @@ func (q *querier) GetTemplateParameterInsights(ctx context.Context, arg database
23112376return q .db .GetTemplateParameterInsights (ctx ,arg )
23122377}
23132378
2379+ func (q * querier )GetTemplatePresetsWithPrebuilds (ctx context.Context ,templateID uuid.NullUUID ) ([]database.GetTemplatePresetsWithPrebuildsRow ,error ) {
2380+ // Although this fetches presets. It filters them by prebuilds and is only of use to the prebuild system.
2381+ // As such, we authorize this in line with other prebuild queries, not with other preset queries.
2382+
2383+ if err := q .authorizeContext (ctx ,policy .ActionRead ,rbac .ResourceTemplate );err != nil {
2384+ return nil ,err
2385+ }
2386+ return q .db .GetTemplatePresetsWithPrebuilds (ctx ,templateID )
2387+ }
2388+
23142389func (q * querier )GetTemplateUsageStats (ctx context.Context ,arg database.GetTemplateUsageStatsParams ) ([]database.TemplateUsageStat ,error ) {
23152390if err := q .authorizeTemplateInsights (ctx ,arg .TemplateIDs );err != nil {
23162391return nil ,err
@@ -3235,6 +3310,13 @@ func (q *querier) InsertPresetParameters(ctx context.Context, arg database.Inser
32353310return q .db .InsertPresetParameters (ctx ,arg )
32363311}
32373312
3313+ func (q * querier )InsertPresetPrebuild (ctx context.Context ,arg database.InsertPresetPrebuildParams ) (database.TemplateVersionPresetPrebuild ,error ) {
3314+ if err := q .authorizeContext (ctx ,policy .ActionCreate ,rbac .ResourceSystem );err != nil {
3315+ return database.TemplateVersionPresetPrebuild {},err
3316+ }
3317+ return q .db .InsertPresetPrebuild (ctx ,arg )
3318+ }
3319+
32383320// TODO: We need to create a ProvisionerJob resource type
32393321func (q * querier )InsertProvisionerJob (ctx context.Context ,arg database.InsertProvisionerJobParams ) (database.ProvisionerJob ,error ) {
32403322// if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil {