mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
test: add unit test to verify group permission behavior (#14223)
* test: add unit test to verify group permission behavior * Update coderd/database/dbauthz/groupsauth_test.go --------- Co-authored-by: Cian Johnston <cian@coder.com>
This commit is contained in:
co-authored by
Cian Johnston
parent
0338250d86
commit
8af8c77e2a
@@ -0,0 +1,168 @@
|
||||
package dbauthz_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cdr.dev/slog/sloggers/slogtest"
|
||||
"github.com/coder/coder/v2/coderd/coderdtest"
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/database/dbauthz"
|
||||
"github.com/coder/coder/v2/coderd/database/dbgen"
|
||||
"github.com/coder/coder/v2/coderd/database/dbmem"
|
||||
"github.com/coder/coder/v2/coderd/database/dbtestutil"
|
||||
"github.com/coder/coder/v2/coderd/rbac"
|
||||
)
|
||||
|
||||
// nolint:tparallel
|
||||
func TestGroupsAuth(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if dbtestutil.WillUsePostgres() {
|
||||
t.Skip("this test would take too long to run on postgres")
|
||||
}
|
||||
|
||||
authz := rbac.NewAuthorizer(prometheus.NewRegistry())
|
||||
|
||||
db := dbauthz.New(dbmem.New(), authz, slogtest.Make(t, &slogtest.Options{
|
||||
IgnoreErrors: true,
|
||||
}), coderdtest.AccessControlStorePointer())
|
||||
|
||||
ownerCtx := dbauthz.As(context.Background(), rbac.Subject{
|
||||
ID: "owner",
|
||||
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.RoleOwner()}.Expand())),
|
||||
Groups: []string{},
|
||||
Scope: rbac.ExpandableScope(rbac.ScopeAll),
|
||||
})
|
||||
|
||||
org := dbgen.Organization(t, db, database.Organization{})
|
||||
group := dbgen.Group(t, db, database.Group{
|
||||
OrganizationID: org.ID,
|
||||
})
|
||||
|
||||
var users []database.User
|
||||
for i := 0; i < 5; i++ {
|
||||
user := dbgen.User(t, db, database.User{})
|
||||
users = append(users, user)
|
||||
err := db.InsertGroupMember(ownerCtx, database.InsertGroupMemberParams{
|
||||
UserID: user.ID,
|
||||
GroupID: group.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
totalMembers := len(users)
|
||||
testCases := []struct {
|
||||
Name string
|
||||
Subject rbac.Subject
|
||||
ReadGroup bool
|
||||
ReadMembers bool
|
||||
MembersExpected int
|
||||
}{
|
||||
{
|
||||
Name: "Owner",
|
||||
Subject: rbac.Subject{
|
||||
ID: "owner",
|
||||
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.RoleOwner()}.Expand())),
|
||||
Groups: []string{},
|
||||
Scope: rbac.ExpandableScope(rbac.ScopeAll),
|
||||
},
|
||||
ReadGroup: true,
|
||||
ReadMembers: true,
|
||||
MembersExpected: totalMembers,
|
||||
},
|
||||
{
|
||||
Name: "UserAdmin",
|
||||
Subject: rbac.Subject{
|
||||
ID: "useradmin",
|
||||
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.RoleUserAdmin()}.Expand())),
|
||||
Groups: []string{},
|
||||
Scope: rbac.ExpandableScope(rbac.ScopeAll),
|
||||
},
|
||||
ReadGroup: true,
|
||||
ReadMembers: true,
|
||||
MembersExpected: totalMembers,
|
||||
},
|
||||
{
|
||||
Name: "OrgAdmin",
|
||||
Subject: rbac.Subject{
|
||||
ID: "orgadmin",
|
||||
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.ScopedRoleOrgAdmin(org.ID)}.Expand())),
|
||||
Groups: []string{},
|
||||
Scope: rbac.ExpandableScope(rbac.ScopeAll),
|
||||
},
|
||||
ReadGroup: true,
|
||||
ReadMembers: true,
|
||||
MembersExpected: totalMembers,
|
||||
},
|
||||
{
|
||||
Name: "OrgUserAdmin",
|
||||
Subject: rbac.Subject{
|
||||
ID: "orgUserAdmin",
|
||||
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.ScopedRoleOrgUserAdmin(org.ID)}.Expand())),
|
||||
Groups: []string{},
|
||||
Scope: rbac.ExpandableScope(rbac.ScopeAll),
|
||||
},
|
||||
ReadGroup: true,
|
||||
ReadMembers: true,
|
||||
MembersExpected: totalMembers,
|
||||
},
|
||||
{
|
||||
Name: "GroupMember",
|
||||
Subject: rbac.Subject{
|
||||
ID: users[0].ID.String(),
|
||||
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.ScopedRoleOrgMember(org.ID)}.Expand())),
|
||||
Groups: []string{
|
||||
group.Name,
|
||||
},
|
||||
Scope: rbac.ExpandableScope(rbac.ScopeAll),
|
||||
},
|
||||
// TODO: currently group members cannot see their own groups.
|
||||
// If this is fixed, these booleans should be flipped to true.
|
||||
ReadGroup: false,
|
||||
ReadMembers: false,
|
||||
// TODO: If fixed, they should only be able to see themselves
|
||||
// MembersExpected: 1,
|
||||
},
|
||||
{
|
||||
// Org admin in the incorrect organization
|
||||
Name: "DifferentOrgAdmin",
|
||||
Subject: rbac.Subject{
|
||||
ID: "orgadmin",
|
||||
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.ScopedRoleOrgUserAdmin(uuid.New())}.Expand())),
|
||||
Groups: []string{},
|
||||
Scope: rbac.ExpandableScope(rbac.ScopeAll),
|
||||
},
|
||||
ReadGroup: false,
|
||||
ReadMembers: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
actorCtx := dbauthz.As(context.Background(), tc.Subject)
|
||||
_, err := db.GetGroupByID(actorCtx, group.ID)
|
||||
if tc.ReadGroup {
|
||||
require.NoError(t, err, "group read")
|
||||
} else {
|
||||
require.Error(t, err, "group read")
|
||||
}
|
||||
|
||||
members, err := db.GetGroupMembersByGroupID(actorCtx, group.ID)
|
||||
if tc.ReadMembers {
|
||||
require.NoError(t, err, "member read")
|
||||
require.Len(t, members, tc.MembersExpected, "member count found does not match")
|
||||
} else {
|
||||
require.Error(t, err, "member read")
|
||||
require.True(t, dbauthz.IsNotAuthorizedError(err), "not authorized error")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user