2021-06-03 23:24:15 +00:00
|
|
|
package authz
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"testing"
|
|
|
|
|
2021-06-26 04:46:51 +00:00
|
|
|
"github.com/fleetdm/fleet/v4/server/fleet"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/ptr"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/test"
|
2021-06-03 23:24:15 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2021-06-06 22:07:29 +00:00
|
|
|
read = fleet.ActionRead
|
|
|
|
list = fleet.ActionList
|
|
|
|
write = fleet.ActionWrite
|
|
|
|
writeRole = fleet.ActionWriteRole
|
|
|
|
run = fleet.ActionRun
|
2021-06-03 23:24:15 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var auth *Authorizer
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
var err error
|
|
|
|
auth, err = NewAuthorizer()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type authTestCase struct {
|
2021-06-06 22:07:29 +00:00
|
|
|
user *fleet.User
|
2021-06-03 23:24:15 +00:00
|
|
|
object interface{}
|
|
|
|
action interface{}
|
|
|
|
allow bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAuthorizeAppConfig(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
config := &fleet.AppConfig{}
|
2021-06-03 23:24:15 +00:00
|
|
|
runTestCases(t, []authTestCase{
|
|
|
|
{user: nil, object: config, action: read, allow: false},
|
|
|
|
{user: nil, object: config, action: write, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserNoRoles, object: config, action: read, allow: true},
|
|
|
|
{user: test.UserNoRoles, object: config, action: write, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserAdmin, object: config, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: config, action: write, allow: true},
|
|
|
|
|
|
|
|
{user: test.UserMaintainer, object: config, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: config, action: write, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserObserver, object: config, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: config, action: write, allow: false},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAuthorizeSession(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
session := &fleet.Session{UserID: 42}
|
2021-06-03 23:24:15 +00:00
|
|
|
runTestCases(t, []authTestCase{
|
|
|
|
{user: nil, object: session, action: read, allow: false},
|
|
|
|
{user: nil, object: session, action: write, allow: false},
|
|
|
|
|
|
|
|
// Admin can read/write all
|
|
|
|
{user: test.UserAdmin, object: session, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: session, action: write, allow: true},
|
|
|
|
|
|
|
|
// Regular users can read self
|
|
|
|
{user: test.UserMaintainer, object: session, action: read, allow: false},
|
|
|
|
{user: test.UserMaintainer, object: session, action: write, allow: false},
|
2021-06-06 22:07:29 +00:00
|
|
|
{user: test.UserMaintainer, object: &fleet.Session{UserID: test.UserMaintainer.ID}, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: &fleet.Session{UserID: test.UserMaintainer.ID}, action: write, allow: true},
|
2021-06-03 23:24:15 +00:00
|
|
|
|
|
|
|
{user: test.UserNoRoles, object: session, action: read, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: session, action: write, allow: false},
|
2021-06-06 22:07:29 +00:00
|
|
|
{user: test.UserNoRoles, object: &fleet.Session{UserID: test.UserNoRoles.ID}, action: read, allow: true},
|
|
|
|
{user: test.UserNoRoles, object: &fleet.Session{UserID: test.UserNoRoles.ID}, action: write, allow: true},
|
2021-06-03 23:24:15 +00:00
|
|
|
|
|
|
|
{user: test.UserObserver, object: session, action: read, allow: false},
|
|
|
|
{user: test.UserObserver, object: session, action: write, allow: false},
|
2021-06-06 22:07:29 +00:00
|
|
|
{user: test.UserObserver, object: &fleet.Session{UserID: test.UserObserver.ID}, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: &fleet.Session{UserID: test.UserObserver.ID}, action: write, allow: true},
|
2021-06-03 23:24:15 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAuthorizeUser(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
user := &fleet.User{ID: 42}
|
2021-06-03 23:24:15 +00:00
|
|
|
runTestCases(t, []authTestCase{
|
|
|
|
{user: nil, object: user, action: read, allow: false},
|
|
|
|
{user: nil, object: user, action: write, allow: false},
|
|
|
|
{user: nil, object: user, action: writeRole, allow: false},
|
|
|
|
|
|
|
|
// Admin can read/write all
|
|
|
|
{user: test.UserAdmin, object: user, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: user, action: write, allow: true},
|
|
|
|
{user: test.UserAdmin, object: user, action: writeRole, allow: true},
|
|
|
|
|
|
|
|
// Regular users can read all users and write self (besides roles)
|
|
|
|
{user: test.UserMaintainer, object: user, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: user, action: write, allow: false},
|
|
|
|
{user: test.UserMaintainer, object: user, action: writeRole, allow: false},
|
|
|
|
{user: test.UserMaintainer, object: test.UserMaintainer, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: test.UserMaintainer, action: write, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: test.UserMaintainer, action: writeRole, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserNoRoles, object: user, action: read, allow: true},
|
|
|
|
{user: test.UserNoRoles, object: user, action: write, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: user, action: writeRole, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: test.UserNoRoles, action: read, allow: true},
|
|
|
|
{user: test.UserNoRoles, object: test.UserNoRoles, action: write, allow: true},
|
|
|
|
{user: test.UserNoRoles, object: test.UserNoRoles, action: writeRole, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserObserver, object: user, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: user, action: write, allow: false},
|
|
|
|
{user: test.UserObserver, object: user, action: writeRole, allow: false},
|
|
|
|
{user: test.UserObserver, object: test.UserObserver, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: test.UserObserver, action: write, allow: true},
|
|
|
|
{user: test.UserObserver, object: test.UserObserver, action: writeRole, allow: false},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAuthorizeInvite(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
invite := &fleet.Invite{}
|
2021-06-03 23:24:15 +00:00
|
|
|
runTestCases(t, []authTestCase{
|
|
|
|
{user: nil, object: invite, action: read, allow: false},
|
|
|
|
{user: nil, object: invite, action: write, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserNoRoles, object: invite, action: read, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: invite, action: write, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserAdmin, object: invite, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: invite, action: write, allow: true},
|
|
|
|
|
|
|
|
{user: test.UserMaintainer, object: invite, action: read, allow: false},
|
|
|
|
{user: test.UserMaintainer, object: invite, action: write, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserObserver, object: invite, action: read, allow: false},
|
|
|
|
{user: test.UserObserver, object: invite, action: write, allow: false},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAuthorizeEnrollSecret(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2021-11-11 16:45:39 +00:00
|
|
|
teamAdmin := &fleet.User{
|
|
|
|
Teams: []fleet.UserTeam{
|
|
|
|
{Team: fleet.Team{ID: 1}, Role: fleet.RoleAdmin},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
teamMaintainer := &fleet.User{
|
|
|
|
Teams: []fleet.UserTeam{
|
|
|
|
{Team: fleet.Team{ID: 1}, Role: fleet.RoleMaintainer},
|
2021-06-03 23:24:15 +00:00
|
|
|
},
|
|
|
|
}
|
2021-06-06 22:07:29 +00:00
|
|
|
teamObserver := &fleet.User{
|
|
|
|
Teams: []fleet.UserTeam{
|
|
|
|
{Team: fleet.Team{ID: 1}, Role: fleet.RoleObserver},
|
2021-06-03 23:24:15 +00:00
|
|
|
},
|
|
|
|
}
|
2021-06-06 22:07:29 +00:00
|
|
|
globalSecret := &fleet.EnrollSecret{}
|
|
|
|
teamSecret := &fleet.EnrollSecret{TeamID: ptr.Uint(1)}
|
2021-06-03 23:24:15 +00:00
|
|
|
runTestCases(t, []authTestCase{
|
|
|
|
// No access
|
|
|
|
{user: nil, object: globalSecret, action: read, allow: false},
|
|
|
|
{user: nil, object: globalSecret, action: write, allow: false},
|
|
|
|
{user: nil, object: teamSecret, action: read, allow: false},
|
|
|
|
{user: nil, object: teamSecret, action: write, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: globalSecret, action: read, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: globalSecret, action: write, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: teamSecret, action: read, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: teamSecret, action: write, allow: false},
|
|
|
|
{user: test.UserObserver, object: globalSecret, action: read, allow: false},
|
|
|
|
{user: test.UserObserver, object: globalSecret, action: write, allow: false},
|
|
|
|
{user: test.UserObserver, object: teamSecret, action: read, allow: false},
|
|
|
|
{user: test.UserObserver, object: teamSecret, action: write, allow: false},
|
|
|
|
{user: teamObserver, object: globalSecret, action: read, allow: false},
|
|
|
|
{user: teamObserver, object: globalSecret, action: write, allow: false},
|
|
|
|
{user: teamObserver, object: teamSecret, action: read, allow: false},
|
|
|
|
{user: teamObserver, object: teamSecret, action: write, allow: false},
|
|
|
|
|
|
|
|
// Admin can read/write all
|
|
|
|
{user: test.UserAdmin, object: globalSecret, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: globalSecret, action: write, allow: true},
|
|
|
|
{user: test.UserAdmin, object: teamSecret, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: teamSecret, action: write, allow: true},
|
|
|
|
|
|
|
|
// Maintainer can read all
|
|
|
|
{user: test.UserMaintainer, object: globalSecret, action: read, allow: true},
|
2021-11-11 16:45:39 +00:00
|
|
|
{user: test.UserMaintainer, object: globalSecret, action: write, allow: true},
|
2021-06-03 23:24:15 +00:00
|
|
|
{user: test.UserMaintainer, object: teamSecret, action: read, allow: true},
|
2021-11-11 16:45:39 +00:00
|
|
|
{user: test.UserMaintainer, object: teamSecret, action: write, allow: true},
|
|
|
|
|
|
|
|
// Team admin can read/write team secret
|
|
|
|
{user: teamAdmin, object: globalSecret, action: read, allow: false},
|
|
|
|
{user: teamAdmin, object: globalSecret, action: write, allow: false},
|
|
|
|
{user: teamAdmin, object: teamSecret, action: read, allow: true},
|
|
|
|
{user: teamAdmin, object: teamSecret, action: write, allow: true},
|
2021-06-03 23:24:15 +00:00
|
|
|
|
2021-11-11 16:45:39 +00:00
|
|
|
// Team maintainer can read/write team secret
|
2021-06-03 23:24:15 +00:00
|
|
|
{user: teamMaintainer, object: globalSecret, action: read, allow: false},
|
|
|
|
{user: teamMaintainer, object: globalSecret, action: write, allow: false},
|
|
|
|
{user: teamMaintainer, object: teamSecret, action: read, allow: true},
|
2021-11-11 16:45:39 +00:00
|
|
|
{user: teamMaintainer, object: teamSecret, action: write, allow: true},
|
2021-06-03 23:24:15 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAuthorizeTeam(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
team := &fleet.Team{}
|
2021-06-03 23:24:15 +00:00
|
|
|
runTestCases(t, []authTestCase{
|
|
|
|
{user: nil, object: team, action: read, allow: false},
|
|
|
|
{user: nil, object: team, action: write, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserNoRoles, object: team, action: read, allow: true},
|
|
|
|
{user: test.UserNoRoles, object: team, action: write, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserAdmin, object: team, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: team, action: write, allow: true},
|
|
|
|
|
|
|
|
{user: test.UserMaintainer, object: team, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: team, action: write, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserObserver, object: team, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: team, action: write, allow: false},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAuthorizeLabel(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
label := &fleet.Label{}
|
2021-06-03 23:24:15 +00:00
|
|
|
runTestCases(t, []authTestCase{
|
|
|
|
{user: nil, object: label, action: read, allow: false},
|
|
|
|
{user: nil, object: label, action: write, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserNoRoles, object: label, action: read, allow: true},
|
|
|
|
{user: test.UserNoRoles, object: label, action: write, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserAdmin, object: label, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: label, action: write, allow: true},
|
|
|
|
|
|
|
|
{user: test.UserMaintainer, object: label, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: label, action: write, allow: true},
|
|
|
|
|
|
|
|
{user: test.UserObserver, object: label, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: label, action: write, allow: false},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAuthorizeHost(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
teamMaintainer := &fleet.User{
|
|
|
|
Teams: []fleet.UserTeam{
|
|
|
|
{Team: fleet.Team{ID: 1}, Role: fleet.RoleMaintainer},
|
2021-06-03 23:24:15 +00:00
|
|
|
},
|
|
|
|
}
|
2021-06-06 22:07:29 +00:00
|
|
|
teamObserver := &fleet.User{
|
|
|
|
Teams: []fleet.UserTeam{
|
|
|
|
{Team: fleet.Team{ID: 1}, Role: fleet.RoleObserver},
|
2021-06-03 23:24:15 +00:00
|
|
|
},
|
|
|
|
}
|
2021-06-06 22:07:29 +00:00
|
|
|
host := &fleet.Host{}
|
|
|
|
hostTeam1 := &fleet.Host{TeamID: ptr.Uint(1)}
|
|
|
|
hostTeam2 := &fleet.Host{TeamID: ptr.Uint(2)}
|
2021-06-03 23:24:15 +00:00
|
|
|
runTestCases(t, []authTestCase{
|
|
|
|
// No access
|
|
|
|
{user: nil, object: host, action: read, allow: false},
|
|
|
|
{user: nil, object: host, action: write, allow: false},
|
|
|
|
{user: nil, object: host, action: list, allow: false},
|
|
|
|
{user: nil, object: hostTeam1, action: read, allow: false},
|
|
|
|
{user: nil, object: hostTeam1, action: write, allow: false},
|
|
|
|
{user: nil, object: hostTeam2, action: read, allow: false},
|
|
|
|
{user: nil, object: hostTeam2, action: write, allow: false},
|
|
|
|
|
|
|
|
// List but no specific host access
|
|
|
|
{user: test.UserNoRoles, object: host, action: read, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: host, action: write, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: host, action: list, allow: true},
|
|
|
|
{user: test.UserNoRoles, object: hostTeam1, action: read, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: hostTeam1, action: write, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: hostTeam2, action: read, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: hostTeam2, action: write, allow: false},
|
|
|
|
|
|
|
|
// Global observer can read all
|
|
|
|
{user: test.UserObserver, object: host, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: host, action: write, allow: false},
|
|
|
|
{user: test.UserObserver, object: host, action: list, allow: true},
|
|
|
|
{user: test.UserObserver, object: hostTeam1, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: hostTeam1, action: write, allow: false},
|
|
|
|
{user: test.UserObserver, object: hostTeam2, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: hostTeam2, action: write, allow: false},
|
|
|
|
|
|
|
|
// Global admin/maintainer can read/write all
|
|
|
|
{user: test.UserAdmin, object: host, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: host, action: write, allow: true},
|
|
|
|
{user: test.UserAdmin, object: host, action: list, allow: true},
|
|
|
|
{user: test.UserAdmin, object: hostTeam1, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: hostTeam1, action: write, allow: true},
|
|
|
|
{user: test.UserAdmin, object: hostTeam2, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: hostTeam2, action: write, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: host, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: host, action: write, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: host, action: list, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: hostTeam1, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: hostTeam1, action: write, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: hostTeam2, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: hostTeam2, action: write, allow: true},
|
|
|
|
|
|
|
|
// Team observer/maintainer can read only on appropriate team
|
|
|
|
{user: teamObserver, object: host, action: read, allow: false},
|
|
|
|
{user: teamObserver, object: host, action: write, allow: false},
|
|
|
|
{user: teamObserver, object: host, action: list, allow: true},
|
|
|
|
{user: teamObserver, object: hostTeam1, action: read, allow: true},
|
|
|
|
{user: teamObserver, object: hostTeam1, action: write, allow: false},
|
|
|
|
{user: teamObserver, object: hostTeam2, action: read, allow: false},
|
|
|
|
{user: teamObserver, object: hostTeam2, action: write, allow: false},
|
|
|
|
{user: teamMaintainer, object: host, action: read, allow: false},
|
|
|
|
{user: teamMaintainer, object: host, action: write, allow: false},
|
|
|
|
{user: teamMaintainer, object: host, action: list, allow: true},
|
|
|
|
{user: teamMaintainer, object: hostTeam1, action: read, allow: true},
|
2021-10-05 18:15:05 +00:00
|
|
|
{user: teamMaintainer, object: hostTeam1, action: write, allow: true},
|
2021-06-03 23:24:15 +00:00
|
|
|
{user: teamMaintainer, object: hostTeam2, action: read, allow: false},
|
|
|
|
{user: teamMaintainer, object: hostTeam2, action: write, allow: false},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAuthorizeQuery(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
teamMaintainer := &fleet.User{
|
|
|
|
Teams: []fleet.UserTeam{
|
|
|
|
{Team: fleet.Team{ID: 1}, Role: fleet.RoleMaintainer},
|
2021-06-03 23:24:15 +00:00
|
|
|
},
|
|
|
|
}
|
2021-06-06 22:07:29 +00:00
|
|
|
teamObserver := &fleet.User{
|
|
|
|
Teams: []fleet.UserTeam{
|
|
|
|
{Team: fleet.Team{ID: 1}, Role: fleet.RoleObserver},
|
2021-06-03 23:24:15 +00:00
|
|
|
},
|
|
|
|
}
|
2021-06-06 22:07:29 +00:00
|
|
|
query := &fleet.Query{}
|
|
|
|
observerQuery := &fleet.Query{ObserverCanRun: true}
|
2021-06-03 23:24:15 +00:00
|
|
|
runTestCases(t, []authTestCase{
|
|
|
|
// No access
|
|
|
|
{user: nil, object: query, action: read, allow: false},
|
|
|
|
{user: nil, object: query, action: write, allow: false},
|
|
|
|
{user: nil, object: query, action: run, allow: false},
|
|
|
|
{user: nil, object: observerQuery, action: read, allow: false},
|
|
|
|
{user: nil, object: observerQuery, action: write, allow: false},
|
|
|
|
{user: nil, object: observerQuery, action: run, allow: false},
|
|
|
|
|
|
|
|
// User can still read queries with no roles
|
|
|
|
{user: test.UserNoRoles, object: query, action: read, allow: true},
|
|
|
|
{user: test.UserNoRoles, object: query, action: write, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: query, action: run, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: observerQuery, action: read, allow: true},
|
|
|
|
{user: test.UserNoRoles, object: observerQuery, action: write, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: query, action: run, allow: false},
|
|
|
|
|
|
|
|
// Global observer can read
|
|
|
|
{user: test.UserObserver, object: query, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: query, action: write, allow: false},
|
|
|
|
{user: test.UserObserver, object: query, action: run, allow: false},
|
|
|
|
{user: test.UserObserver, object: observerQuery, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: observerQuery, action: write, allow: false},
|
|
|
|
// Can run observer query
|
|
|
|
{user: test.UserObserver, object: observerQuery, action: run, allow: true},
|
|
|
|
|
|
|
|
// Global maintainer can read/write/run
|
|
|
|
{user: test.UserMaintainer, object: query, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: query, action: write, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: query, action: run, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: observerQuery, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: observerQuery, action: write, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: observerQuery, action: run, allow: true},
|
|
|
|
|
|
|
|
// Global admin can read/write
|
|
|
|
{user: test.UserAdmin, object: query, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: query, action: write, allow: true},
|
|
|
|
{user: test.UserAdmin, object: query, action: run, allow: true},
|
|
|
|
{user: test.UserAdmin, object: observerQuery, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: observerQuery, action: write, allow: true},
|
|
|
|
{user: test.UserAdmin, object: observerQuery, action: run, allow: true},
|
|
|
|
|
|
|
|
// Team observer read
|
|
|
|
{user: teamObserver, object: query, action: read, allow: true},
|
|
|
|
{user: teamObserver, object: query, action: write, allow: false},
|
|
|
|
{user: teamObserver, object: query, action: run, allow: false},
|
|
|
|
{user: teamObserver, object: observerQuery, action: read, allow: true},
|
|
|
|
{user: teamObserver, object: observerQuery, action: write, allow: false},
|
|
|
|
// Can run observer query
|
|
|
|
{user: teamObserver, object: observerQuery, action: run, allow: true},
|
|
|
|
|
|
|
|
// Team maintainer can read/write
|
|
|
|
{user: teamMaintainer, object: query, action: read, allow: true},
|
2021-09-28 17:53:05 +00:00
|
|
|
{user: teamMaintainer, object: query, action: write, allow: true},
|
2021-06-03 23:24:15 +00:00
|
|
|
{user: teamMaintainer, object: query, action: run, allow: true},
|
|
|
|
{user: teamMaintainer, object: observerQuery, action: read, allow: true},
|
2021-09-28 17:53:05 +00:00
|
|
|
{user: teamMaintainer, object: observerQuery, action: write, allow: true},
|
2021-06-03 23:24:15 +00:00
|
|
|
{user: teamMaintainer, object: observerQuery, action: run, allow: true},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAuthorizeTargets(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
target := &fleet.Target{}
|
2021-06-03 23:24:15 +00:00
|
|
|
runTestCases(t, []authTestCase{
|
|
|
|
{user: nil, object: target, action: read, allow: false},
|
|
|
|
|
|
|
|
// Everyone logged in can retrieve target (filter appropriately for their
|
|
|
|
// access)
|
|
|
|
{user: test.UserNoRoles, object: target, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: target, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: target, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: target, action: read, allow: true},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAuthorizePacks(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
pack := &fleet.Pack{}
|
2021-06-03 23:24:15 +00:00
|
|
|
runTestCases(t, []authTestCase{
|
|
|
|
{user: nil, object: pack, action: read, allow: false},
|
|
|
|
{user: nil, object: pack, action: write, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserNoRoles, object: pack, action: read, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: pack, action: write, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserAdmin, object: pack, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: pack, action: write, allow: true},
|
|
|
|
|
|
|
|
{user: test.UserMaintainer, object: pack, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: pack, action: write, allow: true},
|
|
|
|
|
|
|
|
{user: test.UserObserver, object: pack, action: read, allow: false},
|
|
|
|
{user: test.UserObserver, object: pack, action: write, allow: false},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-12-14 04:53:29 +00:00
|
|
|
func TestAuthorizeTeamPacks(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
runTestCases(t, []authTestCase{
|
|
|
|
// Team maintainer can read packs of the team.
|
|
|
|
{
|
|
|
|
user: test.UserTeamMaintainerTeam1,
|
|
|
|
object: &fleet.Pack{
|
|
|
|
TeamIDs: []uint{1},
|
|
|
|
},
|
|
|
|
action: read,
|
|
|
|
allow: true,
|
|
|
|
},
|
|
|
|
// Team observer cannot read packs of the team.
|
|
|
|
{
|
|
|
|
user: test.UserTeamObserverTeam1TeamAdminTeam2,
|
|
|
|
object: &fleet.Pack{
|
|
|
|
TeamIDs: []uint{1},
|
|
|
|
},
|
|
|
|
action: read,
|
|
|
|
allow: false,
|
|
|
|
},
|
|
|
|
// Team observer cannot write packs of the team.
|
|
|
|
{
|
|
|
|
user: test.UserTeamObserverTeam1TeamAdminTeam2,
|
|
|
|
object: &fleet.Pack{
|
|
|
|
TeamIDs: []uint{1},
|
|
|
|
},
|
|
|
|
action: write,
|
|
|
|
allow: false,
|
|
|
|
},
|
|
|
|
// Members of a team cannot read packs of another team.
|
|
|
|
{
|
|
|
|
user: test.UserTeamAdminTeam1,
|
|
|
|
object: &fleet.Pack{
|
|
|
|
TeamIDs: []uint{2},
|
|
|
|
},
|
|
|
|
action: read,
|
|
|
|
allow: false,
|
|
|
|
},
|
|
|
|
// Members of a team cannot read packs of another team.
|
|
|
|
{
|
|
|
|
user: test.UserTeamAdminTeam1,
|
|
|
|
object: &fleet.Pack{
|
|
|
|
TeamIDs: []uint{2},
|
|
|
|
},
|
|
|
|
action: read,
|
|
|
|
allow: false,
|
|
|
|
},
|
|
|
|
// Team maintainers can read global packs.
|
|
|
|
{
|
|
|
|
user: test.UserTeamMaintainerTeam1,
|
|
|
|
object: &fleet.Pack{},
|
|
|
|
action: read,
|
|
|
|
allow: true,
|
|
|
|
},
|
|
|
|
// Team admins can read global packs.
|
|
|
|
{
|
|
|
|
user: test.UserTeamAdminTeam1,
|
|
|
|
object: &fleet.Pack{},
|
|
|
|
action: read,
|
|
|
|
allow: true,
|
|
|
|
},
|
|
|
|
// Team admins cannot write global packs.
|
|
|
|
{
|
|
|
|
user: test.UserTeamAdminTeam1,
|
|
|
|
object: &fleet.Pack{},
|
|
|
|
action: write,
|
|
|
|
allow: false,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-06-03 23:24:15 +00:00
|
|
|
func TestAuthorizeCarves(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
carve := &fleet.CarveMetadata{}
|
2021-06-03 23:24:15 +00:00
|
|
|
runTestCases(t, []authTestCase{
|
|
|
|
{user: nil, object: carve, action: read, allow: false},
|
|
|
|
{user: nil, object: carve, action: write, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: carve, action: read, allow: false},
|
|
|
|
{user: test.UserNoRoles, object: carve, action: write, allow: false},
|
|
|
|
{user: test.UserMaintainer, object: carve, action: read, allow: false},
|
|
|
|
{user: test.UserMaintainer, object: carve, action: write, allow: false},
|
|
|
|
{user: test.UserObserver, object: carve, action: read, allow: false},
|
|
|
|
{user: test.UserObserver, object: carve, action: write, allow: false},
|
|
|
|
|
|
|
|
// Only admins allowed
|
|
|
|
{user: test.UserAdmin, object: carve, action: read, allow: true},
|
|
|
|
{user: test.UserAdmin, object: carve, action: write, allow: true},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-10-15 10:34:11 +00:00
|
|
|
func TestAuthorizePolicies(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2022-01-18 16:18:40 +00:00
|
|
|
globalPolicy := &fleet.Policy{}
|
2021-11-24 17:16:42 +00:00
|
|
|
teamPolicy := &fleet.Policy{
|
|
|
|
PolicyData: fleet.PolicyData{
|
|
|
|
TeamID: ptr.Uint(1),
|
|
|
|
},
|
|
|
|
}
|
2021-10-15 10:34:11 +00:00
|
|
|
runTestCases(t, []authTestCase{
|
2022-01-18 16:18:40 +00:00
|
|
|
{user: test.UserNoRoles, object: globalPolicy, action: write, allow: false},
|
2021-10-15 10:34:11 +00:00
|
|
|
|
2022-01-18 16:18:40 +00:00
|
|
|
{user: test.UserAdmin, object: globalPolicy, action: write, allow: true},
|
|
|
|
{user: test.UserAdmin, object: globalPolicy, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: globalPolicy, action: write, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: globalPolicy, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: globalPolicy, action: write, allow: false},
|
|
|
|
{user: test.UserObserver, object: globalPolicy, action: read, allow: true},
|
2021-10-15 10:34:11 +00:00
|
|
|
|
|
|
|
{user: test.UserAdmin, object: teamPolicy, action: write, allow: true},
|
|
|
|
{user: test.UserAdmin, object: teamPolicy, action: read, allow: true},
|
|
|
|
{user: test.UserMaintainer, object: teamPolicy, action: write, allow: false},
|
|
|
|
{user: test.UserMaintainer, object: teamPolicy, action: read, allow: true},
|
|
|
|
{user: test.UserObserver, object: teamPolicy, action: write, allow: false},
|
|
|
|
{user: test.UserObserver, object: teamPolicy, action: read, allow: true},
|
|
|
|
|
|
|
|
{user: test.UserTeamAdminTeam1, object: teamPolicy, action: write, allow: true},
|
|
|
|
{user: test.UserTeamAdminTeam1, object: teamPolicy, action: read, allow: true},
|
|
|
|
{user: test.UserTeamAdminTeam2, object: teamPolicy, action: write, allow: false},
|
|
|
|
{user: test.UserTeamAdminTeam2, object: teamPolicy, action: read, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserTeamMaintainerTeam1, object: teamPolicy, action: write, allow: true},
|
|
|
|
{user: test.UserTeamMaintainerTeam1, object: teamPolicy, action: read, allow: true},
|
|
|
|
{user: test.UserTeamMaintainerTeam2, object: teamPolicy, action: write, allow: false},
|
|
|
|
{user: test.UserTeamMaintainerTeam2, object: teamPolicy, action: read, allow: false},
|
|
|
|
|
|
|
|
{user: test.UserTeamObserverTeam1, object: teamPolicy, action: write, allow: false},
|
|
|
|
{user: test.UserTeamObserverTeam1, object: teamPolicy, action: read, allow: true},
|
|
|
|
{user: test.UserTeamObserverTeam2, object: teamPolicy, action: write, allow: false},
|
|
|
|
{user: test.UserTeamObserverTeam2, object: teamPolicy, action: read, allow: false},
|
2022-01-18 16:18:40 +00:00
|
|
|
|
|
|
|
// Team observers cannot write global policies.
|
|
|
|
{user: test.UserTeamObserverTeam1, object: globalPolicy, action: write, allow: false},
|
|
|
|
// Team observers can read global policies.
|
|
|
|
{user: test.UserTeamObserverTeam1, object: globalPolicy, action: read, allow: true},
|
2021-10-15 10:34:11 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
func assertAuthorized(t *testing.T, user *fleet.User, object, action interface{}) {
|
2021-06-03 23:24:15 +00:00
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.NoError(t, auth.Authorize(test.UserContext(user), object, action), "should be authorized\n%v\n%v\n%v", user, object, action)
|
|
|
|
}
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
func assertUnauthorized(t *testing.T, user *fleet.User, object, action interface{}) {
|
2021-06-03 23:24:15 +00:00
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Error(t, auth.Authorize(test.UserContext(user), object, action), "should be unauthorized\n%v\n%v\n%v", user, object, action)
|
|
|
|
}
|
|
|
|
|
|
|
|
func runTestCases(t *testing.T, testCases []authTestCase) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
for _, tt := range testCases {
|
|
|
|
tt := tt
|
|
|
|
t.Run("", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
if tt.allow {
|
|
|
|
assertAuthorized(t, tt.user, tt.object, tt.action)
|
|
|
|
} else {
|
|
|
|
assertUnauthorized(t, tt.user, tt.object, tt.action)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestJSONToInterfaceUser(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
subject, err := jsonToInterface(&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)})
|
2021-06-03 23:24:15 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
{
|
|
|
|
subject := subject.(map[string]interface{})
|
2021-06-06 22:07:29 +00:00
|
|
|
assert.Equal(t, fleet.RoleAdmin, subject["global_role"])
|
2021-06-03 23:24:15 +00:00
|
|
|
assert.Nil(t, subject["teams"])
|
|
|
|
}
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
subject, err = jsonToInterface(&fleet.User{
|
|
|
|
Teams: []fleet.UserTeam{
|
|
|
|
{Team: fleet.Team{ID: 3}, Role: fleet.RoleObserver},
|
|
|
|
{Team: fleet.Team{ID: 42}, Role: fleet.RoleMaintainer},
|
2021-06-03 23:24:15 +00:00
|
|
|
},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
{
|
|
|
|
subject := subject.(map[string]interface{})
|
|
|
|
assert.Equal(t, nil, subject["global_role"])
|
|
|
|
assert.Len(t, subject["teams"], 2)
|
2021-06-06 22:07:29 +00:00
|
|
|
assert.Equal(t, fleet.RoleObserver, subject["teams"].([]interface{})[0].(map[string]interface{})["role"])
|
2021-06-03 23:24:15 +00:00
|
|
|
assert.Equal(t, json.Number("3"), subject["teams"].([]interface{})[0].(map[string]interface{})["id"])
|
2021-06-06 22:07:29 +00:00
|
|
|
assert.Equal(t, fleet.RoleMaintainer, subject["teams"].([]interface{})[1].(map[string]interface{})["role"])
|
2021-06-03 23:24:15 +00:00
|
|
|
assert.Equal(t, json.Number("42"), subject["teams"].([]interface{})[1].(map[string]interface{})["id"])
|
|
|
|
}
|
|
|
|
}
|