diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go index a4e28741ce988..78f597fa55369 100644 --- a/coderd/provisionerdserver/provisionerdserver.go +++ b/coderd/provisionerdserver/provisionerdserver.go @@ -595,17 +595,24 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo }) } - roles, err := s.Database.GetAuthorizationUserRoles(ctx, owner.ID) + allUserRoles, err := s.Database.GetAuthorizationUserRoles(ctx, owner.ID) if err != nil { return nil, failJob(fmt.Sprintf("get owner authorization roles: %s", err)) } ownerRbacRoles := []*sdkproto.Role{} - for _, role := range roles.Roles { - if s.OrganizationID == uuid.Nil { - ownerRbacRoles = append(ownerRbacRoles, &sdkproto.Role{Name: role, OrgId: ""}) - continue + roles, err := allUserRoles.RoleNames() + if err == nil { + for _, role := range roles { + if role.OrganizationID != uuid.Nil && role.OrganizationID != s.OrganizationID { + continue // Only include site wide and org specific roles + } + + orgID := role.OrganizationID.String() + if role.OrganizationID == uuid.Nil { + orgID = "" + } + ownerRbacRoles = append(ownerRbacRoles, &sdkproto.Role{Name: role.Name, OrgId: orgID}) } - ownerRbacRoles = append(ownerRbacRoles, &sdkproto.Role{Name: role, OrgId: s.OrganizationID.String()}) } protoJob.Type = &proto.AcquiredJob_WorkspaceBuild_{ diff --git a/coderd/provisionerdserver/provisionerdserver_test.go b/coderd/provisionerdserver/provisionerdserver_test.go index 9a9eb91ac8b73..caeef8a9793b7 100644 --- a/coderd/provisionerdserver/provisionerdserver_test.go +++ b/coderd/provisionerdserver/provisionerdserver_test.go @@ -6,6 +6,7 @@ import ( "encoding/json" "io" "net/url" + "slices" "strconv" "strings" "sync" @@ -22,6 +23,7 @@ import ( "storj.io/drpc" "cdr.dev/slog/sloggers/slogtest" + "github.com/coder/coder/v2/coderd/rbac" "github.com/coder/quartz" "github.com/coder/serpent" @@ -203,6 +205,20 @@ func TestAcquireJob(t *testing.T) { GroupID: group1.ID, }) require.NoError(t, err) + dbgen.OrganizationMember(t, db, database.OrganizationMember{ + UserID: user.ID, + OrganizationID: pd.OrganizationID, + Roles: []string{rbac.RoleOrgAuditor()}, + }) + + // Add extra erronous roles + secondOrg := dbgen.Organization(t, db, database.Organization{}) + dbgen.OrganizationMember(t, db, database.OrganizationMember{ + UserID: user.ID, + OrganizationID: secondOrg.ID, + Roles: []string{rbac.RoleOrgAuditor()}, + }) + link := dbgen.UserLink(t, db, database.UserLink{ LoginType: database.LoginTypeOIDC, UserID: user.ID, @@ -350,7 +366,7 @@ func TestAcquireJob(t *testing.T) { WorkspaceOwnerEmail: user.Email, WorkspaceOwnerName: user.Name, WorkspaceOwnerOidcAccessToken: link.OAuthAccessToken, - WorkspaceOwnerGroups: []string{group1.Name}, + WorkspaceOwnerGroups: []string{"Everyone", group1.Name}, WorkspaceId: workspace.ID.String(), WorkspaceOwnerId: user.ID.String(), TemplateId: template.ID.String(), @@ -361,11 +377,15 @@ func TestAcquireJob(t *testing.T) { WorkspaceOwnerSshPrivateKey: sshKey.PrivateKey, WorkspaceBuildId: build.ID.String(), WorkspaceOwnerLoginType: string(user.LoginType), - WorkspaceOwnerRbacRoles: []*sdkproto.Role{{Name: "member", OrgId: pd.OrganizationID.String()}}, + WorkspaceOwnerRbacRoles: []*sdkproto.Role{{Name: rbac.RoleOrgMember(), OrgId: pd.OrganizationID.String()}, {Name: "member", OrgId: ""}, {Name: rbac.RoleOrgAuditor(), OrgId: pd.OrganizationID.String()}}, } if prebuiltWorkspace { wantedMetadata.IsPrebuild = true } + + slices.SortFunc(wantedMetadata.WorkspaceOwnerRbacRoles, func(a, b *sdkproto.Role) int { + return strings.Compare(a.Name+a.OrgId, b.Name+b.OrgId) + }) want, err := json.Marshal(&proto.AcquiredJob_WorkspaceBuild_{ WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{ WorkspaceBuildId: build.ID.String(), @@ -467,6 +487,13 @@ func TestAcquireJob(t *testing.T) { job, err := tc.acquire(ctx, srv) require.NoError(t, err) + // sort + if wk, ok := job.Type.(*proto.AcquiredJob_WorkspaceBuild_); ok { + slices.SortFunc(wk.WorkspaceBuild.Metadata.WorkspaceOwnerRbacRoles, func(a, b *sdkproto.Role) int { + return strings.Compare(a.Name+a.OrgId, b.Name+b.OrgId) + }) + } + got, err := json.Marshal(job.Type) require.NoError(t, err)