@@ -282,8 +282,9 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
282
282
// Note: even without PrebuiltWorkspace permissions, access is still granted via Workspace permissions.
283
283
ResourcePrebuiltWorkspace .Type : {policy .ActionUpdate ,policy .ActionDelete },
284
284
})... ),
285
- Org :map [string ][]Permission {},
286
- User : []Permission {},
285
+ Org :map [string ][]Permission {},
286
+ User : []Permission {},
287
+ OrgMember :map [string ][]Permission {},
287
288
}.withCachedRegoValue ()
288
289
289
290
memberRole := Role {
@@ -296,19 +297,14 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
296
297
ResourceWorkspaceProxy .Type : {policy .ActionRead },
297
298
}),
298
299
Org :map [string ][]Permission {},
299
- User :append (allPermsExcept (ResourceWorkspaceDormant ,ResourcePrebuiltWorkspace ,ResourceUser ,ResourceOrganizationMember ),
300
+ User :append (allPermsExcept (ResourceWorkspace , ResourceWorkspaceDormant ,ResourcePrebuiltWorkspace ,ResourceUser ,ResourceOrganizationMember ),
300
301
Permissions (map [string ][]policy.Action {
301
- // Reduced permission set on dormant workspaces. No build, ssh, or exec
302
- ResourceWorkspaceDormant .Type : {policy .ActionRead ,policy .ActionDelete ,policy .ActionCreate ,policy .ActionUpdate ,policy .ActionWorkspaceStop ,policy .ActionCreateAgent ,policy .ActionDeleteAgent },
303
302
// Users cannot do create/update/delete on themselves, but they
304
303
// can read their own details.
305
304
ResourceUser .Type : {policy .ActionRead ,policy .ActionReadPersonal ,policy .ActionUpdatePersonal },
306
- // Can read their own organization member record
307
- ResourceOrganizationMember .Type : {policy .ActionRead },
308
- // Users can create provisioner daemons scoped to themselves.
309
- ResourceProvisionerDaemon .Type : {policy .ActionRead ,policy .ActionCreate ,policy .ActionRead ,policy .ActionUpdate },
310
305
})... ,
311
306
),
307
+ OrgMember :map [string ][]Permission {},
312
308
}.withCachedRegoValue ()
313
309
314
310
auditorRole := Role {
@@ -331,8 +327,9 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
331
327
// Allow auditors to query aibridge interceptions.
332
328
ResourceAibridgeInterception .Type : {policy .ActionRead },
333
329
}),
334
- Org :map [string ][]Permission {},
335
- User : []Permission {},
330
+ Org :map [string ][]Permission {},
331
+ User : []Permission {},
332
+ OrgMember :map [string ][]Permission {},
336
333
}.withCachedRegoValue ()
337
334
338
335
templateAdminRole := Role {
@@ -354,8 +351,9 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
354
351
ResourceOrganization .Type : {policy .ActionRead },
355
352
ResourceOrganizationMember .Type : {policy .ActionRead },
356
353
}),
357
- Org :map [string ][]Permission {},
358
- User : []Permission {},
354
+ Org :map [string ][]Permission {},
355
+ User : []Permission {},
356
+ OrgMember :map [string ][]Permission {},
359
357
}.withCachedRegoValue ()
360
358
361
359
userAdminRole := Role {
@@ -378,8 +376,9 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
378
376
// Manage org membership based on OIDC claims
379
377
ResourceIdpsyncSettings .Type : {policy .ActionRead ,policy .ActionUpdate },
380
378
}),
381
- Org :map [string ][]Permission {},
382
- User : []Permission {},
379
+ Org :map [string ][]Permission {},
380
+ User : []Permission {},
381
+ OrgMember :map [string ][]Permission {},
383
382
}.withCachedRegoValue ()
384
383
385
384
builtInRoles = map [string ]func (orgID uuid.UUID )Role {
@@ -430,7 +429,8 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
430
429
ResourcePrebuiltWorkspace .Type : {policy .ActionUpdate ,policy .ActionDelete },
431
430
})... ),
432
431
},
433
- User : []Permission {},
432
+ User : []Permission {},
433
+ OrgMember :map [string ][]Permission {},
434
434
}
435
435
},
436
436
@@ -452,6 +452,21 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
452
452
}),
453
453
},
454
454
User : []Permission {},
455
+ OrgMember :map [string ][]Permission {
456
+ organizationID .String ():Permissions (map [string ][]policy.Action {
457
+ // Users can create provisioner daemons scoped to themselves.
458
+ // All provisioners still need an organization relation as well.
459
+ ResourceProvisionerDaemon .Type :ResourceProvisionerDaemon .AvailableActions (),
460
+ // All group members can read their own group membership
461
+ ResourceGroupMember .Type : {policy .ActionRead },
462
+ ResourceInboxNotification .Type : {policy .ActionCreate ,policy .ActionRead ,policy .ActionUpdate },
463
+ ResourceWorkspace .Type :ResourceWorkspace .AvailableActions (),
464
+ // Reduced permission set on dormant workspaces. No build, ssh, or exec
465
+ ResourceWorkspaceDormant .Type : {policy .ActionRead ,policy .ActionDelete ,policy .ActionCreate ,policy .ActionUpdate ,policy .ActionWorkspaceStop ,policy .ActionCreateAgent ,policy .ActionDeleteAgent },
466
+ // Can read their own organization member record
467
+ ResourceOrganizationMember .Type : {policy .ActionRead },
468
+ }),
469
+ },
455
470
}
456
471
},
457
472
orgAuditor :func (organizationID uuid.UUID )Role {
@@ -471,7 +486,8 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
471
486
ResourceOrganizationMember .Type : {policy .ActionRead },
472
487
}),
473
488
},
474
- User : []Permission {},
489
+ User : []Permission {},
490
+ OrgMember :map [string ][]Permission {},
475
491
}
476
492
},
477
493
orgUserAdmin :func (organizationID uuid.UUID )Role {
@@ -495,7 +511,8 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
495
511
ResourceIdpsyncSettings .Type : {policy .ActionRead ,policy .ActionUpdate },
496
512
}),
497
513
},
498
- User : []Permission {},
514
+ User : []Permission {},
515
+ OrgMember :map [string ][]Permission {},
499
516
}
500
517
},
501
518
orgTemplateAdmin :func (organizationID uuid.UUID )Role {
@@ -522,7 +539,8 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
522
539
ResourceProvisionerJobs .Type : {policy .ActionRead ,policy .ActionUpdate ,policy .ActionCreate },
523
540
}),
524
541
},
525
- User : []Permission {},
542
+ User : []Permission {},
543
+ OrgMember :map [string ][]Permission {},
526
544
}
527
545
},
528
546
// orgWorkspaceCreationBan prevents creating & deleting workspaces. This
@@ -557,7 +575,8 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
557
575
},
558
576
},
559
577
},
560
- User : []Permission {},
578
+ User : []Permission {},
579
+ OrgMember :map [string ][]Permission {},
561
580
}
562
581
},
563
582
}
@@ -678,19 +697,22 @@ type Role struct {
678
697
Identifier RoleIdentifier `json:"name"`
679
698
// DisplayName is used for UI purposes. If the role has no display name,
680
699
// that means the UI should never display it.
681
- DisplayName string `json:"display_name"`
682
- Site []Permission `json:"site"`
683
- // Org is a map of orgid to permissions. We represent orgid as a string.
684
- // We scope the organizations in the role so we can easily combine all the
685
- // roles.
686
- Org map [string ][]Permission `json:"org"`
687
- User []Permission `json:"user"`
700
+ DisplayName string `json:"display_name"`
701
+ Site []Permission `json:"site"`
702
+ User []Permission `json:"user"`
703
+ ByOrgID map [string ]RolePermissionsByOrgID `json:"by_org_id"`
688
704
689
705
// cachedRegoValue can be used to cache the rego value for this role.
690
706
// This is helpful for static roles that never change.
691
707
cachedRegoValue ast.Value
692
708
}
693
709
710
+ type RolePermissionsByOrgID struct {
711
+ // Org is a map of organization IDs to permissions. Grouping by organization
712
+ // makes roles easy to combine.
713
+ Org []Permission `json:"org"`
714
+ }
715
+
694
716
// Valid will check all it's permissions and ensure they are all correct
695
717
// according to the policy. This verifies every action specified make sense
696
718
// for the given resource.