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

Commit13dd79b

Browse files
committed
workspace dormancy
1 parent5ce4225 commit13dd79b

File tree

3 files changed

+60
-31
lines changed

3 files changed

+60
-31
lines changed

‎coderd/rbac/policy/policy.go

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,21 @@ func (a ActionDefinition) Requires() string {
8282
returnstrings.Join(fields,",")
8383
}
8484

85+
varworkspaceActions=map[Action]ActionDefinition{
86+
ActionCreate:actDef(fieldOwner|fieldOrg,"create a new workspace"),
87+
ActionRead:actDef(fieldOwner|fieldOrg|fieldACL,"read workspace data to view on the UI"),
88+
// TODO: Make updates more granular
89+
ActionUpdate:actDef(fieldOwner|fieldOrg|fieldACL,"edit workspace settings (scheduling, permissions, parameters)"),
90+
ActionDelete:actDef(fieldOwner|fieldOrg|fieldACL,"delete workspace"),
91+
92+
// Workspace provisioning
93+
ActionWorkspaceBuild:actDef(fieldOwner|fieldOrg|fieldACL,"allows starting, stopping, and updating a workspace"),
94+
95+
// Running a workspace
96+
ActionSSH:actDef(fieldOwner|fieldOrg|fieldACL,"ssh into a given workspace"),
97+
ActionApplicationConnect:actDef(fieldOwner|fieldOrg|fieldACL,"connect to workspace apps via browser"),
98+
}
99+
85100
// RBACPermissions is indexed by the type
86101
varRBACPermissions=map[string]PermissionDefinition{
87102
// Wildcard is every object, and the action "*" provides all actions.
@@ -104,23 +119,11 @@ var RBACPermissions = map[string]PermissionDefinition{
104119
},
105120
},
106121
"workspace": {
107-
Actions:map[Action]ActionDefinition{
108-
ActionCreate:actDef(fieldOwner|fieldOrg,"create a new workspace"),
109-
ActionRead:actDef(fieldOwner|fieldOrg|fieldACL,"read workspace data to view on the UI"),
110-
// TODO: Make updates more granular
111-
ActionUpdate:actDef(fieldOwner|fieldOrg|fieldACL,"edit workspace settings (scheduling, permissions, parameters)"),
112-
ActionDelete:actDef(fieldOwner|fieldOrg|fieldACL,"delete workspace"),
113-
114-
// Workspace provisioning
115-
ActionWorkspaceBuild:actDef(fieldOwner|fieldOrg|fieldACL,"allows starting, stopping, and updating a workspace"),
116-
117-
// Running a workspace
118-
ActionSSH:actDef(fieldOwner|fieldOrg|fieldACL,"ssh into a given workspace"),
119-
ActionApplicationConnect:actDef(fieldOwner|fieldOrg|fieldACL,"connect to workspace apps via browser"),
120-
},
122+
Actions:workspaceActions,
121123
},
124+
// Dormant workspaces have the same perms as workspaces.
122125
"workspace_dormant": {
123-
Actions:map[Action]ActionDefinition{},
126+
Actions:workspaceActions,
124127
},
125128
"workspace_proxy": {
126129
Actions:map[Action]ActionDefinition{
@@ -194,8 +197,9 @@ var RBACPermissions = map[string]PermissionDefinition{
194197
"organization": {
195198
Actions:map[Action]ActionDefinition{
196199
ActionCreate:actDef(0,"create an organization"),
197-
ActionRead:actDef(0,"read organizations"),
198-
ActionDelete:actDef(0,"delete a organization"),
200+
ActionRead:actDef(fieldOrg,"read organizations"),
201+
ActionUpdate:actDef(fieldOrg,"update an organization"),
202+
ActionDelete:actDef(fieldOrg,"delete an organization"),
199203
},
200204
},
201205
"organization_member": {

‎coderd/rbac/roles.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
145145
allPermsExcept(ResourceWorkspaceDormant,ResourceWorkspace),
146146
// This adds back in the Workspace permissions.
147147
Permissions(map[string][]policy.Action{
148-
ResourceWorkspace.Type:ownerWorkspaceActions,
148+
ResourceWorkspace.Type:ownerWorkspaceActions,
149+
ResourceWorkspaceDormant.Type: {policy.ActionRead,policy.ActionDelete,policy.ActionCreate,policy.ActionUpdate},
149150
})...),
150151
Org:map[string][]Permission{},
151152
User: []Permission{},
@@ -165,6 +166,9 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
165166
Org:map[string][]Permission{},
166167
User:append(allPermsExcept(ResourceWorkspaceDormant,ResourceUser,ResourceOrganizationMember),
167168
Permissions(map[string][]policy.Action{
169+
// Reduced permission set on dormant workspaces. No build, ssh, or exec
170+
ResourceWorkspaceDormant.Type: {policy.ActionRead,policy.ActionDelete,policy.ActionCreate,policy.ActionUpdate},
171+
168172
// Users cannot do create/update/delete on themselves, but they
169173
// can read their own details.
170174
ResourceUser.Type: {policy.ActionRead,policy.ActionReadPersonal,policy.ActionUpdatePersonal},
@@ -268,7 +272,8 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
268272
Org:map[string][]Permission{
269273
// Org admins should not have workspace exec perms.
270274
organizationID:append(allPermsExcept(ResourceWorkspace,ResourceWorkspaceDormant),Permissions(map[string][]policy.Action{
271-
ResourceWorkspace.Type:slice.Omit(ResourceWorkspace.AvailableActions(),policy.ActionApplicationConnect,policy.ActionSSH),
275+
ResourceWorkspaceDormant.Type: {policy.ActionRead,policy.ActionDelete,policy.ActionCreate,policy.ActionUpdate},
276+
ResourceWorkspace.Type:slice.Omit(ResourceWorkspace.AvailableActions(),policy.ActionApplicationConnect,policy.ActionSSH),
272277
})...),
273278
},
274279
User: []Permission{},

‎coderd/rbac/roles_test.go

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ func TestRolePermissions(t *testing.T) {
265265
},
266266
{
267267
Name:"APIKey",
268-
Actions: []policy.Action{policy.ActionCreate,policy.ActionRead,policy.ActionUpdate,policy.ActionDelete},
268+
Actions: []policy.Action{policy.ActionCreate,policy.ActionRead,policy.ActionDelete},
269269
Resource:rbac.ResourceApiKey.WithID(apiKeyID).WithOwner(currentUser.String()),
270270
AuthorizeMap:map[bool][]authSubject{
271271
true: {owner,orgMemberMe,memberMe},
@@ -332,7 +332,16 @@ func TestRolePermissions(t *testing.T) {
332332
},
333333
{
334334
Name:"WorkspaceDormant",
335-
Actions:rbac.AllActions(),
335+
Actions:crud,
336+
Resource:rbac.ResourceWorkspaceDormant.WithID(uuid.New()).InOrg(orgID).WithOwner(memberMe.Actor.ID),
337+
AuthorizeMap:map[bool][]authSubject{
338+
true: {orgMemberMe,orgAdmin,owner},
339+
false: {userAdmin,otherOrgAdmin,otherOrgMember,memberMe,templateAdmin},
340+
},
341+
},
342+
{
343+
Name:"WorkspaceDormantUse",
344+
Actions: []policy.Action{policy.ActionWorkspaceBuild,policy.ActionApplicationConnect,policy.ActionSSH},
336345
Resource:rbac.ResourceWorkspaceDormant.WithID(uuid.New()).InOrg(orgID).WithOwner(memberMe.Actor.ID),
337346
AuthorizeMap:map[bool][]authSubject{
338347
true: {},
@@ -478,7 +487,7 @@ func TestRolePermissions(t *testing.T) {
478487
},
479488
{
480489
Name:"Oauth2Token",
481-
Actions:crud,
490+
Actions:[]policy.Action{policy.ActionCreate,policy.ActionRead,policy.ActionDelete},
482491
Resource:rbac.ResourceOauth2AppCodeToken,
483492
AuthorizeMap:map[bool][]authSubject{
484493
true: {owner},
@@ -514,6 +523,7 @@ func TestRolePermissions(t *testing.T) {
514523
}
515524
}
516525

526+
passed:=true
517527
for_,c:=rangetestCases {
518528
c:=c
519529
// nolint:tparallel -- These share the same remainingPermissions map
@@ -524,6 +534,13 @@ func TestRolePermissions(t *testing.T) {
524534
}
525535

526536
for_,action:=rangec.Actions {
537+
err:=c.Resource.ValidAction(action)
538+
ok:=assert.NoError(t,err,"%q is not a valid action for type %q",action,c.Resource.Type)
539+
if!ok {
540+
passed=passed&&assert.NoError(t,err,"%q is not a valid action for type %q",action,c.Resource.Type)
541+
continue
542+
}
543+
527544
forresult,subjs:=rangec.AuthorizeMap {
528545
for_,subj:=rangesubjs {
529546
delete(remainingSubjs,subj.Name)
@@ -538,9 +555,9 @@ func TestRolePermissions(t *testing.T) {
538555
delete(remainingPermissions[c.Resource.Type],action)
539556
err:=auth.Authorize(context.Background(),actor,action,c.Resource)
540557
ifresult {
541-
assert.NoError(t,err,fmt.Sprintf("Should pass: %s",msg))
558+
passed=passed&&assert.NoError(t,err,fmt.Sprintf("Should pass: %s",msg))
542559
}else {
543-
assert.ErrorContains(t,err,"forbidden",fmt.Sprintf("Should fail: %s",msg))
560+
passed=passed&&assert.ErrorContains(t,err,"forbidden",fmt.Sprintf("Should fail: %s",msg))
544561
}
545562
}
546563
}
@@ -549,13 +566,16 @@ func TestRolePermissions(t *testing.T) {
549566
})
550567
}
551568

552-
forrtype,v:=rangeremainingPermissions {
553-
// nolint:tparallel -- Making a subtest for easier diagnosing failures.
554-
t.Run(fmt.Sprintf("%s-AllActions",rtype),func(t*testing.T) {
555-
iflen(v)>0 {
556-
assert.Equal(t,map[policy.Action]bool{},v,"remaining permissions should be empty for type %q",rtype)
557-
}
558-
})
569+
// Only run these if the tests on top passed. Otherwise, the error output is too noisy.
570+
ifpassed {
571+
forrtype,v:=rangeremainingPermissions {
572+
// nolint:tparallel -- Making a subtest for easier diagnosing failures.
573+
t.Run(fmt.Sprintf("%s-AllActions",rtype),func(t*testing.T) {
574+
iflen(v)>0 {
575+
assert.Equal(t,map[policy.Action]bool{},v,"remaining permissions should be empty for type %q",rtype)
576+
}
577+
})
578+
}
559579
}
560580
}
561581

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp