@@ -395,11 +395,13 @@ var (
395395Identifier : rbac.RoleIdentifier {Name :"subagentapi" },
396396DisplayName :"Sub Agent API" ,
397397Site : []rbac.Permission {},
398- User :rbac .Permissions (map [string ][]policy.Action {
399- rbac .ResourceWorkspace .Type : {policy .ActionRead ,policy .ActionUpdate ,policy .ActionCreateAgent ,policy .ActionDeleteAgent },
400- }),
398+ User : []rbac.Permission {},
401399ByOrgID :map [string ]rbac.OrgPermissions {
402- orgID .String (): {},
400+ orgID .String (): {
401+ Member :rbac .Permissions (map [string ][]policy.Action {
402+ rbac .ResourceWorkspace .Type : {policy .ActionRead ,policy .ActionUpdate ,policy .ActionCreateAgent ,policy .ActionDeleteAgent },
403+ }),
404+ },
403405},
404406},
405407}),
@@ -1290,14 +1292,17 @@ func (q *querier) customRoleCheck(ctx context.Context, role database.CustomRole)
12901292return xerrors .Errorf ("invalid role: %w" ,err )
12911293}
12921294
1293- if len (rbacRole .ByOrgID )> 0 && len (rbacRole .Site )> 0 {
1294- // This is a choice to keep roles simple. If we allow mixing site and org scoped perms, then knowing who can
1295- // do what gets more complicated.
1296- return xerrors .Errorf ("invalid custom role, cannot assign both org and site permissions at the same time" )
1295+ if len (rbacRole .ByOrgID )> 0 && (len (rbacRole .Site )> 0 || len (rbacRole .User )> 0 ) {
1296+ // This is a choice to keep roles simple. If we allow mixing site and org
1297+ // scoped perms, then knowing who can do what gets more complicated. Roles
1298+ // should either be entirely org-scoped or entirely unrelated to
1299+ // organizations.
1300+ return xerrors .Errorf ("invalid custom role, cannot assign both org-scoped and site/user permissions at the same time" )
12971301}
12981302
12991303if len (rbacRole .ByOrgID )> 1 {
1300- // Again to avoid more complexity in our roles
1304+ // Again to avoid more complexity in our roles. Roles are limited to one
1305+ // organization.
13011306return xerrors .Errorf ("invalid custom role, cannot assign permissions to more than 1 org at a time" )
13021307}
13031308
@@ -1313,7 +1318,18 @@ func (q *querier) customRoleCheck(ctx context.Context, role database.CustomRole)
13131318for _ ,orgPerm := range perms .Org {
13141319err := q .customRoleEscalationCheck (ctx ,act ,orgPerm , rbac.Object {OrgID :orgID ,Type :orgPerm .ResourceType })
13151320if err != nil {
1316- return xerrors .Errorf ("org=%q: %w" ,orgID ,err )
1321+ return xerrors .Errorf ("org=%q: org: %w" ,orgID ,err )
1322+ }
1323+ }
1324+ for _ ,memberPerm := range perms .Member {
1325+ // The person giving the permission should still be required to have
1326+ // the permissions throughout the org in order to give individuals the
1327+ // same permission among their own resources, since the role can be given
1328+ // to anyone. The `Owner` is intentionally omitted from the `Object` to
1329+ // enforce this.
1330+ err := q .customRoleEscalationCheck (ctx ,act ,memberPerm , rbac.Object {OrgID :orgID ,Type :memberPerm .ResourceType })
1331+ if err != nil {
1332+ return xerrors .Errorf ("org=%q: member: %w" ,orgID ,err )
13171333}
13181334}
13191335}
@@ -1331,8 +1347,8 @@ func (q *querier) customRoleCheck(ctx context.Context, role database.CustomRole)
13311347func (q * querier )authorizeProvisionerJob (ctx context.Context ,job database.ProvisionerJob )error {
13321348switch job .Type {
13331349case database .ProvisionerJobTypeWorkspaceBuild :
1334- // Authorized call to get workspace build. If we can read the build, we
1335- //can read the job.
1350+ // Authorized call to get workspace build. If we can read the build, we can
1351+ // read the job.
13361352_ ,err := q .GetWorkspaceBuildByJobID (ctx ,job .ID )
13371353if err != nil {
13381354return xerrors .Errorf ("fetch related workspace build: %w" ,err )
@@ -1375,8 +1391,8 @@ func (q *querier) ActivityBumpWorkspace(ctx context.Context, arg database.Activi
13751391}
13761392
13771393func (q * querier )AllUserIDs (ctx context.Context ,includeSystem bool ) ([]uuid.UUID ,error ) {
1378- // Although this technically only reads users, only system-related functions should be
1379- // allowed to call this.
1394+ // Although this technically only reads users, only system-related functions
1395+ //should be allowed to call this.
13801396if err := q .authorizeContext (ctx ,policy .ActionRead ,rbac .ResourceSystem );err != nil {
13811397return nil ,err
13821398}
@@ -1395,8 +1411,8 @@ func (q *querier) ArchiveUnusedTemplateVersions(ctx context.Context, arg databas
13951411}
13961412
13971413func (q * querier )BatchUpdateWorkspaceLastUsedAt (ctx context.Context ,arg database.BatchUpdateWorkspaceLastUsedAtParams )error {
1398- // Could be any workspace and checking auth to each workspace is overkill for the purpose
1399- // of this function.
1414+ // Could be any workspace and checking auth to each workspace is overkill for
1415+ //the purpose of this function.
14001416if err := q .authorizeContext (ctx ,policy .ActionUpdate ,rbac .ResourceWorkspace .All ());err != nil {
14011417return err
14021418}