Clear policy failing counts on hosts that are not running policies (#22665)

#21470

- [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/Committing-Changes.md#changes-files)
for more information.
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
This commit is contained in:
Lucas Manuel Rodriguez
2024-10-09 08:14:21 -03:00
committed by GitHub
parent d65d78807d
commit 9eea9ffa7f
3 changed files with 75 additions and 8 deletions
+1
View File
@@ -0,0 +1 @@
* Fixed a bug where policy failures of a host were not being cleared in the host details page after configuring the host to not run any policies.
+14 -8
View File
@@ -26,8 +26,10 @@ const policyCols = `
p.calendar_events_enabled, p.software_installer_id, p.script_id
`
var errSoftwareTitleIDOnGlobalPolicy = errors.New("install software title id can be only be set on team policies")
var errScriptIDOnGlobalPolicy = errors.New("run script id can only be set on team or \"no team\" policies")
var (
errSoftwareTitleIDOnGlobalPolicy = errors.New("install software title id can be only be set on team policies")
errScriptIDOnGlobalPolicy = errors.New("run script id can only be set on team or \"no team\" policies")
)
var policySearchColumns = []string{"p.name"}
@@ -177,8 +179,10 @@ func (ds *Datastore) SavePolicy(ctx context.Context, p *fleet.Policy, shouldRemo
)
}
var errMismatchedInstallerTeam = &fleet.BadRequestError{Message: "software installer is associated with a different team"}
var errMismatchedScriptTeam = &fleet.BadRequestError{Message: "script is associated with a different team"}
var (
errMismatchedInstallerTeam = &fleet.BadRequestError{Message: "software installer is associated with a different team"}
errMismatchedScriptTeam = &fleet.BadRequestError{Message: "script is associated with a different team"}
)
func (ds *Datastore) assertTeamMatches(ctx context.Context, teamID uint, softwareInstallerID *uint, scriptID *uint) error {
if softwareInstallerID != nil {
@@ -382,10 +386,12 @@ func (ds *Datastore) RecordPolicyQueryExecutions(ctx context.Context, host *flee
if err != nil {
return err
}
if len(results) > 0 {
if err := ds.UpdateHostIssuesFailingPolicies(ctx, []uint{host.ID}); err != nil {
return err
}
// ds.UpdateHostIssuesFailingPolicies should be executed even if len(results) == 0
// because this means the host is configured to run no policies and we would like
// to cleanup the counts (if any).
if err := ds.UpdateHostIssuesFailingPolicies(ctx, []uint{host.ID}); err != nil {
return err
}
if deferredSaveHost {
+60
View File
@@ -12149,3 +12149,63 @@ func (s *integrationTestSuite) TestAutofillPolicies() {
resp = s.Do("POST", "/api/latest/fleet/autofill/policy", req, http.StatusBadRequest)
assertBodyContains(t, resp, "AI features are disabled")
}
func (s *integrationTestSuite) TestHostWithNoPoliciesClearsPolicyCounts() {
t := s.T()
ctx := context.Background()
team, err := s.ds.NewTeam(ctx, &fleet.Team{Name: "Zoobar"})
require.NoError(t, err)
host, err := s.ds.NewHost(ctx, &fleet.Host{
DetailUpdatedAt: time.Now(),
LabelUpdatedAt: time.Now(),
PolicyUpdatedAt: time.Now(),
SeenTime: time.Now(),
NodeKey: ptr.String("foobar"),
UUID: "foobar",
Hostname: "com.foobar.local",
Platform: "linux",
TeamID: &team.ID,
})
require.NoError(t, err)
policy, err := s.ds.NewTeamPolicy(ctx, team.ID, nil, fleet.PolicyPayload{
Name: "Barfoo",
Query: "SELECT 1;",
})
require.NoError(t, err)
distributedWriteResp := submitDistributedQueryResultsResponse{}
s.DoJSON("POST", "/api/osquery/distributed/write", genDistributedReqWithPolicyResults(
host,
map[uint]*bool{
policy.ID: ptr.Bool(false),
},
), http.StatusOK, &distributedWriteResp)
listHostsResp := listHostsResponse{}
s.DoJSON("GET", "/api/latest/fleet/hosts", nil, http.StatusOK, &listHostsResp)
require.Len(t, listHostsResp.Hosts, 1)
require.Equal(t, uint64(1), listHostsResp.Hosts[0].FailingPoliciesCount)
_, err = s.ds.DeleteTeamPolicies(ctx, team.ID, []uint{policy.ID})
require.NoError(t, err)
distributedWriteResp = submitDistributedQueryResultsResponse{}
results := make(map[string]json.RawMessage)
results[hostNoPoliciesWildcard] = json.RawMessage("{\"1\": \"1\"}")
statuses := make(map[string]interface{})
statuses[hostNoPoliciesWildcard] = 0
s.DoJSON("POST", "/api/osquery/distributed/write", submitDistributedQueryResultsRequestShim{
NodeKey: *host.NodeKey,
Results: results,
Statuses: statuses,
Stats: map[string]*fleet.Stats{},
}, http.StatusOK, &distributedWriteResp)
listHostsResp = listHostsResponse{}
s.DoJSON("GET", "/api/latest/fleet/hosts", nil, http.StatusOK, &listHostsResp)
require.Len(t, listHostsResp.Hosts, 1)
require.Equal(t, uint64(0), listHostsResp.Hosts[0].FailingPoliciesCount)
}