@@ -18,6 +18,7 @@ import (
18
18
19
19
"cdr.dev/slog"
20
20
21
+ "github.com/coder/coder/v2/coderd/prebuilds"
21
22
"github.com/coder/coder/v2/coderd/rbac/policy"
22
23
"github.com/coder/coder/v2/coderd/rbac/rolestore"
23
24
@@ -361,6 +362,27 @@ var (
361
362
}),
362
363
Scope : rbac .ScopeAll ,
363
364
}.WithCachedASTValue ()
365
+
366
+ subjectPrebuildsOrchestrator = rbac.Subject {
367
+ FriendlyName : "Prebuilds Orchestrator" ,
368
+ ID : prebuilds .SystemUserID .String (),
369
+ Roles : rbac .Roles ([]rbac.Role {
370
+ {
371
+ Identifier : rbac.RoleIdentifier {Name : "prebuilds-orchestrator" },
372
+ DisplayName : "Coder" ,
373
+ Site : rbac .Permissions (map [string ][]policy.Action {
374
+ // May use template, read template-related info, & insert template-related resources (preset prebuilds).
375
+ rbac .ResourceTemplate .Type : {policy .ActionRead , policy .ActionUpdate , policy .ActionUse , policy .ActionViewInsights },
376
+ // May CRUD workspaces, and start/stop them.
377
+ rbac .ResourceWorkspace .Type : {
378
+ policy .ActionCreate , policy .ActionDelete , policy .ActionRead , policy .ActionUpdate ,
379
+ policy .ActionWorkspaceStart , policy .ActionWorkspaceStop ,
380
+ },
381
+ }),
382
+ },
383
+ }),
384
+ Scope : rbac .ScopeAll ,
385
+ }.WithCachedASTValue ()
364
386
)
365
387
366
388
// AsProvisionerd returns a context with an actor that has permissions required
@@ -415,6 +437,12 @@ func AsSystemReadProvisionerDaemons(ctx context.Context) context.Context {
415
437
return context .WithValue (ctx , authContextKey {}, subjectSystemReadProvisionerDaemons )
416
438
}
417
439
440
+ // AsPrebuildsOrchestrator returns a context with an actor that has permissions
441
+ // to read orchestrator workspace prebuilds.
442
+ func AsPrebuildsOrchestrator (ctx context.Context ) context.Context {
443
+ return context .WithValue (ctx , authContextKey {}, subjectPrebuildsOrchestrator )
444
+ }
445
+
418
446
var AsRemoveActor = rbac.Subject {
419
447
ID : "remove-actor" ,
420
448
}
@@ -1109,6 +1137,31 @@ func (q *querier) BulkMarkNotificationMessagesSent(ctx context.Context, arg data
1109
1137
return q .db .BulkMarkNotificationMessagesSent (ctx , arg )
1110
1138
}
1111
1139
1140
+ func (q * querier ) ClaimPrebuiltWorkspace (ctx context.Context , arg database.ClaimPrebuiltWorkspaceParams ) (database.ClaimPrebuiltWorkspaceRow , error ) {
1141
+ empty := database.ClaimPrebuiltWorkspaceRow {}
1142
+
1143
+ preset , err := q .db .GetPresetByID (ctx , arg .PresetID )
1144
+ if err != nil {
1145
+ return empty , err
1146
+ }
1147
+
1148
+ workspaceObject := rbac .ResourceWorkspace .WithOwner (arg .NewUserID .String ()).InOrg (preset .OrganizationID )
1149
+ err = q .authorizeContext (ctx , policy .ActionCreate , workspaceObject .RBACObject ())
1150
+ if err != nil {
1151
+ return empty , err
1152
+ }
1153
+
1154
+ tpl , err := q .GetTemplateByID (ctx , preset .TemplateID .UUID )
1155
+ if err != nil {
1156
+ return empty , xerrors .Errorf ("verify template by id: %w" , err )
1157
+ }
1158
+ if err := q .authorizeContext (ctx , policy .ActionUse , tpl ); err != nil {
1159
+ return empty , xerrors .Errorf ("use template for workspace: %w" , err )
1160
+ }
1161
+
1162
+ return q .db .ClaimPrebuiltWorkspace (ctx , arg )
1163
+ }
1164
+
1112
1165
func (q * querier ) CleanTailnetCoordinators (ctx context.Context ) error {
1113
1166
if err := q .authorizeContext (ctx , policy .ActionDelete , rbac .ResourceTailnetCoordinator ); err != nil {
1114
1167
return err
@@ -1130,6 +1183,13 @@ func (q *querier) CleanTailnetTunnels(ctx context.Context) error {
1130
1183
return q .db .CleanTailnetTunnels (ctx )
1131
1184
}
1132
1185
1186
+ func (q * querier ) CountInProgressPrebuilds (ctx context.Context ) ([]database.CountInProgressPrebuildsRow , error ) {
1187
+ if err := q .authorizeContext (ctx , policy .ActionRead , rbac .ResourceWorkspace .All ()); err != nil {
1188
+ return nil , err
1189
+ }
1190
+ return q .db .CountInProgressPrebuilds (ctx )
1191
+ }
1192
+
1133
1193
func (q * querier ) CountUnreadInboxNotificationsByUserID (ctx context.Context , userID uuid.UUID ) (int64 , error ) {
1134
1194
if err := q .authorizeContext (ctx , policy .ActionRead , rbac .ResourceInboxNotification .WithOwner (userID .String ())); err != nil {
1135
1195
return 0 , err
@@ -2096,6 +2156,30 @@ func (q *querier) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUI
2096
2156
return q .db .GetParameterSchemasByJobID (ctx , jobID )
2097
2157
}
2098
2158
2159
+ func (q * querier ) GetPrebuildMetrics (ctx context.Context ) ([]database.GetPrebuildMetricsRow , error ) {
2160
+ // GetPrebuildMetrics returns metrics related to prebuilt workspaces,
2161
+ // such as the number of created and failed prebuilt workspaces.
2162
+ if err := q .authorizeContext (ctx , policy .ActionRead , rbac .ResourceWorkspace .All ()); err != nil {
2163
+ return nil , err
2164
+ }
2165
+ return q .db .GetPrebuildMetrics (ctx )
2166
+ }
2167
+
2168
+ func (q * querier ) GetPresetByID (ctx context.Context , presetID uuid.UUID ) (database.GetPresetByIDRow , error ) {
2169
+ empty := database.GetPresetByIDRow {}
2170
+
2171
+ preset , err := q .db .GetPresetByID (ctx , presetID )
2172
+ if err != nil {
2173
+ return empty , err
2174
+ }
2175
+ _ , err = q .GetTemplateByID (ctx , preset .TemplateID .UUID )
2176
+ if err != nil {
2177
+ return empty , err
2178
+ }
2179
+
2180
+ return preset , nil
2181
+ }
2182
+
2099
2183
func (q * querier ) GetPresetByWorkspaceBuildID (ctx context.Context , workspaceID uuid.UUID ) (database.TemplateVersionPreset , error ) {
2100
2184
if err := q .authorizeContext (ctx , policy .ActionRead , rbac .ResourceTemplate ); err != nil {
2101
2185
return database.TemplateVersionPreset {}, err
@@ -2113,6 +2197,14 @@ func (q *querier) GetPresetParametersByTemplateVersionID(ctx context.Context, te
2113
2197
return q .db .GetPresetParametersByTemplateVersionID (ctx , templateVersionID )
2114
2198
}
2115
2199
2200
+ func (q * querier ) GetPresetsBackoff (ctx context.Context , lookback time.Time ) ([]database.GetPresetsBackoffRow , error ) {
2201
+ // GetPresetsBackoff returns a list of template version presets along with metadata such as the number of failed prebuilds.
2202
+ if err := q .authorizeContext (ctx , policy .ActionViewInsights , rbac .ResourceTemplate .All ()); err != nil {
2203
+ return nil , err
2204
+ }
2205
+ return q .db .GetPresetsBackoff (ctx , lookback )
2206
+ }
2207
+
2116
2208
func (q * querier ) GetPresetsByTemplateVersionID (ctx context.Context , templateVersionID uuid.UUID ) ([]database.TemplateVersionPreset , error ) {
2117
2209
// An actor can read template version presets if they can read the related template version.
2118
2210
_ , err := q .GetTemplateVersionByID (ctx , templateVersionID )
@@ -2164,13 +2256,13 @@ func (q *querier) GetProvisionerJobByID(ctx context.Context, id uuid.UUID) (data
2164
2256
// can read the job.
2165
2257
_ , err := q .GetWorkspaceBuildByJobID (ctx , id )
2166
2258
if err != nil {
2167
- return database.ProvisionerJob {}, err
2259
+ return database.ProvisionerJob {}, xerrors . Errorf ( "fetch related workspace build: %w" , err )
2168
2260
}
2169
2261
case database .ProvisionerJobTypeTemplateVersionDryRun , database .ProvisionerJobTypeTemplateVersionImport :
2170
2262
// Authorized call to get template version.
2171
2263
_ , err := authorizedTemplateVersionFromJob (ctx , q , job )
2172
2264
if err != nil {
2173
- return database.ProvisionerJob {}, err
2265
+ return database.ProvisionerJob {}, xerrors . Errorf ( "fetch related template version: %w" , err )
2174
2266
}
2175
2267
default :
2176
2268
return database.ProvisionerJob {}, xerrors .Errorf ("unknown job type: %q" , job .Type )
@@ -2263,6 +2355,14 @@ func (q *querier) GetReplicasUpdatedAfter(ctx context.Context, updatedAt time.Ti
2263
2355
return q .db .GetReplicasUpdatedAfter (ctx , updatedAt )
2264
2356
}
2265
2357
2358
+ func (q * querier ) GetRunningPrebuiltWorkspaces (ctx context.Context ) ([]database.GetRunningPrebuiltWorkspacesRow , error ) {
2359
+ // This query returns only prebuilt workspaces, but we decided to require permissions for all workspaces.
2360
+ if err := q .authorizeContext (ctx , policy .ActionRead , rbac .ResourceWorkspace .All ()); err != nil {
2361
+ return nil , err
2362
+ }
2363
+ return q .db .GetRunningPrebuiltWorkspaces (ctx )
2364
+ }
2365
+
2266
2366
func (q * querier ) GetRuntimeConfig (ctx context.Context , key string ) (string , error ) {
2267
2367
if err := q .authorizeContext (ctx , policy .ActionRead , rbac .ResourceSystem ); err != nil {
2268
2368
return "" , err
@@ -2387,6 +2487,15 @@ func (q *querier) GetTemplateParameterInsights(ctx context.Context, arg database
2387
2487
return q .db .GetTemplateParameterInsights (ctx , arg )
2388
2488
}
2389
2489
2490
+ func (q * querier ) GetTemplatePresetsWithPrebuilds (ctx context.Context , templateID uuid.NullUUID ) ([]database.GetTemplatePresetsWithPrebuildsRow , error ) {
2491
+ // GetTemplatePresetsWithPrebuilds retrieves template versions with configured presets and prebuilds.
2492
+ // Presets and prebuilds are part of the template, so if you can access templates - you can access them as well.
2493
+ if err := q .authorizeContext (ctx , policy .ActionRead , rbac .ResourceTemplate .All ()); err != nil {
2494
+ return nil , err
2495
+ }
2496
+ return q .db .GetTemplatePresetsWithPrebuilds (ctx , templateID )
2497
+ }
2498
+
2390
2499
func (q * querier ) GetTemplateUsageStats (ctx context.Context , arg database.GetTemplateUsageStatsParams ) ([]database.TemplateUsageStat , error ) {
2391
2500
if err := q .authorizeTemplateInsights (ctx , arg .TemplateIDs ); err != nil {
2392
2501
return nil , err
0 commit comments