Restrict deleting a fleet to global admins (#50271)
# Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Restricted fleet deletion to users with global write permissions, including global administrators and GitOps. * Corrected team deletion authorization to require global write access. * Prevented global technicians, team technicians, and observer-level users from deleting teams. * Updated authorization behavior to consistently enforce the required access level. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -0,0 +1 @@
|
||||
* Restricted deleting a fleet to global write permissions (global admin or GitOps), matching the existing restriction on creating one.
|
||||
@@ -919,7 +919,7 @@ func (svc *Service) ListAvailableTeamsForUser(ctx context.Context, user *fleet.U
|
||||
}
|
||||
|
||||
func (svc *Service) DeleteTeam(ctx context.Context, teamID uint) error {
|
||||
if err := svc.authz.Authorize(ctx, &fleet.Team{ID: teamID}, fleet.ActionWrite); err != nil {
|
||||
if err := svc.authz.Authorize(ctx, &fleet.Team{}, fleet.ActionWrite); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -232,7 +232,7 @@ func TestTeamAuth(t *testing.T) {
|
||||
checkAuthErr(t, tt.shouldFailRead, err)
|
||||
|
||||
err = svc.DeleteTeam(ctx, 1)
|
||||
checkAuthErr(t, tt.shouldFailTeamWrite, err)
|
||||
checkAuthErr(t, tt.shouldFailGlobalWrite, err)
|
||||
|
||||
_, err = svc.TeamEnrollSecrets(ctx, 1)
|
||||
checkAuthErr(t, tt.shouldFailRead, err)
|
||||
@@ -246,6 +246,28 @@ func TestTeamAuth(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteTeamRejectsNonAdminNonGitOpsRoles(t *testing.T) {
|
||||
ds := new(mock.Store)
|
||||
license := &fleet.LicenseInfo{Tier: fleet.TierPremium, Expiration: time.Now().Add(24 * time.Hour)}
|
||||
svc, ctx := newTestService(t, ds, nil, nil, &TestServerOpts{License: license, SkipCreateTestUsers: true})
|
||||
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
user *fleet.User
|
||||
}{
|
||||
{"global technician", &fleet.User{GlobalRole: new(fleet.RoleTechnician)}},
|
||||
{"team technician, belongs to team", &fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleTechnician}}}},
|
||||
{"global observer_plus", &fleet.User{GlobalRole: new(fleet.RoleObserverPlus)}},
|
||||
{"team observer_plus, belongs to team", &fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleObserverPlus}}}},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx := viewer.NewContext(ctx, viewer.Viewer{User: tt.user})
|
||||
err := svc.DeleteTeam(ctx, 1)
|
||||
checkAuthErr(t, true, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestGitOpsCannotManageTeamMembers verifies that a team gitops user cannot
|
||||
// add or remove team members (including self-promotion to admin).
|
||||
func TestGitOpsCannotManageTeamMembers(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user