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:
@@ -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.
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user