fleet/server/vulnerabilities/msrc/sync_test.go
Juan Fernandez 6ff2c449cf
Improve test coverage and bug fix (#10301)
Addresses https://github.com/fleetdm/fleet/issues/10112

Improved test coverage, also fixed a bug related to vulnerability processing for mac office apps.
2023-03-06 15:07:27 -04:00

215 lines
6.3 KiB
Go

package msrc
import (
"context"
"testing"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/fleetdm/fleet/v4/server/vulnerabilities/io"
"github.com/stretchr/testify/require"
)
func newMetadataFile(t *testing.T, name string) io.MetadataFileName {
mfn, err := io.NewMSRCMetadata(name)
require.NoError(t, err)
return mfn
}
type testData struct {
RemoteList map[io.MetadataFileName]string
RemoteDownloaded []string
LocalList []io.MetadataFileName
LocalDeleted []io.MetadataFileName
}
type ghMock struct{ TestData *testData }
func (gh ghMock) MSRCBulletins(ctx context.Context) (map[io.MetadataFileName]string, error) {
return gh.TestData.RemoteList, nil
}
func (gh ghMock) MacOfficeReleaseNotes(ctx context.Context) (io.MetadataFileName, string, error) {
for k, v := range gh.TestData.RemoteList {
return k, v, nil
}
return io.MetadataFileName{}, "", nil
}
func (gh ghMock) Download(url string) (string, error) {
gh.TestData.RemoteDownloaded = append(gh.TestData.RemoteDownloaded, url)
return "", nil
}
type fsMock struct{ TestData *testData }
func (fs fsMock) MSRCBulletins() ([]io.MetadataFileName, error) {
return fs.TestData.LocalList, nil
}
func (fs fsMock) MacOfficeReleaseNotes() ([]io.MetadataFileName, error) {
return fs.TestData.LocalList, nil
}
func (fs fsMock) Delete(d io.MetadataFileName) error {
fs.TestData.LocalDeleted = append(fs.TestData.LocalDeleted, d)
return nil
}
func TestSync(t *testing.T) {
ctx := context.Background()
t.Run("#sync", func(t *testing.T) {
os := []fleet.OperatingSystem{
{
Name: "Microsoft Windows 11 Enterprise",
Version: "21H2",
Arch: "64-bit",
KernelVersion: "10.0.22000.795",
},
{
Name: "Microsoft Windows 10 Pro",
Version: "10.0.19044",
Arch: "64-bit",
KernelVersion: "10.0.19044",
},
}
testData := testData{
RemoteList: map[io.MetadataFileName]string{
newMetadataFile(t, "Windows_10-2022_10_10.json"): "http://somebulletin.com",
},
LocalList: []io.MetadataFileName{newMetadataFile(t, "Windows_10-2022_09_10.json")},
}
err := sync(ctx, os, fsMock{TestData: &testData}, ghMock{TestData: &testData})
require.NoError(t, err)
require.ElementsMatch(t, testData.RemoteDownloaded, []string{"http://somebulletin.com"})
expectedMfn, err := io.NewMSRCMetadata("Windows_10-2022_09_10.json")
require.NoError(t, err)
require.ElementsMatch(t, testData.LocalDeleted, []io.MetadataFileName{expectedMfn})
})
t.Run("#bulletinsDelta", func(t *testing.T) {
t.Run("win OS provided", func(t *testing.T) {
os := []fleet.OperatingSystem{
{
Name: "Microsoft Windows 11 Enterprise",
Version: "21H2",
Arch: "64-bit",
KernelVersion: "10.0.22000.795",
},
{
Name: "Microsoft Windows 10 Pro",
Version: "10.0.19044",
Arch: "64-bit",
KernelVersion: "10.0.19044",
},
}
t.Run("without remote bulletins", func(t *testing.T) {
var remote []io.MetadataFileName
local := []io.MetadataFileName{
newMetadataFile(t, "Windows_10-2022_10_10.json"),
}
toDownload, toDelete := bulletinsDelta(os, local, remote)
require.Empty(t, toDownload)
require.Empty(t, toDelete)
})
t.Run("with remote bulletins", func(t *testing.T) {
remote := []io.MetadataFileName{
newMetadataFile(t, "Windows_10-2022_10_10.json"),
newMetadataFile(t, "Windows_11-2022_10_10.json"),
newMetadataFile(t, "Windows_Server_2016-2022_10_10.json"),
newMetadataFile(t, "Windows_8.1-2022_10_10.json"),
}
t.Run("no local bulletins", func(t *testing.T) {
var local []io.MetadataFileName
toDownload, toDelete := bulletinsDelta(os, local, remote)
require.ElementsMatch(t, toDownload, []io.MetadataFileName{
newMetadataFile(t, "Windows_10-2022_10_10.json"),
newMetadataFile(t, "Windows_11-2022_10_10.json"),
})
require.Empty(t, toDelete)
})
t.Run("missing some local bulletin", func(t *testing.T) {
local := []io.MetadataFileName{
newMetadataFile(t, "Windows_10-2022_10_10.json"),
}
toDownload, toDelete := bulletinsDelta(os, local, remote)
require.ElementsMatch(t, toDownload, []io.MetadataFileName{
newMetadataFile(t, "Windows_11-2022_10_10.json"),
})
require.Empty(t, toDelete)
})
t.Run("out of date local bulletin", func(t *testing.T) {
local := []io.MetadataFileName{
newMetadataFile(t, "Windows_10-2022_09_10.json"),
newMetadataFile(t, "Windows_11-2022_10_10.json"),
}
toDownload, toDelete := bulletinsDelta(os, local, remote)
require.ElementsMatch(t, toDownload, []io.MetadataFileName{
newMetadataFile(t, "Windows_10-2022_10_10.json"),
})
require.ElementsMatch(t, toDelete, []io.MetadataFileName{
newMetadataFile(t, "Windows_10-2022_09_10.json"),
})
})
t.Run("up to date local bulletins", func(t *testing.T) {
local := []io.MetadataFileName{
newMetadataFile(t, "Windows_10-2022_10_10.json"),
newMetadataFile(t, "Windows_11-2022_10_10.json"),
}
toDownload, toDelete := bulletinsDelta(os, local, remote)
require.Empty(t, toDownload)
require.Empty(t, toDelete)
})
})
})
t.Run("no Win OS provided", func(t *testing.T) {
os := []fleet.OperatingSystem{
{
Name: "CentOS",
Version: "8.0.0",
Platform: "rhel",
KernelVersion: "5.10.76-linuxkit",
},
}
local := []io.MetadataFileName{newMetadataFile(t, "Windows_11-2022_10_10.json")}
remote := []io.MetadataFileName{newMetadataFile(t, "Windows_10-2022_10_10.json")}
t.Run("nothing to download, nothing to delete", func(t *testing.T) {
toDownload, toDelete := bulletinsDelta(os, local, remote)
require.Empty(t, toDownload)
require.Empty(t, toDelete)
})
})
t.Run("no OS provided", func(t *testing.T) {
var os []fleet.OperatingSystem
t.Run("no local bulletins", func(t *testing.T) {
var local []io.MetadataFileName
t.Run("returns all remote", func(t *testing.T) {
remote := []io.MetadataFileName{
newMetadataFile(t, "Windows_10-2022_10_10.json"),
newMetadataFile(t, "Windows_11-2022_10_10.json"),
}
toDownload, toDelete := bulletinsDelta(os, local, remote)
require.ElementsMatch(t, toDownload, remote)
require.Empty(t, toDelete)
})
})
})
})
}