mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 17:08:53 +00:00
Update backend authz for software installers feature (#18513)
This commit is contained in:
parent
7e4bcae7c3
commit
845984e3e8
3 changed files with 139 additions and 2 deletions
|
|
@ -643,6 +643,36 @@ allow {
|
|||
action == read
|
||||
}
|
||||
|
||||
# Global admins, maintainers, observers, and observer_plus can read any software installer.
|
||||
allow {
|
||||
object.type == "software_installer"
|
||||
subject.global_role == [admin, maintainer, observer, observer_plus][_]
|
||||
action == read
|
||||
}
|
||||
|
||||
# Global admins, maintainers, and gitops can write any software installer.
|
||||
allow {
|
||||
object.type == "software_installer"
|
||||
subject.global_role == [admin, maintainer, gitops][_]
|
||||
action == write
|
||||
}
|
||||
|
||||
# Team admins, maintainers, observers, and observer_plus can read any software installer in their teams.
|
||||
allow {
|
||||
not is_null(object.team_id)
|
||||
object.type == "software_installer"
|
||||
team_role(subject, object.team_id) == [admin, maintainer, observer, observer_plus][_]
|
||||
action == read
|
||||
}
|
||||
|
||||
# Team admins, maintainers, and gitops can write any software installer in their teams.
|
||||
allow {
|
||||
not is_null(object.team_id)
|
||||
object.type == "software_installer"
|
||||
team_role(subject, object.team_id) == [admin, maintainer, gitops][_]
|
||||
action == write
|
||||
}
|
||||
|
||||
##
|
||||
# Apple and Windows MDM
|
||||
##
|
||||
|
|
|
|||
|
|
@ -500,6 +500,101 @@ func TestAuthorizeSoftwareInventory(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAuthorizeSoftwareInstaller(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
noTeamInstaller := &fleet.SoftwareInstaller{}
|
||||
team1Installer := &fleet.SoftwareInstaller{TeamID: ptr.Uint(1)}
|
||||
team2Installer := &fleet.SoftwareInstaller{TeamID: ptr.Uint(2)}
|
||||
runTestCases(t, []authTestCase{
|
||||
{user: nil, object: noTeamInstaller, action: read, allow: false},
|
||||
{user: nil, object: noTeamInstaller, action: write, allow: false},
|
||||
{user: nil, object: team1Installer, action: read, allow: false},
|
||||
{user: nil, object: team1Installer, action: write, allow: false},
|
||||
{user: nil, object: team2Installer, action: read, allow: false},
|
||||
{user: nil, object: team2Installer, action: write, allow: false},
|
||||
|
||||
{user: test.UserNoRoles, object: noTeamInstaller, action: read, allow: false},
|
||||
{user: test.UserNoRoles, object: noTeamInstaller, action: write, allow: false},
|
||||
{user: test.UserNoRoles, object: team1Installer, action: read, allow: false},
|
||||
{user: test.UserNoRoles, object: team1Installer, action: write, allow: false},
|
||||
{user: test.UserNoRoles, object: team2Installer, action: read, allow: false},
|
||||
{user: test.UserNoRoles, object: team2Installer, action: write, allow: false},
|
||||
|
||||
{user: test.UserAdmin, object: noTeamInstaller, action: read, allow: true},
|
||||
{user: test.UserAdmin, object: noTeamInstaller, action: write, allow: true},
|
||||
{user: test.UserAdmin, object: team1Installer, action: read, allow: true},
|
||||
{user: test.UserAdmin, object: team1Installer, action: write, allow: true},
|
||||
{user: test.UserAdmin, object: team2Installer, action: read, allow: true},
|
||||
{user: test.UserAdmin, object: team2Installer, action: write, allow: true},
|
||||
|
||||
{user: test.UserMaintainer, object: noTeamInstaller, action: read, allow: true},
|
||||
{user: test.UserMaintainer, object: noTeamInstaller, action: write, allow: true},
|
||||
{user: test.UserMaintainer, object: team1Installer, action: read, allow: true},
|
||||
{user: test.UserMaintainer, object: team1Installer, action: write, allow: true},
|
||||
{user: test.UserMaintainer, object: team2Installer, action: read, allow: true},
|
||||
{user: test.UserMaintainer, object: team2Installer, action: write, allow: true},
|
||||
|
||||
{user: test.UserObserver, object: noTeamInstaller, action: read, allow: true},
|
||||
{user: test.UserObserver, object: noTeamInstaller, action: write, allow: false},
|
||||
{user: test.UserObserver, object: team1Installer, action: read, allow: true},
|
||||
{user: test.UserObserver, object: team1Installer, action: write, allow: false},
|
||||
{user: test.UserObserver, object: team2Installer, action: read, allow: true},
|
||||
{user: test.UserObserver, object: team2Installer, action: write, allow: false},
|
||||
|
||||
{user: test.UserObserverPlus, object: noTeamInstaller, action: read, allow: true},
|
||||
{user: test.UserObserverPlus, object: noTeamInstaller, action: write, allow: false},
|
||||
{user: test.UserObserverPlus, object: team1Installer, action: read, allow: true},
|
||||
{user: test.UserObserverPlus, object: team1Installer, action: write, allow: false},
|
||||
{user: test.UserObserverPlus, object: team2Installer, action: read, allow: true},
|
||||
{user: test.UserObserverPlus, object: team2Installer, action: write, allow: false},
|
||||
|
||||
// TODO: confirm gitops permissions
|
||||
{user: test.UserGitOps, object: noTeamInstaller, action: read, allow: false},
|
||||
{user: test.UserGitOps, object: noTeamInstaller, action: write, allow: true},
|
||||
{user: test.UserGitOps, object: team1Installer, action: read, allow: false},
|
||||
{user: test.UserGitOps, object: team1Installer, action: write, allow: true},
|
||||
{user: test.UserGitOps, object: team2Installer, action: read, allow: false},
|
||||
{user: test.UserGitOps, object: team2Installer, action: write, allow: true},
|
||||
|
||||
// TODO: confirm gitops permissions
|
||||
{user: test.UserTeamGitOpsTeam1, object: noTeamInstaller, action: read, allow: false},
|
||||
{user: test.UserTeamGitOpsTeam1, object: noTeamInstaller, action: write, allow: false},
|
||||
{user: test.UserTeamGitOpsTeam1, object: team1Installer, action: read, allow: false},
|
||||
{user: test.UserTeamGitOpsTeam1, object: team1Installer, action: write, allow: true},
|
||||
{user: test.UserTeamGitOpsTeam1, object: team2Installer, action: read, allow: false},
|
||||
{user: test.UserTeamGitOpsTeam1, object: team2Installer, action: write, allow: false},
|
||||
|
||||
{user: test.UserTeamAdminTeam1, object: noTeamInstaller, action: read, allow: false},
|
||||
{user: test.UserTeamAdminTeam1, object: noTeamInstaller, action: write, allow: false},
|
||||
{user: test.UserTeamAdminTeam1, object: team1Installer, action: read, allow: true},
|
||||
{user: test.UserTeamAdminTeam1, object: team1Installer, action: write, allow: true},
|
||||
{user: test.UserTeamAdminTeam1, object: team2Installer, action: read, allow: false},
|
||||
{user: test.UserTeamAdminTeam1, object: team2Installer, action: write, allow: false},
|
||||
|
||||
{user: test.UserTeamMaintainerTeam1, object: noTeamInstaller, action: read, allow: false},
|
||||
{user: test.UserTeamMaintainerTeam1, object: noTeamInstaller, action: write, allow: false},
|
||||
{user: test.UserTeamMaintainerTeam1, object: team1Installer, action: read, allow: true},
|
||||
{user: test.UserTeamMaintainerTeam1, object: team1Installer, action: write, allow: true},
|
||||
{user: test.UserTeamMaintainerTeam1, object: team2Installer, action: read, allow: false},
|
||||
{user: test.UserTeamMaintainerTeam1, object: team2Installer, action: write, allow: false},
|
||||
|
||||
{user: test.UserTeamObserverTeam1, object: noTeamInstaller, action: read, allow: false},
|
||||
{user: test.UserTeamObserverTeam1, object: noTeamInstaller, action: write, allow: false},
|
||||
{user: test.UserTeamObserverTeam1, object: team1Installer, action: read, allow: true},
|
||||
{user: test.UserTeamObserverTeam1, object: team1Installer, action: write, allow: false},
|
||||
{user: test.UserTeamObserverTeam1, object: team2Installer, action: read, allow: false},
|
||||
{user: test.UserTeamObserverTeam1, object: team2Installer, action: write, allow: false},
|
||||
|
||||
{user: test.UserTeamObserverPlusTeam1, object: noTeamInstaller, action: read, allow: false},
|
||||
{user: test.UserTeamObserverPlusTeam1, object: noTeamInstaller, action: write, allow: false},
|
||||
{user: test.UserTeamObserverPlusTeam1, object: team1Installer, action: read, allow: true},
|
||||
{user: test.UserTeamObserverPlusTeam1, object: team1Installer, action: write, allow: false},
|
||||
{user: test.UserTeamObserverPlusTeam1, object: team2Installer, action: read, allow: false},
|
||||
{user: test.UserTeamObserverPlusTeam1, object: team2Installer, action: write, allow: false},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthorizeHost(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@ type SoftwareInstallerStore interface {
|
|||
// FailingSoftwareInstallerStore is an implementation of SoftwareInstallerStore
|
||||
// that fails all operations. It is used when S3 is not configured and the
|
||||
// local filesystem store could not be setup.
|
||||
type FailingSoftwareInstallerStore struct {
|
||||
}
|
||||
type FailingSoftwareInstallerStore struct{}
|
||||
|
||||
func (FailingSoftwareInstallerStore) Get(ctx context.Context, installerID string) (io.ReadCloser, int64, error) {
|
||||
return nil, 0, errors.New("software installer store not properly configured")
|
||||
|
|
@ -32,3 +31,16 @@ func (FailingSoftwareInstallerStore) Put(ctx context.Context, installerID string
|
|||
func (FailingSoftwareInstallerStore) Exists(ctx context.Context, installerID string) (bool, error) {
|
||||
return false, errors.New("software installer store not properly configured")
|
||||
}
|
||||
|
||||
// SoftwareInstaller represents a software installer package that can be used to install software on
|
||||
// hosts in Fleet.
|
||||
type SoftwareInstaller struct {
|
||||
// TeamID is the ID of the team. A value of nil means it is scoped to hosts that are assigned to
|
||||
// no team.
|
||||
TeamID *uint `json:"team_id"`
|
||||
}
|
||||
|
||||
// AuthzType implements authz.AuthzTyper.
|
||||
func (s *SoftwareInstaller) AuthzType() string {
|
||||
return "software_installer"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue