chore: create type for unique role names (#13506)

* chore: create type for unique role names

Using `string` was confusing when something should be combined with
org context, and when not to. Naming this new name, "RoleIdentifier"
This commit is contained in:
Steven Masley
2024-06-11 08:55:28 -05:00
committed by GitHub
parent c9cca9d56e
commit 5ccf5084e8
50 changed files with 553 additions and 458 deletions
+9 -1
View File
@@ -438,8 +438,16 @@ func ExtractAPIKey(rw http.ResponseWriter, r *http.Request, cfg ExtractAPIKeyCon
})
}
roleNames, err := roles.RoleNames()
if err != nil {
return write(http.StatusInternalServerError, codersdk.Response{
Message: "Internal Server Error",
Detail: err.Error(),
})
}
//nolint:gocritic // Permission to lookup custom roles the user has assigned.
rbacRoles, err := rolestore.Expand(dbauthz.AsSystemRestricted(ctx), cfg.DB, roles.Roles)
rbacRoles, err := rolestore.Expand(dbauthz.AsSystemRestricted(ctx), cfg.DB, roleNames)
if err != nil {
return write(http.StatusInternalServerError, codersdk.Response{
Message: "Failed to expand authenticated user roles",
+21 -19
View File
@@ -27,27 +27,26 @@ func TestExtractUserRoles(t *testing.T) {
t.Parallel()
testCases := []struct {
Name string
AddUser func(db database.Store) (database.User, []string, string)
AddUser func(db database.Store) (database.User, []rbac.RoleIdentifier, string)
}{
{
Name: "Member",
AddUser: func(db database.Store) (database.User, []string, string) {
roles := []string{}
user, token := addUser(t, db, roles...)
return user, append(roles, rbac.RoleMember()), token
AddUser: func(db database.Store) (database.User, []rbac.RoleIdentifier, string) {
user, token := addUser(t, db)
return user, []rbac.RoleIdentifier{rbac.RoleMember()}, token
},
},
{
Name: "Admin",
AddUser: func(db database.Store) (database.User, []string, string) {
roles := []string{rbac.RoleOwner()}
Name: "Owner",
AddUser: func(db database.Store) (database.User, []rbac.RoleIdentifier, string) {
roles := []string{codersdk.RoleOwner}
user, token := addUser(t, db, roles...)
return user, append(roles, rbac.RoleMember()), token
return user, []rbac.RoleIdentifier{rbac.RoleOwner(), rbac.RoleMember()}, token
},
},
{
Name: "OrgMember",
AddUser: func(db database.Store) (database.User, []string, string) {
AddUser: func(db database.Store) (database.User, []rbac.RoleIdentifier, string) {
roles := []string{}
user, token := addUser(t, db, roles...)
org, err := db.InsertOrganization(context.Background(), database.InsertOrganizationParams{
@@ -68,15 +67,15 @@ func TestExtractUserRoles(t *testing.T) {
Roles: orgRoles,
})
require.NoError(t, err)
return user, append(roles, append(orgRoles, rbac.RoleMember(), rbac.ScopedRoleOrgMember(org.ID))...), token
return user, []rbac.RoleIdentifier{rbac.RoleMember(), rbac.ScopedRoleOrgMember(org.ID)}, token
},
},
{
Name: "MultipleOrgMember",
AddUser: func(db database.Store) (database.User, []string, string) {
roles := []string{}
user, token := addUser(t, db, roles...)
roles = append(roles, rbac.RoleMember())
AddUser: func(db database.Store) (database.User, []rbac.RoleIdentifier, string) {
expected := []rbac.RoleIdentifier{}
user, token := addUser(t, db)
expected = append(expected, rbac.RoleMember())
for i := 0; i < 3; i++ {
organization, err := db.InsertOrganization(context.Background(), database.InsertOrganizationParams{
ID: uuid.New(),
@@ -89,8 +88,8 @@ func TestExtractUserRoles(t *testing.T) {
orgRoles := []string{}
if i%2 == 0 {
orgRoles = append(orgRoles, rbac.RoleOrgAdmin())
roles = append(roles, rbac.ScopedRoleOrgAdmin(organization.ID))
orgRoles = append(orgRoles, codersdk.RoleOrganizationAdmin)
expected = append(expected, rbac.ScopedRoleOrgAdmin(organization.ID))
}
_, err = db.InsertOrganizationMember(context.Background(), database.InsertOrganizationMemberParams{
OrganizationID: organization.ID,
@@ -100,9 +99,9 @@ func TestExtractUserRoles(t *testing.T) {
Roles: orgRoles,
})
require.NoError(t, err)
roles = append(roles, rbac.ScopedRoleOrgMember(organization.ID))
expected = append(expected, rbac.ScopedRoleOrgMember(organization.ID))
}
return user, roles, token
return user, expected, token
},
},
}
@@ -147,6 +146,9 @@ func addUser(t *testing.T, db database.Store, roles ...string) (database.User, s
id, secret = randomAPIKeyParts()
hashed = sha256.Sum256([]byte(secret))
)
if roles == nil {
roles = []string{}
}
user, err := db.InsertUser(context.Background(), database.InsertUserParams{
ID: uuid.New(),
+2 -1
View File
@@ -11,6 +11,7 @@ import (
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database/dbauthz"
"github.com/coder/coder/v2/coderd/httpmw"
"github.com/coder/coder/v2/coderd/rbac"
)
func TestAsAuthzSystem(t *testing.T) {
@@ -34,7 +35,7 @@ func TestAsAuthzSystem(t *testing.T) {
actor, ok := dbauthz.ActorFromContext(req.Context())
assert.True(t, ok, "actor should exist")
assert.False(t, userActor.Equal(actor), "systemActor should not be the user actor")
assert.Contains(t, actor.Roles.Names(), "system", "should have system role")
assert.Contains(t, actor.Roles.Names(), rbac.RoleIdentifier{Name: "system"}, "should have system role")
})
mwAssertUser := mwAssert(func(req *http.Request) {
+2 -3
View File
@@ -16,7 +16,6 @@ import (
"github.com/coder/coder/v2/coderd/database/dbmem"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/coderd/httpmw"
"github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/testutil"
)
@@ -152,11 +151,11 @@ func TestOrganizationParam(t *testing.T) {
_ = dbgen.OrganizationMember(t, db, database.OrganizationMember{
OrganizationID: organization.ID,
UserID: user.ID,
Roles: []string{rbac.ScopedRoleOrgMember(organization.ID)},
Roles: []string{codersdk.RoleOrganizationMember},
})
_, err := db.UpdateUserRoles(ctx, database.UpdateUserRolesParams{
ID: user.ID,
GrantedRoles: []string{rbac.RoleTemplateAdmin()},
GrantedRoles: []string{codersdk.RoleTemplateAdmin},
})
require.NoError(t, err)
+1 -2
View File
@@ -16,7 +16,6 @@ import (
"github.com/coder/coder/v2/coderd/database/dbgen"
"github.com/coder/coder/v2/coderd/database/dbmem"
"github.com/coder/coder/v2/coderd/httpmw"
"github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/codersdk"
)
@@ -117,7 +116,7 @@ func TestRateLimit(t *testing.T) {
db := dbmem.New()
u := dbgen.User(t, db, database.User{
RBACRoles: []string{rbac.RoleOwner()},
RBACRoles: []string{codersdk.RoleOwner},
})
_, key := dbgen.APIKey(t, db, database.APIKey{UserID: u.ID})
+10 -1
View File
@@ -119,9 +119,18 @@ func ExtractWorkspaceAgentAndLatestBuild(opts ExtractWorkspaceAgentAndLatestBuil
return
}
roleNames, err := roles.RoleNames()
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal server error",
Detail: err.Error(),
})
return
}
subject := rbac.Subject{
ID: row.Workspace.OwnerID.String(),
Roles: rbac.RoleNames(roles.Roles),
Roles: rbac.RoleIdentifiers(roleNames),
Groups: roles.Groups,
Scope: rbac.WorkspaceAgentScope(rbac.WorkspaceAgentScopeParams{
WorkspaceID: row.Workspace.ID,