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

Commitd60f65a

Browse files
committed
make start/stop workspaces different actions
1 parentdda1b4f commitd60f65a

File tree

13 files changed

+94
-84
lines changed

13 files changed

+94
-84
lines changed

‎coderd/coderdtest/coderdtest.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ func NewOptions(t testing.TB, options *Options) (func(http.Handler), context.Can
221221
}
222222

223223
ifoptions.Authorizer==nil {
224-
defAuth:=rbac.NewCachingAuthorizer(prometheus.NewRegistry())
224+
defAuth:=rbac.NewStrictCachingAuthorizer(prometheus.NewRegistry())
225225
if_,ok:=t.(*testing.T);ok {
226226
options.Authorizer=&RecordingAuthorizer{
227227
Wrapped:defAuth,

‎coderd/database/dbauthz/dbauthz.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ var (
169169
rbac.ResourceTemplate.Type: {policy.ActionRead,policy.ActionUpdate},
170170
// Unsure why provisionerd needs update and read personal
171171
rbac.ResourceUser.Type: {policy.ActionRead,policy.ActionReadPersonal,policy.ActionUpdatePersonal},
172-
rbac.ResourceWorkspace.Type: {policy.ActionRead,policy.ActionUpdate,policy.ActionDelete,policy.ActionWorkspaceBuild},
172+
rbac.ResourceWorkspace.Type: {policy.ActionRead,policy.ActionUpdate,policy.ActionDelete,policy.ActionWorkspaceStart,policy.ActionWorkspaceStop},
173173
rbac.ResourceApiKey.Type: {policy.WildcardSymbol},
174174
// When org scoped provisioner credentials are implemented,
175175
// this can be reduced to read a specific org.
@@ -193,7 +193,7 @@ var (
193193
Site:rbac.Permissions(map[string][]policy.Action{
194194
rbac.ResourceSystem.Type: {policy.WildcardSymbol},
195195
rbac.ResourceTemplate.Type: {policy.ActionRead,policy.ActionUpdate},
196-
rbac.ResourceWorkspace.Type: {policy.ActionRead,policy.ActionUpdate,policy.ActionWorkspaceBuild},
196+
rbac.ResourceWorkspace.Type: {policy.ActionRead,policy.ActionUpdate,policy.ActionWorkspaceStart,policy.ActionWorkspaceStop},
197197
rbac.ResourceUser.Type: {policy.ActionRead},
198198
}),
199199
Org:map[string][]rbac.Permission{},
@@ -232,7 +232,7 @@ var (
232232
DisplayName:"Coder",
233233
Site:rbac.Permissions(map[string][]policy.Action{
234234
rbac.ResourceWildcard.Type: {policy.ActionRead},
235-
rbac.ResourceApiKey.Type:{policy.ActionCreate,policy.ActionUpdate,policy.ActionDelete},
235+
rbac.ResourceApiKey.Type:rbac.ResourceApiKey.AvailableActions(),
236236
rbac.ResourceGroup.Type: {policy.ActionCreate,policy.ActionUpdate},
237237
rbac.ResourceAssignRole.Type:rbac.ResourceAssignRole.AvailableActions(),
238238
rbac.ResourceSystem.Type: {policy.WildcardSymbol},
@@ -241,7 +241,7 @@ var (
241241
rbac.ResourceAssignOrgRole.Type: {policy.ActionRead,policy.ActionCreate,policy.ActionDelete},
242242
rbac.ResourceProvisionerDaemon.Type: {policy.ActionCreate,policy.ActionUpdate},
243243
rbac.ResourceUser.Type:rbac.ResourceUser.AvailableActions(),
244-
rbac.ResourceWorkspace.Type: {policy.ActionUpdate,policy.ActionDelete,policy.ActionWorkspaceBuild,policy.ActionSSH},
244+
rbac.ResourceWorkspace.Type: {policy.ActionUpdate,policy.ActionDelete,policy.ActionWorkspaceStart,policy.ActionWorkspaceStop,policy.ActionSSH},
245245
rbac.ResourceWorkspaceProxy.Type: {policy.ActionCreate,policy.ActionUpdate,policy.ActionDelete},
246246
}),
247247
Org:map[string][]rbac.Permission{},
@@ -2531,9 +2531,11 @@ func (q *querier) InsertWorkspaceBuild(ctx context.Context, arg database.InsertW
25312531
returnxerrors.Errorf("get workspace by id: %w",err)
25322532
}
25332533

2534-
varaction policy.Action=policy.ActionWorkspaceBuild
2534+
varaction policy.Action=policy.ActionWorkspaceStart
25352535
ifarg.Transition==database.WorkspaceTransitionDelete {
25362536
action=policy.ActionDelete
2537+
}elseifarg.Transition==database.WorkspaceTransitionStop {
2538+
action=policy.ActionWorkspaceStop
25372539
}
25382540

25392541
iferr=q.authorizeContext(ctx,action,w);err!=nil {
@@ -3280,7 +3282,7 @@ func (q *querier) UpsertAppSecurityKey(ctx context.Context, data string) error {
32803282
}
32813283

32823284
func (q*querier)UpsertApplicationName(ctx context.Context,valuestring)error {
3283-
iferr:=q.authorizeContext(ctx,policy.ActionCreate,rbac.ResourceDeploymentConfig);err!=nil {
3285+
iferr:=q.authorizeContext(ctx,policy.ActionUpdate,rbac.ResourceDeploymentConfig);err!=nil {
32843286
returnerr
32853287
}
32863288
returnq.db.UpsertApplicationName(ctx,value)
@@ -3294,7 +3296,7 @@ func (q *querier) UpsertDefaultProxy(ctx context.Context, arg database.UpsertDef
32943296
}
32953297

32963298
func (q*querier)UpsertHealthSettings(ctx context.Context,valuestring)error {
3297-
iferr:=q.authorizeContext(ctx,policy.ActionCreate,rbac.ResourceDeploymentConfig);err!=nil {
3299+
iferr:=q.authorizeContext(ctx,policy.ActionUpdate,rbac.ResourceDeploymentConfig);err!=nil {
32983300
returnerr
32993301
}
33003302
returnq.db.UpsertHealthSettings(ctx,value)

‎coderd/database/dbauthz/dbauthz_test.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,7 +1432,18 @@ func (s *MethodTestSuite) TestWorkspace() {
14321432
WorkspaceID:w.ID,
14331433
Transition:database.WorkspaceTransitionStart,
14341434
Reason:database.BuildReasonInitiator,
1435-
}).Asserts(w,policy.ActionWorkspaceBuild)
1435+
}).Asserts(w,policy.ActionWorkspaceStart)
1436+
}))
1437+
s.Run("Stop/InsertWorkspaceBuild",s.Subtest(func(db database.Store,check*expects) {
1438+
t:=dbgen.Template(s.T(),db, database.Template{})
1439+
w:=dbgen.Workspace(s.T(),db, database.Workspace{
1440+
TemplateID:t.ID,
1441+
})
1442+
check.Args(database.InsertWorkspaceBuildParams{
1443+
WorkspaceID:w.ID,
1444+
Transition:database.WorkspaceTransitionStop,
1445+
Reason:database.BuildReasonInitiator,
1446+
}).Asserts(w,policy.ActionWorkspaceStop)
14361447
}))
14371448
s.Run("Start/RequireActiveVersion/VersionMismatch/InsertWorkspaceBuild",s.Subtest(func(db database.Store,check*expects) {
14381449
t:=dbgen.Template(s.T(),db, database.Template{})
@@ -1454,7 +1465,7 @@ func (s *MethodTestSuite) TestWorkspace() {
14541465
Reason:database.BuildReasonInitiator,
14551466
TemplateVersionID:v.ID,
14561467
}).Asserts(
1457-
w,policy.ActionWorkspaceBuild,
1468+
w,policy.ActionWorkspaceStart,
14581469
t,policy.ActionUpdate,
14591470
)
14601471
}))
@@ -1482,7 +1493,7 @@ func (s *MethodTestSuite) TestWorkspace() {
14821493
Reason:database.BuildReasonInitiator,
14831494
TemplateVersionID:v.ID,
14841495
}).Asserts(
1485-
w,policy.ActionWorkspaceBuild,
1496+
w,policy.ActionWorkspaceStart,
14861497
)
14871498
}))
14881499
s.Run("Delete/InsertWorkspaceBuild",s.Subtest(func(db database.Store,check*expects) {

‎coderd/rbac/authz.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@ type RegoAuthorizer struct {
214214

215215
authorizeHist*prometheus.HistogramVec
216216
prepareHist prometheus.Histogram
217+
218+
// strict checking also verifies the inputs to the authorizer. Making sure
219+
// the action make sense for the input object.
220+
strictbool
217221
}
218222

219223
var_Authorizer= (*RegoAuthorizer)(nil)
@@ -235,6 +239,13 @@ func NewCachingAuthorizer(registry prometheus.Registerer) Authorizer {
235239
returnCacher(NewAuthorizer(registry))
236240
}
237241

242+
// NewStrictCachingAuthorizer is mainly just for testing.
243+
funcNewStrictCachingAuthorizer(registry prometheus.Registerer)Authorizer {
244+
auth:=NewAuthorizer(registry)
245+
auth.strict=true
246+
returnCacher(auth)
247+
}
248+
238249
funcNewAuthorizer(registry prometheus.Registerer)*RegoAuthorizer {
239250
queryOnce.Do(func() {
240251
varerrerror
@@ -321,6 +332,12 @@ type authSubject struct {
321332
// the object.
322333
// If an error is returned, the authorization is denied.
323334
func (aRegoAuthorizer)Authorize(ctx context.Context,subjectSubject,action policy.Action,objectObject)error {
335+
ifa.strict {
336+
iferr:=object.ValidAction(action);err!=nil {
337+
returnxerrors.Errorf("strict authz check: %w",err)
338+
}
339+
}
340+
324341
start:=time.Now()
325342
ctx,span:=tracing.StartSpan(ctx,
326343
trace.WithTimestamp(start),// Reuse the time.Now for metric and trace

‎coderd/rbac/authz_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func BenchmarkRBACAuthorize(b *testing.B) {
160160

161161
// There is no caching that occurs because a fresh context is used for each
162162
// call. And the context needs 'WithCacheCtx' to work.
163-
authorizer:=rbac.NewCachingAuthorizer(prometheus.NewRegistry())
163+
authorizer:=rbac.NewStrictCachingAuthorizer(prometheus.NewRegistry())
164164
// This benchmarks all the simple cases using just user permissions. Groups
165165
// are added as noise, but do not do anything.
166166
for_,c:=rangebenchCases {
@@ -187,7 +187,7 @@ func BenchmarkRBACAuthorizeGroups(b *testing.B) {
187187
uuid.MustParse("0632b012-49e0-4d70-a5b3-f4398f1dcd52"),
188188
uuid.MustParse("70dbaa7a-ea9c-4f68-a781-97b08af8461d"),
189189
)
190-
authorizer:=rbac.NewCachingAuthorizer(prometheus.NewRegistry())
190+
authorizer:=rbac.NewStrictCachingAuthorizer(prometheus.NewRegistry())
191191

192192
// Same benchmark cases, but this time groups will be used to match.
193193
// Some '*' permissions will still match, but using a fake action reduces
@@ -239,7 +239,7 @@ func BenchmarkRBACFilter(b *testing.B) {
239239
uuid.MustParse("70dbaa7a-ea9c-4f68-a781-97b08af8461d"),
240240
)
241241

242-
authorizer:=rbac.NewCachingAuthorizer(prometheus.NewRegistry())
242+
authorizer:=rbac.NewStrictCachingAuthorizer(prometheus.NewRegistry())
243243

244244
for_,c:=rangebenchCases {
245245
b.Run("PrepareOnly-"+c.Name,func(b*testing.B) {

‎coderd/rbac/input.json

Lines changed: 17 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,22 @@
11
{
2-
"action":"never-match-action",
3-
"object": {
4-
"id":"9046b041-58ed-47a3-9c3a-de302577875a",
5-
"owner":"00000000-0000-0000-0000-000000000000",
6-
"org_owner":"bf7b72bd-a2b1-4ef2-962c-1d698e0483f6",
7-
"type":"workspace",
8-
"acl_user_list": {
9-
"f041847d-711b-40da-a89a-ede39f70dc7f": ["create"]
10-
},
11-
"acl_group_list": {}
2+
"action":"build",
3+
"object":{
4+
"id":"c6ae3dfb-0e55-4eca-b263-8ceaf95ad056",
5+
"owner":"76df8ecb-a179-45cc-9a67-acc8b0512ee5",
6+
"org_owner":"021dcc96-562b-4a43-8405-0d287b5298df",
7+
"type":"workspace_dormant",
8+
"acl_user_list":null,
9+
"acl_group_list":null
1210
},
13-
"subject": {
14-
"id":"10d03e62-7703-4df5-a358-4f76577d4e2f",
15-
"roles": [
16-
{
17-
"name":"owner",
18-
"display_name":"Owner",
19-
"site": [
20-
{
21-
"negate":false,
22-
"resource_type":"*",
23-
"action":"*"
24-
}
25-
],
26-
"org": {},
27-
"user": []
28-
}
11+
"subject":{
12+
"FriendlyName":"testuser",
13+
"ID":"76df8ecb-a179-45cc-9a67-acc8b0512ee5",
14+
"Roles":[
15+
"owner",
16+
"member",
17+
"organization-member:021dcc96-562b-4a43-8405-0d287b5298df"
2918
],
30-
"groups": ["b617a647-b5d0-4cbe-9e40-26f89710bf18"],
31-
"scope": {
32-
"name":"Scope_all",
33-
"display_name":"All operations",
34-
"site": [
35-
{
36-
"negate":false,
37-
"resource_type":"*",
38-
"action":"*"
39-
}
40-
],
41-
"org": {},
42-
"user": [],
43-
"allow_list": ["*"]
44-
}
19+
"Groups":null,
20+
"Scope":"all"
4521
}
4622
}

‎coderd/rbac/object.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func (z Object) ValidAction(action policy.Action) error {
3939
returnfmt.Errorf("invalid type %q",z.Type)
4040
}
4141
if_,ok:=perms.Actions[action];!ok {
42-
returnfmt.Errorf("invalid action %q",action)
42+
returnfmt.Errorf("invalid action %q for type %q",action,z.Type)
4343
}
4444

4545
returnnil

‎coderd/rbac/object_gen.go

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/rbac/policy/policy.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ const (
1616
ActionApplicationConnectAction="application_connect"
1717
ActionViewInsightsAction="view_insights"
1818

19-
ActionWorkspaceBuildAction="build"
19+
ActionWorkspaceStartAction="start"
20+
ActionWorkspaceStopAction="stop"
2021

2122
ActionAssignAction="assign"
2223

@@ -51,8 +52,10 @@ var workspaceActions = map[Action]ActionDefinition{
5152
ActionUpdate:actDef("edit workspace settings (scheduling, permissions, parameters)"),
5253
ActionDelete:actDef("delete workspace"),
5354

54-
// Workspace provisioning
55-
ActionWorkspaceBuild:actDef("allows starting, stopping, and updating a workspace"),
55+
// Workspace provisioning. Start & stop are different so dormant workspaces can be
56+
// stopped, but not stared.
57+
ActionWorkspaceStart:actDef("allows starting a workspace"),
58+
ActionWorkspaceStop:actDef("allows stopping a workspace"),
5659

5760
// Running a workspace
5861
ActionSSH:actDef("ssh into a given workspace"),
@@ -104,12 +107,14 @@ var RBACPermissions = map[string]PermissionDefinition{
104107
},
105108
"audit_log": {
106109
Actions:map[Action]ActionDefinition{
107-
ActionRead:actDef("read audit logs"),
110+
ActionRead:actDef("read audit logs"),
111+
ActionCreate:actDef("create new audit log entries"),
108112
},
109113
},
110114
"deployment_config": {
111115
Actions:map[Action]ActionDefinition{
112-
ActionRead:actDef("read deployment config"),
116+
ActionRead:actDef("read deployment config"),
117+
ActionUpdate:actDef("updating health information"),
113118
},
114119
},
115120
"deployment_stats": {
@@ -173,7 +178,7 @@ var RBACPermissions = map[string]PermissionDefinition{
173178
},
174179
"debug_info": {
175180
Actions:map[Action]ActionDefinition{
176-
ActionUse:actDef("access to debug routes"),
181+
ActionRead:actDef("access to debug routes"),
177182
},
178183
},
179184
"system": {
@@ -189,6 +194,7 @@ var RBACPermissions = map[string]PermissionDefinition{
189194
ActionCreate:actDef("create an api key"),
190195
ActionRead:actDef("read api key details (secrets are not stored)"),
191196
ActionDelete:actDef("delete an api key"),
197+
ActionUpdate:actDef("update an api key, eg expires"),
192198
},
193199
},
194200
"tailnet_coordinator": {

‎coderd/rbac/roles.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
146146
// This adds back in the Workspace permissions.
147147
Permissions(map[string][]policy.Action{
148148
ResourceWorkspace.Type:ownerWorkspaceActions,
149-
ResourceWorkspaceDormant.Type: {policy.ActionRead,policy.ActionDelete,policy.ActionCreate,policy.ActionUpdate},
149+
ResourceWorkspaceDormant.Type: {policy.ActionRead,policy.ActionDelete,policy.ActionCreate,policy.ActionUpdate,policy.ActionWorkspaceStop},
150150
})...),
151151
Org:map[string][]Permission{},
152152
User: []Permission{},
@@ -167,7 +167,7 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
167167
User:append(allPermsExcept(ResourceWorkspaceDormant,ResourceUser,ResourceOrganizationMember),
168168
Permissions(map[string][]policy.Action{
169169
// Reduced permission set on dormant workspaces. No build, ssh, or exec
170-
ResourceWorkspaceDormant.Type: {policy.ActionRead,policy.ActionDelete,policy.ActionCreate,policy.ActionUpdate},
170+
ResourceWorkspaceDormant.Type: {policy.ActionRead,policy.ActionDelete,policy.ActionCreate,policy.ActionUpdate,policy.ActionWorkspaceStop},
171171

172172
// Users cannot do create/update/delete on themselves, but they
173173
// can read their own details.
@@ -272,7 +272,7 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
272272
Org:map[string][]Permission{
273273
// Org admins should not have workspace exec perms.
274274
organizationID:append(allPermsExcept(ResourceWorkspace,ResourceWorkspaceDormant),Permissions(map[string][]policy.Action{
275-
ResourceWorkspaceDormant.Type: {policy.ActionRead,policy.ActionDelete,policy.ActionCreate,policy.ActionUpdate},
275+
ResourceWorkspaceDormant.Type: {policy.ActionRead,policy.ActionDelete,policy.ActionCreate,policy.ActionUpdate,policy.ActionWorkspaceStop},
276276
ResourceWorkspace.Type:slice.Omit(ResourceWorkspace.AvailableActions(),policy.ActionApplicationConnect,policy.ActionSSH),
277277
})...),
278278
},

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp