Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix: allow group members to read group information#14200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation

@hugodutka
Copy link
Contributor

Fixes#13988. See the issue for background information.

This PR:

  • allows Group members to see they are part of the group
  • allows Group members to see the total count of that group's members even if they are not permitted to read detailed information about them, like username or email
  • exposes a new endpoint under/organizations/{organization}/users/{user}/reduced-groups that returns an array ofReducedGroup objects. These objects contain basic information about the group and the total member count.
  • makes the account page (/settings/account) use this endpoint to display information about groups

I asked questions about permission scope in the issue, but didn't get an answer in time, so I assumed that by default:

  • group members should be able to see they are part of the group
  • they should be able to read the total group members count
  • they shouldn't be able to access detailed information about the group members

Let me know if these assumptions are correct.

This is my first PR to Coder, and I'm not that familiar with the codebase, so I'm very much open to feedback and suggestions. :)

Emyrk reacted with hooray emojikylecarbs reacted with eyes emoji
@cdr-botcdr-botbot added the communityPull Requests and issues created by the community. labelAug 7, 2024
@github-actions
Copy link

github-actionsbot commentedAug 7, 2024
edited
Loading

All contributors have signed the CLA ✍️ ✅
Posted by theCLA Assistant Lite bot.

@hugodutka
Copy link
ContributorAuthor

I have read the CLA Document and I hereby sign the CLA

cdrcommunity added a commit to coder/cla that referenced this pull requestAug 7, 2024
Copy link
Member

@EmyrkEmyrk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This has made me realize that groups andusers are pretty intertwined, but we should probably have aGroupMember resource that helps handle some of these permission edge cases.

they shouldn't be able to access detailed information about the group members

This is true, and maybe we should just handle this all the way at the database layer. I know originally we returneddatabase.User because the tablegroup_members has almost no information and is basically useless without more info. So we returned the user.

But we could do something like we do for templates.

Basically, all template queries use the viewtemplates_with_names to join in relevant username, icon, etc information.

This ends up being yourReducedGroup, and optionally you could do theTotalMemberCount there 🤷‍♂️.

SQLc config to make the template view the primary model:https://github.com/coder/coder/blob/main/coderd/database/sqlc.yaml#L77-L78

PR example of updating said view:https://github.com/coder/coder/pull/13858/files

P.S: This is touching many parts of the code with some weak documentation and examples. There is an effort to document some of the RBAC stuff here:#14065

This PR is solving some fundamental problems with groups that should be fixed, and really happy to see this PR coming in 👍

@hugodutka
Copy link
ContributorAuthor

Thank you for the review@Emyrk. Couple of questions:

GroupMember resource

we should probably have a GroupMember resource

I considered this before and found some issues:

  • We don't have much control over custom roles in customer deployments. Any role with Group read permissions would need to be updated with the GroupMember permissions to keep on working as before. I'm not sure if "custom roles" is a widely used feature, but customers would probably need to be informed about this change.
  • We probably should rework the authz checks onInsertGroupMember,DeleteGroupMemberFromGroup, making this a bigger PR

Do you think we should add the new resource given these problems?

GroupMember DB View

I like this idea. It would also simplify querying for members of theEveryone group.

This ends up being yourReducedGroup, and optionally you could do theTotalMemberCount there 🤷‍♂️.

If we add theTotalMemberCount field tocodersdk.Group as you suggested then we don't need theReducedGroup type at all, so I don't think we need the column in the view.

Emyrk reacted with thumbs up emoji

@Emyrk
Copy link
Member

Thank you for the review@Emyrk. Couple of questions:

GroupMember resource

we should probably have a GroupMember resource

I considered this before and found some issues:

  • We don't have much control over custom roles in customer deployments. Any role with Group read permissions would need to be updated with the GroupMember permissions to keep on working as before. I'm not sure if "custom roles" is a widely used feature, but customers would probably need to be informed about this change.

Custom roles is not yet released, it's in experimental. So there are currently no custom_roles in the wild.

You are correct, adding related resources causes an issue when making roles. As granting 1 half of the relation doesn't really make much sense, and there is no obvious linkage between the two.

But this is a flaw of our current RBAC, and it already exists in a few places. The extra resource is easier to understand then the ACL workaround you have in place imo.

The good news of the custom_roles though is that we control the interface to making custom roles. Currently, it's basically a 1:1 with permissions, but we could implement some nicer UI and auto create these linkages. So the custom_roles endpoint or frontend could assumegroup_member.read ifgroup.read is assigned for example.

So tl;dr, this issue exists for other resources today, and I think we can solve this somewhere else.

Actually I do not think we do. When you insert/delete a member from the group, you are not accessing the group member, you are mutating theResourceGroup still imo. A Group is a set of users, if you are mutating the set, then we should useResourceGroup.

If you are reading/updating an individual member, then it makes sense to useResourceGroupMember.


A final note on all of this. If we model this as aResourceGroupMember, we can actually end up doing the authz check in SQL like we do forusers.

As deployments grow, we could easily be fetching a few thousand users, and doing 1k authz checks isn't very efficient (they are in memory and can be ~1ms).

So if we model things as we have been discussing, it's a fast follow up to optimize into a SQL query later.

hugodutka reacted with thumbs up emoji

@hugodutkahugodutkaforce-pushed thehugodutka/13988-group-member-read-permissions branch 3 times, most recently from3930c6b toe07e1d9CompareAugust 9, 2024 17:38
@hugodutka
Copy link
ContributorAuthor

hugodutka commentedAug 9, 2024
edited
Loading

@Emyrk, I adjusted the PR according to your feedback.

List of changes:

  • created agroup_members_expanded database view
  • configured sqlc to use the view as the source of theGroupMember object
  • rewrote group member queries to use the view
  • created the RBAC resourceResourceGroupMember and added it to roles which hadGroup permissions
  • rewrote dbauthz queries to use the new RBAC object
  • refactored code which uses the queries to work with theGroupMember return type (instead ofUser)
  • addedTotalMemberCount tocodersdk.Group
  • removed the/organizations/{organization}/users/{user}/reduced-groups route
  • rolled back frontend changes to use the previous groups by organization endpoint

Let me know if this matches what you had in mind. I'll fix the tests then.

Emyrk reacted with thumbs up emoji

Copy link
Member

@EmyrkEmyrk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This is overall looking good 👍

I created a test to mess around with some of this in an easier setting:
#14223

If I get a review of it intomain, it'll be easier to use for your testing. Right now I just copy pasted it in to check out the code paths.

hugodutka reacted with thumbs up emoji
Comment on lines +1 to +40
CREATE VIEW
group_members_expanded
AS
-- If the group is a user made group, then we need to check the group_members table.
-- If it is the "Everyone" group, then we need to check the organization_members table.
WITH all_membersAS (
SELECT user_id, group_idFROM group_members
UNION
SELECT user_id, organization_idAS group_idFROM organization_members
)
SELECT
users.idAS user_id,
users.emailAS user_email,
users.usernameAS user_username,
users.hashed_passwordAS user_hashed_password,
users.created_atAS user_created_at,
users.updated_atAS user_updated_at,
users.statusAS user_status,
users.rbac_rolesAS user_rbac_roles,
users.login_typeAS user_login_type,
users.avatar_urlAS user_avatar_url,
users.deletedAS user_deleted,
users.last_seen_atAS user_last_seen_at,
users.quiet_hours_scheduleAS user_quiet_hours_schedule,
users.theme_preferenceAS user_theme_preference,
users.nameAS user_name,
users.github_com_user_idAS user_github_com_user_id,
groups.organization_idAS organization_id,
groups.nameAS group_name,
all_members.group_idAS group_id
FROM
all_members
JOIN
usersONusers.id=all_members.user_id
JOIN
groupsONgroups.id=all_members.group_id
WHERE
users.deleted='false';

COMMENT ON VIEW group_members_expanded IS'Joins group members with user information, organization ID, group name. Includes both regular group members and organization members (as part of the "Everyone" group).';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This is exactly what I had in mind. Ideally we trim even more of the excess imo.

I know the UI currently takes acodersdk.User, so let's not fix this in this PR. But a followup action we can take is start removing a lot of the excess fields returned here, and make acodersdk.GroupMember type.

Screenshot from 2024-08-09 13-57-55

hugodutka reacted with thumbs up emoji

// getEveryoneGroupMembersNoLock fetches all the users in an organization.
func (q*FakeQuerier)getEveryoneGroupMembersNoLock(orgID uuid.UUID) []database.User {
func (q*FakeQuerier)getEveryoneGroupMembersNoLock(orgID uuid.UUID) []database.GroupMember {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

TheFakeQuerier has a data fieldgroupMembers []database.GroupMember. This should now begroupMembers []database.GroupMemberTable

Doing that will review some queries that need to be updated to include the joined information.

@hugodutkahugodutkaforce-pushed thehugodutka/13988-group-member-read-permissions branch frome07e1d9 to49297b2CompareAugust 12, 2024 11:44
@Emyrk
Copy link
Member

My unit test was merged.

You will have to just fixup these test assertions:

{
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,
},

Just wanted to get an actual breaking test from these changes 👍

hugodutka reacted with thumbs up emoji

- allow group members to see they are part of the group, but not see that information about other members- add a GetGroupMembersCountByGroupID SQL query, which allows group members to see members count without revealing other information about the members- expose a reducedGroupsByUserAndOrganization API endpoint
- fix type issues coming from replacing User with GroupMember in group member queries
@hugodutkahugodutkaforce-pushed thehugodutka/13988-group-member-read-permissions branch from6d469d5 to1080b29CompareAugust 12, 2024 19:34
@hugodutka
Copy link
ContributorAuthor

@Emyrk I think I updated all the tests. I rebased ontomain andmake test,make lint pass locally.

I updatedgroupsauth_test.go to work with the new permission system. I saw that you assumed that if a user didn't haveGroupMemberread permission thenGetGroupMembersByGroupID would return an error, but my implementation returns an empty list instead. I updated the test to match this behavior. Hope that's ok.

Emyrk reacted with thumbs up emojiEmyrk reacted with hooray emoji

Copy link
Member

@EmyrkEmyrk left a comment
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

@hugodutka this is great 👍

I updated groupsauth_test.go to work with the new permission system. I saw that you assumed that if a user didn't have GroupMember read permission then GetGroupMembersByGroupID would return an error, but my implementation returns an empty list instead. I updated the test to match this behavior. Hope that's ok.

👍 That is fine


My only blocking request is thedbgen change mentioned in one of my comments. If you change that, the rest LGTM and I'll merge it in. Appreciate the contribution 🥳 .

Just leaving notes for myself, I'll open some issues for some follow ups after this:

  • Reduce the number of fields returned ingroup_members_expanded. Requires plumbing through the apis and UI. An excess number of fields is currently returned.
    • Ideally we can replacecodersdk.ReducedUser incodersdk.Group with thisdatabase.GroupMember type?
  • /groups api endpoint exists in/{organization}. Given#14213, we should reconsider a single/groups endpoint with filters, or add additional endpoints for fetching groups.

Comment on lines +186 to +187
func (gmGroupMember)RBACObject() rbac.Object {
returnrbac.ResourceGroupMember.WithID(gm.UserID).InOrg(gm.OrganizationID).WithOwner(gm.UserID.String())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

👍

// Subjects to user
memberMe:=authSubject{Name:"member_me",Actor: rbac.Subject{ID:currentUser.String(),Roles: rbac.RoleIdentifiers{rbac.RoleMember()}}}
orgMemberMe:=authSubject{Name:"org_member_me",Actor: rbac.Subject{ID:currentUser.String(),Roles: rbac.RoleIdentifiers{rbac.RoleMember(),rbac.ScopedRoleOrgMember(orgID)}}}
groupMemberMe:=authSubject{Name:"group_member_me",Actor: rbac.Subject{ID:currentUser.String(),Roles: rbac.RoleIdentifiers{rbac.RoleMember(),rbac.ScopedRoleOrgMember(orgID)},Groups: []string{groupID.String()}}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This is great 👍

@hugodutka
Copy link
ContributorAuthor

@Emyrk I made the changes you requested. Thank you for all the reviews! Contributing this PR was fun.

Copy link
Member

@EmyrkEmyrk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

👍 Approved! I'll merge it in. The weekly-docs CI job is failing because docker changed a link 😢

hugodutka reacted with hooray emoji
@EmyrkEmyrk merged commit6f9b1a3 intocoder:mainAug 13, 2024
@github-actionsgithub-actionsbot locked and limited conversation to collaboratorsAug 13, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.

Reviewers

@johnstcnjohnstcnjohnstcn left review comments

@EmyrkEmyrkEmyrk approved these changes

Assignees

@hugodutkahugodutka

Labels

communityPull Requests and issues created by the community.

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Users who only have role "Member" are not part of the "Everyone" group

3 participants

@hugodutka@Emyrk@johnstcn

[8]ページ先頭

©2009-2025 Movatter.jp