mirror of
https://github.com/anchore/syft.git
synced 2025-11-18 00:43:20 +01:00
feat: emit dependency relationships found in Cargo.lock (#3443)
* feat: emit dependency relationships found in Cargo.lock Include updating test Cargo.lock to have dependencies on multiple versions of the same crate. Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>
This commit is contained in:
parent
926486a7c3
commit
bc35345afb
@ -33,19 +33,50 @@ func parseCargoLock(_ context.Context, _ file.Resolver, _ *generic.Environment,
|
|||||||
}
|
}
|
||||||
|
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
|
pkgIndex := make(map[string]int)
|
||||||
|
|
||||||
for _, p := range m.Packages {
|
for _, p := range m.Packages {
|
||||||
if p.Dependencies == nil {
|
if p.Dependencies == nil {
|
||||||
p.Dependencies = make([]string, 0)
|
p.Dependencies = make([]string, 0)
|
||||||
}
|
}
|
||||||
pkgs = append(
|
newPkg := newPackageFromCargoMetadata(
|
||||||
pkgs,
|
|
||||||
newPackageFromCargoMetadata(
|
|
||||||
p,
|
p,
|
||||||
reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
|
reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
pkgs = append(
|
||||||
|
pkgs,
|
||||||
|
newPkg,
|
||||||
|
)
|
||||||
|
newIx := len(pkgs) - 1
|
||||||
|
// Cargo.lock dependencies are strings that are the name of a package, if that
|
||||||
|
// is unambiguous, or a string like "name version" if the name alone is not
|
||||||
|
// ambiguous. Set both keys in the map, since we don't know which key is
|
||||||
|
// going to be used until we're trying to resolve dependencies. If the
|
||||||
|
// first key is overwritten, that means the package name was an ambiguous dependency
|
||||||
|
// and "name version" will be used as the key anyway.
|
||||||
|
keys := []string{
|
||||||
|
newPkg.Name,
|
||||||
|
fmt.Sprintf("%s %s", newPkg.Name, newPkg.Version),
|
||||||
|
}
|
||||||
|
for _, k := range keys {
|
||||||
|
pkgIndex[k] = newIx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var relationships []artifact.Relationship
|
||||||
|
for _, p := range pkgs {
|
||||||
|
meta := p.Metadata.(pkg.RustCargoLockEntry)
|
||||||
|
for _, d := range meta.Dependencies {
|
||||||
|
i, ok := pkgIndex[d]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
relationships = append(relationships, artifact.Relationship{
|
||||||
|
From: p,
|
||||||
|
To: pkgs[i],
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages")
|
return pkgs, relationships, unknown.IfEmptyf(pkgs, "unable to determine packages")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,8 +12,7 @@ import (
|
|||||||
func TestParseCargoLock(t *testing.T) {
|
func TestParseCargoLock(t *testing.T) {
|
||||||
fixture := "test-fixtures/Cargo.lock"
|
fixture := "test-fixtures/Cargo.lock"
|
||||||
locations := file.NewLocationSet(file.NewLocation(fixture))
|
locations := file.NewLocationSet(file.NewLocation(fixture))
|
||||||
expectedPkgs := []pkg.Package{
|
ansiTerm := pkg.Package{
|
||||||
{
|
|
||||||
Name: "ansi_term",
|
Name: "ansi_term",
|
||||||
Version: "0.12.1",
|
Version: "0.12.1",
|
||||||
PURL: "pkg:cargo/ansi_term@0.12.1",
|
PURL: "pkg:cargo/ansi_term@0.12.1",
|
||||||
@ -30,8 +29,26 @@ func TestParseCargoLock(t *testing.T) {
|
|||||||
"winapi",
|
"winapi",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
errno := pkg.Package{
|
||||||
|
Name: "errno",
|
||||||
|
Version: "0.3.9",
|
||||||
|
PURL: "pkg:cargo/errno@0.3.9",
|
||||||
|
Locations: locations,
|
||||||
|
Language: pkg.Rust,
|
||||||
|
Type: pkg.RustPkg,
|
||||||
|
Licenses: pkg.NewLicenseSet(),
|
||||||
|
Metadata: pkg.RustCargoLockEntry{
|
||||||
|
Name: "errno",
|
||||||
|
Version: "0.3.9",
|
||||||
|
Source: "registry+https://github.com/rust-lang/crates.io-index",
|
||||||
|
Checksum: "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba",
|
||||||
|
Dependencies: []string{
|
||||||
|
"windows-sys 0.52.0",
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
|
}
|
||||||
|
matches := pkg.Package{
|
||||||
Name: "matches",
|
Name: "matches",
|
||||||
Version: "0.1.8",
|
Version: "0.1.8",
|
||||||
PURL: "pkg:cargo/matches@0.1.8",
|
PURL: "pkg:cargo/matches@0.1.8",
|
||||||
@ -46,8 +63,8 @@ func TestParseCargoLock(t *testing.T) {
|
|||||||
Checksum: "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08",
|
Checksum: "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08",
|
||||||
Dependencies: []string{},
|
Dependencies: []string{},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
{
|
memchr := pkg.Package{
|
||||||
Name: "memchr",
|
Name: "memchr",
|
||||||
Version: "2.3.3",
|
Version: "2.3.3",
|
||||||
PURL: "pkg:cargo/memchr@2.3.3",
|
PURL: "pkg:cargo/memchr@2.3.3",
|
||||||
@ -62,8 +79,9 @@ func TestParseCargoLock(t *testing.T) {
|
|||||||
Checksum: "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400",
|
Checksum: "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400",
|
||||||
Dependencies: []string{},
|
Dependencies: []string{},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
{
|
|
||||||
|
natord := pkg.Package{
|
||||||
Name: "natord",
|
Name: "natord",
|
||||||
Version: "1.0.9",
|
Version: "1.0.9",
|
||||||
PURL: "pkg:cargo/natord@1.0.9",
|
PURL: "pkg:cargo/natord@1.0.9",
|
||||||
@ -78,8 +96,9 @@ func TestParseCargoLock(t *testing.T) {
|
|||||||
Checksum: "308d96db8debc727c3fd9744aac51751243420e46edf401010908da7f8d5e57c",
|
Checksum: "308d96db8debc727c3fd9744aac51751243420e46edf401010908da7f8d5e57c",
|
||||||
Dependencies: []string{},
|
Dependencies: []string{},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
{
|
|
||||||
|
nom := pkg.Package{
|
||||||
Name: "nom",
|
Name: "nom",
|
||||||
Version: "4.2.3",
|
Version: "4.2.3",
|
||||||
PURL: "pkg:cargo/nom@4.2.3",
|
PURL: "pkg:cargo/nom@4.2.3",
|
||||||
@ -97,8 +116,27 @@ func TestParseCargoLock(t *testing.T) {
|
|||||||
"version_check",
|
"version_check",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
schannel := pkg.Package{
|
||||||
|
Name: "schannel",
|
||||||
|
Version: "0.1.26",
|
||||||
|
PURL: "pkg:cargo/schannel@0.1.26",
|
||||||
|
Locations: locations,
|
||||||
|
Language: pkg.Rust,
|
||||||
|
Type: pkg.RustPkg,
|
||||||
|
Licenses: pkg.NewLicenseSet(),
|
||||||
|
Metadata: pkg.RustCargoLockEntry{
|
||||||
|
Name: "schannel",
|
||||||
|
Version: "0.1.26",
|
||||||
|
Source: "registry+https://github.com/rust-lang/crates.io-index",
|
||||||
|
Checksum: "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1",
|
||||||
|
Dependencies: []string{
|
||||||
|
"windows-sys 0.59.0",
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
unicodeBidi := pkg.Package{
|
||||||
Name: "unicode-bidi",
|
Name: "unicode-bidi",
|
||||||
Version: "0.3.4",
|
Version: "0.3.4",
|
||||||
PURL: "pkg:cargo/unicode-bidi@0.3.4",
|
PURL: "pkg:cargo/unicode-bidi@0.3.4",
|
||||||
@ -113,10 +151,12 @@ func TestParseCargoLock(t *testing.T) {
|
|||||||
Checksum: "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5",
|
Checksum: "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5",
|
||||||
Dependencies: []string{
|
Dependencies: []string{
|
||||||
"matches",
|
"matches",
|
||||||
|
"bogus", // a bad dependency to test error handling
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
{
|
|
||||||
|
versionCheck := pkg.Package{
|
||||||
Name: "version_check",
|
Name: "version_check",
|
||||||
Version: "0.1.5",
|
Version: "0.1.5",
|
||||||
PURL: "pkg:cargo/version_check@0.1.5",
|
PURL: "pkg:cargo/version_check@0.1.5",
|
||||||
@ -131,8 +171,9 @@ func TestParseCargoLock(t *testing.T) {
|
|||||||
Checksum: "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd",
|
Checksum: "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd",
|
||||||
Dependencies: []string{},
|
Dependencies: []string{},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
{
|
|
||||||
|
winapi := pkg.Package{
|
||||||
Name: "winapi",
|
Name: "winapi",
|
||||||
Version: "0.3.9",
|
Version: "0.3.9",
|
||||||
PURL: "pkg:cargo/winapi@0.3.9",
|
PURL: "pkg:cargo/winapi@0.3.9",
|
||||||
@ -150,8 +191,9 @@ func TestParseCargoLock(t *testing.T) {
|
|||||||
"winapi-x86_64-pc-windows-gnu",
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
{
|
|
||||||
|
winAPIi686PCWindowsGNU := pkg.Package{
|
||||||
Name: "winapi-i686-pc-windows-gnu",
|
Name: "winapi-i686-pc-windows-gnu",
|
||||||
Version: "0.4.0",
|
Version: "0.4.0",
|
||||||
PURL: "pkg:cargo/winapi-i686-pc-windows-gnu@0.4.0",
|
PURL: "pkg:cargo/winapi-i686-pc-windows-gnu@0.4.0",
|
||||||
@ -166,8 +208,9 @@ func TestParseCargoLock(t *testing.T) {
|
|||||||
Checksum: "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6",
|
Checksum: "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6",
|
||||||
Dependencies: []string{},
|
Dependencies: []string{},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
{
|
|
||||||
|
winAPIx8664PCWindowsGNU := pkg.Package{
|
||||||
Name: "winapi-x86_64-pc-windows-gnu",
|
Name: "winapi-x86_64-pc-windows-gnu",
|
||||||
Version: "0.4.0",
|
Version: "0.4.0",
|
||||||
PURL: "pkg:cargo/winapi-x86_64-pc-windows-gnu@0.4.0",
|
PURL: "pkg:cargo/winapi-x86_64-pc-windows-gnu@0.4.0",
|
||||||
@ -182,14 +225,102 @@ func TestParseCargoLock(t *testing.T) {
|
|||||||
Checksum: "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f",
|
Checksum: "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f",
|
||||||
Dependencies: []string{},
|
Dependencies: []string{},
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
windowsSys52 := pkg.Package{
|
||||||
|
Name: "windows-sys",
|
||||||
|
Version: "0.52.0",
|
||||||
|
PURL: "pkg:cargo/windows-sys@0.52.0",
|
||||||
|
Locations: locations,
|
||||||
|
Language: pkg.Rust,
|
||||||
|
Type: pkg.RustPkg,
|
||||||
|
Licenses: pkg.NewLicenseSet(),
|
||||||
|
Metadata: pkg.RustCargoLockEntry{
|
||||||
|
Name: "windows-sys",
|
||||||
|
Version: "0.52.0",
|
||||||
|
Source: "registry+https://github.com/rust-lang/crates.io-index",
|
||||||
|
Checksum: "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d",
|
||||||
|
Dependencies: []string{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: no relationships are under test yet
|
windowsSys59 := pkg.Package{
|
||||||
var expectedRelationships []artifact.Relationship
|
Name: "windows-sys",
|
||||||
|
Version: "0.59.0",
|
||||||
|
PURL: "pkg:cargo/windows-sys@0.59.0",
|
||||||
|
Locations: locations,
|
||||||
|
Language: pkg.Rust,
|
||||||
|
Type: pkg.RustPkg,
|
||||||
|
Licenses: pkg.NewLicenseSet(),
|
||||||
|
Metadata: pkg.RustCargoLockEntry{
|
||||||
|
Name: "windows-sys",
|
||||||
|
Version: "0.59.0",
|
||||||
|
Source: "registry+https://github.com/rust-lang/crates.io-index",
|
||||||
|
Checksum: "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b",
|
||||||
|
Dependencies: []string{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedPkgs := []pkg.Package{
|
||||||
|
ansiTerm,
|
||||||
|
errno,
|
||||||
|
matches,
|
||||||
|
memchr,
|
||||||
|
natord,
|
||||||
|
nom,
|
||||||
|
schannel,
|
||||||
|
unicodeBidi,
|
||||||
|
versionCheck,
|
||||||
|
winapi,
|
||||||
|
winAPIi686PCWindowsGNU,
|
||||||
|
winAPIx8664PCWindowsGNU,
|
||||||
|
windowsSys52,
|
||||||
|
windowsSys59,
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedRelationships := []artifact.Relationship{
|
||||||
|
{
|
||||||
|
From: ansiTerm,
|
||||||
|
To: winapi,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: errno,
|
||||||
|
To: windowsSys52,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: nom,
|
||||||
|
To: memchr,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: nom,
|
||||||
|
To: versionCheck,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: schannel,
|
||||||
|
To: windowsSys59,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: unicodeBidi,
|
||||||
|
To: matches,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: winapi,
|
||||||
|
To: winAPIi686PCWindowsGNU,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: winapi,
|
||||||
|
To: winAPIx8664PCWindowsGNU,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
pkgtest.TestFileParser(t, fixture, parseCargoLock, expectedPkgs, expectedRelationships)
|
pkgtest.TestFileParser(t, fixture, parseCargoLock, expectedPkgs, expectedRelationships)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_corruptCargoLock(t *testing.T) {
|
func Test_corruptCargoLock(t *testing.T) {
|
||||||
|
|||||||
30
syft/pkg/cataloger/rust/test-fixtures/Cargo.lock
generated
30
syft/pkg/cataloger/rust/test-fixtures/Cargo.lock
generated
@ -9,6 +9,15 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matches"
|
name = "matches"
|
||||||
version = "0.1.8"
|
version = "0.1.8"
|
||||||
@ -37,6 +46,15 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schannel"
|
||||||
|
version = "0.1.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
@ -44,6 +62,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"matches",
|
"matches",
|
||||||
|
"bogus", # not present in cargo.lock; test error handling
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -74,3 +93,14 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user