mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
fix usage of query params in host software endpoint (#42302)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #41631 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [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/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. ## Testing - [x] Added/updated automated tests - [x] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [x] QA'd all new/changed functionality manually
This commit is contained in:
parent
8b3674bc55
commit
2e6ffa747d
6 changed files with 84 additions and 52 deletions
2
changes/41631-not-installed
Normal file
2
changes/41631-not-installed
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
- Fixed issue where the `include_available_for_install` query param wasn't being applied correctly
|
||||
to the `GET /api/latest/fleet/hosts/{id}/software` endpoint.
|
||||
|
|
@ -3735,19 +3735,15 @@ func getHostSoftwareEndpoint(ctx context.Context, request interface{}, svc fleet
|
|||
}
|
||||
|
||||
func (svc *Service) ListHostSoftware(ctx context.Context, hostID uint, opts fleet.HostSoftwareTitleListOptions) ([]*fleet.HostSoftwareWithInstaller, *fleet.PaginationMetadata, error) {
|
||||
// When accessed via "My device", we default to only showing inventory (excluding software available for install
|
||||
// but not in inventory), unless we're asked to filter to self-service software only.
|
||||
//
|
||||
// Otherwise (e.g. host software UI within Fleet's admin interface), the default is to show both installed and
|
||||
// available-for-install software, to maintain existing API behavior. This behavior can be explicitly overridden
|
||||
// if needed (see opts.IncludeAvailableForInstallExplicitlySet).
|
||||
// Default to only showing inventory (excluding software available for install but not in
|
||||
// inventory). Callers can explicitly set include_available_for_install=true to also see
|
||||
// library items. See #41631.
|
||||
var includeAvailableForInstall bool
|
||||
|
||||
var host *fleet.Host
|
||||
if !svc.authz.IsAuthenticatedWith(ctx, authzctx.AuthnDeviceToken) &&
|
||||
!svc.authz.IsAuthenticatedWith(ctx, authzctx.AuthnDeviceCertificate) &&
|
||||
!svc.authz.IsAuthenticatedWith(ctx, authzctx.AuthnDeviceURL) {
|
||||
includeAvailableForInstall = true
|
||||
|
||||
if err := svc.authz.Authorize(ctx, &fleet.Host{}, fleet.ActionList); err != nil {
|
||||
return nil, nil, err
|
||||
|
|
|
|||
|
|
@ -11989,9 +11989,17 @@ func (s *integrationEnterpriseTestSuite) TestListHostSoftware() {
|
|||
return err
|
||||
})
|
||||
|
||||
// available installer is returned by user-authenticated endpoint
|
||||
// default (no include_available_for_install param) should only return installed software, not library items (#41631)
|
||||
getHostSw = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", host.ID), nil, http.StatusOK, &getHostSw)
|
||||
require.Len(t, getHostSw.Software, 2) // foo and bar only — ruby is not installed, just available
|
||||
require.Equal(t, getHostSw.Software[0].Name, "bar")
|
||||
require.Equal(t, getHostSw.Software[1].Name, "foo")
|
||||
require.Len(t, getHostSw.Software[1].InstalledVersions, 2)
|
||||
|
||||
// user authenticated endpoint, explicitly request to include available for install software
|
||||
getHostSw = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software?include_available_for_install=true", host.ID), nil, http.StatusOK, &getHostSw)
|
||||
require.Len(t, getHostSw.Software, 3) // foo, bar and ruby.deb
|
||||
require.Equal(t, getHostSw.Software[0].Name, "bar")
|
||||
require.Equal(t, getHostSw.Software[1].Name, "foo")
|
||||
|
|
@ -12005,7 +12013,7 @@ func (s *integrationEnterpriseTestSuite) TestListHostSoftware() {
|
|||
require.True(t, *getHostSw.Software[2].SoftwarePackage.SelfService)
|
||||
require.Nil(t, getHostSw.Software[2].Status)
|
||||
|
||||
// user authenticated endpoint, but explicitly request to not include available for install software
|
||||
// user authenticated endpoint, explicitly request to not include available for install software
|
||||
getHostSw = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software?include_available_for_install=false", host.ID), nil, http.StatusOK, &getHostSw)
|
||||
require.Len(t, getHostSw.Software, 2) // foo and bar
|
||||
|
|
@ -12110,9 +12118,16 @@ func (s *integrationEnterpriseTestSuite) TestListHostSoftware() {
|
|||
s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/hosts/%d/software/%d/install",
|
||||
host.ID, titleID), nil, http.StatusAccepted, &installResp)
|
||||
|
||||
// still returned by user-authenticated endpoint, now pending
|
||||
// default (no param) should still only return installed software, even after install is requested (#41631)
|
||||
getHostSw = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", host.ID), nil, http.StatusOK, &getHostSw)
|
||||
require.Len(t, getHostSw.Software, 2) // foo and bar — ruby has a pending install but is not yet installed
|
||||
require.Equal(t, getHostSw.Software[0].Name, "bar")
|
||||
require.Equal(t, getHostSw.Software[1].Name, "foo")
|
||||
|
||||
// with include_available_for_install=true, the pending install is visible
|
||||
getHostSw = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software?include_available_for_install=true", host.ID), nil, http.StatusOK, &getHostSw)
|
||||
require.Len(t, getHostSw.Software, 3) // foo, bar and ruby.deb
|
||||
require.Equal(t, getHostSw.Software[0].Name, "bar")
|
||||
require.Equal(t, getHostSw.Software[1].Name, "foo")
|
||||
|
|
@ -14173,7 +14188,7 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersSideEffec
|
|||
|
||||
// Get the install response, should be pending
|
||||
getHostSoftwareResp := getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &getHostSoftwareResp, "include_available_for_install", "true")
|
||||
require.Equal(t, fleet.SoftwareInstallPending, *getHostSoftwareResp.Software[0].Status)
|
||||
|
||||
// Switch self-service flag
|
||||
|
|
@ -14214,12 +14229,12 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersSideEffec
|
|||
|
||||
// install should no longer be pending
|
||||
afterPreinstallHostResp := getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &afterPreinstallHostResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &afterPreinstallHostResp, "include_available_for_install", "true")
|
||||
require.Nil(t, afterPreinstallHostResp.Software[0].Status)
|
||||
|
||||
// install software fully
|
||||
s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/hosts/%d/software/%d/install", h.ID, titlesResp.SoftwareTitles[0].ID), nil, http.StatusAccepted, &installResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &getHostSoftwareResp, "include_available_for_install", "true")
|
||||
installUUID := getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall.InstallUUID
|
||||
s.Do("POST", "/api/fleet/orbit/software_install/result", json.RawMessage(fmt.Sprintf(`{
|
||||
"orbit_node_key": %q,
|
||||
|
|
@ -14237,7 +14252,7 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersSideEffec
|
|||
|
||||
// install should show as complete
|
||||
hostResp := getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &hostResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &hostResp, "include_available_for_install", "true")
|
||||
require.Equal(t, fleet.SoftwareInstalled, *hostResp.Software[0].Status)
|
||||
|
||||
// update install script
|
||||
|
|
@ -14261,7 +14276,7 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersSideEffec
|
|||
|
||||
// install should still show as complete
|
||||
hostResp = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &hostResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &hostResp, "include_available_for_install", "true")
|
||||
require.Equal(t, fleet.SoftwareInstalled, *hostResp.Software[0].Status)
|
||||
|
||||
trailer = " " // add a character to the response for the installer HTTP call to ensure the file hashes differently
|
||||
|
|
@ -14283,7 +14298,7 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersSideEffec
|
|||
|
||||
// install should be nulled out
|
||||
hostResp = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &hostResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &hostResp, "include_available_for_install", "true")
|
||||
require.Nil(t, hostResp.Software[0].Status)
|
||||
|
||||
// install details record should still show as installed
|
||||
|
|
@ -14296,7 +14311,7 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersSideEffec
|
|||
s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/hosts/%d/software/%d/install", h.ID, titlesResp.SoftwareTitles[0].ID), nil, http.StatusAccepted, &pendingResp)
|
||||
|
||||
// install should show as pending
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &afterPreinstallHostResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &afterPreinstallHostResp, "include_available_for_install", "true")
|
||||
require.Equal(t, fleet.SoftwareInstallPending, *afterPreinstallHostResp.Software[0].Status)
|
||||
installUUID = afterPreinstallHostResp.Software[0].SoftwarePackage.LastInstall.InstallUUID
|
||||
|
||||
|
|
@ -14305,7 +14320,7 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallersSideEffec
|
|||
s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/hosts/%d/software/%d/uninstall", h2.ID, titlesResp.SoftwareTitles[0].ID), nil, http.StatusAccepted, &uninstallResp)
|
||||
|
||||
// uninstall should show as pending
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h2.ID), nil, http.StatusOK, &afterPreinstallHostResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h2.ID), nil, http.StatusOK, &afterPreinstallHostResp, "include_available_for_install", "true")
|
||||
require.Equal(t, fleet.SoftwareUninstallPending, *afterPreinstallHostResp.Software[0].Status)
|
||||
|
||||
// delete all installers
|
||||
|
|
@ -14689,7 +14704,7 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerHostRequests() {
|
|||
|
||||
// Get the results, should be pending
|
||||
getHostSoftwareResp := getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &getHostSoftwareResp, "include_available_for_install", "true")
|
||||
require.Len(t, getHostSoftwareResp.Software, 1)
|
||||
require.NotNil(t, getHostSoftwareResp.Software[0].SoftwarePackage)
|
||||
require.NotNil(t, getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall)
|
||||
|
|
@ -14724,7 +14739,7 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerHostRequests() {
|
|||
require.NoError(t, s.ds.UpdateHostRefetchRequested(context.Background(), h4.ID, false))
|
||||
|
||||
s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/hosts/%d/software/%d/install", h2.ID, titleID), nil, http.StatusAccepted, &resp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h2.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h2.ID), nil, http.StatusOK, &getHostSoftwareResp, "include_available_for_install", "true")
|
||||
require.Len(t, getHostSoftwareResp.Software, 1)
|
||||
installUUID2 := getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall.InstallUUID
|
||||
s.Do("POST", "/api/fleet/orbit/software_install/result", json.RawMessage(fmt.Sprintf(`{
|
||||
|
|
@ -14735,13 +14750,24 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerHostRequests() {
|
|||
"install_script_output": "ok"
|
||||
}`, *h2.OrbitNodeKey, installUUID2)), http.StatusNoContent)
|
||||
|
||||
software := []fleet.Software{
|
||||
{Name: payload.Title, Version: payload.Version, Source: "deb_packages"},
|
||||
}
|
||||
_, err = s.ds.UpdateHostSoftware(context.Background(), h2.ID, software)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Note: no need to use the "include_available_for_install" query param
|
||||
// since we simulated ingesting the software above
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h2.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
require.Len(t, getHostSoftwareResp.Software, 1)
|
||||
|
||||
// Verify refetch requested is set after successful install
|
||||
var hostResp getHostResponse
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d", h2.ID), nil, http.StatusOK, &hostResp)
|
||||
require.True(t, hostResp.Host.RefetchRequested, "RefetchRequested should be true after successful software install")
|
||||
|
||||
s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/hosts/%d/software/%d/install", h3.ID, titleID), nil, http.StatusAccepted, &resp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h3.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h3.ID), nil, http.StatusOK, &getHostSoftwareResp, "include_available_for_install", "true")
|
||||
require.Len(t, getHostSoftwareResp.Software, 1)
|
||||
installUUID3 := getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall.InstallUUID
|
||||
s.Do("POST", "/api/fleet/orbit/software_install/result", json.RawMessage(fmt.Sprintf(`{
|
||||
|
|
@ -14761,7 +14787,7 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerHostRequests() {
|
|||
// Server-side retries queue up to MaxSoftwareInstallAttempts attempts.
|
||||
for attempt := 2; attempt <= fleet.MaxSoftwareInstallAttempts; attempt++ {
|
||||
getHostSoftwareResp = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h3.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h3.ID), nil, http.StatusOK, &getHostSoftwareResp, "include_available_for_install", "true")
|
||||
require.Len(t, getHostSoftwareResp.Software, 1)
|
||||
require.NotNil(t, getHostSoftwareResp.Software[0].SoftwarePackage)
|
||||
require.NotNil(t, getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall)
|
||||
|
|
@ -14778,7 +14804,7 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerHostRequests() {
|
|||
}
|
||||
|
||||
s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/hosts/%d/software/%d/install", h4.ID, titleID), nil, http.StatusAccepted, &resp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h4.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h4.ID), nil, http.StatusOK, &getHostSoftwareResp, "include_available_for_install", "true")
|
||||
require.Len(t, getHostSoftwareResp.Software, 1)
|
||||
installUUID4a := getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall.InstallUUID
|
||||
s.Do("POST", "/api/fleet/orbit/software_install/result", json.RawMessage(fmt.Sprintf(`{
|
||||
|
|
@ -14795,7 +14821,7 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerHostRequests() {
|
|||
// Exhaust automatic retries for h4 so it reaches terminal "failed" state.
|
||||
for attempt := 2; attempt <= fleet.MaxSoftwareInstallAttempts; attempt++ {
|
||||
getHostSoftwareResp = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h4.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h4.ID), nil, http.StatusOK, &getHostSoftwareResp, "include_available_for_install", "true")
|
||||
require.Len(t, getHostSoftwareResp.Software, 1)
|
||||
require.NotNil(t, getHostSoftwareResp.Software[0].SoftwarePackage)
|
||||
require.NotNil(t, getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall)
|
||||
|
|
@ -14810,7 +14836,7 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerHostRequests() {
|
|||
}
|
||||
|
||||
s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/hosts/%d/software/%d/install", h4.ID, titleID), nil, http.StatusAccepted, &resp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h4.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h4.ID), nil, http.StatusOK, &getHostSoftwareResp, "include_available_for_install", "true")
|
||||
require.Len(t, getHostSoftwareResp.Software, 1)
|
||||
installUUID4b := getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall.InstallUUID
|
||||
_ = installUUID4b
|
||||
|
|
@ -14941,7 +14967,8 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerHostRequests() {
|
|||
}
|
||||
distributedResp := submitDistributedQueryResultsResponse{}
|
||||
s.DoJSON("POST", "/api/osquery/distributed/write", distributedReq, http.StatusOK, &distributedResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h2.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h2.ID), nil, http.StatusOK, &getHostSoftwareResp,
|
||||
"include_available_for_install", "true")
|
||||
require.Len(t, getHostSoftwareResp.Software, 1)
|
||||
assert.NotNil(t, getHostSoftwareResp.Software[0].Status)
|
||||
assert.NotNil(t, getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall)
|
||||
|
|
@ -14962,7 +14989,8 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerHostRequests() {
|
|||
distributedResp = submitDistributedQueryResultsResponse{}
|
||||
s.DoJSON("POST", "/api/osquery/distributed/write", distributedReq, http.StatusOK, &distributedResp)
|
||||
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h2.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h2.ID), nil, http.StatusOK, &getHostSoftwareResp,
|
||||
"include_available_for_install", "true")
|
||||
require.Len(t, getHostSoftwareResp.Software, 1)
|
||||
assert.Nil(t, getHostSoftwareResp.Software[0].Status)
|
||||
assert.Nil(t, getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall)
|
||||
|
|
@ -15000,7 +15028,8 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerHostRequests() {
|
|||
|
||||
// Do uninstall on h
|
||||
s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/hosts/%d/software/%d/uninstall", h.ID, titleID), nil, http.StatusAccepted, &resp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &getHostSoftwareResp,
|
||||
"include_available_for_install", "true")
|
||||
require.Len(t, getHostSoftwareResp.Software, 1)
|
||||
assert.NotNil(t, getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall)
|
||||
assert.Equal(t, fleet.SoftwareUninstallPending, *getHostSoftwareResp.Software[0].Status)
|
||||
|
|
@ -15073,7 +15102,8 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerHostRequests() {
|
|||
s.DoRawNoAuth("GET", fmt.Sprintf("/api/v1/fleet/device/%s/software/uninstall/%s/results", token, uninstallExecutionID), nil, http.StatusOK)
|
||||
|
||||
// Software should be available for install again
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &getHostSoftwareResp,
|
||||
"include_available_for_install", "true")
|
||||
require.Len(t, getHostSoftwareResp.Software, 1)
|
||||
assert.NotNil(t, getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall)
|
||||
require.NotNil(t, getHostSoftwareResp.Software[0].SoftwarePackage.LastUninstall)
|
||||
|
|
@ -15087,7 +15117,8 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerHostRequests() {
|
|||
// Since host_script_results does not use fine-grained timestamps yet, we adjust
|
||||
beforeUninstall = beforeUninstall.Add(-time.Second)
|
||||
s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/hosts/%d/software/%d/uninstall", h.ID, titleID), nil, http.StatusAccepted, &resp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", h.ID), nil, http.StatusOK, &getHostSoftwareResp,
|
||||
"include_available_for_install", "true")
|
||||
require.Len(t, getHostSoftwareResp.Software, 1)
|
||||
assert.NotNil(t, getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall)
|
||||
assert.Equal(t, fleet.SoftwareUninstallPending, *getHostSoftwareResp.Software[0].Status)
|
||||
|
|
@ -15261,7 +15292,8 @@ func (s *integrationEnterpriseTestSuite) TestSelfServiceSoftwareInstallUninstall
|
|||
// Do uninstall on host
|
||||
s.DoRawNoAuth("POST", fmt.Sprintf("/api/v1/fleet/device/%s/software/uninstall/%d", token, titleIDSS), nil, http.StatusAccepted)
|
||||
var getHostSoftwareResp getHostSoftwareResponse
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", host1.ID), nil, http.StatusOK, &getHostSoftwareResp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", host1.ID), nil, http.StatusOK, &getHostSoftwareResp,
|
||||
"include_available_for_install", "true")
|
||||
require.Len(t, getHostSoftwareResp.Software, 2)
|
||||
assert.NotNil(t, getHostSoftwareResp.Software[0].SoftwarePackage.LastInstall)
|
||||
assert.Equal(t, fleet.SoftwareUninstallPending, *getHostSoftwareResp.Software[0].Status)
|
||||
|
|
@ -17169,9 +17201,9 @@ func (s *integrationEnterpriseTestSuite) TestVPPAppsWithoutMDM() {
|
|||
}
|
||||
s.uploadSoftwareInstaller(t, pkgPayload, http.StatusOK, "")
|
||||
|
||||
// We don't see VPP, but we do still see the installers
|
||||
// We don't see VPP, but we do still see the installers (need include_available_for_install=true since it's not in osquery inventory)
|
||||
resp := getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", orbitHost.ID), getHostSoftwareRequest{}, http.StatusOK, &resp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software?include_available_for_install=true", orbitHost.ID), getHostSoftwareRequest{}, http.StatusOK, &resp)
|
||||
assert.Len(t, resp.Software, 1)
|
||||
assert.NotNil(t, resp.Software[0].SoftwarePackage)
|
||||
assert.Nil(t, resp.Software[0].AppStoreApp)
|
||||
|
|
@ -20724,8 +20756,9 @@ func (s *integrationEnterpriseTestSuite) TestListHostSoftwareWithLabelScoping()
|
|||
http.StatusNoContent)
|
||||
|
||||
// Software is now installed on the host. We should see it in the host software list
|
||||
// (need include_available_for_install=true since the install was tracked via an installer, not osquery inventory)
|
||||
getHostSw := getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", host.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software?include_available_for_install=true", host.ID), nil, http.StatusOK, &getHostSw)
|
||||
require.Len(t, getHostSw.Software, 1)
|
||||
require.Equal(t, getHostSw.Software[0].Name, "ruby")
|
||||
|
||||
|
|
@ -20770,7 +20803,7 @@ func (s *integrationEnterpriseTestSuite) TestListHostSoftwareWithLabelScoping()
|
|||
updateInstallerLabel(installerID, lbl2.ID, true)
|
||||
|
||||
// We should still see the software at this point, because we haven't uninstalled it yet
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", host.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software?include_available_for_install=true", host.ID), nil, http.StatusOK, &getHostSw)
|
||||
require.Len(t, getHostSw.Software, 1)
|
||||
|
||||
// installer should be out of scope since the label is "exclude any"
|
||||
|
|
@ -20785,7 +20818,7 @@ func (s *integrationEnterpriseTestSuite) TestListHostSoftwareWithLabelScoping()
|
|||
|
||||
// uninstall the software
|
||||
s.DoJSON("POST", fmt.Sprintf("/api/latest/fleet/hosts/%d/software/%d/uninstall", host.ID, titleID), nil, http.StatusAccepted, &resp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", host.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software?include_available_for_install=true", host.ID), nil, http.StatusOK, &getHostSw)
|
||||
require.Len(t, getHostSw.Software, 1)
|
||||
// TODO this is a corner case where we have visibility on a descoped uninstall, but this will disappear
|
||||
// once we complete the uninstall because at that point we'll be relying solely on inventory to determine software
|
||||
|
|
|
|||
|
|
@ -4082,9 +4082,10 @@ func (s *integrationMDMTestSuite) TestSetupExperienceAndroid() {
|
|||
require.Equal(t, app2.AdamID, getHostSw.Software[1].AppStoreApp.AppStoreID)
|
||||
require.Nil(t, getHostSw.Software[1].Status)
|
||||
|
||||
// the software now shows up in the host inventory
|
||||
// the software now shows up when including available-for-install (tracked via installer, not osquery inventory)
|
||||
getHostSw = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", host.ID), nil, http.StatusOK, &getHostSw, "order_key", "name")
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", host.ID), nil, http.StatusOK, &getHostSw, "order_key", "name",
|
||||
"include_available_for_install", "true")
|
||||
require.Len(t, getHostSw.Software, 2)
|
||||
require.NotNil(t, getHostSw.Software[0].AppStoreApp)
|
||||
require.Equal(t, app1.AdamID, getHostSw.Software[0].AppStoreApp.AppStoreID)
|
||||
|
|
|
|||
|
|
@ -14249,7 +14249,7 @@ func (s *integrationMDMTestSuite) TestVPPApps() {
|
|||
// Check list host software
|
||||
|
||||
getHostSw := getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw, "include_available_for_install", "true")
|
||||
gotSW := getHostSw.Software
|
||||
require.Len(t, gotSW, 2) // App 1 and App 2
|
||||
got1, got2 := gotSW[0], gotSW[1]
|
||||
|
|
@ -14276,7 +14276,7 @@ func (s *integrationMDMTestSuite) TestVPPApps() {
|
|||
|
||||
// Check with a query
|
||||
getHostSw = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw, "query", "App 1")
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw, "query", "App 1", "include_available_for_install", "true")
|
||||
require.Len(t, getHostSw.Software, 1) // App 1 only
|
||||
got1 = getHostSw.Software[0]
|
||||
require.Equal(t, got1.Name, "App 1")
|
||||
|
|
@ -14332,7 +14332,7 @@ func (s *integrationMDMTestSuite) TestVPPApps() {
|
|||
|
||||
// Check list host software
|
||||
getHostSw = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw, "include_available_for_install", "true")
|
||||
gotSW = getHostSw.Software
|
||||
require.Len(t, gotSW, 2) // App 1 and App 2
|
||||
got1 = gotSW[0]
|
||||
|
|
@ -14507,7 +14507,7 @@ func (s *integrationMDMTestSuite) TestVPPApps() {
|
|||
|
||||
// Check list host software
|
||||
getHostSw = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", installHost.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", installHost.ID), nil, http.StatusOK, &getHostSw, "include_available_for_install", "true")
|
||||
require.Len(t, getHostSw.Software, install.hostCount+install.extraAvailable)
|
||||
var foundInstalledApp bool
|
||||
for index := range getHostSw.Software {
|
||||
|
|
@ -17956,7 +17956,7 @@ func (s *integrationMDMTestSuite) TestVPPAppsMDMFiltering() {
|
|||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", orbitHost.ID), getHostSoftwareRequest{}, http.StatusOK, &resp)
|
||||
assert.Len(t, resp.Software, 0)
|
||||
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), getHostSoftwareRequest{}, http.StatusOK, &resp)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), getHostSoftwareRequest{}, http.StatusOK, &resp, "include_available_for_install", "true")
|
||||
assert.Len(t, resp.Software, 1)
|
||||
}
|
||||
|
||||
|
|
@ -19759,7 +19759,7 @@ func (s *integrationMDMTestSuite) TestSoftwareCategories() {
|
|||
host.ID, titleID), nil, http.StatusAccepted, &installResp)
|
||||
|
||||
getHostSw := getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", host.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", host.ID), nil, http.StatusOK, &getHostSw, "include_available_for_install", "true")
|
||||
require.Len(t, getHostSw.Software, 1)
|
||||
require.Equal(t, getHostSw.Software[0].Name, "ruby")
|
||||
require.NotNil(t, getHostSw.Software[0].SoftwarePackage)
|
||||
|
|
@ -19789,7 +19789,7 @@ func (s *integrationMDMTestSuite) TestSoftwareCategories() {
|
|||
require.Equal(t, cat3.Name, getDeviceSw.Software[0].SoftwarePackage.Categories[0])
|
||||
|
||||
getHostSw = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", host.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", host.ID), nil, http.StatusOK, &getHostSw, "include_available_for_install", "true")
|
||||
require.Len(t, getHostSw.Software, 1)
|
||||
require.Equal(t, getHostSw.Software[0].Name, "ruby")
|
||||
require.NotNil(t, getHostSw.Software[0].SoftwarePackage)
|
||||
|
|
|
|||
|
|
@ -505,7 +505,7 @@ func (s *integrationMDMTestSuite) TestVPPAppInstallVerification() {
|
|||
|
||||
// Check list host software
|
||||
getHostSw := getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw, "include_available_for_install", "true")
|
||||
gotSW := getHostSw.Software
|
||||
require.Len(t, gotSW, 2) // App 1 and App 2
|
||||
got1, got2 := gotSW[0], gotSW[1]
|
||||
|
|
@ -543,7 +543,7 @@ func (s *integrationMDMTestSuite) TestVPPAppInstallVerification() {
|
|||
require.Equal(t, 0, countResp.Count)
|
||||
|
||||
// We should instead have 1 pending
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw, "include_available_for_install", "true")
|
||||
gotSW = getHostSw.Software
|
||||
require.Len(t, gotSW, 2) // App 1 and App 2
|
||||
checkVPPApp(gotSW[0], addedApp, installCmdUUID, fleet.SoftwareInstallPending)
|
||||
|
|
@ -570,7 +570,7 @@ func (s *integrationMDMTestSuite) TestVPPAppInstallVerification() {
|
|||
require.Equal(t, 0, countResp.Count)
|
||||
|
||||
// We should instead have 1 pending
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw, "include_available_for_install", "true")
|
||||
gotSW = getHostSw.Software
|
||||
require.Len(t, gotSW, 2) // App 1 and App 2
|
||||
checkVPPApp(gotSW[0], addedApp, installCmdUUID, fleet.SoftwareInstallPending)
|
||||
|
|
@ -589,7 +589,7 @@ func (s *integrationMDMTestSuite) TestVPPAppInstallVerification() {
|
|||
|
||||
checkCommandsInFlight(0)
|
||||
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw, "include_available_for_install", "true")
|
||||
gotSW = getHostSw.Software
|
||||
require.Len(t, gotSW, 2) // App 1 and App 2
|
||||
checkVPPApp(gotSW[0], addedApp, installCmdUUID, fleet.SoftwareInstalled)
|
||||
|
|
@ -665,7 +665,7 @@ func (s *integrationMDMTestSuite) TestVPPAppInstallVerification() {
|
|||
|
||||
// Check list host software
|
||||
getHostSw = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw, "include_available_for_install", "true")
|
||||
gotSW = getHostSw.Software
|
||||
require.Len(t, gotSW, 2) // App 1 and App 2
|
||||
got1, got2 = gotSW[0], gotSW[1]
|
||||
|
|
@ -757,7 +757,7 @@ func (s *integrationMDMTestSuite) TestVPPAppInstallVerification() {
|
|||
s.Do("DELETE", fmt.Sprintf("/api/latest/fleet/hosts/%d/activities/upcoming/%s", selfServiceHost.ID, listUpcomingAct.Activities[0].UUID), nil, http.StatusNoContent)
|
||||
|
||||
getHostSw = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw, "include_available_for_install", "true")
|
||||
gotSW = getHostSw.Software
|
||||
require.Len(t, gotSW, 2) // App 1 and App 2
|
||||
got1, got2 = gotSW[0], gotSW[1]
|
||||
|
|
@ -814,7 +814,7 @@ func (s *integrationMDMTestSuite) TestVPPAppInstallVerification() {
|
|||
})
|
||||
|
||||
getHostSw = getHostSoftwareResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/software", mdmHost.ID), nil, http.StatusOK, &getHostSw, "include_available_for_install", "true")
|
||||
gotSW = getHostSw.Software
|
||||
require.Len(t, gotSW, 2) // App 1 and App 2
|
||||
got1, got2 = gotSW[0], gotSW[1]
|
||||
|
|
|
|||
Loading…
Reference in a new issue