Skip to content

Commit 04a2cae

Browse files
committed
chore: add owner to resourceUser rbac object
1 parent e508d9a commit 04a2cae

File tree

8 files changed

+40
-15
lines changed

8 files changed

+40
-15
lines changed

coderd/coderdtest/authorize.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func (RBACAsserter) convertObjects(t *testing.T, objs ...interface{}) []rbac.Obj
116116
case codersdk.TemplateVersion:
117117
robj = rbac.ResourceTemplate.InOrg(obj.OrganizationID)
118118
case codersdk.User:
119-
robj = rbac.ResourceUser.WithID(obj.ID)
119+
robj = rbac.ResourceUser.WithID(obj.ID).WithOwner(obj.ID.String())
120120
case codersdk.Workspace:
121121
robj = rbac.ResourceWorkspace.WithID(obj.ID).InOrg(obj.OrganizationID).WithOwner(obj.OwnerID.String())
122122
default:

coderd/database/dbauthz/dbauthz.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -1181,15 +1181,15 @@ func (q *querier) GetProvisionerLogsAfterID(ctx context.Context, arg database.Ge
11811181
}
11821182

11831183
func (q *querier) GetQuotaAllowanceForUser(ctx context.Context, userID uuid.UUID) (int64, error) {
1184-
err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceUser.WithID(userID))
1184+
err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceUser.WithID(userID).WithOwner(userID.String()))
11851185
if err != nil {
11861186
return -1, err
11871187
}
11881188
return q.db.GetQuotaAllowanceForUser(ctx, userID)
11891189
}
11901190

11911191
func (q *querier) GetQuotaConsumedForUser(ctx context.Context, userID uuid.UUID) (int64, error) {
1192-
err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceUser.WithID(userID))
1192+
err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceUser.WithID(userID).WithOwner(userID.String()))
11931193
if err != nil {
11941194
return -1, err
11951195
}
@@ -1436,7 +1436,7 @@ func (q *querier) GetUsers(ctx context.Context, arg database.GetUsersParams) ([]
14361436
// itself.
14371437
func (q *querier) GetUsersByIDs(ctx context.Context, ids []uuid.UUID) ([]database.User, error) {
14381438
for _, uid := range ids {
1439-
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceUser.WithID(uid)); err != nil {
1439+
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceUser.WithID(uid).WithOwner(uid.String())); err != nil {
14401440
return nil, err
14411441
}
14421442
}
@@ -1942,7 +1942,7 @@ func (q *querier) InsertUserGroupsByName(ctx context.Context, arg database.Inser
19421942

19431943
// TODO: Should this be in system.go?
19441944
func (q *querier) InsertUserLink(ctx context.Context, arg database.InsertUserLinkParams) (database.UserLink, error) {
1945-
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceUser.WithID(arg.UserID)); err != nil {
1945+
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceUser.WithID(arg.UserID).WithOwner(arg.UserID.String())); err != nil {
19461946
return database.UserLink{}, err
19471947
}
19481948
return q.db.InsertUserLink(ctx, arg)

coderd/database/dbauthz/dbauthz_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ func (s *MethodTestSuite) TestOrganization() {
521521
ma := dbgen.OrganizationMember(s.T(), db, database.OrganizationMember{OrganizationID: oa.ID})
522522
mb := dbgen.OrganizationMember(s.T(), db, database.OrganizationMember{OrganizationID: ob.ID})
523523
check.Args([]uuid.UUID{ma.UserID, mb.UserID}).
524-
Asserts(rbac.ResourceUser.WithID(ma.UserID), rbac.ActionRead, rbac.ResourceUser.WithID(mb.UserID), rbac.ActionRead)
524+
Asserts(rbac.ResourceUser.WithID(ma.UserID).WithOwner(ma.UserID.String()), rbac.ActionRead, rbac.ResourceUser.WithID(mb.UserID).WithOwner(mb.UserID.String()), rbac.ActionRead)
525525
}))
526526
s.Run("GetOrganizationMemberByUserID", s.Subtest(func(db database.Store, check *expects) {
527527
mem := dbgen.OrganizationMember(s.T(), db, database.OrganizationMember{})

coderd/database/modelmethods.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ func (m GetOrganizationIDsByMemberIDsRow) RBACObject() rbac.Object {
201201
// TODO: This feels incorrect as we are really returning a list of orgmembers.
202202
// This return type should be refactored to return a list of orgmembers, not this
203203
// special type.
204-
return rbac.ResourceUser.WithID(m.UserID)
204+
return rbac.ResourceUser.WithID(m.UserID).WithOwner(m.UserID.String())
205205
}
206206

207207
func (o Organization) RBACObject() rbac.Object {
@@ -233,15 +233,15 @@ func (f File) RBACObject() rbac.Object {
233233
// If you are trying to get the RBAC object for the UserData, use
234234
// u.UserDataRBACObject() instead.
235235
func (u User) RBACObject() rbac.Object {
236-
return rbac.ResourceUser.WithID(u.ID)
236+
return rbac.ResourceUser.WithID(u.ID).WithOwner(u.ID.String())
237237
}
238238

239239
func (u User) UserDataRBACObject() rbac.Object {
240240
return rbac.ResourceUserData.WithID(u.ID).WithOwner(u.ID.String())
241241
}
242242

243243
func (u GetUsersRow) RBACObject() rbac.Object {
244-
return rbac.ResourceUser.WithID(u.ID)
244+
return rbac.ResourceUser.WithID(u.ID).WithOwner(u.ID.String())
245245
}
246246

247247
func (u GitSSHKey) RBACObject() rbac.Object {

coderd/database/modelqueries.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,10 @@ type userQuerier interface {
256256
}
257257

258258
func (q *sqlQuerier) GetAuthorizedUserCount(ctx context.Context, arg GetFilteredUserCountParams, prepared rbac.PreparedAuthorized) (int64, error) {
259-
authorizedFilter, err := prepared.CompileToSQL(ctx, rbac.ConfigWithoutACL())
259+
authorizedFilter, err := prepared.CompileToSQL(ctx, regosql.ConvertConfig{
260+
VariableConverter: regosql.UserConverter(),
261+
})
262+
260263
if err != nil {
261264
return -1, xerrors.Errorf("compile authorized filter: %w", err)
262265
}

coderd/rbac/regosql/configs.go

+16
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,22 @@ func userACLMatcher(m sqltypes.VariableMatcher) sqltypes.VariableMatcher {
2222
return ACLGroupMatcher(m, "user_acl", []string{"input", "object", "acl_user_list"})
2323
}
2424

25+
func UserConverter() *sqltypes.VariableConverter {
26+
matcher := sqltypes.NewVariableConverter().RegisterMatcher(
27+
resourceIDMatcher(),
28+
// Users are never owned by an organization.
29+
sqltypes.AlwaysFalse(organizationOwnerMatcher()),
30+
// Users are always owned by themselves.
31+
sqltypes.StringVarMatcher("id :: text", []string{"input", "object", "owner"}),
32+
)
33+
matcher.RegisterMatcher(
34+
// No ACLs on the user type
35+
sqltypes.AlwaysFalse(groupACLMatcher(matcher)),
36+
sqltypes.AlwaysFalse(userACLMatcher(matcher)),
37+
)
38+
return matcher
39+
}
40+
2541
func TemplateConverter() *sqltypes.VariableConverter {
2642
matcher := sqltypes.NewVariableConverter().RegisterMatcher(
2743
resourceIDMatcher(),

coderd/rbac/roles.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,18 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
145145
Name: member,
146146
DisplayName: "",
147147
Site: Permissions(map[string][]Action{
148-
// All users can read all other users and know they exist.
149-
ResourceUser.Type: {ActionRead},
150148
ResourceRoleAssignment.Type: {ActionRead},
151149
// All users can see the provisioner daemons.
152150
ResourceProvisionerDaemon.Type: {ActionRead},
153151
}),
154-
Org: map[string][]Permission{},
155-
User: allPermsExcept(ResourceWorkspaceLocked),
152+
Org: map[string][]Permission{},
153+
User: append(allPermsExcept(ResourceWorkspaceLocked, ResourceUser),
154+
Permissions(map[string][]Action{
155+
// Users cannot do create/update/delete on themselves, but they
156+
// can read their own details.
157+
ResourceUser.Type: {ActionRead},
158+
})...,
159+
),
156160
}.withCachedRegoValue()
157161

158162
auditorRole := Role{
@@ -163,6 +167,7 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
163167
// are not in.
164168
ResourceTemplate.Type: {ActionRead},
165169
ResourceAuditLog.Type: {ActionRead},
170+
ResourceUser.Type: {ActionRead},
166171
}),
167172
Org: map[string][]Permission{},
168173
User: []Permission{},
@@ -172,6 +177,7 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
172177
Name: templateAdmin,
173178
DisplayName: "Template Admin",
174179
Site: Permissions(map[string][]Action{
180+
ResourceUser.Type: {ActionRead},
175181
ResourceTemplate.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},
176182
// CRUD all files, even those they did not upload.
177183
ResourceFile.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},

coderd/rbac/roles_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func TestRolePermissions(t *testing.T) {
106106
{
107107
Name: "MyUser",
108108
Actions: []rbac.Action{rbac.ActionRead},
109-
Resource: rbac.ResourceUser.WithID(currentUser),
109+
Resource: rbac.ResourceUser.WithID(currentUser).WithOwner(currentUser.String()),
110110
AuthorizeMap: map[bool][]authSubject{
111111
true: {owner, memberMe, orgMemberMe, orgAdmin, otherOrgMember, otherOrgAdmin, templateAdmin, userAdmin},
112112
false: {},

0 commit comments

Comments
 (0)