Skip to content

Commit 36d9f5d

Browse files
committed
feat: implement WorkspaceCreationBan org role
Using negative permissions, this role prevents a user's ability to create & delete a workspace within a given organization. Workspaces are uniquely owned by an org and a user, so the org has to supercede the user permission with a negative permission.
1 parent 8f33c6d commit 36d9f5d

File tree

1 file changed

+72
-35
lines changed

1 file changed

+72
-35
lines changed

coderd/rbac/roles.go

Lines changed: 72 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,12 @@ const (
2727
customSiteRole string = "custom-site-role"
2828
customOrganizationRole string = "custom-organization-role"
2929

30-
orgAdmin string = "organization-admin"
31-
orgMember string = "organization-member"
32-
orgAuditor string = "organization-auditor"
33-
orgUserAdmin string = "organization-user-admin"
34-
orgTemplateAdmin string = "organization-template-admin"
30+
orgAdmin string = "organization-admin"
31+
orgMember string = "organization-member"
32+
orgAuditor string = "organization-auditor"
33+
orgUserAdmin string = "organization-user-admin"
34+
orgTemplateAdmin string = "organization-template-admin"
35+
orgWorkspaceCreationBan string = "organization-workspace-creation-ban"
3536
)
3637

3738
func init() {
@@ -159,6 +160,10 @@ func RoleOrgTemplateAdmin() string {
159160
return orgTemplateAdmin
160161
}
161162

163+
func RoleOrgWorkspaceCreationBan() string {
164+
return orgWorkspaceCreationBan
165+
}
166+
162167
// ScopedRoleOrgAdmin is the org role with the organization ID
163168
func ScopedRoleOrgAdmin(organizationID uuid.UUID) RoleIdentifier {
164169
return RoleIdentifier{Name: RoleOrgAdmin(), OrganizationID: organizationID}
@@ -181,6 +186,10 @@ func ScopedRoleOrgTemplateAdmin(organizationID uuid.UUID) RoleIdentifier {
181186
return RoleIdentifier{Name: RoleOrgTemplateAdmin(), OrganizationID: organizationID}
182187
}
183188

189+
func ScopedRoleOrgWorkspaceCreationBan(organizationID uuid.UUID) RoleIdentifier {
190+
return RoleIdentifier{Name: RoleOrgWorkspaceCreationBan(), OrganizationID: organizationID}
191+
}
192+
184193
func allPermsExcept(excepts ...Objecter) []Permission {
185194
resources := AllResources()
186195
var perms []Permission
@@ -496,6 +505,31 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
496505
User: []Permission{},
497506
}
498507
},
508+
// orgWorkspaceCreationBan prevents creating & deleting workspaces. This
509+
// overrides any permissions granted by the org or user level. It accomplishes
510+
// this by using negative permissions.
511+
orgWorkspaceCreationBan: func(organizationID uuid.UUID) Role {
512+
return Role{
513+
Identifier: RoleIdentifier{Name: orgWorkspaceCreationBan, OrganizationID: organizationID},
514+
DisplayName: "Organization Workspace Creation Ban",
515+
Site: []Permission{},
516+
Org: map[string][]Permission{
517+
organizationID.String(): {
518+
{
519+
Negate: true,
520+
ResourceType: ResourceWorkspace.Type,
521+
Action: policy.ActionCreate,
522+
},
523+
{
524+
Negate: true,
525+
ResourceType: ResourceWorkspace.Type,
526+
Action: policy.ActionDelete,
527+
},
528+
},
529+
},
530+
User: []Permission{},
531+
}
532+
},
499533
}
500534
}
501535

@@ -506,44 +540,47 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
506540
// map[actor_role][assign_role]<can_assign>
507541
var assignRoles = map[string]map[string]bool{
508542
"system": {
509-
owner: true,
510-
auditor: true,
511-
member: true,
512-
orgAdmin: true,
513-
orgMember: true,
514-
orgAuditor: true,
515-
orgUserAdmin: true,
516-
orgTemplateAdmin: true,
517-
templateAdmin: true,
518-
userAdmin: true,
519-
customSiteRole: true,
520-
customOrganizationRole: true,
543+
owner: true,
544+
auditor: true,
545+
member: true,
546+
orgAdmin: true,
547+
orgMember: true,
548+
orgAuditor: true,
549+
orgUserAdmin: true,
550+
orgTemplateAdmin: true,
551+
orgWorkspaceCreationBan: true,
552+
templateAdmin: true,
553+
userAdmin: true,
554+
customSiteRole: true,
555+
customOrganizationRole: true,
521556
},
522557
owner: {
523-
owner: true,
524-
auditor: true,
525-
member: true,
526-
orgAdmin: true,
527-
orgMember: true,
528-
orgAuditor: true,
529-
orgUserAdmin: true,
530-
orgTemplateAdmin: true,
531-
templateAdmin: true,
532-
userAdmin: true,
533-
customSiteRole: true,
534-
customOrganizationRole: true,
558+
owner: true,
559+
auditor: true,
560+
member: true,
561+
orgAdmin: true,
562+
orgMember: true,
563+
orgAuditor: true,
564+
orgUserAdmin: true,
565+
orgTemplateAdmin: true,
566+
orgWorkspaceCreationBan: true,
567+
templateAdmin: true,
568+
userAdmin: true,
569+
customSiteRole: true,
570+
customOrganizationRole: true,
535571
},
536572
userAdmin: {
537573
member: true,
538574
orgMember: true,
539575
},
540576
orgAdmin: {
541-
orgAdmin: true,
542-
orgMember: true,
543-
orgAuditor: true,
544-
orgUserAdmin: true,
545-
orgTemplateAdmin: true,
546-
customOrganizationRole: true,
577+
orgAdmin: true,
578+
orgMember: true,
579+
orgAuditor: true,
580+
orgUserAdmin: true,
581+
orgTemplateAdmin: true,
582+
orgWorkspaceCreationBan: true,
583+
customOrganizationRole: true,
547584
},
548585
orgUserAdmin: {
549586
orgMember: true,

0 commit comments

Comments
 (0)