From 8b3c8f5ca2cd530f6c081b8e77bd30454303af24 Mon Sep 17 00:00:00 2001 From: Octogonapus Date: Fri, 19 May 2023 20:57:54 -0400 Subject: [PATCH 1/6] feat(julia): Add Julia language analyzer support --- .github/workflows/semantic-pr.yaml | 1 + docs/community/contribute/pr.md | 1 + docs/docs/coverage/language/index.md | 1 + docs/docs/coverage/language/julia.md | 25 ++ mkdocs.yml | 1 + pkg/detector/library/driver.go | 3 + pkg/fanal/analyzer/all/import.go | 1 + pkg/fanal/analyzer/const.go | 4 + pkg/fanal/analyzer/language/julia/pkg/pkg.go | 188 +++++++++++++ .../analyzer/language/julia/pkg/pkg_test.go | 247 ++++++++++++++++++ .../pkg/testdata/dep_ext_v1.9/Manifest.toml | 16 ++ .../pkg/testdata/dep_ext_v1.9/Project.toml | 9 + .../julia/pkg/testdata/happy/Manifest.toml | 72 +++++ .../julia/pkg/testdata/happy/Project.toml | 17 ++ .../pkg/testdata/no_deps_v1.6/Manifest.toml | 2 + .../pkg/testdata/no_deps_v1.6/Project.toml | 3 + .../pkg/testdata/no_manifest/Project.toml | 2 + .../testdata/shadowed_dep_v1.9/Manifest.toml | 16 ++ .../testdata/shadowed_dep_v1.9/Project.toml | 7 + pkg/fanal/types/const.go | 4 + pkg/purl/purl.go | 18 ++ pkg/sbom/cyclonedx/marshal_test.go | 10 +- pkg/sbom/spdx/marshal_test.go | 7 +- 23 files changed, 648 insertions(+), 7 deletions(-) create mode 100644 docs/docs/coverage/language/julia.md create mode 100644 pkg/fanal/analyzer/language/julia/pkg/pkg.go create mode 100644 pkg/fanal/analyzer/language/julia/pkg/pkg_test.go create mode 100644 pkg/fanal/analyzer/language/julia/pkg/testdata/dep_ext_v1.9/Manifest.toml create mode 100644 pkg/fanal/analyzer/language/julia/pkg/testdata/dep_ext_v1.9/Project.toml create mode 100644 pkg/fanal/analyzer/language/julia/pkg/testdata/happy/Manifest.toml create mode 100644 pkg/fanal/analyzer/language/julia/pkg/testdata/happy/Project.toml create mode 100644 pkg/fanal/analyzer/language/julia/pkg/testdata/no_deps_v1.6/Manifest.toml create mode 100644 pkg/fanal/analyzer/language/julia/pkg/testdata/no_deps_v1.6/Project.toml create mode 100644 pkg/fanal/analyzer/language/julia/pkg/testdata/no_manifest/Project.toml create mode 100644 pkg/fanal/analyzer/language/julia/pkg/testdata/shadowed_dep_v1.9/Manifest.toml create mode 100644 pkg/fanal/analyzer/language/julia/pkg/testdata/shadowed_dep_v1.9/Project.toml diff --git a/.github/workflows/semantic-pr.yaml b/.github/workflows/semantic-pr.yaml index f02ef758ae91..ce418b74ad55 100644 --- a/.github/workflows/semantic-pr.yaml +++ b/.github/workflows/semantic-pr.yaml @@ -76,6 +76,7 @@ jobs: swift bitnami conda + julia os lang diff --git a/docs/community/contribute/pr.md b/docs/community/contribute/pr.md index 2538cce3327f..5e57cbbb2788 100644 --- a/docs/community/contribute/pr.md +++ b/docs/community/contribute/pr.md @@ -142,6 +142,7 @@ language: - go - elixir - dart +- julia vuln: diff --git a/docs/docs/coverage/language/index.md b/docs/docs/coverage/language/index.md index 470250216eea..eb694bbcc228 100644 --- a/docs/docs/coverage/language/index.md +++ b/docs/docs/coverage/language/index.md @@ -47,6 +47,7 @@ On the other hand, when the target is a post-build artifact, like a container im | [Dart](dart.md) | pubspec.lock | - | - | ✅ | ✅ | | [Swift](swift.md) | Podfile.lock | - | - | ✅ | ✅ | | | Package.resolved | - | - | ✅ | ✅ | +| [Julia](julia.md) | Manifest.toml | ✅ | ✅ | ✅ | ✅ | The path of these files does not matter. diff --git a/docs/docs/coverage/language/julia.md b/docs/docs/coverage/language/julia.md new file mode 100644 index 000000000000..82f197fd432a --- /dev/null +++ b/docs/docs/coverage/language/julia.md @@ -0,0 +1,25 @@ +# Julia + +## Features + +Trivy supports [Pkg.jl](https://pkgdocs.julialang.org/v1/), which is the Julia package manager. +The following table provides an outline of the features Trivy offers. + +| Package manager | File | Transitive dependencies | Dev dependencies | License | Dependency graph | Position | +| --------------- | ------------- | :---------------------: | :--------------- | :-----: | :--------------: | :------: | +| Pkg.jl | Manifest.toml | ✅ | Excluded[^1] | - | ✅ | ✅ | + +### Pkg.jl + +Trivy searches for `Manifest.toml` to detect dependencies. + +Trivy also supports dependency trees; however, to display an accurate tree, it needs to know whether each package is a direct dependency of the project. +Since this information is not included in `Manifest.toml`, Trivy parses `Project.toml`, which should be located next to `Project.toml`. +If you want to see the dependency tree, please ensure that `Project.toml` is present. + +Scanning `Manifest.toml` and `Project.toml` together also removes developer dependencies. + +Dependency extensions are currently ignored. +Shadowed dependencies are not supported and will overwrite each other in exported SBOMs. + +[^1]: When you scan `Manifest.toml` and `Project.toml` together. diff --git a/mkdocs.yml b/mkdocs.yml index c3437fecf413..e00db5ab5623 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -102,6 +102,7 @@ nav: - Ruby: docs/coverage/language/ruby.md - Rust: docs/coverage/language/rust.md - Swift: docs/coverage/language/swift.md + - Julia: docs/coverage/language/julia.md - IaC: - Overview: docs/coverage/iac/index.md - Azure ARM Template: docs/coverage/iac/azure-arm.md diff --git a/pkg/detector/library/driver.go b/pkg/detector/library/driver.go index 64bd140ed57e..4151dfec08f8 100644 --- a/pkg/detector/library/driver.go +++ b/pkg/detector/library/driver.go @@ -81,6 +81,9 @@ func NewDriver(libType ftypes.LangType) (Driver, bool) { case ftypes.K8sUpstream: ecosystem = vulnerability.Kubernetes comparer = compare.GenericComparer{} + case ftypes.Julia: + log.Logger.Warn("Julia is supported for SBOM, not for vulnerability scanning") + return Driver{}, false default: log.Warn("The library type is not supported for vulnerability scanning", log.String("type", string(libType))) diff --git a/pkg/fanal/analyzer/all/import.go b/pkg/fanal/analyzer/all/import.go index acd0b4cc70e2..a5b0d05298a1 100644 --- a/pkg/fanal/analyzer/all/import.go +++ b/pkg/fanal/analyzer/all/import.go @@ -20,6 +20,7 @@ import ( _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/java/gradle" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/java/jar" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/java/pom" + _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/julia/pkg" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/nodejs/npm" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/nodejs/pkg" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/nodejs/pnpm" diff --git a/pkg/fanal/analyzer/const.go b/pkg/fanal/analyzer/const.go index ef20482a782c..99ac3cf4bee5 100644 --- a/pkg/fanal/analyzer/const.go +++ b/pkg/fanal/analyzer/const.go @@ -94,6 +94,9 @@ const ( // Dart TypePubSpecLock Type = "pubspec-lock" + // Julia + TypeJulia Type = "julia" + // ============ // Non-packaged // ============ @@ -191,6 +194,7 @@ var ( TypeSwift, TypePubSpecLock, TypeMixLock, + TypeJulia, } // TypeLockfiles has all lock file analyzers diff --git a/pkg/fanal/analyzer/language/julia/pkg/pkg.go b/pkg/fanal/analyzer/language/julia/pkg/pkg.go new file mode 100644 index 000000000000..e688079b8d2e --- /dev/null +++ b/pkg/fanal/analyzer/language/julia/pkg/pkg.go @@ -0,0 +1,188 @@ +package pkgjl + +import ( + "context" + "errors" + "io" + "io/fs" + "os" + "path/filepath" + "sort" + + "github.com/BurntSushi/toml" + "github.com/samber/lo" + "golang.org/x/exp/maps" + "golang.org/x/exp/slices" + "golang.org/x/xerrors" + + julia "github.com/aquasecurity/trivy/pkg/dependency/parser/julia/manifest" + godeptypes "github.com/aquasecurity/trivy/pkg/dependency/types" + "github.com/aquasecurity/trivy/pkg/fanal/analyzer" + "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language" + "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/utils/fsutils" +) + +func init() { + analyzer.RegisterPostAnalyzer(analyzer.TypeJulia, newJuliaAnalyzer) +} + +const version = 1 + +var requiredFiles = []string{ + types.JuliaManifest, + types.JuliaProject, +} + +type juliaAnalyzer struct { + lockParser godeptypes.Parser +} + +type Project struct { + Dependencies map[string]string `toml:"deps"` + Extras map[string]string `toml:"extras"` +} + +func newJuliaAnalyzer(_ analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) { + return &juliaAnalyzer{ + lockParser: julia.NewParser(), + }, nil +} + +func (a juliaAnalyzer) PostAnalyze(_ context.Context, input analyzer.PostAnalysisInput) (*analyzer.AnalysisResult, error) { + var apps []types.Application + + required := func(path string, d fs.DirEntry) bool { + return filepath.Base(path) == types.JuliaManifest + } + + err := fsutils.WalkDir(input.FS, ".", required, func(path string, d fs.DirEntry, r io.Reader) error { + // Parse Manifest.toml + app, err := a.parseJuliaManifest(path, r) + if err != nil { + return xerrors.Errorf("parse error: %w", err) + } else if app == nil { + return nil + } + + // Parse Project.toml alongside Manifest.toml to identify the direct dependencies. This mutates `app`. + if err = analyzeDependencies(input.FS, filepath.Dir(path), app); err != nil { + log.Logger.Warnf("Unable to parse %q to analyze dependencies: %s", filepath.Join(filepath.Dir(path), types.JuliaProject), err) + } + + sort.Sort(app.Libraries) + apps = append(apps, *app) + return nil + }) + if err != nil { + return nil, xerrors.Errorf("julia walk error: %w", err) + } + + return &analyzer.AnalysisResult{ + Applications: apps, + }, nil +} + +func (a juliaAnalyzer) Required(filePath string, _ os.FileInfo) bool { + fileName := filepath.Base(filePath) + return slices.Contains(requiredFiles, fileName) +} + +func (a juliaAnalyzer) Type() analyzer.Type { + return analyzer.TypeJulia +} + +func (a juliaAnalyzer) Version() int { + return version +} + +func (a juliaAnalyzer) parseJuliaManifest(path string, r io.Reader) (*types.Application, error) { + return language.Parse(types.Julia, path, r, a.lockParser) +} + +func analyzeDependencies(fsys fs.FS, dir string, app *types.Application) error { + deps, devDeps, err := getProjectDeps(fsys, dir) + if err != nil { + return err + } + + pkgs := walkDependencies(deps, app.Libraries, false) + devPkgs := walkDependencies(devDeps, app.Libraries, true) + app.Libraries = append(pkgs, devPkgs...) + return nil +} + +// getProjectDeps parses project.toml and returns root and dev dependencies. +func getProjectDeps(fsys fs.FS, dir string) (map[string]string, map[string]string, error) { + projectPath := filepath.Join(dir, types.JuliaProject) + project, err := parseJuliaProject(fsys, projectPath) + if errors.Is(err, fs.ErrNotExist) { + log.Logger.Debugf("Julia: %s not found", projectPath) + return nil, nil, nil + } else if err != nil { + return nil, nil, xerrors.Errorf("unable to parse %s: %w", projectPath, err) + } + return project.Dependencies, project.Extras, nil +} + +// Parses Project.toml +func parseJuliaProject(fsys fs.FS, path string) (Project, error) { + proj := Project{} + f, err := fsys.Open(path) + if err != nil { + return proj, xerrors.Errorf("file open error: %w", err) + } + defer func() { _ = f.Close() }() + + if _, err = toml.NewDecoder(f).Decode(&proj); err != nil { + return proj, xerrors.Errorf("decode error: %w", err) + } + return proj, nil +} + +// Marks the given direct dependencies as direct, then marks those packages' dependencies as indirect. +// Marks all encountered packages' Dev flag according to `dev`. +// Modifies the packages in `allPackages`. +func walkDependencies(directDeps map[string]string, allPackages types.Packages, dev bool) []types.Package { + pkgsByID := lo.SliceToMap(allPackages, func(pkg types.Package) (string, types.Package) { + return pkg.ID, pkg + }) + + // Identify direct dependencies + // Everything in `directDeps` is assumed to be direct + visited := make(map[string]types.Package) + for _, uuid := range directDeps { + if pkg, ok := pkgsByID[uuid]; ok { + pkg.Indirect = false + pkg.Dev = dev + visited[pkg.ID] = pkg + } + } + + // Identify indirect dependencies + for _, pkg := range visited { + walkIndirectDependencies(pkg, pkgsByID, visited) + } + + return maps.Values(visited) +} + +// Marks all indirect dependencies as indirect. Starts from `rootPkg`. Visited deps are added to `visited`. +func walkIndirectDependencies(rootPkg types.Package, allPkgIDs, visited map[string]types.Package) { + for _, pkgID := range rootPkg.DependsOn { + if _, ok := visited[pkgID]; ok { + continue + } + + dep, ok := allPkgIDs[pkgID] + if !ok { + continue + } + + dep.Indirect = true + dep.Dev = rootPkg.Dev + visited[dep.ID] = dep + walkIndirectDependencies(dep, allPkgIDs, visited) + } +} diff --git a/pkg/fanal/analyzer/language/julia/pkg/pkg_test.go b/pkg/fanal/analyzer/language/julia/pkg/pkg_test.go new file mode 100644 index 000000000000..350b10c883ce --- /dev/null +++ b/pkg/fanal/analyzer/language/julia/pkg/pkg_test.go @@ -0,0 +1,247 @@ +package pkgjl + +import ( + "context" + "os" + "testing" + + "github.com/aquasecurity/trivy/pkg/fanal/analyzer" + "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_juliaAnalyzer_Analyze(t *testing.T) { + tests := []struct { + name string + dir string + want *analyzer.AnalysisResult + }{ + { + name: "happy path", + dir: "testdata/happy", + want: &analyzer.AnalysisResult{ + Applications: []types.Application{ + { + Type: types.Julia, + FilePath: "Manifest.toml", + Libraries: []types.Package{ + { + ID: "ade2ca70-3891-5945-98fb-dc099432e06a", + Name: "Dates", + Version: "1.9.0", + Indirect: false, + Locations: []types.Location{{StartLine: 7, EndLine: 9}}, + DependsOn: []string{"de0858da-6303-5e67-8744-51eddeeeb8d7"}, + }, + { + ID: "d9a60922-03b4-4a1b-81be-b8d05b827236", + Name: "DevDep", + Version: "1.0.0", + Indirect: false, + Dev: true, + Locations: []types.Location{{StartLine: 65, EndLine: 68}}, + DependsOn: []string{"b637660b-5035-4894-8335-b3805a4b50d8"}, + }, + { + ID: "b637660b-5035-4894-8335-b3805a4b50d8", + Name: "IndirectDevDep", + Version: "2.0.0", + Indirect: true, + Dev: true, + Locations: []types.Location{{StartLine: 70, EndLine: 72}}, + }, + { + ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", + Name: "JSON", + Version: "0.21.4", + Indirect: false, + Locations: []types.Location{{StartLine: 11, EndLine: 15}}, + DependsOn: []string{ + "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", + "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", + "a63ad114-7e13-5084-954f-fe012c677804", + "ade2ca70-3891-5945-98fb-dc099432e06a", + }, + }, + { + ID: "a63ad114-7e13-5084-954f-fe012c677804", + Name: "Mmap", + Version: "1.9.0", + Indirect: true, + Locations: []types.Location{{StartLine: 17, EndLine: 18}}, + }, + { + ID: "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", + Name: "Parsers", + Version: "2.5.10", + Indirect: true, + Locations: []types.Location{{StartLine: 20, EndLine: 24}}, + DependsOn: []string{ + "ade2ca70-3891-5945-98fb-dc099432e06a", + "aea7be01-6a6a-4083-8856-8a6e6704d82a", + "cf7118a7-6976-5b1a-9a39-7adc72f591a4", + }, + }, + { + ID: "aea7be01-6a6a-4083-8856-8a6e6704d82a", + Name: "PrecompileTools", + Version: "1.1.1", + Indirect: true, + Locations: []types.Location{{StartLine: 26, EndLine: 30}}, + DependsOn: []string{"21216c6a-2e73-6563-6e65-726566657250"}, + }, + { + ID: "21216c6a-2e73-6563-6e65-726566657250", + Name: "Preferences", + Version: "1.4.0", + Indirect: true, + Locations: []types.Location{{StartLine: 32, EndLine: 36}}, + DependsOn: []string{"fa267f1f-6049-4f14-aa54-33bafae1ed76"}, + }, + { + ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", + Name: "Printf", + Version: "1.9.0", + Indirect: true, + Locations: []types.Location{{StartLine: 38, EndLine: 40}}, + DependsOn: []string{"4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"}, + }, + { + ID: "9a3f8284-a2c9-5f02-9a11-845980a1fd5c", + Name: "Random", + Version: "1.9.0", + Indirect: true, + Locations: []types.Location{{StartLine: 42, EndLine: 44}}, + DependsOn: []string{"9e88b42a-f829-5b0c-bbe9-9e923198166b", "ea8e919c-243c-51af-8825-aaa63cd721ce"}, + }, + { + ID: "ea8e919c-243c-51af-8825-aaa63cd721ce", + Name: "SHA", + Version: "0.7.0", + Indirect: true, + Locations: []types.Location{{StartLine: 46, EndLine: 48}}, + }, + { + ID: "9e88b42a-f829-5b0c-bbe9-9e923198166b", + Name: "Serialization", + Version: "1.9.0", + Indirect: true, + Locations: []types.Location{{StartLine: 50, EndLine: 51}}, + }, + { + ID: "fa267f1f-6049-4f14-aa54-33bafae1ed76", + Name: "TOML", + Version: "1.0.3", + Indirect: true, + Locations: []types.Location{{StartLine: 53, EndLine: 56}}, + DependsOn: []string{"ade2ca70-3891-5945-98fb-dc099432e06a"}, + }, + { + ID: "cf7118a7-6976-5b1a-9a39-7adc72f591a4", + Name: "UUIDs", + Version: "1.9.0", + Indirect: true, + Locations: []types.Location{{StartLine: 58, EndLine: 60}}, + DependsOn: []string{"9a3f8284-a2c9-5f02-9a11-845980a1fd5c", "ea8e919c-243c-51af-8825-aaa63cd721ce"}, + }, + { + ID: "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", + Name: "Unicode", + Version: "1.9.0", + Indirect: true, + Locations: []types.Location{{StartLine: 62, EndLine: 63}}, + }, + }, + }, + }, + }, + }, + { + name: "no_deps_v1.6", + dir: "testdata/no_deps_v1.6", + want: &analyzer.AnalysisResult{}, + }, + { + name: "dep_ext_v1.9", + dir: "testdata/dep_ext_v1.9", + want: &analyzer.AnalysisResult{ + Applications: []types.Application{ + { + Type: types.Julia, + FilePath: "Manifest.toml", + Libraries: []types.Package{ + { + ID: "621f4979-c628-5d54-868e-fcf4e3e8185c", + Name: "AbstractFFTs", + Version: "1.3.1", + Indirect: false, + Locations: []types.Location{{StartLine: 7, EndLine: 10}}, + DependsOn: nil, + }, + }, + }, + }, + }, + }, + { + name: "shadowed_dep_v1.9", + dir: "testdata/shadowed_dep_v1.9", + want: &analyzer.AnalysisResult{ + Applications: []types.Application{ + { + Type: types.Julia, + FilePath: "Manifest.toml", + Libraries: []types.Package{ + { + ID: "ead4f63c-334e-11e9-00e6-e7f0a5f21b60", + Name: "A", + Version: "1.9.0", + Indirect: false, + Locations: []types.Location{{StartLine: 7, EndLine: 8}}, + DependsOn: []string{"f41f7b98-334e-11e9-1257-49272045fb24"}, + }, + { + ID: "edca9bc6-334e-11e9-3554-9595dbb4349c", + Name: "B", + Version: "1.9.0", + Indirect: false, + Locations: []types.Location{{StartLine: 15, EndLine: 16}}, + DependsOn: nil, + }, + { + ID: "f41f7b98-334e-11e9-1257-49272045fb24", + Name: "B", + Version: "1.9.0", + Indirect: true, + Locations: []types.Location{{StartLine: 13, EndLine: 14}}, + DependsOn: nil, + }, + }, + }, + }, + }, + }, + { + name: "no_manifest", + dir: "testdata/no_manifest", + want: &analyzer.AnalysisResult{ + Applications: nil, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + a, err := newJuliaAnalyzer(analyzer.AnalyzerOptions{}) + require.NoError(t, err) + + got, err := a.PostAnalyze(context.Background(), analyzer.PostAnalysisInput{ + FS: os.DirFS(tt.dir), + }) + + assert.NoError(t, err) + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/pkg/fanal/analyzer/language/julia/pkg/testdata/dep_ext_v1.9/Manifest.toml b/pkg/fanal/analyzer/language/julia/pkg/testdata/dep_ext_v1.9/Manifest.toml new file mode 100644 index 000000000000..c3b22a724c15 --- /dev/null +++ b/pkg/fanal/analyzer/language/julia/pkg/testdata/dep_ext_v1.9/Manifest.toml @@ -0,0 +1,16 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.9.0" +manifest_format = "2.0" +project_hash = "f0a796fb78285c02ad123fec6e14c8bac09a2ccc" + +[[deps.AbstractFFTs]] +git-tree-sha1 = "16b6dbc4cf7caee4e1e75c49485ec67b667098a0" +uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c" +version = "1.3.1" + + [deps.AbstractFFTs.extensions] + AbstractFFTsChainRulesCoreExt = "ChainRulesCore" + + [deps.AbstractFFTs.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" diff --git a/pkg/fanal/analyzer/language/julia/pkg/testdata/dep_ext_v1.9/Project.toml b/pkg/fanal/analyzer/language/julia/pkg/testdata/dep_ext_v1.9/Project.toml new file mode 100644 index 000000000000..7d99fdb4f598 --- /dev/null +++ b/pkg/fanal/analyzer/language/julia/pkg/testdata/dep_ext_v1.9/Project.toml @@ -0,0 +1,9 @@ +name = "packageName" +uuid = "1c653b0a-0b5a-4cff-b25a-92f0db012773" +version = "0.1.0" + +[deps] +AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c" + +[compat] +AbstractFFTs = "1.3" diff --git a/pkg/fanal/analyzer/language/julia/pkg/testdata/happy/Manifest.toml b/pkg/fanal/analyzer/language/julia/pkg/testdata/happy/Manifest.toml new file mode 100644 index 000000000000..316bf1497e44 --- /dev/null +++ b/pkg/fanal/analyzer/language/julia/pkg/testdata/happy/Manifest.toml @@ -0,0 +1,72 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.9.0" +manifest_format = "2.0" +project_hash = "f65b9de676a27ce78ee011db6d477b3d44d1a7c5" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" + +[[deps.JSON]] +deps = ["Dates", "Mmap", "Parsers", "Unicode"] +git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" +uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +version = "0.21.4" + +[[deps.Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" + +[[deps.Parsers]] +deps = ["Dates", "PrecompileTools", "UUIDs"] +git-tree-sha1 = "a5aef8d4a6e8d81f171b2bd4be5265b01384c74c" +uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" +version = "2.5.10" + +[[deps.PrecompileTools]] +deps = ["Preferences"] +git-tree-sha1 = "259e206946c293698122f63e2b513a7c99a244e8" +uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +version = "1.1.1" + +[[deps.Preferences]] +deps = ["TOML"] +git-tree-sha1 = "7eb1686b4f04b82f96ed7a4ea5890a4f0c7a09f1" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.4.0" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[deps.Random]] +deps = ["SHA", "Serialization"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" + +[[deps.DevDep]] +deps = ["IndirectDevDep"] +uuid = "d9a60922-03b4-4a1b-81be-b8d05b827236" +version = "1.0.0" + +[[deps.IndirectDevDep]] +uuid = "b637660b-5035-4894-8335-b3805a4b50d8" +version = "2.0.0" diff --git a/pkg/fanal/analyzer/language/julia/pkg/testdata/happy/Project.toml b/pkg/fanal/analyzer/language/julia/pkg/testdata/happy/Project.toml new file mode 100644 index 000000000000..f24e31bc961a --- /dev/null +++ b/pkg/fanal/analyzer/language/julia/pkg/testdata/happy/Project.toml @@ -0,0 +1,17 @@ +name = "packageName" +uuid = "1c653b0a-0b5a-4cff-b25a-92f0db012773" +version = "0.1.0" + +[deps] +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" + +[compat] +JSON = "0.21" +julia = "1.8" + +[extras] +DevDep = "d9a60922-03b4-4a1b-81be-b8d05b827236" + +[targets] +test = ["DevDep"] diff --git a/pkg/fanal/analyzer/language/julia/pkg/testdata/no_deps_v1.6/Manifest.toml b/pkg/fanal/analyzer/language/julia/pkg/testdata/no_deps_v1.6/Manifest.toml new file mode 100644 index 000000000000..f45eecff031f --- /dev/null +++ b/pkg/fanal/analyzer/language/julia/pkg/testdata/no_deps_v1.6/Manifest.toml @@ -0,0 +1,2 @@ +# This file is machine-generated - editing it directly is not advised + diff --git a/pkg/fanal/analyzer/language/julia/pkg/testdata/no_deps_v1.6/Project.toml b/pkg/fanal/analyzer/language/julia/pkg/testdata/no_deps_v1.6/Project.toml new file mode 100644 index 000000000000..84c8138906dd --- /dev/null +++ b/pkg/fanal/analyzer/language/julia/pkg/testdata/no_deps_v1.6/Project.toml @@ -0,0 +1,3 @@ +name = "packageName" +uuid = "1c653b0a-0b5a-4cff-b25a-92f0db012773" +version = "0.1.0" diff --git a/pkg/fanal/analyzer/language/julia/pkg/testdata/no_manifest/Project.toml b/pkg/fanal/analyzer/language/julia/pkg/testdata/no_manifest/Project.toml new file mode 100644 index 000000000000..dec02c4d6cd3 --- /dev/null +++ b/pkg/fanal/analyzer/language/julia/pkg/testdata/no_manifest/Project.toml @@ -0,0 +1,2 @@ +[deps] +A = "ead4f63c-334e-11e9-00e6-e7f0a5f21b62" diff --git a/pkg/fanal/analyzer/language/julia/pkg/testdata/shadowed_dep_v1.9/Manifest.toml b/pkg/fanal/analyzer/language/julia/pkg/testdata/shadowed_dep_v1.9/Manifest.toml new file mode 100644 index 000000000000..dd4ea00b943d --- /dev/null +++ b/pkg/fanal/analyzer/language/julia/pkg/testdata/shadowed_dep_v1.9/Manifest.toml @@ -0,0 +1,16 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.9.0" +manifest_format = "2.0" +project_hash = "f0a796fb78285c02ad123fec6e14c8bac09a2ccc" + +[[deps.A]] +uuid = "ead4f63c-334e-11e9-00e6-e7f0a5f21b60" + + [deps.A.deps] + B = "f41f7b98-334e-11e9-1257-49272045fb24" + +[[deps.B]] +uuid = "f41f7b98-334e-11e9-1257-49272045fb24" +[[deps.B]] +uuid = "edca9bc6-334e-11e9-3554-9595dbb4349c" diff --git a/pkg/fanal/analyzer/language/julia/pkg/testdata/shadowed_dep_v1.9/Project.toml b/pkg/fanal/analyzer/language/julia/pkg/testdata/shadowed_dep_v1.9/Project.toml new file mode 100644 index 000000000000..24fe6178c480 --- /dev/null +++ b/pkg/fanal/analyzer/language/julia/pkg/testdata/shadowed_dep_v1.9/Project.toml @@ -0,0 +1,7 @@ +name = "packageName" +uuid = "1c653b0a-0b5a-4cff-b25a-92f0db012773" +version = "0.1.0" + +[deps] +A = "ead4f63c-334e-11e9-00e6-e7f0a5f21b60" +B = "edca9bc6-334e-11e9-3554-9595dbb4349c" diff --git a/pkg/fanal/types/const.go b/pkg/fanal/types/const.go index 56f56036a590..6874b8a40b06 100644 --- a/pkg/fanal/types/const.go +++ b/pkg/fanal/types/const.go @@ -73,6 +73,7 @@ const ( Pub LangType = "pub" Hex LangType = "hex" Bitnami LangType = "bitnami" + Julia LangType = "julia" K8sUpstream LangType = "kubernetes" EKS LangType = "eks" // Amazon Elastic Kubernetes Service @@ -143,4 +144,7 @@ const ( CondaEnvYaml = "environment.yaml" CondaEnvYml = "environment.yml" + + JuliaProject = "Project.toml" + JuliaManifest = "Manifest.toml" ) diff --git a/pkg/purl/purl.go b/pkg/purl/purl.go index 608c7b0b4029..92ce07be9741 100644 --- a/pkg/purl/purl.go +++ b/pkg/purl/purl.go @@ -109,6 +109,10 @@ func New(t ftypes.TargetType, metadata types.Metadata, pkg ftypes.Package) (*Pac return nil, nil } return (*PackageURL)(purl), nil + case packageurl.TypeJulia: + var qs packageurl.Qualifiers + namespace, name, qs = parseJulia(name, pkg.ID) // for Julia, the ID is set to the package UUID + qualifiers = append(qualifiers, qs...) } return (*PackageURL)(packageurl.NewPackageURL(ptype, namespace, name, ver, qualifiers, subpath)), nil @@ -424,6 +428,18 @@ func parseNpm(pkgName string) (string, string) { return parsePkgName(name) } +// ref. https://github.com/package-url/purl-spec/blob/7759d1cf81629267742eeeb0cdfccf5ebd624cc5/PURL-TYPES.rst#julia +func parseJulia(pkgName, pkgUUID string) (string, string, packageurl.Qualifiers) { + namespace, name := parsePkgName(pkgName) + qualifiers := packageurl.Qualifiers{ + { + Key: "uuid", + Value: pkgUUID, + }, + } + return namespace, name, qualifiers +} + func purlType(t ftypes.TargetType) string { switch t { case ftypes.Jar, ftypes.Pom, ftypes.Gradle: @@ -462,6 +478,8 @@ func purlType(t ftypes.TargetType) string { return packageurl.TypeRPM case TypeOCI: return packageurl.TypeOCI + case ftypes.Julia: + return packageurl.TypeJulia } return string(t) } diff --git a/pkg/sbom/cyclonedx/marshal_test.go b/pkg/sbom/cyclonedx/marshal_test.go index d3d104b28347..52781b865a8f 100644 --- a/pkg/sbom/cyclonedx/marshal_test.go +++ b/pkg/sbom/cyclonedx/marshal_test.go @@ -2,20 +2,22 @@ package cyclonedx_test import ( "context" - "github.com/aquasecurity/trivy/pkg/fanal/artifact" - "github.com/aquasecurity/trivy/pkg/sbom/core" - "github.com/package-url/packageurl-go" "testing" "time" + "github.com/aquasecurity/trivy/pkg/fanal/artifact" + "github.com/package-url/packageurl-go" + + "github.com/aquasecurity/trivy/pkg/sbom/core" + cdx "github.com/CycloneDX/cyclonedx-go" + "github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/samber/lo" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" dtypes "github.com/aquasecurity/trivy-db/pkg/types" - "github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability" "github.com/aquasecurity/trivy/pkg/clock" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/report" diff --git a/pkg/sbom/spdx/marshal_test.go b/pkg/sbom/spdx/marshal_test.go index ee4c10949148..e6b4a9360c32 100644 --- a/pkg/sbom/spdx/marshal_test.go +++ b/pkg/sbom/spdx/marshal_test.go @@ -2,13 +2,14 @@ package spdx_test import ( "context" - "github.com/aquasecurity/trivy/pkg/fanal/artifact" - "github.com/aquasecurity/trivy/pkg/sbom/core" - "github.com/package-url/packageurl-go" "hash/fnv" "testing" "time" + "github.com/aquasecurity/trivy/pkg/fanal/artifact" + "github.com/aquasecurity/trivy/pkg/sbom/core" + "github.com/package-url/packageurl-go" + v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/mitchellh/hashstructure/v2" "github.com/spdx/tools-golang/spdx" From bc70c06a6070c681a38d223ebf83e994ffd0628d Mon Sep 17 00:00:00 2001 From: Octogonapus Date: Wed, 6 Dec 2023 17:01:44 -0500 Subject: [PATCH 2/6] Add integration test for Julia SBOMs --- integration/repo_test.go | 18 +++ .../fixtures/repo/julia/Manifest.toml | 16 +++ .../testdata/fixtures/repo/julia/Project.toml | 7 + .../testdata/julia-cyclonedx.json.golden | 126 ++++++++++++++++++ integration/testdata/julia-spdx.json.golden | 124 +++++++++++++++++ 5 files changed, 291 insertions(+) create mode 100644 integration/testdata/fixtures/repo/julia/Manifest.toml create mode 100644 integration/testdata/fixtures/repo/julia/Project.toml create mode 100644 integration/testdata/julia-cyclonedx.json.golden create mode 100644 integration/testdata/julia-spdx.json.golden diff --git a/integration/repo_test.go b/integration/repo_test.go index 72edba8a562f..2d8fb53e20ca 100644 --- a/integration/repo_test.go +++ b/integration/repo_test.go @@ -397,6 +397,24 @@ func TestRepository(t *testing.T) { want.ArtifactType = artifact.TypeFilesystem }, }, + { + name: "julia generating SPDX SBOM", + args: args{ + command: "rootfs", + format: "spdx-json", + input: "testdata/fixtures/repo/julia", + }, + golden: "testdata/julia-spdx.json.golden", + }, + { + name: "julia generating CycloneDX SBOM", + args: args{ + command: "rootfs", + format: "cyclonedx", + input: "testdata/fixtures/repo/julia", + }, + golden: "testdata/julia-cyclonedx.json.golden", + }, } // Set up testing DB diff --git a/integration/testdata/fixtures/repo/julia/Manifest.toml b/integration/testdata/fixtures/repo/julia/Manifest.toml new file mode 100644 index 000000000000..dd4ea00b943d --- /dev/null +++ b/integration/testdata/fixtures/repo/julia/Manifest.toml @@ -0,0 +1,16 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.9.0" +manifest_format = "2.0" +project_hash = "f0a796fb78285c02ad123fec6e14c8bac09a2ccc" + +[[deps.A]] +uuid = "ead4f63c-334e-11e9-00e6-e7f0a5f21b60" + + [deps.A.deps] + B = "f41f7b98-334e-11e9-1257-49272045fb24" + +[[deps.B]] +uuid = "f41f7b98-334e-11e9-1257-49272045fb24" +[[deps.B]] +uuid = "edca9bc6-334e-11e9-3554-9595dbb4349c" diff --git a/integration/testdata/fixtures/repo/julia/Project.toml b/integration/testdata/fixtures/repo/julia/Project.toml new file mode 100644 index 000000000000..24fe6178c480 --- /dev/null +++ b/integration/testdata/fixtures/repo/julia/Project.toml @@ -0,0 +1,7 @@ +name = "packageName" +uuid = "1c653b0a-0b5a-4cff-b25a-92f0db012773" +version = "0.1.0" + +[deps] +A = "ead4f63c-334e-11e9-00e6-e7f0a5f21b60" +B = "edca9bc6-334e-11e9-3554-9595dbb4349c" diff --git a/integration/testdata/julia-cyclonedx.json.golden b/integration/testdata/julia-cyclonedx.json.golden new file mode 100644 index 000000000000..425a674eaed2 --- /dev/null +++ b/integration/testdata/julia-cyclonedx.json.golden @@ -0,0 +1,126 @@ +{ + "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "serialNumber": "urn:uuid:3ff14136-e09f-4df9-80ea-000000000001", + "version": 1, + "metadata": { + "timestamp": "2021-08-25T12:20:30+00:00", + "tools": [ + { + "vendor": "aquasecurity", + "name": "trivy", + "version": "dev" + } + ], + "component": { + "bom-ref": "3ff14136-e09f-4df9-80ea-000000000002", + "type": "application", + "name": "testdata/fixtures/repo/julia", + "properties": [ + { + "name": "aquasecurity:trivy:SchemaVersion", + "value": "2" + } + ] + } + }, + "components": [ + { + "bom-ref": "98bde055-d07d-4cb8-91a7-cf00399e7169", + "type": "application", + "name": "Manifest.toml", + "properties": [ + { + "name": "aquasecurity:trivy:Class", + "value": "lang-pkgs" + }, + { + "name": "aquasecurity:trivy:Type", + "value": "julia" + } + ] + }, + { + "bom-ref": "pkg:julia/A@1.9.0?uuid=ead4f63c-334e-11e9-00e6-e7f0a5f21b60", + "type": "library", + "name": "A", + "version": "1.9.0", + "purl": "pkg:julia/A@1.9.0?uuid=ead4f63c-334e-11e9-00e6-e7f0a5f21b60", + "properties": [ + { + "name": "aquasecurity:trivy:PkgID", + "value": "ead4f63c-334e-11e9-00e6-e7f0a5f21b60" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "julia" + } + ] + }, + { + "bom-ref": "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c", + "type": "library", + "name": "B", + "version": "1.9.0", + "purl": "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c", + "properties": [ + { + "name": "aquasecurity:trivy:PkgID", + "value": "edca9bc6-334e-11e9-3554-9595dbb4349c" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "julia" + } + ] + }, + { + "bom-ref": "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24", + "type": "library", + "name": "B", + "version": "1.9.0", + "purl": "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24", + "properties": [ + { + "name": "aquasecurity:trivy:PkgID", + "value": "f41f7b98-334e-11e9-1257-49272045fb24" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "julia" + } + ] + } + ], + "dependencies": [ + { + "ref": "3ff14136-e09f-4df9-80ea-000000000002", + "dependsOn": [ + "3ff14136-e09f-4df9-80ea-000000000003" + ] + }, + { + "ref": "3ff14136-e09f-4df9-80ea-000000000003", + "dependsOn": [ + "pkg:julia/A@1.9.0?uuid=ead4f63c-334e-11e9-00e6-e7f0a5f21b60", + "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c" + ] + }, + { + "ref": "pkg:julia/A@1.9.0?uuid=ead4f63c-334e-11e9-00e6-e7f0a5f21b60", + "dependsOn": [ + "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24" + ] + }, + { + "ref": "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c", + "dependsOn": [] + }, + { + "ref": "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24", + "dependsOn": [] + } + ], + "vulnerabilities": [] +} diff --git a/integration/testdata/julia-spdx.json.golden b/integration/testdata/julia-spdx.json.golden new file mode 100644 index 000000000000..4542630ba4a1 --- /dev/null +++ b/integration/testdata/julia-spdx.json.golden @@ -0,0 +1,124 @@ +{ + "spdxVersion": "SPDX-2.3", + "dataLicense": "CC0-1.0", + "SPDXID": "SPDXRef-DOCUMENT", + "name": "testdata/fixtures/repo/julia", + "documentNamespace": "http://aquasecurity.github.io/trivy/filesystem/testdata/fixtures/repo/julia-3ff14136-e09f-4df9-80ea-000000000001", + "creationInfo": { + "creators": [ + "Organization: aquasecurity", + "Tool: trivy-dev" + ], + "created": "2021-08-25T12:20:30Z" + }, + "packages": [ + { + "name": "A", + "SPDXID": "SPDXRef-Package-46973d9aca091871", + "versionInfo": "1.9.0", + "supplier": "NOASSERTION", + "downloadLocation": "NONE", + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:julia/A@1.9.0?uuid=ead4f63c-334e-11e9-00e6-e7f0a5f21b60" + } + ], + "attributionTexts": [ + "PkgID: ead4f63c-334e-11e9-00e6-e7f0a5f21b60" + ], + "primaryPackagePurpose": "LIBRARY" + }, + { + "name": "B", + "SPDXID": "SPDXRef-Package-436cd42285772e07", + "versionInfo": "1.9.0", + "supplier": "NOASSERTION", + "downloadLocation": "NONE", + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24" + } + ], + "attributionTexts": [ + "PkgID: f41f7b98-334e-11e9-1257-49272045fb24" + ], + "primaryPackagePurpose": "LIBRARY" + }, + { + "name": "B", + "SPDXID": "SPDXRef-Package-fa368ab116ed505f", + "versionInfo": "1.9.0", + "supplier": "NOASSERTION", + "downloadLocation": "NONE", + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c" + } + ], + "attributionTexts": [ + "PkgID: edca9bc6-334e-11e9-3554-9595dbb4349c" + ], + "primaryPackagePurpose": "LIBRARY" + }, + { + "name": "julia", + "SPDXID": "SPDXRef-Application-7d3c9e4ebc4e0210", + "downloadLocation": "NONE", + "filesAnalyzed": false, + "sourceInfo": "Manifest.toml", + "primaryPackagePurpose": "APPLICATION" + }, + { + "name": "testdata/fixtures/repo/julia", + "SPDXID": "SPDXRef-Filesystem-1be792dd0077c431", + "downloadLocation": "NONE", + "filesAnalyzed": false, + "attributionTexts": [ + "SchemaVersion: 2" + ], + "primaryPackagePurpose": "SOURCE" + } + ], + "relationships": [ + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relatedSpdxElement": "SPDXRef-Filesystem-1be792dd0077c431", + "relationshipType": "DESCRIBES" + }, + { + "spdxElementId": "SPDXRef-Filesystem-1be792dd0077c431", + "relatedSpdxElement": "SPDXRef-Application-7d3c9e4ebc4e0210", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Application-7d3c9e4ebc4e0210", + "relatedSpdxElement": "SPDXRef-Package-46973d9aca091871", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Application-7d3c9e4ebc4e0210", + "relatedSpdxElement": "SPDXRef-Package-fa368ab116ed505f", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Application-7d3c9e4ebc4e0210", + "relatedSpdxElement": "SPDXRef-Package-436cd42285772e07", + "relationshipType": "CONTAINS" + } + ] +} From a86794f97c2c193302bef1e632aa07f77e6ec986 Mon Sep 17 00:00:00 2001 From: Octogonapus Date: Mon, 11 Dec 2023 16:18:31 -0500 Subject: [PATCH 3/6] Add test for Julia PURL parsing --- pkg/purl/purl_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/pkg/purl/purl_test.go b/pkg/purl/purl_test.go index 646930ee5b76..18456d94c2ba 100644 --- a/pkg/purl/purl_test.go +++ b/pkg/purl/purl_test.go @@ -406,6 +406,28 @@ func TestNewPackageURL(t *testing.T) { }, wantErr: "failed to parse digest", }, + { + name: "julia project", + typ: ftypes.Julia, + pkg: ftypes.Package{ + ID: "ade2ca70-3891-5945-98fb-dc099432e06a", + Name: "Dates", + Version: "1.9.0", + }, + want: &purl.PackageURL{ + PackageURL: packageurl.PackageURL{ + Type: packageurl.TypeJulia, + Name: "Dates", + Version: "1.9.0", + Qualifiers: packageurl.Qualifiers{ + { + Key: "uuid", + Value: "ade2ca70-3891-5945-98fb-dc099432e06a", + }, + }, + }, + }, + }, } for _, tc := range testCases { From 56cd72965e4ed07c34a4070cc7fad49cd1ae94b4 Mon Sep 17 00:00:00 2001 From: Octogonapus Date: Tue, 20 Feb 2024 09:59:55 -0500 Subject: [PATCH 4/6] Fix parsing Julia v1.0 Manifests --- pkg/dependency/parser/julia/manifest/parse.go | 5 +- .../parser/julia/manifest/parse_test.go | 20 +++-- .../parser/julia/manifest/parse_testcase.go | 77 +++++++++++-------- .../testdata/julia_v1.0_format/Manifest.toml | 28 +++++++ .../testdata/julia_v1.0_format/Project.toml | 6 ++ 5 files changed, 96 insertions(+), 40 deletions(-) create mode 100644 pkg/dependency/parser/julia/manifest/testdata/julia_v1.0_format/Manifest.toml create mode 100644 pkg/dependency/parser/julia/manifest/testdata/julia_v1.0_format/Project.toml diff --git a/pkg/dependency/parser/julia/manifest/parse.go b/pkg/dependency/parser/julia/manifest/parse.go index 061676d3f599..13d1cb208bcb 100644 --- a/pkg/dependency/parser/julia/manifest/parse.go +++ b/pkg/dependency/parser/julia/manifest/parse.go @@ -36,8 +36,9 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc var primMan primitiveManifest var manMetadata toml.MetaData decoder := toml.NewDecoder(r) - // Try to read the old Manifest format. If that fails, try the new format. - if _, err := decoder.Decode(&oldDeps); err != nil { + // Try to read the old Manifest format. This can also read the v1.0 Manifest format, which we parse out later. + var err error + if manMetadata, err = decoder.Decode(&oldDeps); err != nil { if _, err = r.Seek(0, io.SeekStart); err != nil { return nil, nil, xerrors.Errorf("seek error: %w", err) } diff --git a/pkg/dependency/parser/julia/manifest/parse_test.go b/pkg/dependency/parser/julia/manifest/parse_test.go index 229499c6cb71..95a1180f6de9 100644 --- a/pkg/dependency/parser/julia/manifest/parse_test.go +++ b/pkg/dependency/parser/julia/manifest/parse_test.go @@ -21,14 +21,14 @@ func TestParse(t *testing.T) { { name: "Manifest v1.6", file: "testdata/primary/Manifest_v1.6.toml", - want: juliaV1_6Pkgs, - wantDeps: juliaV1_6Deps, + want: juliaV16Libs, + wantDeps: juliaV16Deps, }, { name: "Manifest v1.8", file: "testdata/primary/Manifest_v1.8.toml", - want: juliaV1_8Pkgs, - wantDeps: juliaV1_8Deps, + want: juliaV18Libs, + wantDeps: juliaV18Deps, }, { name: "no deps v1.6", @@ -45,14 +45,20 @@ func TestParse(t *testing.T) { { name: "dep extensions v1.9", file: "testdata/dep_ext_v1.9/Manifest.toml", - want: juliaV1_9DepExtPkgs, + want: juliaV19DepExtLibs, wantDeps: nil, }, { name: "shadowed dep v1.9", file: "testdata/shadowed_dep_v1.9/Manifest.toml", - want: juliaV1_9ShadowedDepPkgs, - wantDeps: juliaV1_9ShadowedDepDeps, + want: juliaV19ShadowedDepLibs, + wantDeps: juliaV19ShadowedDepDeps, + }, + { + name: "julia v1.0 format", + file: "testdata/julia_v1.0_format/Manifest.toml", + want: juliaV10FormatLibs, + wantDeps: juliaV10FormatDeps, }, } diff --git a/pkg/dependency/parser/julia/manifest/parse_testcase.go b/pkg/dependency/parser/julia/manifest/parse_testcase.go index 75602f7311f8..e75df9b2b840 100644 --- a/pkg/dependency/parser/julia/manifest/parse_testcase.go +++ b/pkg/dependency/parser/julia/manifest/parse_testcase.go @@ -1,18 +1,18 @@ package julia -import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" +import "github.com/aquasecurity/trivy/pkg/fanal/types" var ( - juliaV1_6Pkgs = []ftypes.Package{ - {ID: "ade2ca70-3891-5945-98fb-dc099432e06a", Name: "Dates", Version: "unknown", Locations: []ftypes.Location{{StartLine: 3, EndLine: 5}}}, - {ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", Name: "JSON", Version: "0.21.4", Locations: []ftypes.Location{{StartLine: 7, EndLine: 11}}}, - {ID: "a63ad114-7e13-5084-954f-fe012c677804", Name: "Mmap", Version: "unknown", Locations: []ftypes.Location{{StartLine: 13, EndLine: 14}}}, - {ID: "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", Name: "Parsers", Version: "2.4.2", Locations: []ftypes.Location{{StartLine: 16, EndLine: 20}}}, - {ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", Name: "Printf", Version: "unknown", Locations: []ftypes.Location{{StartLine: 22, EndLine: 24}}}, - {ID: "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", Name: "Unicode", Version: "unknown", Locations: []ftypes.Location{{StartLine: 26, EndLine: 27}}}, + juliaV16Libs = []ftypes.Library{ + {ID: "ade2ca70-3891-5945-98fb-dc099432e06a", Name: "Dates", Version: "unknown", Locations: []types.Location{{StartLine: 3, EndLine: 5}}}, + {ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", Name: "JSON", Version: "0.21.4", Locations: []types.Location{{StartLine: 7, EndLine: 11}}}, + {ID: "a63ad114-7e13-5084-954f-fe012c677804", Name: "Mmap", Version: "unknown", Locations: []types.Location{{StartLine: 13, EndLine: 14}}}, + {ID: "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", Name: "Parsers", Version: "2.4.2", Locations: []types.Location{{StartLine: 16, EndLine: 20}}}, + {ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", Name: "Printf", Version: "unknown", Locations: []types.Location{{StartLine: 22, EndLine: 24}}}, + {ID: "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", Name: "Unicode", Version: "unknown", Locations: []types.Location{{StartLine: 26, EndLine: 27}}}, } - juliaV1_6Deps = []ftypes.Dependency{ + juliaV16Deps = []ftypes.Dependency{ {ID: "ade2ca70-3891-5945-98fb-dc099432e06a", DependsOn: []string{"de0858da-6303-5e67-8744-51eddeeeb8d7"}}, {ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", DependsOn: []string{ "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", @@ -24,23 +24,23 @@ var ( {ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", DependsOn: []string{"4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"}}, } - juliaV1_8Pkgs = []ftypes.Package{ - {ID: "ade2ca70-3891-5945-98fb-dc099432e06a", Name: "Dates", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 7, EndLine: 9}}}, - {ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", Name: "JSON", Version: "0.21.4", Locations: []ftypes.Location{{StartLine: 11, EndLine: 15}}}, - {ID: "a63ad114-7e13-5084-954f-fe012c677804", Name: "Mmap", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 17, EndLine: 18}}}, - {ID: "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", Name: "Parsers", Version: "2.5.10", Locations: []ftypes.Location{{StartLine: 20, EndLine: 24}}}, - {ID: "aea7be01-6a6a-4083-8856-8a6e6704d82a", Name: "PrecompileTools", Version: "1.1.1", Locations: []ftypes.Location{{StartLine: 26, EndLine: 30}}}, - {ID: "21216c6a-2e73-6563-6e65-726566657250", Name: "Preferences", Version: "1.4.0", Locations: []ftypes.Location{{StartLine: 32, EndLine: 36}}}, - {ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", Name: "Printf", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 38, EndLine: 40}}}, - {ID: "9a3f8284-a2c9-5f02-9a11-845980a1fd5c", Name: "Random", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 42, EndLine: 44}}}, - {ID: "ea8e919c-243c-51af-8825-aaa63cd721ce", Name: "SHA", Version: "0.7.0", Locations: []ftypes.Location{{StartLine: 46, EndLine: 48}}}, - {ID: "9e88b42a-f829-5b0c-bbe9-9e923198166b", Name: "Serialization", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 50, EndLine: 51}}}, - {ID: "fa267f1f-6049-4f14-aa54-33bafae1ed76", Name: "TOML", Version: "1.0.0", Locations: []ftypes.Location{{StartLine: 53, EndLine: 56}}}, - {ID: "cf7118a7-6976-5b1a-9a39-7adc72f591a4", Name: "UUIDs", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 58, EndLine: 60}}}, - {ID: "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", Name: "Unicode", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 62, EndLine: 63}}}, + juliaV18Libs = []ftypes.Library{ + {ID: "ade2ca70-3891-5945-98fb-dc099432e06a", Name: "Dates", Version: "1.8.5", Locations: []types.Location{{StartLine: 7, EndLine: 9}}}, + {ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", Name: "JSON", Version: "0.21.4", Locations: []types.Location{{StartLine: 11, EndLine: 15}}}, + {ID: "a63ad114-7e13-5084-954f-fe012c677804", Name: "Mmap", Version: "1.8.5", Locations: []types.Location{{StartLine: 17, EndLine: 18}}}, + {ID: "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", Name: "Parsers", Version: "2.5.10", Locations: []types.Location{{StartLine: 20, EndLine: 24}}}, + {ID: "aea7be01-6a6a-4083-8856-8a6e6704d82a", Name: "PrecompileTools", Version: "1.1.1", Locations: []types.Location{{StartLine: 26, EndLine: 30}}}, + {ID: "21216c6a-2e73-6563-6e65-726566657250", Name: "Preferences", Version: "1.4.0", Locations: []types.Location{{StartLine: 32, EndLine: 36}}}, + {ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", Name: "Printf", Version: "1.8.5", Locations: []types.Location{{StartLine: 38, EndLine: 40}}}, + {ID: "9a3f8284-a2c9-5f02-9a11-845980a1fd5c", Name: "Random", Version: "1.8.5", Locations: []types.Location{{StartLine: 42, EndLine: 44}}}, + {ID: "ea8e919c-243c-51af-8825-aaa63cd721ce", Name: "SHA", Version: "0.7.0", Locations: []types.Location{{StartLine: 46, EndLine: 48}}}, + {ID: "9e88b42a-f829-5b0c-bbe9-9e923198166b", Name: "Serialization", Version: "1.8.5", Locations: []types.Location{{StartLine: 50, EndLine: 51}}}, + {ID: "fa267f1f-6049-4f14-aa54-33bafae1ed76", Name: "TOML", Version: "1.0.0", Locations: []types.Location{{StartLine: 53, EndLine: 56}}}, + {ID: "cf7118a7-6976-5b1a-9a39-7adc72f591a4", Name: "UUIDs", Version: "1.8.5", Locations: []types.Location{{StartLine: 58, EndLine: 60}}}, + {ID: "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", Name: "Unicode", Version: "1.8.5", Locations: []types.Location{{StartLine: 62, EndLine: 63}}}, } - juliaV1_8Deps = []ftypes.Dependency{ + juliaV18Deps = []ftypes.Dependency{ {ID: "ade2ca70-3891-5945-98fb-dc099432e06a", DependsOn: []string{"de0858da-6303-5e67-8744-51eddeeeb8d7"}}, {ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", DependsOn: []string{ "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", @@ -61,17 +61,32 @@ var ( {ID: "cf7118a7-6976-5b1a-9a39-7adc72f591a4", DependsOn: []string{"9a3f8284-a2c9-5f02-9a11-845980a1fd5c", "ea8e919c-243c-51af-8825-aaa63cd721ce"}}, } - juliaV1_9DepExtPkgs = []ftypes.Package{ - {ID: "621f4979-c628-5d54-868e-fcf4e3e8185c", Name: "AbstractFFTs", Version: "1.3.1", Locations: []ftypes.Location{{StartLine: 7, EndLine: 10}}}, + juliaV19DepExtLibs = []ftypes.Library{ + {ID: "621f4979-c628-5d54-868e-fcf4e3e8185c", Name: "AbstractFFTs", Version: "1.3.1", Locations: []types.Location{{StartLine: 7, EndLine: 10}}}, } - juliaV1_9ShadowedDepPkgs = []ftypes.Package{ - {ID: "ead4f63c-334e-11e9-00e6-e7f0a5f21b60", Name: "A", Version: "1.9.0", Locations: []ftypes.Location{{StartLine: 7, EndLine: 8}}}, - {ID: "f41f7b98-334e-11e9-1257-49272045fb24", Name: "B", Version: "1.9.0", Locations: []ftypes.Location{{StartLine: 13, EndLine: 14}}}, - {ID: "edca9bc6-334e-11e9-3554-9595dbb4349c", Name: "B", Version: "1.9.0", Locations: []ftypes.Location{{StartLine: 15, EndLine: 16}}}, + juliaV19ShadowedDepLibs = []ftypes.Library{ + {ID: "ead4f63c-334e-11e9-00e6-e7f0a5f21b60", Name: "A", Version: "1.9.0", Locations: []types.Location{{StartLine: 7, EndLine: 8}}}, + {ID: "f41f7b98-334e-11e9-1257-49272045fb24", Name: "B", Version: "1.9.0", Locations: []types.Location{{StartLine: 13, EndLine: 14}}}, + {ID: "edca9bc6-334e-11e9-3554-9595dbb4349c", Name: "B", Version: "1.9.0", Locations: []types.Location{{StartLine: 15, EndLine: 16}}}, } - juliaV1_9ShadowedDepDeps = []ftypes.Dependency{ + juliaV19ShadowedDepDeps = []ftypes.Dependency{ {ID: "ead4f63c-334e-11e9-00e6-e7f0a5f21b60", DependsOn: []string{"f41f7b98-334e-11e9-1257-49272045fb24"}}, } + + juliaV10FormatLibs = []ftypes.Library{ + {ID: "767738be-2f1f-45a9-b806-0234f3164144", Name: "Foo", Version: "unknown", Locations: []types.Location{{StartLine: 1, EndLine: 5}}}, + {ID: "6f418443-bd2e-4783-b551-cdbac608adf2", Name: "Foo", Version: "unknown", Locations: []types.Location{{StartLine: 7, EndLine: 10}}}, + {ID: "2a550a13-6bab-4a91-a4ee-dff34d6b99d0", Name: "Bar", Version: "unknown", Locations: []types.Location{{StartLine: 12, EndLine: 14}}}, + {ID: "6801f525-dc68-44e8-a4e8-cabd286279e7", Name: "Baz", Version: "unknown", Locations: []types.Location{{StartLine: 19, EndLine: 21}}}, + {ID: "b5ec9b9c-e354-47fd-b367-a348bdc8f909", Name: "Qux", Version: "unknown", Locations: []types.Location{{StartLine: 26, EndLine: 28}}}, + } + + juliaV10FormatDeps = []ftypes.Dependency{ + {ID: "767738be-2f1f-45a9-b806-0234f3164144", DependsOn: []string{"2a550a13-6bab-4a91-a4ee-dff34d6b99d0", "6801f525-dc68-44e8-a4e8-cabd286279e7", "b5ec9b9c-e354-47fd-b367-a348bdc8f909"}}, + {ID: "6f418443-bd2e-4783-b551-cdbac608adf2", DependsOn: []string{"b5ec9b9c-e354-47fd-b367-a348bdc8f909"}}, + {ID: "2a550a13-6bab-4a91-a4ee-dff34d6b99d0", DependsOn: []string{"6801f525-dc68-44e8-a4e8-cabd286279e7", "6f418443-bd2e-4783-b551-cdbac608adf2"}}, + {ID: "6801f525-dc68-44e8-a4e8-cabd286279e7", DependsOn: []string{"6f418443-bd2e-4783-b551-cdbac608adf2", "b5ec9b9c-e354-47fd-b367-a348bdc8f909"}}, + } ) diff --git a/pkg/dependency/parser/julia/manifest/testdata/julia_v1.0_format/Manifest.toml b/pkg/dependency/parser/julia/manifest/testdata/julia_v1.0_format/Manifest.toml new file mode 100644 index 000000000000..a5a893066c36 --- /dev/null +++ b/pkg/dependency/parser/julia/manifest/testdata/julia_v1.0_format/Manifest.toml @@ -0,0 +1,28 @@ +[[Foo]] +deps = ["Bar", "Baz", "Qux"] +uuid = "767738be-2f1f-45a9-b806-0234f3164144" +git-tree-sha1 = "7c626031568a5e432112a74009c3763f9b851e3e" +path = "deps/Foo1" + +[[Foo]] +deps = ["Qux"] +uuid = "6f418443-bd2e-4783-b551-cdbac608adf2" +path = "deps/Foo2.jl" + +[[Bar]] +uuid = "2a550a13-6bab-4a91-a4ee-dff34d6b99d0" +path = "deps/Bar" +[Bar.deps] +Baz = "6801f525-dc68-44e8-a4e8-cabd286279e7" +Foo = "6f418443-bd2e-4783-b551-cdbac608adf2" + +[[Baz]] +uuid = "6801f525-dc68-44e8-a4e8-cabd286279e7" +git-tree-sha1 = "efc7e24c53d6a328011975294a2c75fed2f9800a" +[Baz.deps] +Foo = "6f418443-bd2e-4783-b551-cdbac608adf2" +Qux = "b5ec9b9c-e354-47fd-b367-a348bdc8f909" + +[[Qux]] +uuid = "b5ec9b9c-e354-47fd-b367-a348bdc8f909" +path = "deps/Qux.jl" diff --git a/pkg/dependency/parser/julia/manifest/testdata/julia_v1.0_format/Project.toml b/pkg/dependency/parser/julia/manifest/testdata/julia_v1.0_format/Project.toml new file mode 100644 index 000000000000..9d42e37cd67f --- /dev/null +++ b/pkg/dependency/parser/julia/manifest/testdata/julia_v1.0_format/Project.toml @@ -0,0 +1,6 @@ +name = "TestProject" +uuid = "84c38c17-0c6f-4d12-a694-d20b69c16777" + +[deps] +Foo = "767738be-2f1f-45a9-b806-0234f3164144" +Bar = "2a550a13-6bab-4a91-a4ee-dff34d6b99d0" From 73f058c79a01c62161f159faa078a7002f25daae Mon Sep 17 00:00:00 2001 From: Octogonapus Date: Tue, 20 Feb 2024 10:28:15 -0500 Subject: [PATCH 5/6] Fix julia integ test --- docs/docs/coverage/language/julia.md | 1 - .../testdata/julia-cyclonedx.json.golden | 32 ++++---- integration/testdata/julia-spdx.json.golden | 74 +++++++++++-------- .../parser/julia/manifest/parse_test.go | 16 ++-- .../parser/julia/manifest/parse_testcase.go | 74 +++++++++---------- pkg/detector/library/driver.go | 2 +- pkg/fanal/analyzer/language/julia/pkg/pkg.go | 26 ++++--- .../analyzer/language/julia/pkg/pkg_test.go | 42 +---------- pkg/purl/purl_test.go | 16 ++-- pkg/sbom/cyclonedx/marshal_test.go | 10 +-- pkg/sbom/spdx/marshal_test.go | 7 +- 11 files changed, 138 insertions(+), 162 deletions(-) diff --git a/docs/docs/coverage/language/julia.md b/docs/docs/coverage/language/julia.md index 82f197fd432a..3817dacfeb1b 100644 --- a/docs/docs/coverage/language/julia.md +++ b/docs/docs/coverage/language/julia.md @@ -20,6 +20,5 @@ If you want to see the dependency tree, please ensure that `Project.toml` is pre Scanning `Manifest.toml` and `Project.toml` together also removes developer dependencies. Dependency extensions are currently ignored. -Shadowed dependencies are not supported and will overwrite each other in exported SBOMs. [^1]: When you scan `Manifest.toml` and `Project.toml` together. diff --git a/integration/testdata/julia-cyclonedx.json.golden b/integration/testdata/julia-cyclonedx.json.golden index 425a674eaed2..f86ae2dfe472 100644 --- a/integration/testdata/julia-cyclonedx.json.golden +++ b/integration/testdata/julia-cyclonedx.json.golden @@ -2,19 +2,22 @@ "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.5", - "serialNumber": "urn:uuid:3ff14136-e09f-4df9-80ea-000000000001", + "serialNumber": "urn:uuid:3ff14136-e09f-4df9-80ea-000000000006", "version": 1, "metadata": { "timestamp": "2021-08-25T12:20:30+00:00", - "tools": [ - { - "vendor": "aquasecurity", - "name": "trivy", - "version": "dev" - } - ], + "tools": { + "components": [ + { + "type": "application", + "group": "aquasecurity", + "name": "trivy", + "version": "dev" + } + ] + }, "component": { - "bom-ref": "3ff14136-e09f-4df9-80ea-000000000002", + "bom-ref": "3ff14136-e09f-4df9-80ea-000000000001", "type": "application", "name": "testdata/fixtures/repo/julia", "properties": [ @@ -27,7 +30,7 @@ }, "components": [ { - "bom-ref": "98bde055-d07d-4cb8-91a7-cf00399e7169", + "bom-ref": "3ff14136-e09f-4df9-80ea-000000000002", "type": "application", "name": "Manifest.toml", "properties": [ @@ -95,16 +98,17 @@ ], "dependencies": [ { - "ref": "3ff14136-e09f-4df9-80ea-000000000002", + "ref": "3ff14136-e09f-4df9-80ea-000000000001", "dependsOn": [ - "3ff14136-e09f-4df9-80ea-000000000003" + "3ff14136-e09f-4df9-80ea-000000000002" ] }, { - "ref": "3ff14136-e09f-4df9-80ea-000000000003", + "ref": "3ff14136-e09f-4df9-80ea-000000000002", "dependsOn": [ "pkg:julia/A@1.9.0?uuid=ead4f63c-334e-11e9-00e6-e7f0a5f21b60", - "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c" + "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c", + "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24" ] }, { diff --git a/integration/testdata/julia-spdx.json.golden b/integration/testdata/julia-spdx.json.golden index 4542630ba4a1..483991784365 100644 --- a/integration/testdata/julia-spdx.json.golden +++ b/integration/testdata/julia-spdx.json.golden @@ -3,7 +3,7 @@ "dataLicense": "CC0-1.0", "SPDXID": "SPDXRef-DOCUMENT", "name": "testdata/fixtures/repo/julia", - "documentNamespace": "http://aquasecurity.github.io/trivy/filesystem/testdata/fixtures/repo/julia-3ff14136-e09f-4df9-80ea-000000000001", + "documentNamespace": "http://aquasecurity.github.io/trivy/filesystem/testdata/fixtures/repo/julia-3ff14136-e09f-4df9-80ea-000000000006", "creationInfo": { "creators": [ "Organization: aquasecurity", @@ -12,13 +12,25 @@ "created": "2021-08-25T12:20:30Z" }, "packages": [ + { + "name": "Manifest.toml", + "SPDXID": "SPDXRef-Application-18fc3597717a3e56", + "downloadLocation": "NONE", + "filesAnalyzed": false, + "attributionTexts": [ + "Class: lang-pkgs", + "Type: julia" + ], + "primaryPackagePurpose": "APPLICATION" + }, { "name": "A", - "SPDXID": "SPDXRef-Package-46973d9aca091871", + "SPDXID": "SPDXRef-Package-2a46714189f3b9de", "versionInfo": "1.9.0", "supplier": "NOASSERTION", "downloadLocation": "NONE", "filesAnalyzed": false, + "sourceInfo": "package found in: Manifest.toml", "licenseConcluded": "NONE", "licenseDeclared": "NONE", "externalRefs": [ @@ -29,60 +41,57 @@ } ], "attributionTexts": [ - "PkgID: ead4f63c-334e-11e9-00e6-e7f0a5f21b60" + "PkgID: ead4f63c-334e-11e9-00e6-e7f0a5f21b60", + "PkgType: julia" ], "primaryPackagePurpose": "LIBRARY" }, { "name": "B", - "SPDXID": "SPDXRef-Package-436cd42285772e07", + "SPDXID": "SPDXRef-Package-4a8e351c4c9b7318", "versionInfo": "1.9.0", "supplier": "NOASSERTION", "downloadLocation": "NONE", "filesAnalyzed": false, + "sourceInfo": "package found in: Manifest.toml", "licenseConcluded": "NONE", "licenseDeclared": "NONE", "externalRefs": [ { "referenceCategory": "PACKAGE-MANAGER", "referenceType": "purl", - "referenceLocator": "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24" + "referenceLocator": "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c" } ], "attributionTexts": [ - "PkgID: f41f7b98-334e-11e9-1257-49272045fb24" + "PkgID: edca9bc6-334e-11e9-3554-9595dbb4349c", + "PkgType: julia" ], "primaryPackagePurpose": "LIBRARY" }, { "name": "B", - "SPDXID": "SPDXRef-Package-fa368ab116ed505f", + "SPDXID": "SPDXRef-Package-d10d5e4a30a43fff", "versionInfo": "1.9.0", "supplier": "NOASSERTION", "downloadLocation": "NONE", "filesAnalyzed": false, + "sourceInfo": "package found in: Manifest.toml", "licenseConcluded": "NONE", "licenseDeclared": "NONE", "externalRefs": [ { "referenceCategory": "PACKAGE-MANAGER", "referenceType": "purl", - "referenceLocator": "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c" + "referenceLocator": "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24" } ], "attributionTexts": [ - "PkgID: edca9bc6-334e-11e9-3554-9595dbb4349c" + "PkgID: f41f7b98-334e-11e9-1257-49272045fb24", + "PkgType: julia" ], "primaryPackagePurpose": "LIBRARY" }, - { - "name": "julia", - "SPDXID": "SPDXRef-Application-7d3c9e4ebc4e0210", - "downloadLocation": "NONE", - "filesAnalyzed": false, - "sourceInfo": "Manifest.toml", - "primaryPackagePurpose": "APPLICATION" - }, { "name": "testdata/fixtures/repo/julia", "SPDXID": "SPDXRef-Filesystem-1be792dd0077c431", @@ -96,29 +105,34 @@ ], "relationships": [ { - "spdxElementId": "SPDXRef-DOCUMENT", - "relatedSpdxElement": "SPDXRef-Filesystem-1be792dd0077c431", - "relationshipType": "DESCRIBES" + "spdxElementId": "SPDXRef-Application-18fc3597717a3e56", + "relatedSpdxElement": "SPDXRef-Package-2a46714189f3b9de", + "relationshipType": "CONTAINS" }, { - "spdxElementId": "SPDXRef-Filesystem-1be792dd0077c431", - "relatedSpdxElement": "SPDXRef-Application-7d3c9e4ebc4e0210", + "spdxElementId": "SPDXRef-Application-18fc3597717a3e56", + "relatedSpdxElement": "SPDXRef-Package-4a8e351c4c9b7318", "relationshipType": "CONTAINS" }, { - "spdxElementId": "SPDXRef-Application-7d3c9e4ebc4e0210", - "relatedSpdxElement": "SPDXRef-Package-46973d9aca091871", + "spdxElementId": "SPDXRef-Application-18fc3597717a3e56", + "relatedSpdxElement": "SPDXRef-Package-d10d5e4a30a43fff", "relationshipType": "CONTAINS" }, { - "spdxElementId": "SPDXRef-Application-7d3c9e4ebc4e0210", - "relatedSpdxElement": "SPDXRef-Package-fa368ab116ed505f", - "relationshipType": "CONTAINS" + "spdxElementId": "SPDXRef-DOCUMENT", + "relatedSpdxElement": "SPDXRef-Filesystem-1be792dd0077c431", + "relationshipType": "DESCRIBES" }, { - "spdxElementId": "SPDXRef-Application-7d3c9e4ebc4e0210", - "relatedSpdxElement": "SPDXRef-Package-436cd42285772e07", + "spdxElementId": "SPDXRef-Filesystem-1be792dd0077c431", + "relatedSpdxElement": "SPDXRef-Application-18fc3597717a3e56", "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-2a46714189f3b9de", + "relatedSpdxElement": "SPDXRef-Package-d10d5e4a30a43fff", + "relationshipType": "DEPENDS_ON" } ] -} +} \ No newline at end of file diff --git a/pkg/dependency/parser/julia/manifest/parse_test.go b/pkg/dependency/parser/julia/manifest/parse_test.go index 95a1180f6de9..efbc0bfcbee5 100644 --- a/pkg/dependency/parser/julia/manifest/parse_test.go +++ b/pkg/dependency/parser/julia/manifest/parse_test.go @@ -21,14 +21,14 @@ func TestParse(t *testing.T) { { name: "Manifest v1.6", file: "testdata/primary/Manifest_v1.6.toml", - want: juliaV16Libs, - wantDeps: juliaV16Deps, + want: juliaV1_6Pkgs, + wantDeps: juliaV1_6Deps, }, { name: "Manifest v1.8", file: "testdata/primary/Manifest_v1.8.toml", - want: juliaV18Libs, - wantDeps: juliaV18Deps, + want: juliaV1_8Pkgs, + wantDeps: juliaV1_8Deps, }, { name: "no deps v1.6", @@ -45,19 +45,19 @@ func TestParse(t *testing.T) { { name: "dep extensions v1.9", file: "testdata/dep_ext_v1.9/Manifest.toml", - want: juliaV19DepExtLibs, + want: juliaV1_9DepExtPkgs, wantDeps: nil, }, { name: "shadowed dep v1.9", file: "testdata/shadowed_dep_v1.9/Manifest.toml", - want: juliaV19ShadowedDepLibs, - wantDeps: juliaV19ShadowedDepDeps, + want: juliaV1_9ShadowedDepPkgs, + wantDeps: juliaV1_9ShadowedDepDeps, }, { name: "julia v1.0 format", file: "testdata/julia_v1.0_format/Manifest.toml", - want: juliaV10FormatLibs, + want: juliaV10FormatPkgs, wantDeps: juliaV10FormatDeps, }, } diff --git a/pkg/dependency/parser/julia/manifest/parse_testcase.go b/pkg/dependency/parser/julia/manifest/parse_testcase.go index e75df9b2b840..232529065c55 100644 --- a/pkg/dependency/parser/julia/manifest/parse_testcase.go +++ b/pkg/dependency/parser/julia/manifest/parse_testcase.go @@ -1,18 +1,18 @@ package julia -import "github.com/aquasecurity/trivy/pkg/fanal/types" +import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" var ( - juliaV16Libs = []ftypes.Library{ - {ID: "ade2ca70-3891-5945-98fb-dc099432e06a", Name: "Dates", Version: "unknown", Locations: []types.Location{{StartLine: 3, EndLine: 5}}}, - {ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", Name: "JSON", Version: "0.21.4", Locations: []types.Location{{StartLine: 7, EndLine: 11}}}, - {ID: "a63ad114-7e13-5084-954f-fe012c677804", Name: "Mmap", Version: "unknown", Locations: []types.Location{{StartLine: 13, EndLine: 14}}}, - {ID: "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", Name: "Parsers", Version: "2.4.2", Locations: []types.Location{{StartLine: 16, EndLine: 20}}}, - {ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", Name: "Printf", Version: "unknown", Locations: []types.Location{{StartLine: 22, EndLine: 24}}}, - {ID: "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", Name: "Unicode", Version: "unknown", Locations: []types.Location{{StartLine: 26, EndLine: 27}}}, + juliaV1_6Pkgs = []ftypes.Package{ + {ID: "ade2ca70-3891-5945-98fb-dc099432e06a", Name: "Dates", Version: "unknown", Locations: []ftypes.Location{{StartLine: 3, EndLine: 5}}}, + {ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", Name: "JSON", Version: "0.21.4", Locations: []ftypes.Location{{StartLine: 7, EndLine: 11}}}, + {ID: "a63ad114-7e13-5084-954f-fe012c677804", Name: "Mmap", Version: "unknown", Locations: []ftypes.Location{{StartLine: 13, EndLine: 14}}}, + {ID: "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", Name: "Parsers", Version: "2.4.2", Locations: []ftypes.Location{{StartLine: 16, EndLine: 20}}}, + {ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", Name: "Printf", Version: "unknown", Locations: []ftypes.Location{{StartLine: 22, EndLine: 24}}}, + {ID: "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", Name: "Unicode", Version: "unknown", Locations: []ftypes.Location{{StartLine: 26, EndLine: 27}}}, } - juliaV16Deps = []ftypes.Dependency{ + juliaV1_6Deps = []ftypes.Dependency{ {ID: "ade2ca70-3891-5945-98fb-dc099432e06a", DependsOn: []string{"de0858da-6303-5e67-8744-51eddeeeb8d7"}}, {ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", DependsOn: []string{ "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", @@ -24,23 +24,23 @@ var ( {ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", DependsOn: []string{"4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"}}, } - juliaV18Libs = []ftypes.Library{ - {ID: "ade2ca70-3891-5945-98fb-dc099432e06a", Name: "Dates", Version: "1.8.5", Locations: []types.Location{{StartLine: 7, EndLine: 9}}}, - {ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", Name: "JSON", Version: "0.21.4", Locations: []types.Location{{StartLine: 11, EndLine: 15}}}, - {ID: "a63ad114-7e13-5084-954f-fe012c677804", Name: "Mmap", Version: "1.8.5", Locations: []types.Location{{StartLine: 17, EndLine: 18}}}, - {ID: "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", Name: "Parsers", Version: "2.5.10", Locations: []types.Location{{StartLine: 20, EndLine: 24}}}, - {ID: "aea7be01-6a6a-4083-8856-8a6e6704d82a", Name: "PrecompileTools", Version: "1.1.1", Locations: []types.Location{{StartLine: 26, EndLine: 30}}}, - {ID: "21216c6a-2e73-6563-6e65-726566657250", Name: "Preferences", Version: "1.4.0", Locations: []types.Location{{StartLine: 32, EndLine: 36}}}, - {ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", Name: "Printf", Version: "1.8.5", Locations: []types.Location{{StartLine: 38, EndLine: 40}}}, - {ID: "9a3f8284-a2c9-5f02-9a11-845980a1fd5c", Name: "Random", Version: "1.8.5", Locations: []types.Location{{StartLine: 42, EndLine: 44}}}, - {ID: "ea8e919c-243c-51af-8825-aaa63cd721ce", Name: "SHA", Version: "0.7.0", Locations: []types.Location{{StartLine: 46, EndLine: 48}}}, - {ID: "9e88b42a-f829-5b0c-bbe9-9e923198166b", Name: "Serialization", Version: "1.8.5", Locations: []types.Location{{StartLine: 50, EndLine: 51}}}, - {ID: "fa267f1f-6049-4f14-aa54-33bafae1ed76", Name: "TOML", Version: "1.0.0", Locations: []types.Location{{StartLine: 53, EndLine: 56}}}, - {ID: "cf7118a7-6976-5b1a-9a39-7adc72f591a4", Name: "UUIDs", Version: "1.8.5", Locations: []types.Location{{StartLine: 58, EndLine: 60}}}, - {ID: "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", Name: "Unicode", Version: "1.8.5", Locations: []types.Location{{StartLine: 62, EndLine: 63}}}, + juliaV1_8Pkgs = []ftypes.Package{ + {ID: "ade2ca70-3891-5945-98fb-dc099432e06a", Name: "Dates", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 7, EndLine: 9}}}, + {ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", Name: "JSON", Version: "0.21.4", Locations: []ftypes.Location{{StartLine: 11, EndLine: 15}}}, + {ID: "a63ad114-7e13-5084-954f-fe012c677804", Name: "Mmap", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 17, EndLine: 18}}}, + {ID: "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", Name: "Parsers", Version: "2.5.10", Locations: []ftypes.Location{{StartLine: 20, EndLine: 24}}}, + {ID: "aea7be01-6a6a-4083-8856-8a6e6704d82a", Name: "PrecompileTools", Version: "1.1.1", Locations: []ftypes.Location{{StartLine: 26, EndLine: 30}}}, + {ID: "21216c6a-2e73-6563-6e65-726566657250", Name: "Preferences", Version: "1.4.0", Locations: []ftypes.Location{{StartLine: 32, EndLine: 36}}}, + {ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", Name: "Printf", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 38, EndLine: 40}}}, + {ID: "9a3f8284-a2c9-5f02-9a11-845980a1fd5c", Name: "Random", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 42, EndLine: 44}}}, + {ID: "ea8e919c-243c-51af-8825-aaa63cd721ce", Name: "SHA", Version: "0.7.0", Locations: []ftypes.Location{{StartLine: 46, EndLine: 48}}}, + {ID: "9e88b42a-f829-5b0c-bbe9-9e923198166b", Name: "Serialization", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 50, EndLine: 51}}}, + {ID: "fa267f1f-6049-4f14-aa54-33bafae1ed76", Name: "TOML", Version: "1.0.0", Locations: []ftypes.Location{{StartLine: 53, EndLine: 56}}}, + {ID: "cf7118a7-6976-5b1a-9a39-7adc72f591a4", Name: "UUIDs", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 58, EndLine: 60}}}, + {ID: "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", Name: "Unicode", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 62, EndLine: 63}}}, } - juliaV18Deps = []ftypes.Dependency{ + juliaV1_8Deps = []ftypes.Dependency{ {ID: "ade2ca70-3891-5945-98fb-dc099432e06a", DependsOn: []string{"de0858da-6303-5e67-8744-51eddeeeb8d7"}}, {ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", DependsOn: []string{ "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", @@ -61,26 +61,26 @@ var ( {ID: "cf7118a7-6976-5b1a-9a39-7adc72f591a4", DependsOn: []string{"9a3f8284-a2c9-5f02-9a11-845980a1fd5c", "ea8e919c-243c-51af-8825-aaa63cd721ce"}}, } - juliaV19DepExtLibs = []ftypes.Library{ - {ID: "621f4979-c628-5d54-868e-fcf4e3e8185c", Name: "AbstractFFTs", Version: "1.3.1", Locations: []types.Location{{StartLine: 7, EndLine: 10}}}, + juliaV1_9DepExtPkgs = []ftypes.Package{ + {ID: "621f4979-c628-5d54-868e-fcf4e3e8185c", Name: "AbstractFFTs", Version: "1.3.1", Locations: []ftypes.Location{{StartLine: 7, EndLine: 10}}}, } - juliaV19ShadowedDepLibs = []ftypes.Library{ - {ID: "ead4f63c-334e-11e9-00e6-e7f0a5f21b60", Name: "A", Version: "1.9.0", Locations: []types.Location{{StartLine: 7, EndLine: 8}}}, - {ID: "f41f7b98-334e-11e9-1257-49272045fb24", Name: "B", Version: "1.9.0", Locations: []types.Location{{StartLine: 13, EndLine: 14}}}, - {ID: "edca9bc6-334e-11e9-3554-9595dbb4349c", Name: "B", Version: "1.9.0", Locations: []types.Location{{StartLine: 15, EndLine: 16}}}, + juliaV1_9ShadowedDepPkgs = []ftypes.Package{ + {ID: "ead4f63c-334e-11e9-00e6-e7f0a5f21b60", Name: "A", Version: "1.9.0", Locations: []ftypes.Location{{StartLine: 7, EndLine: 8}}}, + {ID: "f41f7b98-334e-11e9-1257-49272045fb24", Name: "B", Version: "1.9.0", Locations: []ftypes.Location{{StartLine: 13, EndLine: 14}}}, + {ID: "edca9bc6-334e-11e9-3554-9595dbb4349c", Name: "B", Version: "1.9.0", Locations: []ftypes.Location{{StartLine: 15, EndLine: 16}}}, } - juliaV19ShadowedDepDeps = []ftypes.Dependency{ + juliaV1_9ShadowedDepDeps = []ftypes.Dependency{ {ID: "ead4f63c-334e-11e9-00e6-e7f0a5f21b60", DependsOn: []string{"f41f7b98-334e-11e9-1257-49272045fb24"}}, } - juliaV10FormatLibs = []ftypes.Library{ - {ID: "767738be-2f1f-45a9-b806-0234f3164144", Name: "Foo", Version: "unknown", Locations: []types.Location{{StartLine: 1, EndLine: 5}}}, - {ID: "6f418443-bd2e-4783-b551-cdbac608adf2", Name: "Foo", Version: "unknown", Locations: []types.Location{{StartLine: 7, EndLine: 10}}}, - {ID: "2a550a13-6bab-4a91-a4ee-dff34d6b99d0", Name: "Bar", Version: "unknown", Locations: []types.Location{{StartLine: 12, EndLine: 14}}}, - {ID: "6801f525-dc68-44e8-a4e8-cabd286279e7", Name: "Baz", Version: "unknown", Locations: []types.Location{{StartLine: 19, EndLine: 21}}}, - {ID: "b5ec9b9c-e354-47fd-b367-a348bdc8f909", Name: "Qux", Version: "unknown", Locations: []types.Location{{StartLine: 26, EndLine: 28}}}, + juliaV10FormatPkgs = []ftypes.Package{ + {ID: "767738be-2f1f-45a9-b806-0234f3164144", Name: "Foo", Version: "unknown", Locations: []ftypes.Location{{StartLine: 1, EndLine: 5}}}, + {ID: "6f418443-bd2e-4783-b551-cdbac608adf2", Name: "Foo", Version: "unknown", Locations: []ftypes.Location{{StartLine: 7, EndLine: 10}}}, + {ID: "2a550a13-6bab-4a91-a4ee-dff34d6b99d0", Name: "Bar", Version: "unknown", Locations: []ftypes.Location{{StartLine: 12, EndLine: 14}}}, + {ID: "6801f525-dc68-44e8-a4e8-cabd286279e7", Name: "Baz", Version: "unknown", Locations: []ftypes.Location{{StartLine: 19, EndLine: 21}}}, + {ID: "b5ec9b9c-e354-47fd-b367-a348bdc8f909", Name: "Qux", Version: "unknown", Locations: []ftypes.Location{{StartLine: 26, EndLine: 28}}}, } juliaV10FormatDeps = []ftypes.Dependency{ diff --git a/pkg/detector/library/driver.go b/pkg/detector/library/driver.go index 4151dfec08f8..f78932b13442 100644 --- a/pkg/detector/library/driver.go +++ b/pkg/detector/library/driver.go @@ -82,7 +82,7 @@ func NewDriver(libType ftypes.LangType) (Driver, bool) { ecosystem = vulnerability.Kubernetes comparer = compare.GenericComparer{} case ftypes.Julia: - log.Logger.Warn("Julia is supported for SBOM, not for vulnerability scanning") + log.Warn("Julia is supported for SBOM, not for vulnerability scanning") return Driver{}, false default: log.Warn("The library type is not supported for vulnerability scanning", diff --git a/pkg/fanal/analyzer/language/julia/pkg/pkg.go b/pkg/fanal/analyzer/language/julia/pkg/pkg.go index e688079b8d2e..c2b9fda035e3 100644 --- a/pkg/fanal/analyzer/language/julia/pkg/pkg.go +++ b/pkg/fanal/analyzer/language/julia/pkg/pkg.go @@ -16,7 +16,6 @@ import ( "golang.org/x/xerrors" julia "github.com/aquasecurity/trivy/pkg/dependency/parser/julia/manifest" - godeptypes "github.com/aquasecurity/trivy/pkg/dependency/types" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language" "github.com/aquasecurity/trivy/pkg/fanal/types" @@ -36,7 +35,8 @@ var requiredFiles = []string{ } type juliaAnalyzer struct { - lockParser godeptypes.Parser + lockParser language.Parser + logger *log.Logger } type Project struct { @@ -47,6 +47,7 @@ type Project struct { func newJuliaAnalyzer(_ analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) { return &juliaAnalyzer{ lockParser: julia.NewParser(), + logger: log.WithPrefix("julia"), }, nil } @@ -67,11 +68,12 @@ func (a juliaAnalyzer) PostAnalyze(_ context.Context, input analyzer.PostAnalysi } // Parse Project.toml alongside Manifest.toml to identify the direct dependencies. This mutates `app`. - if err = analyzeDependencies(input.FS, filepath.Dir(path), app); err != nil { - log.Logger.Warnf("Unable to parse %q to analyze dependencies: %s", filepath.Join(filepath.Dir(path), types.JuliaProject), err) + if err = a.analyzeDependencies(input.FS, filepath.Dir(path), app); err != nil { + a.logger.Warn("Unable to parse file to analyze dependencies", + log.String("FILEPATH", filepath.Join(filepath.Dir(path), types.JuliaProject)), log.Err(err)) } - sort.Sort(app.Libraries) + sort.Sort(app.Packages) apps = append(apps, *app) return nil }) @@ -101,24 +103,24 @@ func (a juliaAnalyzer) parseJuliaManifest(path string, r io.Reader) (*types.Appl return language.Parse(types.Julia, path, r, a.lockParser) } -func analyzeDependencies(fsys fs.FS, dir string, app *types.Application) error { - deps, devDeps, err := getProjectDeps(fsys, dir) +func (a juliaAnalyzer) analyzeDependencies(fsys fs.FS, dir string, app *types.Application) error { + deps, devDeps, err := a.getProjectDeps(fsys, dir) if err != nil { return err } - pkgs := walkDependencies(deps, app.Libraries, false) - devPkgs := walkDependencies(devDeps, app.Libraries, true) - app.Libraries = append(pkgs, devPkgs...) + pkgs := walkDependencies(deps, app.Packages, false) + devPkgs := walkDependencies(devDeps, app.Packages, true) + app.Packages = append(pkgs, devPkgs...) return nil } // getProjectDeps parses project.toml and returns root and dev dependencies. -func getProjectDeps(fsys fs.FS, dir string) (map[string]string, map[string]string, error) { +func (a juliaAnalyzer) getProjectDeps(fsys fs.FS, dir string) (map[string]string, map[string]string, error) { projectPath := filepath.Join(dir, types.JuliaProject) project, err := parseJuliaProject(fsys, projectPath) if errors.Is(err, fs.ErrNotExist) { - log.Logger.Debugf("Julia: %s not found", projectPath) + a.logger.Debug("Julia project not found", log.String("PROJECT_PATH", projectPath)) return nil, nil, nil } else if err != nil { return nil, nil, xerrors.Errorf("unable to parse %s: %w", projectPath, err) diff --git a/pkg/fanal/analyzer/language/julia/pkg/pkg_test.go b/pkg/fanal/analyzer/language/julia/pkg/pkg_test.go index 350b10c883ce..8e96e0574d93 100644 --- a/pkg/fanal/analyzer/language/julia/pkg/pkg_test.go +++ b/pkg/fanal/analyzer/language/julia/pkg/pkg_test.go @@ -25,7 +25,7 @@ func Test_juliaAnalyzer_Analyze(t *testing.T) { { Type: types.Julia, FilePath: "Manifest.toml", - Libraries: []types.Package{ + Packages: types.Packages{ { ID: "ade2ca70-3891-5945-98fb-dc099432e06a", Name: "Dates", @@ -170,7 +170,7 @@ func Test_juliaAnalyzer_Analyze(t *testing.T) { { Type: types.Julia, FilePath: "Manifest.toml", - Libraries: []types.Package{ + Packages: types.Packages{ { ID: "621f4979-c628-5d54-868e-fcf4e3e8185c", Name: "AbstractFFTs", @@ -184,44 +184,6 @@ func Test_juliaAnalyzer_Analyze(t *testing.T) { }, }, }, - { - name: "shadowed_dep_v1.9", - dir: "testdata/shadowed_dep_v1.9", - want: &analyzer.AnalysisResult{ - Applications: []types.Application{ - { - Type: types.Julia, - FilePath: "Manifest.toml", - Libraries: []types.Package{ - { - ID: "ead4f63c-334e-11e9-00e6-e7f0a5f21b60", - Name: "A", - Version: "1.9.0", - Indirect: false, - Locations: []types.Location{{StartLine: 7, EndLine: 8}}, - DependsOn: []string{"f41f7b98-334e-11e9-1257-49272045fb24"}, - }, - { - ID: "edca9bc6-334e-11e9-3554-9595dbb4349c", - Name: "B", - Version: "1.9.0", - Indirect: false, - Locations: []types.Location{{StartLine: 15, EndLine: 16}}, - DependsOn: nil, - }, - { - ID: "f41f7b98-334e-11e9-1257-49272045fb24", - Name: "B", - Version: "1.9.0", - Indirect: true, - Locations: []types.Location{{StartLine: 13, EndLine: 14}}, - DependsOn: nil, - }, - }, - }, - }, - }, - }, { name: "no_manifest", dir: "testdata/no_manifest", diff --git a/pkg/purl/purl_test.go b/pkg/purl/purl_test.go index 18456d94c2ba..90af61d7b949 100644 --- a/pkg/purl/purl_test.go +++ b/pkg/purl/purl_test.go @@ -415,15 +415,13 @@ func TestNewPackageURL(t *testing.T) { Version: "1.9.0", }, want: &purl.PackageURL{ - PackageURL: packageurl.PackageURL{ - Type: packageurl.TypeJulia, - Name: "Dates", - Version: "1.9.0", - Qualifiers: packageurl.Qualifiers{ - { - Key: "uuid", - Value: "ade2ca70-3891-5945-98fb-dc099432e06a", - }, + Type: packageurl.TypeJulia, + Name: "Dates", + Version: "1.9.0", + Qualifiers: packageurl.Qualifiers{ + { + Key: "uuid", + Value: "ade2ca70-3891-5945-98fb-dc099432e06a", }, }, }, diff --git a/pkg/sbom/cyclonedx/marshal_test.go b/pkg/sbom/cyclonedx/marshal_test.go index 52781b865a8f..d3d104b28347 100644 --- a/pkg/sbom/cyclonedx/marshal_test.go +++ b/pkg/sbom/cyclonedx/marshal_test.go @@ -2,22 +2,20 @@ package cyclonedx_test import ( "context" - "testing" - "time" - "github.com/aquasecurity/trivy/pkg/fanal/artifact" - "github.com/package-url/packageurl-go" - "github.com/aquasecurity/trivy/pkg/sbom/core" + "github.com/package-url/packageurl-go" + "testing" + "time" cdx "github.com/CycloneDX/cyclonedx-go" - "github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/samber/lo" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" dtypes "github.com/aquasecurity/trivy-db/pkg/types" + "github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability" "github.com/aquasecurity/trivy/pkg/clock" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/report" diff --git a/pkg/sbom/spdx/marshal_test.go b/pkg/sbom/spdx/marshal_test.go index e6b4a9360c32..ee4c10949148 100644 --- a/pkg/sbom/spdx/marshal_test.go +++ b/pkg/sbom/spdx/marshal_test.go @@ -2,13 +2,12 @@ package spdx_test import ( "context" - "hash/fnv" - "testing" - "time" - "github.com/aquasecurity/trivy/pkg/fanal/artifact" "github.com/aquasecurity/trivy/pkg/sbom/core" "github.com/package-url/packageurl-go" + "hash/fnv" + "testing" + "time" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/mitchellh/hashstructure/v2" From fe064b6264c5c705542de9a7b19e4fba384ee5de Mon Sep 17 00:00:00 2001 From: Octogonapus Date: Tue, 14 May 2024 09:47:03 -0400 Subject: [PATCH 6/6] Remove cyclonedx test because it is not necessary now --- integration/repo_test.go | 9 -- .../testdata/julia-cyclonedx.json.golden | 130 ------------------ 2 files changed, 139 deletions(-) delete mode 100644 integration/testdata/julia-cyclonedx.json.golden diff --git a/integration/repo_test.go b/integration/repo_test.go index 2d8fb53e20ca..3bc94416710a 100644 --- a/integration/repo_test.go +++ b/integration/repo_test.go @@ -406,15 +406,6 @@ func TestRepository(t *testing.T) { }, golden: "testdata/julia-spdx.json.golden", }, - { - name: "julia generating CycloneDX SBOM", - args: args{ - command: "rootfs", - format: "cyclonedx", - input: "testdata/fixtures/repo/julia", - }, - golden: "testdata/julia-cyclonedx.json.golden", - }, } // Set up testing DB diff --git a/integration/testdata/julia-cyclonedx.json.golden b/integration/testdata/julia-cyclonedx.json.golden deleted file mode 100644 index f86ae2dfe472..000000000000 --- a/integration/testdata/julia-cyclonedx.json.golden +++ /dev/null @@ -1,130 +0,0 @@ -{ - "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", - "bomFormat": "CycloneDX", - "specVersion": "1.5", - "serialNumber": "urn:uuid:3ff14136-e09f-4df9-80ea-000000000006", - "version": 1, - "metadata": { - "timestamp": "2021-08-25T12:20:30+00:00", - "tools": { - "components": [ - { - "type": "application", - "group": "aquasecurity", - "name": "trivy", - "version": "dev" - } - ] - }, - "component": { - "bom-ref": "3ff14136-e09f-4df9-80ea-000000000001", - "type": "application", - "name": "testdata/fixtures/repo/julia", - "properties": [ - { - "name": "aquasecurity:trivy:SchemaVersion", - "value": "2" - } - ] - } - }, - "components": [ - { - "bom-ref": "3ff14136-e09f-4df9-80ea-000000000002", - "type": "application", - "name": "Manifest.toml", - "properties": [ - { - "name": "aquasecurity:trivy:Class", - "value": "lang-pkgs" - }, - { - "name": "aquasecurity:trivy:Type", - "value": "julia" - } - ] - }, - { - "bom-ref": "pkg:julia/A@1.9.0?uuid=ead4f63c-334e-11e9-00e6-e7f0a5f21b60", - "type": "library", - "name": "A", - "version": "1.9.0", - "purl": "pkg:julia/A@1.9.0?uuid=ead4f63c-334e-11e9-00e6-e7f0a5f21b60", - "properties": [ - { - "name": "aquasecurity:trivy:PkgID", - "value": "ead4f63c-334e-11e9-00e6-e7f0a5f21b60" - }, - { - "name": "aquasecurity:trivy:PkgType", - "value": "julia" - } - ] - }, - { - "bom-ref": "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c", - "type": "library", - "name": "B", - "version": "1.9.0", - "purl": "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c", - "properties": [ - { - "name": "aquasecurity:trivy:PkgID", - "value": "edca9bc6-334e-11e9-3554-9595dbb4349c" - }, - { - "name": "aquasecurity:trivy:PkgType", - "value": "julia" - } - ] - }, - { - "bom-ref": "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24", - "type": "library", - "name": "B", - "version": "1.9.0", - "purl": "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24", - "properties": [ - { - "name": "aquasecurity:trivy:PkgID", - "value": "f41f7b98-334e-11e9-1257-49272045fb24" - }, - { - "name": "aquasecurity:trivy:PkgType", - "value": "julia" - } - ] - } - ], - "dependencies": [ - { - "ref": "3ff14136-e09f-4df9-80ea-000000000001", - "dependsOn": [ - "3ff14136-e09f-4df9-80ea-000000000002" - ] - }, - { - "ref": "3ff14136-e09f-4df9-80ea-000000000002", - "dependsOn": [ - "pkg:julia/A@1.9.0?uuid=ead4f63c-334e-11e9-00e6-e7f0a5f21b60", - "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c", - "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24" - ] - }, - { - "ref": "pkg:julia/A@1.9.0?uuid=ead4f63c-334e-11e9-00e6-e7f0a5f21b60", - "dependsOn": [ - "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24" - ] - }, - { - "ref": "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c", - "dependsOn": [] - }, - { - "ref": "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24", - "dependsOn": [] - } - ], - "vulnerabilities": [] -}