mirror of
https://github.com/fleetdm/fleet
synced 2026-05-22 16:39:01 +00:00
Revert "Add "ExcludeFleetMaintainedApps" option to software titles query (#26383)
This feature was requested by a customer that has since decided not to
continue using the MSP dashboard. We had identified some edge cases with
the feature that we wanted to add patches for, so rather than leave it
in the current state (which isn't being used) we decided to back the
code out entirely.
This is a revert of commit
8419b8e87a.
This commit is contained in:
parent
6e3d6ddc66
commit
f200bb38c0
4 changed files with 9 additions and 240 deletions
|
|
@ -1 +0,0 @@
|
|||
- Add "exclude_fleet_maintained_apps" option to `GET /api/v1/fleet/software/titles`
|
||||
|
|
@ -410,12 +410,6 @@ GROUP BY st.id, package_self_service, package_name, package_version, package_url
|
|||
defaultFilter += ` AND ( si.self_service = 1 OR vat.self_service = 1 ) `
|
||||
}
|
||||
|
||||
// if excluding fleet maintained apps, filter out any row from software_titles
|
||||
// that has a matching row in fleet_library_apps.
|
||||
if opt.ExcludeFleetMaintainedApps {
|
||||
additionalWhere += " AND NOT EXISTS ( SELECT FALSE FROM fleet_library_apps AS fla WHERE fla.bundle_identifier = st.bundle_identifier )"
|
||||
}
|
||||
|
||||
stmt = fmt.Sprintf(stmt, softwareInstallersJoinCond, vppAppsJoinCond, vppAppsTeamsJoinCond, countsJoin, softwareJoin, additionalWhere, defaultFilter)
|
||||
return stmt, args
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ func TestSoftwareTitles(t *testing.T) {
|
|||
{"ListSoftwareTitlesInstallersOnly", testListSoftwareTitlesInstallersOnly},
|
||||
{"ListSoftwareTitlesAvailableForInstallFilter", testListSoftwareTitlesAvailableForInstallFilter},
|
||||
{"ListSoftwareTitlesAllTeams", testListSoftwareTitlesAllTeams},
|
||||
{"ListSoftwareTitlesNotFleetMaintained", testListSoftwareTitlesNotFleetMaintained},
|
||||
{"UploadedSoftwareExists", testUploadedSoftwareExists},
|
||||
{"ListSoftwareTitlesVulnerabilityFilters", testListSoftwareTitlesVulnerabilityFilters},
|
||||
}
|
||||
|
|
@ -640,7 +639,6 @@ func testTeamFilterSoftwareTitles(t *testing.T, ds *Datastore) {
|
|||
InstallScript: "echo",
|
||||
Filename: "installer1.pkg",
|
||||
BundleIdentifier: "foo.bar",
|
||||
Platform: string(fleet.MacOSPlatform),
|
||||
TeamID: &team1.ID,
|
||||
UserID: user1.ID,
|
||||
ValidatedLabels: &fleet.LabelIdentsWithScope{},
|
||||
|
|
@ -867,20 +865,6 @@ func testTeamFilterSoftwareTitles(t *testing.T, ds *Datastore) {
|
|||
require.NoError(t, err)
|
||||
require.Len(t, titles, 1)
|
||||
require.Equal(t, "vpp3", titles[0].Name)
|
||||
|
||||
// Testing with Platform filter
|
||||
titles, count, _, err = ds.ListSoftwareTitles(
|
||||
context.Background(), fleet.SoftwareTitleListOptions{
|
||||
ListOptions: fleet.ListOptions{},
|
||||
Platform: string(fleet.MacOSPlatform),
|
||||
AvailableForInstall: true,
|
||||
TeamID: &team1.ID,
|
||||
}, globalTeamFilter,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, count)
|
||||
require.Len(t, titles, 1)
|
||||
require.Equal(t, "installer1", titles[0].Name)
|
||||
}
|
||||
|
||||
func sortTitlesByName(titles []fleet.SoftwareTitleListResult) {
|
||||
|
|
@ -1387,213 +1371,6 @@ func testListSoftwareTitlesAllTeams(t *testing.T, ds *Datastore) {
|
|||
}, names)
|
||||
}
|
||||
|
||||
func testListSoftwareTitlesNotFleetMaintained(t *testing.T, ds *Datastore) {
|
||||
ctx := context.Background()
|
||||
|
||||
test.CreateInsertGlobalVPPToken(t, ds)
|
||||
|
||||
// Add a couple of apps to the Fleet library.
|
||||
_, err := ds.UpsertMaintainedApp(ctx, &fleet.MaintainedApp{
|
||||
Name: "Awesome Fleet Maintained App",
|
||||
Token: "abc123",
|
||||
Version: "1.2.3",
|
||||
// for now, maintained apps are always macOS (darwin)
|
||||
Platform: fleet.MacOSPlatform,
|
||||
InstallerURL: "http://installmycoolapp.com",
|
||||
SHA256: "abc123",
|
||||
BundleIdentifier: "com.fleetmaintained_installer.xyz",
|
||||
InstallScript: "echo",
|
||||
UninstallScript: "sleep",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = ds.UpsertMaintainedApp(ctx, &fleet.MaintainedApp{
|
||||
Name: "Another Fleet Maintained App",
|
||||
Token: "xxxyyy",
|
||||
Version: "5.5.5",
|
||||
// for now, maintained apps are always macOS (darwin)
|
||||
Platform: fleet.MacOSPlatform,
|
||||
InstallerURL: "http://installmycoolapp.com",
|
||||
SHA256: "xyz999",
|
||||
BundleIdentifier: "fma.com.xyz",
|
||||
InstallScript: "echo",
|
||||
UninstallScript: "sleep",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
user1 := test.NewUser(t, ds, "Alice", "alice@example.com", true)
|
||||
|
||||
// Create a macOS software foobar installer on "No team".
|
||||
macOSInstallerNoTeam, _, err := ds.MatchOrCreateSoftwareInstaller(ctx, &fleet.UploadSoftwareInstallerPayload{
|
||||
Title: "foobar",
|
||||
BundleIdentifier: "com.foo.bar",
|
||||
Source: "apps",
|
||||
InstallScript: "echo",
|
||||
Filename: "foobar.pkg",
|
||||
TeamID: nil,
|
||||
UserID: user1.ID,
|
||||
ValidatedLabels: &fleet.LabelIdentsWithScope{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotZero(t, macOSInstallerNoTeam)
|
||||
|
||||
// Create another macOS software installer on "No team" that we'll set as a Fleet Maintained App.
|
||||
macOSInstallerNoTeam2, _, err := ds.MatchOrCreateSoftwareInstaller(ctx, &fleet.UploadSoftwareInstallerPayload{
|
||||
Title: "fleetmaintained_installer",
|
||||
BundleIdentifier: "com.fleetmaintained_installer.xyz",
|
||||
Source: "apps",
|
||||
InstallScript: "echo",
|
||||
Filename: "fleetmaintained_installer.pkg",
|
||||
TeamID: nil,
|
||||
UserID: user1.ID,
|
||||
ValidatedLabels: &fleet.LabelIdentsWithScope{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotZero(t, macOSInstallerNoTeam2)
|
||||
|
||||
// Add a macOS host on "No team" with some software.
|
||||
host := test.NewHost(t, ds, "host", "", "hostkey", "hostuuid", time.Now())
|
||||
software := []fleet.Software{
|
||||
{Name: "foo", Version: "0.0.1", Source: "chrome_extensions", BundleIdentifier: "foo.com.bar"},
|
||||
{Name: "foo", Version: "0.0.3", Source: "chrome_extensions", BundleIdentifier: "foo.com.bar"},
|
||||
{Name: "bar", Version: "0.0.3", Source: "deb_packages", BundleIdentifier: "bar.com.baz"},
|
||||
{Name: "fma", Version: "1.2.3", Source: "deb_packages", BundleIdentifier: "fma.com.xyz"},
|
||||
}
|
||||
_, err = ds.UpdateHostSoftware(ctx, host.ID, software)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Simulate vulnerabilities cron
|
||||
require.NoError(t, ds.SyncHostsSoftware(ctx, time.Now()))
|
||||
require.NoError(t, ds.ReconcileSoftwareTitles(ctx))
|
||||
require.NoError(t, ds.SyncHostsSoftwareTitles(ctx, time.Now()))
|
||||
|
||||
// List software titles for "All teams", should only return the host software titles
|
||||
// and no installers/VPP-apps because none is installed yet.
|
||||
titles, counts, _, err := ds.ListSoftwareTitles(
|
||||
ctx,
|
||||
fleet.SoftwareTitleListOptions{
|
||||
ListOptions: fleet.ListOptions{
|
||||
OrderKey: "name",
|
||||
OrderDirection: fleet.OrderAscending,
|
||||
},
|
||||
ExcludeFleetMaintainedApps: true,
|
||||
TeamID: nil,
|
||||
},
|
||||
fleet.TeamFilter{User: &fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)}},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 2, counts)
|
||||
assert.Len(t, titles, 2)
|
||||
type nameSource struct {
|
||||
name string
|
||||
source string
|
||||
}
|
||||
names := make([]nameSource, 0, len(titles))
|
||||
for _, title := range titles {
|
||||
names = append(names, nameSource{name: title.Name, source: title.Source})
|
||||
}
|
||||
assert.ElementsMatch(t, []nameSource{
|
||||
{name: "bar", source: "deb_packages"},
|
||||
{name: "foo", source: "chrome_extensions"},
|
||||
}, names)
|
||||
|
||||
// List software for "No team". Should list the host's software + the macOS installer.
|
||||
titles, counts, _, err = ds.ListSoftwareTitles(
|
||||
ctx,
|
||||
fleet.SoftwareTitleListOptions{
|
||||
ListOptions: fleet.ListOptions{
|
||||
OrderKey: "name",
|
||||
OrderDirection: fleet.OrderAscending,
|
||||
},
|
||||
ExcludeFleetMaintainedApps: true,
|
||||
TeamID: ptr.Uint(0),
|
||||
},
|
||||
fleet.TeamFilter{User: &fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)}},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 3, counts)
|
||||
assert.Len(t, titles, 3)
|
||||
names = make([]nameSource, 0, len(titles))
|
||||
for _, title := range titles {
|
||||
names = append(names, nameSource{name: title.Name, source: title.Source})
|
||||
}
|
||||
assert.ElementsMatch(t, []nameSource{
|
||||
{name: "bar", source: "deb_packages"},
|
||||
{name: "foo", source: "chrome_extensions"},
|
||||
{name: "foobar", source: "apps"},
|
||||
}, names)
|
||||
|
||||
// List software for "No team", with match for non-FMA title.
|
||||
// This should return a result.
|
||||
titles, counts, _, err = ds.ListSoftwareTitles(
|
||||
ctx,
|
||||
fleet.SoftwareTitleListOptions{
|
||||
ListOptions: fleet.ListOptions{
|
||||
OrderKey: "name",
|
||||
OrderDirection: fleet.OrderAscending,
|
||||
MatchQuery: "foobar",
|
||||
},
|
||||
ExcludeFleetMaintainedApps: true,
|
||||
TeamID: ptr.Uint(0),
|
||||
},
|
||||
fleet.TeamFilter{User: &fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)}},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, counts)
|
||||
assert.Len(t, titles, 1)
|
||||
names = make([]nameSource, 0, len(titles))
|
||||
for _, title := range titles {
|
||||
names = append(names, nameSource{name: title.Name, source: title.Source})
|
||||
}
|
||||
assert.ElementsMatch(t, []nameSource{
|
||||
{name: "foobar", source: "apps"},
|
||||
}, names)
|
||||
|
||||
// List software for "No team", with match for an FMA title.
|
||||
// This should not return a result since we're excluding FMAs.
|
||||
titles, counts, _, err = ds.ListSoftwareTitles(
|
||||
ctx,
|
||||
fleet.SoftwareTitleListOptions{
|
||||
ListOptions: fleet.ListOptions{
|
||||
OrderKey: "name",
|
||||
OrderDirection: fleet.OrderAscending,
|
||||
MatchQuery: "fma",
|
||||
},
|
||||
ExcludeFleetMaintainedApps: true,
|
||||
TeamID: ptr.Uint(0),
|
||||
},
|
||||
fleet.TeamFilter{User: &fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)}},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 0, counts)
|
||||
assert.Len(t, titles, 0)
|
||||
|
||||
// List software available for install on "No team". Should list "foobar" package only.
|
||||
titles, counts, _, err = ds.ListSoftwareTitles(
|
||||
ctx,
|
||||
fleet.SoftwareTitleListOptions{
|
||||
ListOptions: fleet.ListOptions{
|
||||
OrderKey: "name",
|
||||
OrderDirection: fleet.OrderAscending,
|
||||
},
|
||||
ExcludeFleetMaintainedApps: true,
|
||||
AvailableForInstall: true,
|
||||
TeamID: ptr.Uint(0),
|
||||
},
|
||||
fleet.TeamFilter{User: &fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)}},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, 1, counts)
|
||||
require.Len(t, titles, 1)
|
||||
|
||||
names = make([]nameSource, 0, len(titles))
|
||||
for _, title := range titles {
|
||||
names = append(names, nameSource{name: title.Name, source: title.Source})
|
||||
}
|
||||
assert.ElementsMatch(t, []nameSource{
|
||||
{name: "foobar", source: "apps"},
|
||||
}, names)
|
||||
}
|
||||
|
||||
func testUploadedSoftwareExists(t *testing.T, ds *Datastore) {
|
||||
ctx := context.Background()
|
||||
|
||||
|
|
|
|||
|
|
@ -223,16 +223,15 @@ type SoftwareTitleListOptions struct {
|
|||
// ListOptions cannot be embedded in order to unmarshall with validation.
|
||||
ListOptions ListOptions `url:"list_options"`
|
||||
|
||||
TeamID *uint `query:"team_id,optional"`
|
||||
VulnerableOnly bool `query:"vulnerable,optional"`
|
||||
AvailableForInstall bool `query:"available_for_install,optional"`
|
||||
SelfServiceOnly bool `query:"self_service,optional"`
|
||||
KnownExploit bool `query:"exploit,optional"`
|
||||
MinimumCVSS float64 `query:"min_cvss_score,optional"`
|
||||
MaximumCVSS float64 `query:"max_cvss_score,optional"`
|
||||
PackagesOnly bool `query:"packages_only,optional"`
|
||||
Platform string `query:"platform,optional"`
|
||||
ExcludeFleetMaintainedApps bool `query:"exclude_fleet_maintained_apps,optional"`
|
||||
TeamID *uint `query:"team_id,optional"`
|
||||
VulnerableOnly bool `query:"vulnerable,optional"`
|
||||
AvailableForInstall bool `query:"available_for_install,optional"`
|
||||
SelfServiceOnly bool `query:"self_service,optional"`
|
||||
KnownExploit bool `query:"exploit,optional"`
|
||||
MinimumCVSS float64 `query:"min_cvss_score,optional"`
|
||||
MaximumCVSS float64 `query:"max_cvss_score,optional"`
|
||||
PackagesOnly bool `query:"packages_only,optional"`
|
||||
Platform string `query:"platform,optional"`
|
||||
}
|
||||
|
||||
type HostSoftwareTitleListOptions struct {
|
||||
|
|
|
|||
Loading…
Reference in a new issue