Skip to content

Commit 9c4623a

Browse files
fix: improve rbac policies
1 parent d549c2b commit 9c4623a

File tree

8 files changed

+174
-19
lines changed

8 files changed

+174
-19
lines changed

coderd/database/dbauthz/dbauthz.go

+43-11
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ var (
378378
policy.ActionCreate, policy.ActionDelete, policy.ActionRead, policy.ActionUpdate,
379379
policy.ActionWorkspaceStart, policy.ActionWorkspaceStop,
380380
},
381+
rbac.ResourceSystem.Type: {policy.ActionRead},
381382
}),
382383
},
383384
}),
@@ -1137,13 +1138,29 @@ func (q *querier) BulkMarkNotificationMessagesSent(ctx context.Context, arg data
11371138
return q.db.BulkMarkNotificationMessagesSent(ctx, arg)
11381139
}
11391140

1140-
func (q *querier) ClaimPrebuiltWorkspace(ctx context.Context, newOwnerID database.ClaimPrebuiltWorkspaceParams) (database.ClaimPrebuiltWorkspaceRow, error) {
1141-
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceWorkspace); err != nil {
1142-
return database.ClaimPrebuiltWorkspaceRow{
1143-
ID: uuid.Nil,
1144-
}, err
1141+
func (q *querier) ClaimPrebuiltWorkspace(ctx context.Context, arg database.ClaimPrebuiltWorkspaceParams) (database.ClaimPrebuiltWorkspaceRow, error) {
1142+
empty := database.ClaimPrebuiltWorkspaceRow{}
1143+
1144+
preset, err := q.db.GetPresetByID(ctx, arg.PresetID)
1145+
if err != nil {
1146+
return empty, err
1147+
}
1148+
1149+
workspaceObject := rbac.ResourceWorkspace.WithOwner(arg.NewUserID.String()).InOrg(preset.OrganizationID)
1150+
err = q.authorizeContext(ctx, policy.ActionCreate, workspaceObject.RBACObject())
1151+
if err != nil {
1152+
return empty, err
1153+
}
1154+
1155+
tpl, err := q.GetTemplateByID(ctx, preset.TemplateID.UUID)
1156+
if err != nil {
1157+
return empty, xerrors.Errorf("verify template by id: %w", err)
11451158
}
1146-
return q.db.ClaimPrebuiltWorkspace(ctx, newOwnerID)
1159+
if err := q.authorizeContext(ctx, policy.ActionUse, tpl); err != nil {
1160+
return empty, xerrors.Errorf("use template for workspace: %w", err)
1161+
}
1162+
1163+
return q.db.ClaimPrebuiltWorkspace(ctx, arg)
11471164
}
11481165

11491166
func (q *querier) CleanTailnetCoordinators(ctx context.Context) error {
@@ -1168,7 +1185,7 @@ func (q *querier) CleanTailnetTunnels(ctx context.Context) error {
11681185
}
11691186

11701187
func (q *querier) CountInProgressPrebuilds(ctx context.Context) ([]database.CountInProgressPrebuildsRow, error) {
1171-
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
1188+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
11721189
return nil, err
11731190
}
11741191
return q.db.CountInProgressPrebuilds(ctx)
@@ -2118,12 +2135,27 @@ func (q *querier) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUI
21182135
}
21192136

21202137
func (q *querier) GetPrebuildMetrics(ctx context.Context) ([]database.GetPrebuildMetricsRow, error) {
2121-
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
2138+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
21222139
return nil, err
21232140
}
21242141
return q.db.GetPrebuildMetrics(ctx)
21252142
}
21262143

2144+
func (q *querier) GetPresetByID(ctx context.Context, presetID uuid.UUID) (database.GetPresetByIDRow, error) {
2145+
empty := database.GetPresetByIDRow{}
2146+
2147+
preset, err := q.db.GetPresetByID(ctx, presetID)
2148+
if err != nil {
2149+
return empty, err
2150+
}
2151+
_, err = q.GetTemplateByID(ctx, preset.TemplateID.UUID)
2152+
if err != nil {
2153+
return empty, err
2154+
}
2155+
2156+
return preset, nil
2157+
}
2158+
21272159
func (q *querier) GetPresetByWorkspaceBuildID(ctx context.Context, workspaceID uuid.UUID) (database.TemplateVersionPreset, error) {
21282160
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
21292161
return database.TemplateVersionPreset{}, err
@@ -2142,7 +2174,7 @@ func (q *querier) GetPresetParametersByTemplateVersionID(ctx context.Context, te
21422174
}
21432175

21442176
func (q *querier) GetPresetsBackoff(ctx context.Context, lookback time.Time) ([]database.GetPresetsBackoffRow, error) {
2145-
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
2177+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
21462178
return nil, err
21472179
}
21482180
return q.db.GetPresetsBackoff(ctx, lookback)
@@ -2299,7 +2331,7 @@ func (q *querier) GetReplicasUpdatedAfter(ctx context.Context, updatedAt time.Ti
22992331
}
23002332

23012333
func (q *querier) GetRunningPrebuiltWorkspaces(ctx context.Context) ([]database.GetRunningPrebuiltWorkspacesRow, error) {
2302-
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
2334+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
23032335
return nil, err
23042336
}
23052337
return q.db.GetRunningPrebuiltWorkspaces(ctx)
@@ -2433,7 +2465,7 @@ func (q *querier) GetTemplatePresetsWithPrebuilds(ctx context.Context, templateI
24332465
// Although this fetches presets. It filters them by prebuilds and is only of use to the prebuild system.
24342466
// As such, we authorize this in line with other prebuild queries, not with other preset queries.
24352467

2436-
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
2468+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
24372469
return nil, err
24382470
}
24392471
return q.db.GetTemplatePresetsWithPrebuilds(ctx, templateID)

coderd/database/dbauthz/dbauthz_test.go

+64-8
Original file line numberDiff line numberDiff line change
@@ -4801,37 +4801,93 @@ func (s *MethodTestSuite) TestNotifications() {
48014801

48024802
func (s *MethodTestSuite) TestPrebuilds() {
48034803
s.Run("ClaimPrebuiltWorkspace", s.Subtest(func(db database.Store, check *expects) {
4804-
check.Args(database.ClaimPrebuiltWorkspaceParams{}).
4805-
Asserts(rbac.ResourceWorkspace, policy.ActionUpdate).
4806-
ErrorsWithInMemDB(dbmem.ErrUnimplemented).
4804+
org := dbgen.Organization(s.T(), db, database.Organization{})
4805+
user := dbgen.User(s.T(), db, database.User{})
4806+
template := dbgen.Template(s.T(), db, database.Template{
4807+
OrganizationID: org.ID,
4808+
CreatedBy: user.ID,
4809+
})
4810+
templateVersion := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
4811+
TemplateID: uuid.NullUUID{
4812+
UUID: template.ID,
4813+
Valid: true,
4814+
},
4815+
OrganizationID: org.ID,
4816+
CreatedBy: user.ID,
4817+
})
4818+
preset := dbgen.Preset(s.T(), db, database.InsertPresetParams{
4819+
TemplateVersionID: templateVersion.ID,
4820+
})
4821+
check.Args(database.ClaimPrebuiltWorkspaceParams{
4822+
NewUserID: user.ID,
4823+
NewName: "",
4824+
PresetID: preset.ID,
4825+
}).Asserts(
4826+
rbac.ResourceWorkspace.WithOwner(user.ID.String()).InOrg(org.ID), policy.ActionCreate,
4827+
template, policy.ActionRead,
4828+
template, policy.ActionUse,
4829+
).ErrorsWithInMemDB(dbmem.ErrUnimplemented).
48074830
ErrorsWithPG(sql.ErrNoRows)
48084831
}))
48094832
s.Run("GetPrebuildMetrics", s.Subtest(func(_ database.Store, check *expects) {
48104833
check.Args().
4811-
Asserts(rbac.ResourceTemplate, policy.ActionRead).
4834+
Asserts(rbac.ResourceSystem, policy.ActionRead).
48124835
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
48134836
}))
48144837
s.Run("CountInProgressPrebuilds", s.Subtest(func(_ database.Store, check *expects) {
48154838
check.Args().
4816-
Asserts(rbac.ResourceTemplate, policy.ActionRead).
4839+
Asserts(rbac.ResourceSystem, policy.ActionRead).
48174840
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
48184841
}))
48194842
s.Run("GetPresetsBackoff", s.Subtest(func(_ database.Store, check *expects) {
48204843
check.Args(time.Time{}).
4821-
Asserts(rbac.ResourceTemplate, policy.ActionRead).
4844+
Asserts(rbac.ResourceSystem, policy.ActionRead).
48224845
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
48234846
}))
48244847
s.Run("GetRunningPrebuiltWorkspaces", s.Subtest(func(_ database.Store, check *expects) {
48254848
check.Args().
4826-
Asserts(rbac.ResourceTemplate, policy.ActionRead).
4849+
Asserts(rbac.ResourceSystem, policy.ActionRead).
48274850
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
48284851
}))
48294852
s.Run("GetTemplatePresetsWithPrebuilds", s.Subtest(func(db database.Store, check *expects) {
48304853
user := dbgen.User(s.T(), db, database.User{})
48314854
check.Args(uuid.NullUUID{UUID: user.ID, Valid: true}).
4832-
Asserts(rbac.ResourceTemplate, policy.ActionRead).
4855+
Asserts(rbac.ResourceSystem, policy.ActionRead).
48334856
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
48344857
}))
4858+
s.Run("GetPresetByID", s.Subtest(func(db database.Store, check *expects) {
4859+
org := dbgen.Organization(s.T(), db, database.Organization{})
4860+
user := dbgen.User(s.T(), db, database.User{})
4861+
template := dbgen.Template(s.T(), db, database.Template{
4862+
OrganizationID: org.ID,
4863+
CreatedBy: user.ID,
4864+
})
4865+
templateVersion := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
4866+
TemplateID: uuid.NullUUID{
4867+
UUID: template.ID,
4868+
Valid: true,
4869+
},
4870+
OrganizationID: org.ID,
4871+
CreatedBy: user.ID,
4872+
})
4873+
preset := dbgen.Preset(s.T(), db, database.InsertPresetParams{
4874+
TemplateVersionID: templateVersion.ID,
4875+
})
4876+
check.Args(preset.ID).
4877+
Asserts(template, policy.ActionRead).
4878+
ErrorsWithInMemDB(dbmem.ErrUnimplemented).
4879+
Returns(database.GetPresetByIDRow{
4880+
ID: preset.ID,
4881+
TemplateVersionID: preset.TemplateVersionID,
4882+
Name: preset.Name,
4883+
CreatedAt: preset.CreatedAt,
4884+
TemplateID: uuid.NullUUID{
4885+
UUID: template.ID,
4886+
Valid: true,
4887+
},
4888+
OrganizationID: org.ID,
4889+
})
4890+
}))
48354891
}
48364892

48374893
func (s *MethodTestSuite) TestOAuth2ProviderApps() {

coderd/database/dbmem/dbmem.go

+4
Original file line numberDiff line numberDiff line change
@@ -4171,6 +4171,10 @@ func (*FakeQuerier) GetPrebuildMetrics(_ context.Context) ([]database.GetPrebuil
41714171
return nil, ErrUnimplemented
41724172
}
41734173

4174+
func (q *FakeQuerier) GetPresetByID(ctx context.Context, presetID uuid.UUID) (database.GetPresetByIDRow, error) {
4175+
return database.GetPresetByIDRow{}, ErrUnimplemented
4176+
}
4177+
41744178
func (q *FakeQuerier) GetPresetByWorkspaceBuildID(_ context.Context, workspaceBuildID uuid.UUID) (database.TemplateVersionPreset, error) {
41754179
q.mutex.RLock()
41764180
defer q.mutex.RUnlock()

coderd/database/dbmetrics/querymetrics.go

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbmock/dbmock.go

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/querier.go

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

+34
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/presets.sql

+6
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,9 @@ FROM
4848
INNER JOIN template_version_presets ON template_version_preset_parameters.template_version_preset_id = template_version_presets.id
4949
WHERE
5050
template_version_presets.template_version_id = @template_version_id;
51+
52+
-- name: GetPresetByID :one
53+
SELECT tvp.*, tv.template_id, tv.organization_id FROM
54+
template_version_presets tvp
55+
INNER JOIN template_versions tv ON tvp.template_version_id = tv.id
56+
WHERE tvp.id = @preset_id;

0 commit comments

Comments
 (0)