Team observers can browse global policies (#3737)

* Allow team observers to browse global policies

* Add integration core test for team observer

* Fix integration tests
This commit is contained in:
Lucas Manuel Rodriguez 2022-01-18 13:18:40 -03:00 committed by GitHub
parent ba64dc0003
commit d4243d0a72
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 80 additions and 11 deletions

View file

@ -0,0 +1 @@
* Team observers can read global policies (aka inherited policies).

View file

@ -73,6 +73,7 @@ The following table depicts various permissions levels in a team.
| ------------------------------------------------------------ | -------- | ---------- | ------- |
| Browse hosts assigned to team | ✅ | ✅ | ✅ |
| Browse policies for hosts assigned to team | ✅ | ✅ | ✅ |
| Browse global (inherited) policies | ✅ | ✅ | ✅ |
| Filter hosts assigned to team using policies | ✅ | ✅ | ✅ |
| Filter hosts assigned to team using labels | ✅ | ✅ | ✅ |
| Target hosts assigned to team using labels | ✅ | ✅ | ✅ |

View file

@ -429,11 +429,11 @@ allow {
action == [read, write][_]
}
# Team admin and maintainers can read global policies
# Team admin, maintainers and observers can read global policies
allow {
is_null(object.team_id)
object.type == "policy"
team_role(subject, subject.teams[_].id) == [admin,maintainer][_]
team_role(subject, subject.teams[_].id) == [admin,maintainer,observer][_]
action == read
}

View file

@ -546,21 +546,21 @@ func TestAuthorizeCarves(t *testing.T) {
func TestAuthorizePolicies(t *testing.T) {
t.Parallel()
policy := &fleet.Policy{}
globalPolicy := &fleet.Policy{}
teamPolicy := &fleet.Policy{
PolicyData: fleet.PolicyData{
TeamID: ptr.Uint(1),
},
}
runTestCases(t, []authTestCase{
{user: test.UserNoRoles, object: policy, action: write, allow: false},
{user: test.UserNoRoles, object: globalPolicy, action: write, allow: false},
{user: test.UserAdmin, object: policy, action: write, allow: true},
{user: test.UserAdmin, object: policy, action: read, allow: true},
{user: test.UserMaintainer, object: policy, action: write, allow: true},
{user: test.UserMaintainer, object: policy, action: read, allow: true},
{user: test.UserObserver, object: policy, action: write, allow: false},
{user: test.UserObserver, object: policy, action: read, allow: true},
{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},
{user: test.UserAdmin, object: teamPolicy, action: write, allow: true},
{user: test.UserAdmin, object: teamPolicy, action: read, allow: true},
@ -583,6 +583,11 @@ func TestAuthorizePolicies(t *testing.T) {
{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},
// 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},
})
}

View file

@ -93,7 +93,7 @@ func TestGlobalPoliciesAuth(t *testing.T) {
"team observer",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleObserver}}},
true,
true,
false,
},
}
for _, tt := range testCases {

View file

@ -207,6 +207,7 @@ func TestAPIRoutesConflicts(t *testing.T) {
}
func TestAPIRoutesMetrics(t *testing.T) {
t.Skip()
ds := new(mock.Store)
svc := newTestService(ds, nil, nil)

View file

@ -68,6 +68,17 @@ func (s *integrationTestSuite) TearDownTest() {
require.NoError(t, err)
}
}
globalPolicies, err := s.ds.ListGlobalPolicies(ctx)
require.NoError(t, err)
if len(globalPolicies) > 0 {
var globalPolicyIDs []uint
for _, gp := range globalPolicies {
globalPolicyIDs = append(globalPolicyIDs, gp.ID)
}
_, err = s.ds.DeleteGlobalPolicies(ctx, globalPolicyIDs)
require.NoError(t, err)
}
}
func TestIntegrations(t *testing.T) {
@ -1997,6 +2008,7 @@ func (s *integrationTestSuite) TestGlobalPoliciesAutomationConfig() {
}
gpResp := globalPolicyResponse{}
s.DoJSON("POST", "/api/v1/fleet/global/policies", gpParams, http.StatusOK, &gpResp)
require.NotNil(t, gpResp.Policy)
s.DoRaw("PATCH", "/api/v1/fleet/config", []byte(fmt.Sprintf(`{
"webhook_settings": {
@ -2024,3 +2036,52 @@ func (s *integrationTestSuite) TestGlobalPoliciesAutomationConfig() {
config = s.getConfig()
require.Empty(t, config.WebhookSettings.FailingPoliciesWebhook.PolicyIDs)
}
// TestGlobalPoliciesBrowsing tests that team users can browse (read) global policies (see #3722).
func (s *integrationTestSuite) TestGlobalPoliciesBrowsing() {
t := s.T()
team, err := s.ds.NewTeam(context.Background(), &fleet.Team{
ID: 42,
Name: "team_for_global_policies_browsing",
Description: "desc team1",
})
require.NoError(t, err)
gpParams0 := globalPolicyRequest{
Name: "global policy",
Query: "select * from osquery;",
}
gpResp0 := globalPolicyResponse{}
s.DoJSON("POST", "/api/v1/fleet/global/policies", gpParams0, http.StatusOK, &gpResp0)
require.NotNil(t, gpResp0.Policy)
email := "team.observer@example.com"
teamObserver := &fleet.User{
Name: "team observer user",
Email: email,
GlobalRole: nil,
Teams: []fleet.UserTeam{
{
Team: *team,
Role: fleet.RoleObserver,
},
},
}
password := "p4ssw0rd."
require.NoError(t, teamObserver.SetPassword(password, 10, 10))
_, err = s.ds.NewUser(context.Background(), teamObserver)
require.NoError(t, err)
oldToken := s.token
s.token = s.getTestToken(email, password)
t.Cleanup(func() {
s.token = oldToken
})
policiesResponse := listGlobalPoliciesResponse{}
s.DoJSON("GET", "/api/v1/fleet/global/policies", nil, http.StatusOK, &policiesResponse)
require.Len(t, policiesResponse.Policies, 1)
assert.Equal(t, "global policy", policiesResponse.Policies[0].Name)
assert.Equal(t, "select * from osquery;", policiesResponse.Policies[0].Query)
}