Skip to content

Commit c91b9c8

Browse files
Emyrkjohnstcn
authored andcommitted
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>
1 parent bb7fec0 commit c91b9c8

File tree

1 file changed

+168
-0
lines changed

1 file changed

+168
-0
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
package dbauthz_test
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/google/uuid"
8+
"github.com/prometheus/client_golang/prometheus"
9+
"github.com/stretchr/testify/require"
10+
11+
"cdr.dev/slog/sloggers/slogtest"
12+
"github.com/coder/coder/v2/coderd/coderdtest"
13+
"github.com/coder/coder/v2/coderd/database"
14+
"github.com/coder/coder/v2/coderd/database/dbauthz"
15+
"github.com/coder/coder/v2/coderd/database/dbgen"
16+
"github.com/coder/coder/v2/coderd/database/dbmem"
17+
"github.com/coder/coder/v2/coderd/database/dbtestutil"
18+
"github.com/coder/coder/v2/coderd/rbac"
19+
)
20+
21+
// nolint:tparallel
22+
func TestGroupsAuth(t *testing.T) {
23+
t.Parallel()
24+
25+
if dbtestutil.WillUsePostgres() {
26+
t.Skip("this test would take too long to run on postgres")
27+
}
28+
29+
authz := rbac.NewAuthorizer(prometheus.NewRegistry())
30+
31+
db := dbauthz.New(dbmem.New(), authz, slogtest.Make(t, &slogtest.Options{
32+
IgnoreErrors: true,
33+
}), coderdtest.AccessControlStorePointer())
34+
35+
ownerCtx := dbauthz.As(context.Background(), rbac.Subject{
36+
ID: "owner",
37+
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.RoleOwner()}.Expand())),
38+
Groups: []string{},
39+
Scope: rbac.ExpandableScope(rbac.ScopeAll),
40+
})
41+
42+
org := dbgen.Organization(t, db, database.Organization{})
43+
group := dbgen.Group(t, db, database.Group{
44+
OrganizationID: org.ID,
45+
})
46+
47+
var users []database.User
48+
for i := 0; i < 5; i++ {
49+
user := dbgen.User(t, db, database.User{})
50+
users = append(users, user)
51+
err := db.InsertGroupMember(ownerCtx, database.InsertGroupMemberParams{
52+
UserID: user.ID,
53+
GroupID: group.ID,
54+
})
55+
require.NoError(t, err)
56+
}
57+
58+
totalMembers := len(users)
59+
testCases := []struct {
60+
Name string
61+
Subject rbac.Subject
62+
ReadGroup bool
63+
ReadMembers bool
64+
MembersExpected int
65+
}{
66+
{
67+
Name: "Owner",
68+
Subject: rbac.Subject{
69+
ID: "owner",
70+
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.RoleOwner()}.Expand())),
71+
Groups: []string{},
72+
Scope: rbac.ExpandableScope(rbac.ScopeAll),
73+
},
74+
ReadGroup: true,
75+
ReadMembers: true,
76+
MembersExpected: totalMembers,
77+
},
78+
{
79+
Name: "UserAdmin",
80+
Subject: rbac.Subject{
81+
ID: "useradmin",
82+
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.RoleUserAdmin()}.Expand())),
83+
Groups: []string{},
84+
Scope: rbac.ExpandableScope(rbac.ScopeAll),
85+
},
86+
ReadGroup: true,
87+
ReadMembers: true,
88+
MembersExpected: totalMembers,
89+
},
90+
{
91+
Name: "OrgAdmin",
92+
Subject: rbac.Subject{
93+
ID: "orgadmin",
94+
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.ScopedRoleOrgAdmin(org.ID)}.Expand())),
95+
Groups: []string{},
96+
Scope: rbac.ExpandableScope(rbac.ScopeAll),
97+
},
98+
ReadGroup: true,
99+
ReadMembers: true,
100+
MembersExpected: totalMembers,
101+
},
102+
{
103+
Name: "OrgUserAdmin",
104+
Subject: rbac.Subject{
105+
ID: "orgUserAdmin",
106+
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.ScopedRoleOrgUserAdmin(org.ID)}.Expand())),
107+
Groups: []string{},
108+
Scope: rbac.ExpandableScope(rbac.ScopeAll),
109+
},
110+
ReadGroup: true,
111+
ReadMembers: true,
112+
MembersExpected: totalMembers,
113+
},
114+
{
115+
Name: "GroupMember",
116+
Subject: rbac.Subject{
117+
ID: users[0].ID.String(),
118+
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.ScopedRoleOrgMember(org.ID)}.Expand())),
119+
Groups: []string{
120+
group.Name,
121+
},
122+
Scope: rbac.ExpandableScope(rbac.ScopeAll),
123+
},
124+
// TODO: currently group members cannot see their own groups.
125+
// If this is fixed, these booleans should be flipped to true.
126+
ReadGroup: false,
127+
ReadMembers: false,
128+
// TODO: If fixed, they should only be able to see themselves
129+
// MembersExpected: 1,
130+
},
131+
{
132+
// Org admin in the incorrect organization
133+
Name: "DifferentOrgAdmin",
134+
Subject: rbac.Subject{
135+
ID: "orgadmin",
136+
Roles: rbac.Roles(must(rbac.RoleIdentifiers{rbac.ScopedRoleOrgUserAdmin(uuid.New())}.Expand())),
137+
Groups: []string{},
138+
Scope: rbac.ExpandableScope(rbac.ScopeAll),
139+
},
140+
ReadGroup: false,
141+
ReadMembers: false,
142+
},
143+
}
144+
145+
for _, tc := range testCases {
146+
tc := tc
147+
t.Run(tc.Name, func(t *testing.T) {
148+
t.Parallel()
149+
150+
actorCtx := dbauthz.As(context.Background(), tc.Subject)
151+
_, err := db.GetGroupByID(actorCtx, group.ID)
152+
if tc.ReadGroup {
153+
require.NoError(t, err, "group read")
154+
} else {
155+
require.Error(t, err, "group read")
156+
}
157+
158+
members, err := db.GetGroupMembersByGroupID(actorCtx, group.ID)
159+
if tc.ReadMembers {
160+
require.NoError(t, err, "member read")
161+
require.Len(t, members, tc.MembersExpected, "member count found does not match")
162+
} else {
163+
require.Error(t, err, "member read")
164+
require.True(t, dbauthz.IsNotAuthorizedError(err), "not authorized error")
165+
}
166+
})
167+
}
168+
}

0 commit comments

Comments
 (0)