Return non-installed 'windows_updates' only. (#28531)
Fixes #25987 When querying the 'windows_updates' Orbit table return non-installed windows updates only.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
- Updated the 'windows_updates' Orbit table so that results are only returned iff there are non-installed windows updates.
|
||||
+19
-5
@@ -27,6 +27,13 @@ const (
|
||||
HistoryTable
|
||||
)
|
||||
|
||||
type windowsUpdatesSearcher interface {
|
||||
QueryHistoryAll() ([]*windowsupdate.IUpdateHistoryEntry, error)
|
||||
Search(criteria string) (*windowsupdate.ISearchResult, error)
|
||||
}
|
||||
|
||||
type queryFuncType func(searcher windowsUpdatesSearcher) (interface{}, error)
|
||||
|
||||
type Table struct {
|
||||
logger zerolog.Logger
|
||||
queryFunc queryFuncType
|
||||
@@ -55,16 +62,23 @@ func TablePlugin(mode tableMode, logger zerolog.Logger) *table.Plugin {
|
||||
return table.NewPlugin(t.name, columns, t.generate)
|
||||
}
|
||||
|
||||
func queryUpdates(searcher *windowsupdate.IUpdateSearcher) (interface{}, error) {
|
||||
return searcher.Search("Type='Software'")
|
||||
func queryUpdates(searcher windowsUpdatesSearcher) (interface{}, error) {
|
||||
searchResult, err := searcher.Search("Type='Software' AND IsInstalled=0")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We only care about the results iff we got some updates
|
||||
if searchResult != nil && len(searchResult.Updates) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return searchResult, nil
|
||||
}
|
||||
|
||||
func queryHistory(searcher *windowsupdate.IUpdateSearcher) (interface{}, error) {
|
||||
func queryHistory(searcher windowsUpdatesSearcher) (interface{}, error) {
|
||||
return searcher.QueryHistoryAll()
|
||||
}
|
||||
|
||||
type queryFuncType func(*windowsupdate.IUpdateSearcher) (interface{}, error)
|
||||
|
||||
func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
|
||||
var results []map[string]string
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
// based on github.com/kolide/launcher/pkg/osquery/tables
|
||||
package windowsupdatetable
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/windows/windowsupdate"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type windowsUpdatesSearcherMock struct {
|
||||
searchCriteria string
|
||||
SearchResult *windowsupdate.ISearchResult
|
||||
History []*windowsupdate.IUpdateHistoryEntry
|
||||
}
|
||||
|
||||
func (wus *windowsUpdatesSearcherMock) Search(criteria string) (*windowsupdate.ISearchResult, error) {
|
||||
wus.searchCriteria = criteria
|
||||
return wus.SearchResult, nil
|
||||
}
|
||||
|
||||
func (wus *windowsUpdatesSearcherMock) QueryHistoryAll() ([]*windowsupdate.IUpdateHistoryEntry, error) {
|
||||
return wus.History, nil
|
||||
}
|
||||
|
||||
func TestQueryUpdates(t *testing.T) {
|
||||
t.Run("the right criteria is used", func(t *testing.T) {
|
||||
searcher := &windowsUpdatesSearcherMock{}
|
||||
_, err := queryUpdates(searcher)
|
||||
require.NoError(t, err)
|
||||
|
||||
criteriaParts := strings.Split(searcher.searchCriteria, " AND ")
|
||||
require.Contains(t, criteriaParts, "Type='Software'")
|
||||
require.Contains(t, criteriaParts, "IsInstalled=0")
|
||||
})
|
||||
|
||||
t.Run("only return results iff any updates", func(t *testing.T) {
|
||||
testCases := []struct {
|
||||
updates []*windowsupdate.IUpdate
|
||||
isNil bool
|
||||
}{
|
||||
{updates: nil, isNil: true},
|
||||
{updates: []*windowsupdate.IUpdate{}, isNil: true},
|
||||
{updates: []*windowsupdate.IUpdate{{}}, isNil: false},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
searcher := &windowsUpdatesSearcherMock{
|
||||
SearchResult: &windowsupdate.ISearchResult{
|
||||
Updates: tt.updates,
|
||||
},
|
||||
}
|
||||
r, err := queryUpdates(searcher)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, r == nil, tt.isNil)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestTable(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
queryFunc queryFuncType
|
||||
}{
|
||||
{name: "updates", queryFunc: queryUpdates},
|
||||
{name: "history", queryFunc: queryHistory},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
table := Table{
|
||||
logger: zerolog.Nop(),
|
||||
queryFunc: tt.queryFunc,
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// ci doesn't return data, but we can, at least, check that the underlying API doesn't error.
|
||||
_, err := table.generate(ctx, tablehelpers.MockQueryContext(nil))
|
||||
require.NoError(t, err, "generate")
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
// based on github.com/kolide/launcher/pkg/osquery/tables
|
||||
package windowsupdatetable
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTable(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
queryFunc queryFuncType
|
||||
}{
|
||||
{name: "updates", queryFunc: queryUpdates},
|
||||
{name: "history", queryFunc: queryHistory},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
table := Table{
|
||||
logger: zerolog.Nop(),
|
||||
queryFunc: tt.queryFunc,
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// ci doesn't return data, but we can, at least, check that the underlying API doesn't error.
|
||||
_, err := table.generate(ctx, tablehelpers.MockQueryContext(nil))
|
||||
require.NoError(t, err, "generate")
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user