func TestInsertVulnerabilityNotifications(t *testing.T) { Open("memstore", "") defer Close() pkg1 := &Package{OS: "testOS", Name: "testpkg1", Version: types.NewVersionUnsafe("1.0")} pkg1b := &Package{OS: "testOS", Name: "testpkg1", Version: types.NewVersionUnsafe("1.2")} pkg2 := &Package{OS: "testOS", Name: "testpkg2", Version: types.NewVersionUnsafe("1.0")} InsertPackages([]*Package{pkg1, pkg1b, pkg2}) // NewVulnerabilityNotification vuln1 := &Vulnerability{ID: "test1", Link: "link1", Priority: types.Medium, Description: "testDescription1", FixedInNodes: []string{pkg1.Node}} vuln2 := &Vulnerability{ID: "test2", Link: "link2", Priority: types.High, Description: "testDescription2", FixedInNodes: []string{pkg1.Node, pkg2.Node}} vuln1b := &Vulnerability{ID: "test1", Priority: types.High, FixedInNodes: []string{"pkg3"}} notifications, err := InsertVulnerabilities([]*Vulnerability{vuln1, vuln2, vuln1b}) if assert.Nil(t, err) { // We should only have two NewVulnerabilityNotification notifications: one for test1 and one for test2 // We should not have a VulnerabilityPriorityIncreasedNotification or a VulnerabilityPackageChangedNotification // for test1 because it is in the same batch if assert.Len(t, notifications, 2) { for _, n := range notifications { _, ok := n.(*NewVulnerabilityNotification) assert.True(t, ok) } } } // VulnerabilityPriorityIncreasedNotification vuln1c := &Vulnerability{ID: "test1", Priority: types.Critical} notifications, err = InsertVulnerabilities([]*Vulnerability{vuln1c}) if assert.Nil(t, err) { if assert.Len(t, notifications, 1) { if nn, ok := notifications[0].(*VulnerabilityPriorityIncreasedNotification); assert.True(t, ok) { assert.Equal(t, vuln1b.Priority, nn.OldPriority) assert.Equal(t, vuln1c.Priority, nn.NewPriority) } } } notifications, err = InsertVulnerabilities([]*Vulnerability{&Vulnerability{ID: "test1", Priority: types.Low}}) assert.Nil(t, err) assert.Len(t, notifications, 0) // VulnerabilityPackageChangedNotification vuln1e := &Vulnerability{ID: "test1", FixedInNodes: []string{pkg1b.Node}} vuln1f := &Vulnerability{ID: "test1", FixedInNodes: []string{pkg2.Node}} notifications, err = InsertVulnerabilities([]*Vulnerability{vuln1e, vuln1f}) if assert.Nil(t, err) { if assert.Len(t, notifications, 1) { if nn, ok := notifications[0].(*VulnerabilityPackageChangedNotification); assert.True(t, ok) { // Here, we say that pkg1b fixes the vulnerability, but as pkg1b is in // the same branch as pkg1, pkg1 should be removed and pkg1b added // We also add pkg2 as fixed assert.Contains(t, nn.AddedFixedInNodes, pkg1b.Node) assert.Contains(t, nn.RemovedFixedInNodes, pkg1.Node) assert.Contains(t, nn.AddedFixedInNodes, pkg2.Node) } } } }
func TestRHELParser(t *testing.T) { _, filename, _, _ := runtime.Caller(0) path := path.Join(path.Dir(filename)) // Test parsing testdata/fetcher_rhel_test.1.xml testFile, _ := os.Open(path + "/testdata/fetcher_rhel_test.1.xml") vulnerabilities, err := parseRHSA(testFile) if assert.Nil(t, err) && assert.Len(t, vulnerabilities, 1) { assert.Equal(t, "RHSA-2015:1193", vulnerabilities[0].ID) assert.Equal(t, "https://rhn.redhat.com/errata/RHSA-2015-1193.html", vulnerabilities[0].Link) assert.Equal(t, types.Medium, vulnerabilities[0].Priority) assert.Equal(t, `Xerces-C is a validating XML parser written in a portable subset of C++. A flaw was found in the way the Xerces-C XML parser processed certain XML documents. A remote attacker could provide specially crafted XML input that, when parsed by an application using Xerces-C, would cause that application to crash.`, vulnerabilities[0].Description) if assert.Len(t, vulnerabilities[0].FixedIn, 3) { assert.Contains(t, vulnerabilities[0].FixedIn, &database.Package{ OS: "centos:7", Name: "xerces-c", Version: types.NewVersionUnsafe("3.1.1-7.el7_1"), }) assert.Contains(t, vulnerabilities[0].FixedIn, &database.Package{ OS: "centos:7", Name: "xerces-c-devel", Version: types.NewVersionUnsafe("3.1.1-7.el7_1"), }) assert.Contains(t, vulnerabilities[0].FixedIn, &database.Package{ OS: "centos:7", Name: "xerces-c-doc", Version: types.NewVersionUnsafe("3.1.1-7.el7_1"), }) } } // Test parsing testdata/fetcher_rhel_test.2.xml testFile, _ = os.Open(path + "/testdata/fetcher_rhel_test.2.xml") vulnerabilities, err = parseRHSA(testFile) if assert.Nil(t, err) && assert.Len(t, vulnerabilities, 1) { assert.Equal(t, "RHSA-2015:1207", vulnerabilities[0].ID) assert.Equal(t, "https://rhn.redhat.com/errata/RHSA-2015-1207.html", vulnerabilities[0].Link) assert.Equal(t, types.Critical, vulnerabilities[0].Priority) assert.Equal(t, `Mozilla Firefox is an open source web browser. XULRunner provides the XUL Runtime environment for Mozilla Firefox. Several flaws were found in the processing of malformed web content. A web page containing malicious content could cause Firefox to crash or, potentially, execute arbitrary code with the privileges of the user running Firefox.`, vulnerabilities[0].Description) if assert.Len(t, vulnerabilities[0].FixedIn, 2) { assert.Contains(t, vulnerabilities[0].FixedIn, &database.Package{ OS: "centos:6", Name: "firefox", Version: types.NewVersionUnsafe("38.1.0-1.el6_6"), }) assert.Contains(t, vulnerabilities[0].FixedIn, &database.Package{ OS: "centos:7", Name: "firefox", Version: types.NewVersionUnsafe("38.1.0-1.el7_1"), }) } } }
func TestDebianParser(t *testing.T) { _, filename, _, _ := runtime.Caller(0) // Test parsing testdata/fetcher_debian_test.json testFile, _ := os.Open(path.Join(path.Dir(filename)) + "/testdata/fetcher_debian_test.json") response, err := buildResponse(testFile, "") if assert.Nil(t, err) && assert.Len(t, response.Vulnerabilities, 2) { for _, vulnerability := range response.Vulnerabilities { if vulnerability.ID == "CVE-2015-1323" { assert.Equal(t, "https://security-tracker.debian.org/tracker/CVE-2015-1323", vulnerability.Link) assert.Equal(t, types.Low, vulnerability.Priority) assert.Equal(t, "This vulnerability is not very dangerous.", vulnerability.Description) if assert.Len(t, vulnerability.FixedIn, 2) { assert.Contains(t, vulnerability.FixedIn, &database.Package{ OS: "debian:8", Name: "aptdaemon", Version: types.MaxVersion, }) assert.Contains(t, vulnerability.FixedIn, &database.Package{ OS: "debian:unstable", Name: "aptdaemon", Version: types.NewVersionUnsafe("1.1.1+bzr982-1"), }) } } else if vulnerability.ID == "CVE-2003-0779" { assert.Equal(t, "https://security-tracker.debian.org/tracker/CVE-2003-0779", vulnerability.Link) assert.Equal(t, types.High, vulnerability.Priority) assert.Equal(t, "But this one is very dangerous.", vulnerability.Description) if assert.Len(t, vulnerability.FixedIn, 3) { assert.Contains(t, vulnerability.FixedIn, &database.Package{ OS: "debian:8", Name: "aptdaemon", Version: types.NewVersionUnsafe("0.7.0"), }) assert.Contains(t, vulnerability.FixedIn, &database.Package{ OS: "debian:unstable", Name: "aptdaemon", Version: types.NewVersionUnsafe("0.7.0"), }) assert.Contains(t, vulnerability.FixedIn, &database.Package{ OS: "debian:8", Name: "asterisk", Version: types.NewVersionUnsafe("0.5.56"), }) } } else { assert.Fail(t, "Wrong vulnerability name: ", vulnerability.ID) } } } }
func generateLayersData(sublayersCount, packagesCount, packagesPerBranchesCount int) string { var startPackages []string var allPackages []*database.Package for i := 0; i < packagesCount; i++ { for j := 0; j < packagesPerBranchesCount; j++ { p := &database.Package{ OS: "testOS", Name: "p" + strconv.Itoa(i), Version: types.NewVersionUnsafe(strconv.Itoa(j)), } allPackages = append(allPackages, p) if j == 0 { startPackages = append(startPackages, p.GetNode()) } } } err := database.InsertPackages(allPackages) if err != nil { panic(err) } var allLayers []*database.Layer var packagesCursor int for i := 0; i < sublayersCount; i++ { parentNode := "" if i > 0 { parentNode = allLayers[i-1].GetNode() } var installedPackagesNodes []string if i == sublayersCount-1 { if packagesCursor <= packagesCount-1 { installedPackagesNodes = startPackages[packagesCursor:packagesCount] } } else if (packagesCount / sublayersCount) > 0 { upperPackageCursor := int(math.Min(float64(packagesCursor+(packagesCount/sublayersCount)), float64(packagesCount))) installedPackagesNodes = startPackages[packagesCursor:upperPackageCursor] packagesCursor = upperPackageCursor } layer := &database.Layer{ ID: "l" + strconv.Itoa(i), ParentNode: parentNode, Content: database.LayerContent{ TarSum: "lc" + strconv.Itoa(i), OS: "testOS", InstalledPackagesNodes: installedPackagesNodes, }, } err := database.InsertLayer(layer) if err != nil { panic(err) } allLayers = append(allLayers, layer) } return allLayers[sublayersCount-1].ID }
func TestDistUpgrade(t *testing.T) { database.Open("memstore", "") defer database.Close() _, f, _, _ := runtime.Caller(0) path := path.Join(path.Dir(f)) + "/testdata/DistUpgrade/" // blank.tar: MAINTAINER Quentin MACHU <quentin.machu.fr> // wheezy.tar: FROM debian:wheezy // jessie.tar: RUN sed -i "s/precise/trusty/" /etc/apt/sources.list && apt-get update && apt-get -y dist-upgrade assert.Nil(t, Process("blank", "", path+"blank.tar.gz")) assert.Nil(t, Process("wheezy", "blank", path+"wheezy.tar.gz")) assert.Nil(t, Process("jessie", "wheezy", path+"jessie.tar.gz")) wheezy, err := database.FindOneLayerByID("wheezy", database.FieldLayerAll) if assert.Nil(t, err) { assert.Equal(t, "debian:7", wheezy.OS) assert.Len(t, wheezy.InstalledPackagesNodes, 52) assert.Len(t, wheezy.RemovedPackagesNodes, 0) jessie, err := database.FindOneLayerByID("jessie", database.FieldLayerAll) if assert.Nil(t, err) { assert.Equal(t, "debian:8", jessie.OS) assert.Len(t, jessie.InstalledPackagesNodes, 66) assert.Len(t, jessie.RemovedPackagesNodes, 44) packageNodes, err := jessie.AllPackages() if assert.Nil(t, err) { // These packages haven't been upgraded nonUpgradedPackages := []database.Package{ database.Package{Name: "libtext-wrapi18n-perl", Version: types.NewVersionUnsafe("0.06-7")}, database.Package{Name: "libtext-charwidth-perl", Version: types.NewVersionUnsafe("0.04-7")}, database.Package{Name: "libtext-iconv-perl", Version: types.NewVersionUnsafe("1.7-5")}, database.Package{Name: "mawk", Version: types.NewVersionUnsafe("1.3.3-17")}, database.Package{Name: "insserv", Version: types.NewVersionUnsafe("1.14.0-5")}, database.Package{Name: "db", Version: types.NewVersionUnsafe("5.1.29-5")}, database.Package{Name: "ustr", Version: types.NewVersionUnsafe("1.0.4-3")}, database.Package{Name: "xz-utils", Version: types.NewVersionUnsafe("5.1.1alpha+20120614-2")}, } for _, p := range nonUpgradedPackages { p.OS = "debian:7" assert.Contains(t, packageNodes, p.GetNode(), "Jessie layer doesn't have %s but it should.", p) } for _, p := range nonUpgradedPackages { p.OS = "debian:8" assert.NotContains(t, packageNodes, p.GetNode(), "Jessie layer has %s but it shouldn't.", p) } } } } }
import ( "testing" "github.com/coreos/quay-sec/database" "github.com/coreos/quay-sec/utils/types" ) var rpmPackagesTests = []packagesTest{ // Test a CentOS 7 RPM database // Memo: Use the following command on a RPM-based system to shrink a database: rpm -qa --qf "%{NAME}\n" |tail -n +3| xargs rpm -e --justdb packagesTest{ packages: []*database.Package{ &database.Package{ Name: "centos-release", // Two packages from this source are installed, it should only appear one time Version: types.NewVersionUnsafe("7-1.1503.el7.centos.2.8"), }, &database.Package{ Name: "filesystem", // Two packages from this source are installed, it should only appear one time Version: types.NewVersionUnsafe("3.2-18.el7"), }, }, data: map[string][]byte{ "var/lib/rpm/Packages": loadFileForTest("testdata/rpm_Packages"), }, }, } func TestRpmPackagesDetector(t *testing.T) { testPackagesDetector(t, &RpmPackagesDetector{}, rpmPackagesTests) }
package packages import ( "testing" "github.com/coreos/quay-sec/database" "github.com/coreos/quay-sec/utils/types" ) var dpkgPackagesTests = []packagesTest{ // Test an Ubuntu dpkg status file packagesTest{ packages: []*database.Package{ &database.Package{ Name: "pam", // Two packages from this source are installed, it should only appear one time Version: types.NewVersionUnsafe("1.1.8-3.1ubuntu3"), }, &database.Package{ Name: "makedev", // The source name and the package name are equals Version: types.NewVersionUnsafe("2.3.1-93ubuntu1"), // The version comes from the "Version:" line }, &database.Package{ Name: "gcc-5", Version: types.NewVersionUnsafe("5.1.1-12ubuntu1"), // The version comes from the "Source:" line }, }, data: map[string][]byte{ "var/lib/dpkg/status": loadFileForTest("testdata/dpkg_status"), }, }, }
func TestPackage(t *testing.T) { Open("memstore", "") defer Close() // Try to insert invalid packages for _, invalidPkg := range []*Package{ &Package{OS: "", Name: "testpkg1", Version: types.NewVersionUnsafe("1.0")}, &Package{OS: "testOS", Name: "", Version: types.NewVersionUnsafe("1.0")}, &Package{OS: "testOS", Name: "testpkg1", Version: types.NewVersionUnsafe("")}, &Package{OS: "testOS", Name: "testpkg1", Version: types.NewVersionUnsafe("bad version")}, &Package{OS: "", Name: "", Version: types.NewVersionUnsafe("")}, } { err := InsertPackages([]*Package{invalidPkg}) assert.Error(t, err) } // Insert a package pkg1 := &Package{OS: "testOS", Name: "testpkg1", Version: types.NewVersionUnsafe("1.0")} err := InsertPackages([]*Package{pkg1}) if assert.Nil(t, err) { // Find the inserted package and verify its content pkg1b, err := FindOnePackage(pkg1.OS, pkg1.Name, pkg1.Version, FieldPackageAll) if assert.Nil(t, err) && assert.NotNil(t, pkg1b) { assert.Equal(t, pkg1.Node, pkg1b.Node) assert.Equal(t, pkg1.OS, pkg1b.OS) assert.Equal(t, pkg1.Name, pkg1b.Name) assert.Equal(t, pkg1.Version, pkg1b.Version) } // Find packages from the inserted branch and verify their content // (the first one should be a start package, the second one the inserted one and the third one the end package) pkgs1c, err := FindAllPackagesByBranch(pkg1.OS, pkg1.Name, FieldPackageAll) if assert.Nil(t, err) && assert.Equal(t, 3, len(pkgs1c)) { sort.Sort(ByVersion(pkgs1c)) assert.Equal(t, pkg1.OS, pkgs1c[0].OS) assert.Equal(t, pkg1.Name, pkgs1c[0].Name) assert.Equal(t, types.MinVersion, pkgs1c[0].Version) assert.Equal(t, pkg1.OS, pkgs1c[1].OS) assert.Equal(t, pkg1.Name, pkgs1c[1].Name) assert.Equal(t, pkg1.Version, pkgs1c[1].Version) assert.Equal(t, pkg1.OS, pkgs1c[2].OS) assert.Equal(t, pkg1.Name, pkgs1c[2].Name) assert.Equal(t, types.MaxVersion, pkgs1c[2].Version) } } // Insert multiple packages in the same branch, one in another branch, insert local duplicates and database duplicates as well pkg2 := []*Package{ &Package{OS: "testOS", Name: "testpkg1", Version: types.NewVersionUnsafe("0.8")}, &Package{OS: "testOS", Name: "testpkg1", Version: types.NewVersionUnsafe("0.9")}, &Package{OS: "testOS", Name: "testpkg1", Version: types.NewVersionUnsafe("1.0")}, // Already present in the database &Package{OS: "testOS", Name: "testpkg1", Version: types.NewVersionUnsafe("1.1")}, &Package{OS: "testOS", Name: "testpkg2", Version: types.NewVersionUnsafe("1.0")}, // Another branch &Package{OS: "testOS", Name: "testpkg2", Version: types.NewVersionUnsafe("1.0")}, // Local duplicates } nbInSameBranch := 4 + 2 // (start/end packages) err = InsertPackages(shuffle(pkg2)) if assert.Nil(t, err) { // Find packages from the inserted branch, verify their order and NextVersion / PreviousVersion pkgs2b, err := FindAllPackagesByBranch("testOS", "testpkg1", FieldPackageAll) if assert.Nil(t, err) && assert.Equal(t, nbInSameBranch, len(pkgs2b)) { sort.Sort(ByVersion(pkgs2b)) for i := 0; i < nbInSameBranch; i = i + 1 { if i == 0 { assert.Equal(t, types.MinVersion, pkgs2b[0].Version) } else if i < nbInSameBranch-2 { assert.Equal(t, pkg2[i].Version, pkgs2b[i+1].Version) nv, err := pkgs2b[i+1].NextVersion(FieldPackageAll) assert.Nil(t, err) assert.Equal(t, pkgs2b[i+2], nv) if i > 0 { pv, err := pkgs2b[i].PreviousVersion(FieldPackageAll) assert.Nil(t, err) assert.Equal(t, pkgs2b[i-1], pv) } else { pv, err := pkgs2b[i].PreviousVersion(FieldPackageAll) assert.Nil(t, err) assert.Nil(t, pv) } } else { assert.Equal(t, types.MaxVersion, pkgs2b[nbInSameBranch-1].Version) nv, err := pkgs2b[nbInSameBranch-1].NextVersion(FieldPackageAll) assert.Nil(t, err) assert.Nil(t, nv) pv, err := pkgs2b[i].PreviousVersion(FieldPackageAll) assert.Nil(t, err) assert.Equal(t, pkgs2b[i-1], pv) } } // NextVersions nv, err := pkgs2b[0].NextVersions(FieldPackageAll) if assert.Nil(t, err) && assert.Len(t, nv, nbInSameBranch-1) { for i := 0; i < nbInSameBranch-1; i = i + 1 { if i < nbInSameBranch-2 { assert.Equal(t, pkg2[i].Version, nv[i].Version) } else { assert.Equal(t, types.MaxVersion, nv[i].Version) } } } // PreviousVersions pv, err := pkgs2b[nbInSameBranch-1].PreviousVersions(FieldPackageAll) if assert.Nil(t, err) && assert.Len(t, pv, nbInSameBranch-1) { for i := 0; i < len(pv); i = i + 1 { assert.Equal(t, pkgs2b[len(pkgs2b)-i-2], pv[i]) } } } // Verify that the one we added which was already present in the database has the same node value (meaning that we just fetched it actually) assert.Contains(t, pkg2, pkg1) } // Insert duplicated latest packages directly, ensure only one is actually inserted. Then insert another package in the branch and ensure that its next version is the latest one pkg3a := &Package{OS: "testOS", Name: "testpkg3", Version: types.MaxVersion} pkg3b := &Package{OS: "testOS", Name: "testpkg3", Version: types.MaxVersion} pkg3c := &Package{OS: "testOS", Name: "testpkg3", Version: types.MaxVersion} err1 := InsertPackages([]*Package{pkg3a, pkg3b}) err2 := InsertPackages([]*Package{pkg3c}) if assert.Nil(t, err1) && assert.Nil(t, err2) { assert.Equal(t, pkg3a, pkg3b) assert.Equal(t, pkg3b, pkg3c) } pkg4 := Package{OS: "testOS", Name: "testpkg3", Version: types.NewVersionUnsafe("1.0")} InsertPackages([]*Package{&pkg4}) pkgs34, _ := FindAllPackagesByBranch("testOS", "testpkg3", FieldPackageAll) if assert.Len(t, pkgs34, 3) { sort.Sort(ByVersion(pkgs34)) assert.Equal(t, pkg4.Node, pkgs34[1].Node) assert.Equal(t, pkg3a.Node, pkgs34[2].Node) assert.Equal(t, pkg3a.Node, pkgs34[1].NextVersionNode) } // Insert two identical packages but with "different" versions // The second version should be simplified to the first one // Therefore, we should just have three packages (the inserted one and the start/end packages of the branch) InsertPackages([]*Package{&Package{OS: "testOS", Name: "testdirtypkg", Version: types.NewVersionUnsafe("0.1")}}) InsertPackages([]*Package{&Package{OS: "testOS", Name: "testdirtypkg", Version: types.NewVersionUnsafe("0:0.1")}}) dirtypkgs, err := FindAllPackagesByBranch("testOS", "testdirtypkg", FieldPackageAll) assert.Nil(t, err) assert.Len(t, dirtypkgs, 3) }
func TestVulnerability(t *testing.T) { Open("memstore", "") defer Close() // Insert invalid vulnerabilities for _, vulnerability := range []Vulnerability{ Vulnerability{ID: "", Link: "link1", Priority: types.Medium, FixedInNodes: []string{"pkg1"}}, Vulnerability{ID: "test1", Link: "", Priority: types.Medium, FixedInNodes: []string{"pkg1"}}, Vulnerability{ID: "test1", Link: "link1", Priority: "InvalidPriority", FixedInNodes: []string{"pkg1"}}, Vulnerability{ID: "test1", Link: "link1", Priority: types.Medium, FixedInNodes: []string{}}, } { _, err := InsertVulnerabilities([]*Vulnerability{&vulnerability}) assert.Error(t, err) } // Some data vuln1 := &Vulnerability{ID: "test1", Link: "link1", Priority: types.Medium, Description: "testDescription1", FixedInNodes: []string{"pkg1"}} vuln2 := &Vulnerability{ID: "test2", Link: "link2", Priority: types.High, Description: "testDescription2", FixedInNodes: []string{"pkg1", "pkg2"}} vuln3 := &Vulnerability{ID: "test3", Link: "link3", Priority: types.High, FixedInNodes: []string{"pkg3"}} // Empty description // Insert some vulnerabilities _, err := InsertVulnerabilities([]*Vulnerability{vuln1, vuln2, vuln3}) if assert.Nil(t, err) { // Find one of the vulnerabilities we just inserted and verify its content v1, err := FindOneVulnerability(vuln1.ID, FieldVulnerabilityAll) if assert.Nil(t, err) && assert.NotNil(t, v1) { assert.Equal(t, vuln1.ID, v1.ID) assert.Equal(t, vuln1.Link, v1.Link) assert.Equal(t, vuln1.Priority, v1.Priority) assert.Equal(t, vuln1.Description, v1.Description) if assert.Len(t, v1.FixedInNodes, 1) { assert.Equal(t, vuln1.FixedInNodes[0], v1.FixedInNodes[0]) } } // Ensure that vulnerabilities with empty descriptions work as well v3, err := FindOneVulnerability(vuln3.ID, FieldVulnerabilityAll) if assert.Nil(t, err) && assert.NotNil(t, v3) { assert.Equal(t, vuln3.Description, v3.Description) } // Find vulnerabilities by fixed packages vulnsFixedInPkg1AndPkg3, err := FindAllVulnerabilitiesByFixedIn([]string{"pkg2", "pkg3"}, FieldVulnerabilityAll) assert.Nil(t, err) assert.Len(t, vulnsFixedInPkg1AndPkg3, 2) // Delete vulnerability if assert.Nil(t, DeleteVulnerability(vuln1.ID)) { v1, err := FindOneVulnerability(vuln1.ID, FieldVulnerabilityAll) assert.Equal(t, cerrors.ErrNotFound, err) assert.Nil(t, v1) } } // Update a vulnerability and verify its new content pkg1 := &Package{OS: "testOS", Name: "testpkg1", Version: types.NewVersionUnsafe("1.0")} InsertPackages([]*Package{pkg1}) vuln5 := &Vulnerability{ID: "test5", Link: "link5", Priority: types.Medium, Description: "testDescription5", FixedInNodes: []string{pkg1.Node}} _, err = InsertVulnerabilities([]*Vulnerability{vuln5}) if assert.Nil(t, err) { // Partial updates // # Just a field update vuln5b := &Vulnerability{ID: "test5", Priority: types.High} _, err := InsertVulnerabilities([]*Vulnerability{vuln5b}) if assert.Nil(t, err) { v5b, err := FindOneVulnerability(vuln5b.ID, FieldVulnerabilityAll) if assert.Nil(t, err) && assert.NotNil(t, v5b) { assert.Equal(t, vuln5b.ID, v5b.ID) assert.Equal(t, vuln5b.Priority, v5b.Priority) if assert.Len(t, v5b.FixedInNodes, 1) { assert.Contains(t, v5b.FixedInNodes, pkg1.Node) } } } // # Just a field update, twice in the same transaction vuln5b1 := &Vulnerability{ID: "test5", Link: "http://foo.bar"} vuln5b2 := &Vulnerability{ID: "test5", Link: "http://bar.foo"} _, err = InsertVulnerabilities([]*Vulnerability{vuln5b1, vuln5b2}) if assert.Nil(t, err) { v5b2, err := FindOneVulnerability(vuln5b2.ID, FieldVulnerabilityAll) if assert.Nil(t, err) && assert.NotNil(t, v5b2) { assert.Equal(t, vuln5b2.Link, v5b2.Link) } } // # All fields except fixedIn update vuln5c := &Vulnerability{ID: "test5", Link: "link5c", Priority: types.Critical, Description: "testDescription5c"} _, err = InsertVulnerabilities([]*Vulnerability{vuln5c}) if assert.Nil(t, err) { v5c, err := FindOneVulnerability(vuln5c.ID, FieldVulnerabilityAll) if assert.Nil(t, err) && assert.NotNil(t, v5c) { assert.Equal(t, vuln5c.ID, v5c.ID) assert.Equal(t, vuln5c.Link, v5c.Link) assert.Equal(t, vuln5c.Priority, v5c.Priority) assert.Equal(t, vuln5c.Description, v5c.Description) if assert.Len(t, v5c.FixedInNodes, 1) { assert.Contains(t, v5c.FixedInNodes, pkg1.Node) } } } // Complete update pkg2 := &Package{OS: "testOS", Name: "testpkg1", Version: types.NewVersionUnsafe("1.1")} pkg3 := &Package{OS: "testOS", Name: "testpkg2", Version: types.NewVersionUnsafe("1.0")} InsertPackages([]*Package{pkg2, pkg3}) vuln5d := &Vulnerability{ID: "test5", Link: "link5d", Priority: types.Low, Description: "testDescription5d", FixedInNodes: []string{pkg2.Node, pkg3.Node}} _, err = InsertVulnerabilities([]*Vulnerability{vuln5d}) if assert.Nil(t, err) { v5d, err := FindOneVulnerability(vuln5d.ID, FieldVulnerabilityAll) if assert.Nil(t, err) && assert.NotNil(t, v5d) { assert.Equal(t, vuln5d.ID, v5d.ID) assert.Equal(t, vuln5d.Link, v5d.Link) assert.Equal(t, vuln5d.Priority, v5d.Priority) assert.Equal(t, vuln5d.Description, v5d.Description) // Here, we ensure that a vulnerability can only be fixed by one package of a given branch at a given time // And that we can add new fixed packages as well if assert.Len(t, v5d.FixedInNodes, 2) { assert.NotContains(t, v5d.FixedInNodes, pkg1.Node) } } } } // Create and update a vulnerability's packages (and from the same branch) in the same batch pkg1 = &Package{OS: "testOS", Name: "testpkg1", Version: types.NewVersionUnsafe("1.0")} pkg1b := &Package{OS: "testOS", Name: "testpkg1", Version: types.NewVersionUnsafe("1.1")} InsertPackages([]*Package{pkg1, pkg1b}) // # A vulnerability can't be inserted if fixed by two packages of the same branch _, err = InsertVulnerabilities([]*Vulnerability{&Vulnerability{ID: "test6", Link: "link6", Priority: types.Medium, Description: "testDescription6", FixedInNodes: []string{pkg1.Node, pkg1b.Node}}}) assert.Error(t, err) // # Two updates of the same vulnerability in the same batch with packages of the same branch pkg0 := &Package{OS: "testOS", Name: "testpkg0", Version: types.NewVersionUnsafe("1.0")} InsertPackages([]*Package{pkg0}) _, err = InsertVulnerabilities([]*Vulnerability{&Vulnerability{ID: "test7", Link: "link7", Priority: types.Medium, Description: "testDescription7", FixedInNodes: []string{pkg0.Node}}}) if assert.Nil(t, err) { vuln7b := &Vulnerability{ID: "test7", FixedInNodes: []string{pkg1.Node}} vuln7c := &Vulnerability{ID: "test7", FixedInNodes: []string{pkg1b.Node}} _, err = InsertVulnerabilities([]*Vulnerability{vuln7b, vuln7c}) if assert.Nil(t, err) { v7, err := FindOneVulnerability("test7", FieldVulnerabilityAll) if assert.Nil(t, err) && assert.Len(t, v7.FixedInNodes, 2) { assert.Contains(t, v7.FixedInNodes, pkg0.Node) assert.NotContains(t, v7.FixedInNodes, pkg1.Node) assert.Contains(t, v7.FixedInNodes, pkg1b.Node) } // # A vulnerability can't be updated if fixed by two packages of the same branch _, err = InsertVulnerabilities([]*Vulnerability{&Vulnerability{ID: "test7", FixedInNodes: []string{pkg1.Node, pkg1b.Node}}}) assert.Error(t, err) } } }