Allow team maintainers to run new queries in the team hosts (#2076)

* Allow team maintainers to run new queries in the team hosts

* Add policies for other roles
This commit is contained in:
Tomas Touceda 2021-09-20 11:09:51 -03:00 committed by GitHub
parent baa42d367e
commit e286ee387e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 1 deletions

View file

@ -0,0 +1 @@
* Allow team maintainers to run new queries in the team hosts.

View file

@ -15,6 +15,7 @@ list := "list"
write := "write"
write_role := "write_role"
run := "run"
run_new := "run_new"
# Roles
admin := "admin"
@ -265,6 +266,16 @@ allow {
subject.global_role == maintainer
action = run
}
allow {
object.type == "query"
subject.global_role == admin
action = run_new
}
allow {
object.type == "query"
subject.global_role == maintainer
action = run_new
}
# Team maintainer running a non-observers_can_run query must have the targets
# filtered to only teams that they maintain
allow {
@ -274,6 +285,22 @@ allow {
action == run
}
# Team maintainer can run a new query
allow {
object.type == "query"
# If role is maintainer on any team
team_role(subject, subject.teams[_].id) == maintainer
action == run_new
}
# Team admin can run a new query
allow {
object.type == "query"
# If role is maintainer on any team
team_role(subject, subject.teams[_].id) == admin
action == run_new
}
# (Team) observers can run only if observers_can_run
allow {
object.type == "query"

View file

@ -11,4 +11,6 @@ const (
ActionWriteRole = "write_role"
// ActionRun is the action for running a live query.
ActionRun = "run"
// ActionRunNew is the action for running a new live query.
ActionRunNew = "run_new"
)

View file

@ -61,7 +61,7 @@ func (svc Service) NewDistributedQueryCampaign(ctx context.Context, queryString
}
queryString = query.Query
} else {
if err := svc.authz.Authorize(ctx, &fleet.Query{}, fleet.ActionWrite); err != nil {
if err := svc.authz.Authorize(ctx, &fleet.Query{}, fleet.ActionRunNew); err != nil {
return nil, err
}
query = &fleet.Query{

View file

@ -1746,6 +1746,63 @@ func TestObserversCanOnlyRunDistributedCampaigns(t *testing.T) {
require.NoError(t, err)
}
func TestTeamMaintainerCanRunNewDistributedCampaigns(t *testing.T) {
ds := new(mock.Store)
rs := &mock.QueryResultStore{
HealthCheckFunc: func() error {
return nil
},
}
lq := &live_query.MockLiveQuery{}
mockClock := clock.NewMockClock()
svc := newTestServiceWithClock(ds, rs, lq, mockClock)
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return &fleet.AppConfig{}, nil
}
ds.NewDistributedQueryCampaignFunc = func(ctx context.Context, camp *fleet.DistributedQueryCampaign) (*fleet.DistributedQueryCampaign, error) {
return camp, nil
}
ds.QueryFunc = func(ctx context.Context, id uint) (*fleet.Query, error) {
return &fleet.Query{
ID: 42,
Name: "query",
Query: "select 1;",
ObserverCanRun: false,
}, nil
}
viewerCtx := viewer.NewContext(context.Background(), viewer.Viewer{
User: &fleet.User{ID: 0, Teams: []fleet.UserTeam{{Role: fleet.RoleMaintainer}}},
})
q := "select year, month, day, hour, minutes, seconds from time"
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
return nil
}
//var gotQuery *fleet.Query
ds.NewQueryFunc = func(ctx context.Context, query *fleet.Query, opts ...fleet.OptionalArg) (*fleet.Query, error) {
//gotQuery = query
query.ID = 42
return query, nil
}
ds.NewDistributedQueryCampaignTargetFunc = func(ctx context.Context, target *fleet.DistributedQueryCampaignTarget) (*fleet.DistributedQueryCampaignTarget, error) {
return target, nil
}
ds.CountHostsInTargetsFunc = func(ctx context.Context, filter fleet.TeamFilter, targets fleet.HostTargets, now time.Time) (fleet.TargetMetrics, error) {
return fleet.TargetMetrics{}, nil
}
ds.HostIDsInTargetsFunc = func(ctx context.Context, filter fleet.TeamFilter, targets fleet.HostTargets) ([]uint, error) {
return []uint{1, 3, 5}, nil
}
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
return nil
}
lq.On("RunQuery", "0", "select year, month, day, hour, minutes, seconds from time", []uint{1, 3, 5}).Return(nil)
_, err := svc.NewDistributedQueryCampaign(viewerCtx, q, nil, fleet.HostTargets{HostIDs: []uint{2}, LabelIDs: []uint{1}})
require.NoError(t, err)
}
func TestPolicyQueries(t *testing.T) {
mockClock := clock.NewMockClock()
ds := new(mock.Store)