From b0442e32f9735809caa0e289a52dc0f9e1114adc Mon Sep 17 00:00:00 2001 From: Xueqin Cui Date: Fri, 20 Sep 2024 15:56:40 +1000 Subject: [PATCH 1/9] feat: fetch Maven metadata from specified repositories --- cmd/osv-scanner/__snapshots__/main_test.snap | 36 +++++++ cmd/osv-scanner/fix/main.go | 9 +- cmd/osv-scanner/fix/noninteractive.go | 11 ++ .../fixtures/maven-transitive/parent.xml | 30 ++++++ .../fixtures/maven-transitive/registry.xml | 28 +++++ cmd/osv-scanner/main_test.go | 10 ++ cmd/osv-scanner/scan/main.go | 20 ++++ cmd/osv-scanner/update/main.go | 2 +- internal/manifest/maven.go | 16 ++- internal/manifest/maven_test.go | 18 ++-- internal/remediation/testhelpers_test.go | 2 +- internal/resolution/client/client.go | 2 + internal/resolution/client/depsdev_client.go | 2 + .../client/maven_registry_client.go | 27 +++-- .../resolution/client/npm_registry_client.go | 2 + .../clienttest/mock_resolution_client.go | 5 +- .../resolution/datasource/maven_registry.go | 102 +++++++++++++----- .../datasource/maven_registry_test.go | 102 ++++++++++++++++-- internal/resolution/manifest/manifest.go | 4 +- internal/resolution/manifest/maven.go | 20 ++-- internal/resolution/manifest/maven_test.go | 5 +- internal/utility/maven/maven.go | 6 +- pkg/osvscanner/osvscanner.go | 36 +++++-- .../generate_mock_resolution_universe/main.go | 2 +- 24 files changed, 416 insertions(+), 81 deletions(-) create mode 100644 cmd/osv-scanner/fixtures/maven-transitive/parent.xml create mode 100644 cmd/osv-scanner/fixtures/maven-transitive/registry.xml diff --git a/cmd/osv-scanner/__snapshots__/main_test.snap b/cmd/osv-scanner/__snapshots__/main_test.snap index 753a78f4260..6ab2642a307 100755 --- a/cmd/osv-scanner/__snapshots__/main_test.snap +++ b/cmd/osv-scanner/__snapshots__/main_test.snap @@ -2277,6 +2277,42 @@ No issues found --- +[TestRun_MavenTransitive/resolve_transitive_dependencies_with_native_datda_source - 1] +Scanned /fixtures/maven-transitive/registry.xml file as a pom.xml and found 13 packages ++-------------------------------------+------+-----------+-------------------------------------+---------+----------------------------------------+ +| OSV URL | CVSS | ECOSYSTEM | PACKAGE | VERSION | SOURCE | ++-------------------------------------+------+-----------+-------------------------------------+---------+----------------------------------------+ +| https://osv.dev/GHSA-735f-pc8j-v9w8 | 8.7 | Maven | com.google.protobuf:protobuf-java | 4.28.0 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-7rjr-3q55-vv33 | 9.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-8489-44mv-ggj8 | 6.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-jfh8-c2jp-5v3q | 10.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-p6xc-xr62-6r2g | 8.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | ++-------------------------------------+------+-----------+-------------------------------------+---------+----------------------------------------+ + +--- + +[TestRun_MavenTransitive/resolve_transitive_dependencies_with_native_datda_source - 2] + +--- + +[TestRun_MavenTransitive/scans_dependencies_from_multiple_registries - 1] +Scanned /fixtures/maven-transitive/registry.xml file as a pom.xml and found 13 packages ++-------------------------------------+------+-----------+-------------------------------------+---------+----------------------------------------+ +| OSV URL | CVSS | ECOSYSTEM | PACKAGE | VERSION | SOURCE | ++-------------------------------------+------+-----------+-------------------------------------+---------+----------------------------------------+ +| https://osv.dev/GHSA-735f-pc8j-v9w8 | 8.7 | Maven | com.google.protobuf:protobuf-java | 4.28.0 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-7rjr-3q55-vv33 | 9.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-8489-44mv-ggj8 | 6.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-jfh8-c2jp-5v3q | 10.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-p6xc-xr62-6r2g | 8.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | ++-------------------------------------+------+-----------+-------------------------------------+---------+----------------------------------------+ + +--- + +[TestRun_MavenTransitive/scans_dependencies_from_multiple_registries - 2] + +--- + [TestRun_MavenTransitive/scans_transitive_dependencies_by_specifying_pom.xml - 1] Scanned /fixtures/maven-transitive/abc.xml file as a pom.xml and found 3 packages +-------------------------------------+------+-----------+-------------------------------------+---------+-----------------------------------+ diff --git a/cmd/osv-scanner/fix/main.go b/cmd/osv-scanner/fix/main.go index ba451b02f23..31bfb0af7fa 100644 --- a/cmd/osv-scanner/fix/main.go +++ b/cmd/osv-scanner/fix/main.go @@ -13,7 +13,6 @@ import ( "github.com/google/osv-scanner/internal/remediation/upgrade" "github.com/google/osv-scanner/internal/resolution" "github.com/google/osv-scanner/internal/resolution/client" - "github.com/google/osv-scanner/internal/resolution/datasource" "github.com/google/osv-scanner/internal/resolution/lockfile" "github.com/google/osv-scanner/internal/resolution/manifest" "github.com/google/osv-scanner/pkg/depsdev" @@ -68,6 +67,10 @@ func Command(stdout, stderr io.Writer, r *reporter.Reporter) *cli.Command { return nil }, }, + &cli.StringFlag{ + Name: "maven-registry", + Usage: "URL of the default Maven registry to fetch metadata", + }, &cli.StringFlag{ Name: "relock-cmd", Usage: "command to run to regenerate lockfile on disk after changing the manifest", @@ -269,7 +272,7 @@ func action(ctx *cli.Context, stdout, stderr io.Writer) (reporter.Reporter, erro } if opts.Manifest != "" { - rw, err := manifest.GetManifestIO(opts.Manifest) + rw, err := manifest.GetManifestIO(opts.Manifest, ctx.String("maven-registry")) if err != nil { return nil, err } @@ -302,7 +305,7 @@ func action(ctx *cli.Context, stdout, stderr io.Writer) (reporter.Reporter, erro } opts.Client.DependencyClient = cl case resolve.Maven: - cl, err := client.NewMavenRegistryClient(datasource.MavenCentral) + cl, err := client.NewMavenRegistryClient(ctx.String("maven-registry")) if err != nil { return nil, err } diff --git a/cmd/osv-scanner/fix/noninteractive.go b/cmd/osv-scanner/fix/noninteractive.go index dcac2d17a12..fc2a14a983a 100644 --- a/cmd/osv-scanner/fix/noninteractive.go +++ b/cmd/osv-scanner/fix/noninteractive.go @@ -295,6 +295,17 @@ func autoOverride(ctx context.Context, r reporter.Reporter, opts osvFixOptions, return err } + if opts.ManifestRW.System() == resolve.Maven { + // Update Maven registries based on the pom.xml + specific, ok := manif.EcosystemSpecific.(manifest.MavenManifestSpecific) + if ok { + registries := make([]string, len(specific.Repositories)) + for i, repo := range specific.Repositories { + registries[i] = string(repo.URL) + } + opts.Client.DependencyClient.UpdateRegistries(registries) + } + } client.PreFetch(opts.Client, ctx, manif.Requirements, manif.FilePath) res, err := resolution.Resolve(ctx, opts.Client, manif, opts.ResolveOpts) if err != nil { diff --git a/cmd/osv-scanner/fixtures/maven-transitive/parent.xml b/cmd/osv-scanner/fixtures/maven-transitive/parent.xml new file mode 100644 index 00000000000..d31cbe88038 --- /dev/null +++ b/cmd/osv-scanner/fixtures/maven-transitive/parent.xml @@ -0,0 +1,30 @@ + + + + 4.0.0 + + com.mycompany.app + parent + 1.0.0 + + my-app + + pom + + + + com.google.protobuf + protobuf-java-util + 4.28.0 + + + + + + google-andriod + https://dl.google.com/dl/android/maven2 + + + + diff --git a/cmd/osv-scanner/fixtures/maven-transitive/registry.xml b/cmd/osv-scanner/fixtures/maven-transitive/registry.xml new file mode 100644 index 00000000000..5f3c3150b0a --- /dev/null +++ b/cmd/osv-scanner/fixtures/maven-transitive/registry.xml @@ -0,0 +1,28 @@ + + + + 4.0.0 + + com.mycompany.app + my-app + 1.0.0 + + my-app + + + com.mycompany.app + parent + 1.0.0 + ./parent.xml + + + + + org.apache.logging.log4j + log4j-web + 2.14.1 + + + + diff --git a/cmd/osv-scanner/main_test.go b/cmd/osv-scanner/main_test.go index f27e8c7051c..9db7226434c 100644 --- a/cmd/osv-scanner/main_test.go +++ b/cmd/osv-scanner/main_test.go @@ -870,6 +870,16 @@ func TestRun_MavenTransitive(t *testing.T) { args: []string{"", "--config=./fixtures/osv-scanner-empty-config.toml", "--experimental-offline", "--experimental-download-offline-databases", "./fixtures/maven-transitive/pom.xml"}, exit: 0, }, + { + name: "scans dependencies from multiple registries", + args: []string{"", "--config=./fixtures/osv-scanner-empty-config.toml", "-L", "pom.xml:./fixtures/maven-transitive/registry.xml"}, + exit: 1, + }, + { + name: "resolve transitive dependencies with native datda source", + args: []string{"", "--config=./fixtures/osv-scanner-empty-config.toml", "--experimental-resolution-data-source=native", "-L", "pom.xml:./fixtures/maven-transitive/registry.xml"}, + exit: 1, + }, } for _, tt := range tests { diff --git a/cmd/osv-scanner/scan/main.go b/cmd/osv-scanner/scan/main.go index b401ce4a830..b75166352c1 100644 --- a/cmd/osv-scanner/scan/main.go +++ b/cmd/osv-scanner/scan/main.go @@ -132,6 +132,22 @@ func Command(stdout, stderr io.Writer, r *reporter.Reporter) *cli.Command { TakesFile: true, Hidden: true, }, + &cli.StringFlag{ + Name: "experimental-resolution-data-source", + Usage: "source to fetch package information from; value can be: deps.dev, native", + Value: "deps.dev", + Action: func(ctx *cli.Context, s string) error { + if s != "deps.dev" && s != "native" { + return fmt.Errorf("unsupported data-source \"%s\" - must be one of: deps.dev, native", s) + } + + return nil + }, + }, + &cli.StringFlag{ + Name: "experimental-maven-registry", + Usage: "URL of the default registry to fetch Maven metadata", + }, }, ArgsUsage: "[directory1 directory2...]", Action: func(c *cli.Context) error { @@ -222,6 +238,10 @@ func action(context *cli.Context, stdout, stderr io.Writer) (reporter.Reporter, ScanLicensesSummary: context.Bool("experimental-licenses-summary"), ScanLicensesAllowlist: context.StringSlice("experimental-licenses"), ScanOCIImage: context.String("experimental-oci-image"), + TransitiveScanningActions: osvscanner.TransitiveScanningActions{ + NativeDataSource: context.String("experimental-resolution-data-source") == "native", + MavenRegistry: context.String("experimental-maven-registry"), + }, }, }, r) diff --git a/cmd/osv-scanner/update/main.go b/cmd/osv-scanner/update/main.go index f9fa7dadfdb..e43d6a27023 100644 --- a/cmd/osv-scanner/update/main.go +++ b/cmd/osv-scanner/update/main.go @@ -78,7 +78,7 @@ func action(ctx *cli.Context, stdout, stderr io.Writer) (reporter.Reporter, erro if err != nil { return nil, err } - options.ManifestRW, err = manifest.GetManifestIO(options.Manifest) + options.ManifestRW, err = manifest.GetManifestIO(options.Manifest, "") if err != nil { return nil, err } diff --git a/internal/manifest/maven.go b/internal/manifest/maven.go index faef0e4e4a6..55aac6b1118 100644 --- a/internal/manifest/maven.go +++ b/internal/manifest/maven.go @@ -32,11 +32,18 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD var project maven.Project if err := xml.NewDecoder(f).Decode(&project); err != nil { - return []lockfile.PackageDetails{}, fmt.Errorf("could not extract from %s: %w", f.Path(), err) + return nil, fmt.Errorf("could not extract from %s: %w", f.Path(), err) + } + // Empty JDK and ActivationOS indicates merging the default profiles. + if err := project.MergeProfiles("", maven.ActivationOS{}); err != nil { + return nil, fmt.Errorf("failed to merge profiles: %w", err) + } + for _, repo := range project.Repositories { + e.MavenRegistryAPIClient.Add(string(repo.URL)) } // Merging parents data by parsing local parent pom.xml or fetching from upstream. if err := mavenutil.MergeParents(ctx, e.MavenRegistryAPIClient, &project, project.Parent, 1, f.Path(), true); err != nil { - return []lockfile.PackageDetails{}, fmt.Errorf("failed to merge parents: %w", err) + return nil, fmt.Errorf("failed to merge parents: %w", err) } // Process the dependencies: // - dedupe dependencies and dependency management @@ -52,6 +59,7 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD return result.DependencyManagement, nil }) + e.DependencyClient.UpdateRegistries(e.MavenRegistryAPIClient.GetRegistries()) overrideClient := client.NewOverrideClient(e.DependencyClient) resolver := mavenresolve.NewResolver(overrideClient) @@ -96,7 +104,7 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD g, err := resolver.Resolve(ctx, root.VersionKey) if err != nil { - return []lockfile.PackageDetails{}, fmt.Errorf("failed resolving %v: %w", root, err) + return nil, fmt.Errorf("failed resolving %v: %w", root, err) } for i, e := range g.Edges { e.Type = dep.Type{} @@ -128,7 +136,7 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD func ParseMavenWithResolver(depClient client.DependencyClient, mavenClient *datasource.MavenRegistryAPIClient, pathToLockfile string) ([]lockfile.PackageDetails, error) { f, err := lockfile.OpenLocalDepFile(pathToLockfile) if err != nil { - return []lockfile.PackageDetails{}, err + return nil, err } defer f.Close() diff --git a/internal/manifest/maven_test.go b/internal/manifest/maven_test.go index 882affb7019..6144159a74d 100644 --- a/internal/manifest/maven_test.go +++ b/internal/manifest/maven_test.go @@ -92,7 +92,8 @@ func TestParseMavenWithResolver_InvalidSyntax(t *testing.T) { func TestParseMavenWithResolver_NoPackages(t *testing.T) { t.Parallel() - packages, err := manifest.ParseMavenWithResolver(nil, nil, "fixtures/maven/empty.xml") + resolutionClient := clienttest.NewMockResolutionClient(t, "fixtures/universe/basic-universe.yaml") + packages, err := manifest.ParseMavenWithResolver(resolutionClient, &datasource.MavenRegistryAPIClient{}, "fixtures/maven/empty.xml") if err != nil { t.Errorf("Got unexpected error: %v", err) } @@ -104,7 +105,7 @@ func TestParseMavenWithResolver_OnePackage(t *testing.T) { t.Parallel() resolutionClient := clienttest.NewMockResolutionClient(t, "fixtures/universe/basic-universe.yaml") - packages, err := manifest.ParseMavenWithResolver(resolutionClient, nil, "fixtures/maven/one-package.xml") + packages, err := manifest.ParseMavenWithResolver(resolutionClient, &datasource.MavenRegistryAPIClient{}, "fixtures/maven/one-package.xml") if err != nil { t.Errorf("Got unexpected error: %v", err) } @@ -123,7 +124,7 @@ func TestParseMavenWithResolver_TwoPackages(t *testing.T) { t.Parallel() resolutionClient := clienttest.NewMockResolutionClient(t, "fixtures/universe/basic-universe.yaml") - packages, err := manifest.ParseMavenWithResolver(resolutionClient, nil, "fixtures/maven/two-packages.xml") + packages, err := manifest.ParseMavenWithResolver(resolutionClient, &datasource.MavenRegistryAPIClient{}, "fixtures/maven/two-packages.xml") if err != nil { t.Errorf("Got unexpected error: %v", err) } @@ -148,7 +149,7 @@ func TestParseMavenWithResolver_WithDependencyManagement(t *testing.T) { t.Parallel() resolutionClient := clienttest.NewMockResolutionClient(t, "fixtures/universe/basic-universe.yaml") - packages, err := manifest.ParseMavenWithResolver(resolutionClient, nil, "fixtures/maven/with-dependency-management.xml") + packages, err := manifest.ParseMavenWithResolver(resolutionClient, &datasource.MavenRegistryAPIClient{}, "fixtures/maven/with-dependency-management.xml") if err != nil { t.Errorf("Got unexpected error: %v", err) } @@ -173,7 +174,7 @@ func TestParseMavenWithResolver_Interpolation(t *testing.T) { t.Parallel() resolutionClient := clienttest.NewMockResolutionClient(t, "fixtures/universe/basic-universe.yaml") - packages, err := manifest.ParseMavenWithResolver(resolutionClient, nil, "fixtures/maven/interpolation.xml") + packages, err := manifest.ParseMavenWithResolver(resolutionClient, &datasource.MavenRegistryAPIClient{}, "fixtures/maven/interpolation.xml") if err != nil { t.Errorf("Got unexpected error: %v", err) } @@ -204,7 +205,7 @@ func TestParseMavenWithResolver_WithScope(t *testing.T) { t.Parallel() resolutionClient := clienttest.NewMockResolutionClient(t, "fixtures/universe/basic-universe.yaml") - packages, err := manifest.ParseMavenWithResolver(resolutionClient, nil, "fixtures/maven/with-scope.xml") + packages, err := manifest.ParseMavenWithResolver(resolutionClient, &datasource.MavenRegistryAPIClient{}, "fixtures/maven/with-scope.xml") if err != nil { t.Errorf("Got unexpected error: %v", err) } @@ -258,7 +259,8 @@ func TestParseMavenWithResolver_WithParent(t *testing.T) { `)) resolutionClient := clienttest.NewMockResolutionClient(t, "fixtures/universe/basic-universe.yaml") - packages, err := manifest.ParseMavenWithResolver(resolutionClient, datasource.NewMavenRegistryAPIClient(srv.URL), "fixtures/maven/with-parent.xml") + client, _ := datasource.NewMavenRegistryAPIClient(srv.URL) + packages, err := manifest.ParseMavenWithResolver(resolutionClient, client, "fixtures/maven/with-parent.xml") if err != nil { t.Errorf("Got unexpected error: %v", err) } @@ -307,7 +309,7 @@ func TestParseMavenWithResolver_Transitive(t *testing.T) { t.Parallel() resolutionClient := clienttest.NewMockResolutionClient(t, "fixtures/universe/basic-universe.yaml") - packages, err := manifest.ParseMavenWithResolver(resolutionClient, nil, "fixtures/maven/transitive.xml") + packages, err := manifest.ParseMavenWithResolver(resolutionClient, &datasource.MavenRegistryAPIClient{}, "fixtures/maven/transitive.xml") if err != nil { t.Errorf("Got unexpected error: %v", err) } diff --git a/internal/remediation/testhelpers_test.go b/internal/remediation/testhelpers_test.go index 61761fcbc6c..45c377a1571 100644 --- a/internal/remediation/testhelpers_test.go +++ b/internal/remediation/testhelpers_test.go @@ -19,7 +19,7 @@ import ( func parseRemediationFixture(t *testing.T, universePath, manifestPath string, opts resolution.ResolveOpts) (*resolution.ResolutionResult, client.ResolutionClient) { t.Helper() - io, err := manifest.GetManifestIO(manifestPath) + io, err := manifest.GetManifestIO(manifestPath, "") if err != nil { t.Fatalf("Failed to get ManifestIO: %v", err) } diff --git a/internal/resolution/client/client.go b/internal/resolution/client/client.go index 95e29480133..57ffc279c24 100644 --- a/internal/resolution/client/client.go +++ b/internal/resolution/client/client.go @@ -30,6 +30,8 @@ type DependencyClient interface { WriteCache(filepath string) error // LoadCache loads a manifest-specific resolution cache. LoadCache(filepath string) error + // UpdateRegistries updates the registries to fetch data. + UpdateRegistries(registries []string) } // PreFetch loads cache, then makes and caches likely queries needed for resolving a package with a list of requirements diff --git a/internal/resolution/client/depsdev_client.go b/internal/resolution/client/depsdev_client.go index dce6580232d..c6730168be3 100644 --- a/internal/resolution/client/depsdev_client.go +++ b/internal/resolution/client/depsdev_client.go @@ -25,6 +25,8 @@ func NewDepsDevClient(addr string) (*DepsDevClient, error) { return &DepsDevClient{APIClient: *resolve.NewAPIClient(c), c: c}, nil } +func (d *DepsDevClient) UpdateRegistries(registries []string) {} + func (d *DepsDevClient) WriteCache(path string) error { f, err := os.Create(path + depsDevCacheExt) if err != nil { diff --git a/internal/resolution/client/maven_registry_client.go b/internal/resolution/client/maven_registry_client.go index e79e190b3de..3814c431225 100644 --- a/internal/resolution/client/maven_registry_client.go +++ b/internal/resolution/client/maven_registry_client.go @@ -5,13 +5,11 @@ import ( "encoding/gob" "fmt" "os" - "slices" "strings" "deps.dev/util/maven" "deps.dev/util/resolve" "deps.dev/util/resolve/version" - "deps.dev/util/semver" "github.com/google/osv-scanner/internal/resolution/datasource" mavenutil "github.com/google/osv-scanner/internal/utility/maven" ) @@ -23,9 +21,12 @@ type MavenRegistryClient struct { } func NewMavenRegistryClient(registry string) (*MavenRegistryClient, error) { - return &MavenRegistryClient{ - api: datasource.NewMavenRegistryAPIClient(registry), - }, nil + client, err := datasource.NewMavenRegistryAPIClient(registry) + if err != nil { + return nil, err + } + + return &MavenRegistryClient{api: client}, nil } func (c *MavenRegistryClient) Version(ctx context.Context, vk resolve.VersionKey) (resolve.Version, error) { @@ -69,13 +70,13 @@ func (c *MavenRegistryClient) Versions(ctx context.Context, pk resolve.PackageKe if !found { return nil, fmt.Errorf("invalid Maven package name %s", pk.Name) } - metadata, err := c.api.GetArtifactMetadata(ctx, g, a) + versions, err := c.api.GetVersions(ctx, g, a) if err != nil { return nil, err } - vks := make([]resolve.Version, len(metadata.Versioning.Versions)) - for i, v := range metadata.Versioning.Versions { + vks := make([]resolve.Version, len(versions)) + for i, v := range versions { vks[i] = resolve.Version{ VersionKey: resolve.VersionKey{ PackageKey: pk, @@ -83,7 +84,6 @@ func (c *MavenRegistryClient) Versions(ctx context.Context, pk resolve.PackageKe VersionType: resolve.Concrete, }} } - slices.SortFunc(vks, func(a, b resolve.Version) int { return semver.Maven.Compare(a.Version, b.Version) }) return vks, nil } @@ -106,6 +106,9 @@ func (c *MavenRegistryClient) Requirements(ctx context.Context, vk resolve.Versi if err := proj.MergeProfiles("", maven.ActivationOS{}); err != nil { return nil, err } + for _, repo := range proj.Repositories { + c.api.Add(string(repo.URL)) + } // We need to merge parents for potential dependencies in parents. if err := mavenutil.MergeParents(ctx, c.api, &proj, proj.Parent, 1, "", false); err != nil { return nil, err @@ -151,6 +154,12 @@ func (c *MavenRegistryClient) MatchingVersions(ctx context.Context, vk resolve.V return resolve.MatchRequirement(vk, versions), nil } +func (c *MavenRegistryClient) UpdateRegistries(registries []string) { + for _, reg := range registries { + c.api.Add(reg) + } +} + func (c *MavenRegistryClient) WriteCache(path string) error { f, err := os.Create(path + mavenRegistryCacheExt) if err != nil { diff --git a/internal/resolution/client/npm_registry_client.go b/internal/resolution/client/npm_registry_client.go index 99867f6f643..fef22e0ecd7 100644 --- a/internal/resolution/client/npm_registry_client.go +++ b/internal/resolution/client/npm_registry_client.go @@ -229,6 +229,8 @@ func isNpmBundle(pk resolve.PackageKey) bool { return strings.Contains(pk.Name, ">") } +func (c *NpmRegistryClient) UpdateRegistries(registries []string) {} + func (c *NpmRegistryClient) WriteCache(path string) error { f, err := os.Create(path + npmRegistryCacheExt) if err != nil { diff --git a/internal/resolution/clienttest/mock_resolution_client.go b/internal/resolution/clienttest/mock_resolution_client.go index d20ea26957e..825af3e3c07 100644 --- a/internal/resolution/clienttest/mock_resolution_client.go +++ b/internal/resolution/clienttest/mock_resolution_client.go @@ -42,8 +42,9 @@ type mockDependencyClient struct { *resolve.LocalClient } -func (mdc mockDependencyClient) LoadCache(string) error { return nil } -func (mdc mockDependencyClient) WriteCache(string) error { return nil } +func (mdc mockDependencyClient) LoadCache(string) error { return nil } +func (mdc mockDependencyClient) WriteCache(string) error { return nil } +func (mdc mockDependencyClient) UpdateRegistries(registries []string) {} func NewMockResolutionClient(t *testing.T, universeYAML string) client.ResolutionClient { t.Helper() diff --git a/internal/resolution/datasource/maven_registry.go b/internal/resolution/datasource/maven_registry.go index 5dd6630e9b1..01bfb56c3e1 100644 --- a/internal/resolution/datasource/maven_registry.go +++ b/internal/resolution/datasource/maven_registry.go @@ -7,18 +7,24 @@ import ( "fmt" "net/http" "net/url" + "slices" "strings" "sync" "time" "deps.dev/util/maven" + "deps.dev/util/semver" "golang.org/x/net/html/charset" ) const MavenCentral = "https://repo.maven.apache.org/maven2" +var errAPIFailed = errors.New("API query failed") + type MavenRegistryAPIClient struct { - registry string // Base URL of the registry that we are making requests + defaultRegistry string // Base URL of the default registry that we are making requests + // TODO: disable fetching snapshot if specified in pom.xml + registries []string // URLs of the registries to fetch projects // Cache fields mu sync.Mutex @@ -27,50 +33,98 @@ type MavenRegistryAPIClient struct { metadata *RequestCache[string, maven.Metadata] } -func NewMavenRegistryAPIClient(registry string) *MavenRegistryAPIClient { +func NewMavenRegistryAPIClient(registry string) (*MavenRegistryAPIClient, error) { + if registry == "" { + registry = MavenCentral + } else if _, err := url.Parse(registry); err != nil { + return nil, fmt.Errorf("invalid Maven registry %s: %w", registry, err) + } + return &MavenRegistryAPIClient{ - registry: registry, - projects: NewRequestCache[string, maven.Project](), - metadata: NewRequestCache[string, maven.Metadata](), + defaultRegistry: registry, + projects: NewRequestCache[string, maven.Project](), + metadata: NewRequestCache[string, maven.Metadata](), + }, nil +} + +// Add adds the given registry to the list of registries if it has not been added. +func (m *MavenRegistryAPIClient) Add(registry string) { + if !slices.Contains(m.registries, registry) { + if _, err := url.Parse(registry); err == nil { + m.registries = append(m.registries, registry) + } } } -var errAPIFailed = errors.New("API query failed") +func (m *MavenRegistryAPIClient) GetRegistries() []string { + return m.registries +} // GetProject fetches a pom.xml specified by groupID, artifactID and version and parses it to maven.Project. +// Each registry in the list is tried until we find the project. // For a snapshot version, version level metadata is used to find the extact version string. // More about Maven Repository Metadata Model: https://maven.apache.org/ref/3.9.9/maven-repository-metadata/ // More about Maven Metadata: https://maven.apache.org/repositories/metadata.html func (m *MavenRegistryAPIClient) GetProject(ctx context.Context, groupID, artifactID, version string) (maven.Project, error) { if !strings.HasSuffix(version, "-SNAPSHOT") { - return m.getProject(ctx, groupID, artifactID, version, "") + for _, registry := range append(m.registries, m.defaultRegistry) { + project, err := m.getProject(ctx, registry, groupID, artifactID, version, "") + if err == nil { + return project, nil + } + } + + return maven.Project{}, fmt.Errorf("failed to fetch Maven project %s:%s@%s", groupID, artifactID, version) } - // Fetch version metadata for snapshot versions. - metadata, err := m.getVersionMetadata(ctx, groupID, artifactID, version) - if err != nil { - return maven.Project{}, err + for _, registry := range append(m.registries, m.defaultRegistry) { + // Fetch version metadata for snapshot versions. + metadata, err := m.getVersionMetadata(ctx, registry, groupID, artifactID, version) + if err != nil { + continue + } + + snapshot := "" + for _, sv := range metadata.Versioning.SnapshotVersions { + if sv.Extension == "pom" { + // We only look for pom.xml for project metadata. + snapshot = string(sv.Value) + break + } + } + + project, err := m.getProject(ctx, registry, groupID, artifactID, version, snapshot) + if err == nil { + return project, nil + } } - snapshot := "" - for _, sv := range metadata.Versioning.SnapshotVersions { - if sv.Extension == "pom" { - // We only look for pom.xml for project metadata. - snapshot = string(sv.Value) - break + return maven.Project{}, fmt.Errorf("failed to fetch Maven project %s:%s@%s", groupID, artifactID, version) +} + +// GetVersions returns the list of available versions of a Maven package specified by groupID and artifactID. +// Versions found in all registries are unioned, then sorted by semver. +func (m *MavenRegistryAPIClient) GetVersions(ctx context.Context, groupID, artifactID string) ([]maven.String, error) { + var versions []maven.String + for _, registry := range append(m.registries, m.defaultRegistry) { + metadata, err := m.getArtifactMetadata(ctx, registry, groupID, artifactID) + if err != nil { + continue } + versions = append(versions, metadata.Versioning.Versions...) } + slices.SortFunc(versions, func(a, b maven.String) int { return semver.Maven.Compare(string(a), string(b)) }) - return m.getProject(ctx, groupID, artifactID, version, snapshot) + return slices.Compact(versions), nil } // getProject fetches a pom.xml specified by groupID, artifactID and version and parses it to maven.Project. // For snapshot versions, the exact version value is specified by snapshot. -func (m *MavenRegistryAPIClient) getProject(ctx context.Context, groupID, artifactID, version, snapshot string) (maven.Project, error) { +func (m *MavenRegistryAPIClient) getProject(ctx context.Context, registry, groupID, artifactID, version, snapshot string) (maven.Project, error) { if snapshot == "" { snapshot = version } - u, err := url.JoinPath(m.registry, strings.ReplaceAll(groupID, ".", "/"), artifactID, version, fmt.Sprintf("%s-%s.pom", artifactID, snapshot)) + u, err := url.JoinPath(registry, strings.ReplaceAll(groupID, ".", "/"), artifactID, version, fmt.Sprintf("%s-%s.pom", artifactID, snapshot)) if err != nil { return maven.Project{}, fmt.Errorf("failed to join path: %w", err) } @@ -86,8 +140,8 @@ func (m *MavenRegistryAPIClient) getProject(ctx context.Context, groupID, artifa } // getVersionMetadata fetches a version level maven-metadata.xml and parses it to maven.Metadata. -func (m *MavenRegistryAPIClient) getVersionMetadata(ctx context.Context, groupID, artifactID, version string) (maven.Metadata, error) { - u, err := url.JoinPath(m.registry, strings.ReplaceAll(groupID, ".", "/"), artifactID, version, "maven-metadata.xml") +func (m *MavenRegistryAPIClient) getVersionMetadata(ctx context.Context, registry, groupID, artifactID, version string) (maven.Metadata, error) { + u, err := url.JoinPath(registry, strings.ReplaceAll(groupID, ".", "/"), artifactID, version, "maven-metadata.xml") if err != nil { return maven.Metadata{}, fmt.Errorf("failed to join path: %w", err) } @@ -103,8 +157,8 @@ func (m *MavenRegistryAPIClient) getVersionMetadata(ctx context.Context, groupID } // GetArtifactMetadata fetches an artifact level maven-metadata.xml and parses it to maven.Metadata. -func (m *MavenRegistryAPIClient) GetArtifactMetadata(ctx context.Context, groupID, artifactID string) (maven.Metadata, error) { - u, err := url.JoinPath(m.registry, strings.ReplaceAll(groupID, ".", "/"), artifactID, "maven-metadata.xml") +func (m *MavenRegistryAPIClient) getArtifactMetadata(ctx context.Context, registry, groupID, artifactID string) (maven.Metadata, error) { + u, err := url.JoinPath(registry, strings.ReplaceAll(groupID, ".", "/"), artifactID, "maven-metadata.xml") if err != nil { return maven.Metadata{}, fmt.Errorf("failed to join path: %w", err) } diff --git a/internal/resolution/datasource/maven_registry_test.go b/internal/resolution/datasource/maven_registry_test.go index ba651943371..d526ca57f39 100644 --- a/internal/resolution/datasource/maven_registry_test.go +++ b/internal/resolution/datasource/maven_registry_test.go @@ -13,7 +13,7 @@ func TestGetProject(t *testing.T) { t.Parallel() srv := testutility.NewMockHTTPServer(t) - client := NewMavenRegistryAPIClient(srv.URL) + client, _ := NewMavenRegistryAPIClient(srv.URL) srv.SetResponse(t, "org/example/x.y.z/1.0.0/x.y.z-1.0.0.pom", []byte(` org.example @@ -42,7 +42,7 @@ func TestGetProjectSnapshot(t *testing.T) { t.Parallel() srv := testutility.NewMockHTTPServer(t) - client := NewMavenRegistryAPIClient(srv.URL) + client, _ := NewMavenRegistryAPIClient(srv.URL) srv.SetResponse(t, "org/example/x.y.z/3.3.1-SNAPSHOT/maven-metadata.xml", []byte(` org.example @@ -96,7 +96,7 @@ func TestGetArtifactMetadata(t *testing.T) { t.Parallel() srv := testutility.NewMockHTTPServer(t) - client := NewMavenRegistryAPIClient(srv.URL) + client, _ := NewMavenRegistryAPIClient(srv.URL) srv.SetResponse(t, "org/example/x.y.z/maven-metadata.xml", []byte(` org.example @@ -113,7 +113,7 @@ func TestGetArtifactMetadata(t *testing.T) { `)) - got, err := client.GetArtifactMetadata(context.Background(), "org.example", "x.y.z") + got, err := client.getArtifactMetadata(context.Background(), srv.URL, "org.example", "x.y.z") if err != nil { t.Fatalf("failed to get artifact metadata for %s:%s: %v", "org.example", "x.y.z", err) } @@ -139,7 +139,7 @@ func TestGetVersionMetadata(t *testing.T) { t.Parallel() srv := testutility.NewMockHTTPServer(t) - client := NewMavenRegistryAPIClient(srv.URL) + client, _ := NewMavenRegistryAPIClient(srv.URL) srv.SetResponse(t, "org/example/x.y.z/3.3.1-SNAPSHOT/maven-metadata.xml", []byte(` org.example @@ -166,7 +166,7 @@ func TestGetVersionMetadata(t *testing.T) { `)) - got, err := client.getVersionMetadata(context.Background(), "org.example", "x.y.z", "3.3.1-SNAPSHOT") + got, err := client.getVersionMetadata(context.Background(), srv.URL, "org.example", "x.y.z", "3.3.1-SNAPSHOT") if err != nil { t.Fatalf("failed to get metadata for %s:%s verion %s: %v", "org.example", "x.y.z", "3.3.1-SNAPSHOT", err) } @@ -197,3 +197,93 @@ func TestGetVersionMetadata(t *testing.T) { t.Errorf("getVersionMetadata(%s, %s):\ngot %v\nwant %v\n", "org.example", "x.y.z", got, want) } } + +func TestMultipleRegistry(t *testing.T) { + t.Parallel() + + dft := testutility.NewMockHTTPServer(t) + client, _ := NewMavenRegistryAPIClient(dft.URL) + dft.SetResponse(t, "org/example/x.y.z/maven-metadata.xml", []byte(` + + org.example + x.y.z + + 3.0.0 + 3.0.0 + + 2.0.0 + 3.0.0 + + + + `)) + dft.SetResponse(t, "org/example/x.y.z/2.0.0/x.y.z-2.0.0.pom", []byte(` + + org.example + x.y.z + 2.0.0 + + `)) + dft.SetResponse(t, "org/example/x.y.z/3.0.0/x.y.z-3.0.0.pom", []byte(` + + org.example + x.y.z + 3.0.0 + + `)) + + srv := testutility.NewMockHTTPServer(t) + client.Add(srv.URL) + srv.SetResponse(t, "org/example/x.y.z/maven-metadata.xml", []byte(` + + org.example + x.y.z + + 2.0.0 + 2.0.0 + + 1.0.0 + 2.0.0 + + + + `)) + srv.SetResponse(t, "org/example/x.y.z/1.0.0/x.y.z-1.0.0.pom", []byte(` + + org.example + x.y.z + 1.0.0 + + `)) + srv.SetResponse(t, "org/example/x.y.z/2.0.0/x.y.z-2.0.0.pom", []byte(` + + org.example + x.y.z + 2.0.0 + + `)) + + gotProj, err := client.GetProject(context.Background(), "org.example", "x.y.z", "1.0.0") + if err != nil { + t.Fatalf("failed to get Maven project %s:%s verion %s: %v", "org.example", "x.y.z", "1.0.0", err) + } + wantProj := maven.Project{ + ProjectKey: maven.ProjectKey{ + GroupID: "org.example", + ArtifactID: "x.y.z", + Version: "1.0.0", + }, + } + if !reflect.DeepEqual(gotProj, wantProj) { + t.Errorf("GetProject(%s, %s, %s):\ngot %v\nwant %v\n", "org.example", "x.y.z", "1.0.0", gotProj, wantProj) + } + + gotVersions, err := client.GetVersions(context.Background(), "org.example", "x.y.z") + if err != nil { + t.Fatalf("failed to get versions for Maven package %s:%s: %v", "org.example", "x.y.z", err) + } + wantVersions := []maven.String{"1.0.0", "2.0.0", "3.0.0"} + if !reflect.DeepEqual(gotVersions, wantVersions) { + t.Errorf("GetVersions(%s, %s):\ngot %v\nwant %v\n", "org.example", "x.y.z", gotVersions, wantVersions) + } +} diff --git a/internal/resolution/manifest/manifest.go b/internal/resolution/manifest/manifest.go index 8da6315c99c..634cb4af8e1 100644 --- a/internal/resolution/manifest/manifest.go +++ b/internal/resolution/manifest/manifest.go @@ -92,11 +92,11 @@ func Overwrite(rw ManifestIO, filename string, p ManifestPatch) error { return nil } -func GetManifestIO(pathToManifest string) (ManifestIO, error) { +func GetManifestIO(pathToManifest, mavenRegistry string) (ManifestIO, error) { base := filepath.Base(pathToManifest) switch { case base == "pom.xml": - return NewMavenManifestIO(), nil + return NewMavenManifestIO(mavenRegistry) case base == "package.json": return NpmManifestIO{}, nil default: diff --git a/internal/resolution/manifest/maven.go b/internal/resolution/manifest/maven.go index 12b79cddbe0..38120765ef5 100644 --- a/internal/resolution/manifest/maven.go +++ b/internal/resolution/manifest/maven.go @@ -36,15 +36,18 @@ func mavenRequirementKey(requirement resolve.RequirementVersion) RequirementKey } type MavenManifestIO struct { - *datasource.MavenRegistryAPIClient + client *datasource.MavenRegistryAPIClient } func (MavenManifestIO) System() resolve.System { return resolve.Maven } -func NewMavenManifestIO() MavenManifestIO { - return MavenManifestIO{ - MavenRegistryAPIClient: datasource.NewMavenRegistryAPIClient(datasource.MavenCentral), +func NewMavenManifestIO(registry string) (MavenManifestIO, error) { + client, err := datasource.NewMavenRegistryAPIClient(registry) + if err != nil { + return MavenManifestIO{}, err } + + return MavenManifestIO{client: client}, nil } type MavenManifestSpecific struct { @@ -52,6 +55,7 @@ type MavenManifestSpecific struct { Properties []PropertyWithOrigin // Properties from the base project OriginalRequirements []DependencyWithOrigin // Dependencies from the base project RequirementsForUpdates []resolve.RequirementVersion // Requirements that we only need for updates + Repositories []maven.Repository } type PropertyWithOrigin struct { @@ -94,9 +98,12 @@ func (m MavenManifestIO) Read(df lockfile.DepFile) (Manifest, error) { if err := project.MergeProfiles("", maven.ActivationOS{}); err != nil { return Manifest{}, fmt.Errorf("failed to merge profiles: %w", err) } + for _, repo := range project.Repositories { + m.client.Add(string(repo.URL)) + } // Merging parents data by parsing local parent pom.xml or fetching from upstream. - if err := mavenutil.MergeParents(ctx, m.MavenRegistryAPIClient, &project, project.Parent, 1, df.Path(), true); err != nil { + if err := mavenutil.MergeParents(ctx, m.client, &project, project.Parent, 1, df.Path(), true); err != nil { return Manifest{}, fmt.Errorf("failed to merge parents: %w", err) } @@ -119,7 +126,7 @@ func (m MavenManifestIO) Read(df lockfile.DepFile) (Manifest, error) { // To get dependency management from another project, we need the // project with parents merged, so we call mergeParents by passing // an empty project. - if err := mavenutil.MergeParents(ctx, m.MavenRegistryAPIClient, &result, root, 0, "", false); err != nil { + if err := mavenutil.MergeParents(ctx, m.client, &result, root, 0, "", false); err != nil { return maven.DependencyManagement{}, err } @@ -158,6 +165,7 @@ func (m MavenManifestIO) Read(df lockfile.DepFile) (Manifest, error) { Properties: properties, OriginalRequirements: origRequirements, RequirementsForUpdates: reqsForUpdates, + Repositories: project.Repositories, }, }, nil } diff --git a/internal/resolution/manifest/maven_test.go b/internal/resolution/manifest/maven_test.go index f3a0d675c01..d1a8d83464e 100644 --- a/internal/resolution/manifest/maven_test.go +++ b/internal/resolution/manifest/maven_test.go @@ -109,9 +109,8 @@ func TestMavenReadWrite(t *testing.T) { } defer df.Close() - mavenIO := MavenManifestIO{ - MavenRegistryAPIClient: datasource.NewMavenRegistryAPIClient(srv.URL), - } + client, _ := datasource.NewMavenRegistryAPIClient(srv.URL) + mavenIO := MavenManifestIO{client: client} got, err := mavenIO.Read(df) if err != nil { diff --git a/internal/utility/maven/maven.go b/internal/utility/maven/maven.go index 16f85bd95d2..6230b43d054 100644 --- a/internal/utility/maven/maven.go +++ b/internal/utility/maven/maven.go @@ -68,8 +68,7 @@ func MergeParents(ctx context.Context, mavenClient *datasource.MavenRegistryAPIC allowLocal = false var err error - proj, err = mavenClient.GetProject(ctx, string(current.GroupID), string(current.ArtifactID), string(current.Version)) - if err != nil { + if proj, err = mavenClient.GetProject(ctx, string(current.GroupID), string(current.ArtifactID), string(current.Version)); err != nil { return fmt.Errorf("failed to get Maven project %s:%s:%s: %w", current.GroupID, current.ArtifactID, current.Version, err) } if n > 0 && proj.Packaging != "pom" { @@ -85,6 +84,9 @@ func MergeParents(ctx context.Context, mavenClient *datasource.MavenRegistryAPIC if err := result.MergeProfiles("", maven.ActivationOS{}); err != nil { return err } + for _, repo := range proj.Repositories { + mavenClient.Add(string(repo.URL)) + } result.MergeParent(proj) current = proj.Parent } diff --git a/pkg/osvscanner/osvscanner.go b/pkg/osvscanner/osvscanner.go index 4e91492f939..b4c413ff547 100644 --- a/pkg/osvscanner/osvscanner.go +++ b/pkg/osvscanner/osvscanner.go @@ -59,6 +59,12 @@ type ExperimentalScannerActions struct { ScanOCIImage string LocalDBPath string + TransitiveScanningActions +} + +type TransitiveScanningActions struct { + NativeDataSource bool + MavenRegistry string } // NoPackagesFoundErr for when no packages are found during a scan. @@ -107,7 +113,7 @@ const ( // - Any lockfiles with scanLockfile // - Any SBOM files with scanSBOMFile // - Any git repositories with scanGit -func scanDir(r reporter.Reporter, dir string, skipGit bool, recursive bool, useGitIgnore bool, compareOffline bool) ([]scannedPackage, error) { +func scanDir(r reporter.Reporter, dir string, skipGit bool, recursive bool, useGitIgnore bool, compareOffline bool, transitiveAct TransitiveScanningActions) ([]scannedPackage, error) { var ignoreMatcher *gitIgnoreMatcher if useGitIgnore { var err error @@ -164,7 +170,7 @@ func scanDir(r reporter.Reporter, dir string, skipGit bool, recursive bool, useG if !info.IsDir() { if extractor, _ := lockfile.FindExtractor(path, ""); extractor != nil { - pkgs, err := scanLockfile(r, path, "", compareOffline) + pkgs, err := scanLockfile(r, path, "", compareOffline, transitiveAct) if err != nil { r.Errorf("Attempted to scan lockfile but failed: %s\n", path) } @@ -346,7 +352,7 @@ func scanImage(r reporter.Reporter, path string) ([]scannedPackage, error) { // scanLockfile will load, identify, and parse the lockfile path passed in, and add the dependencies specified // within to `query` -func scanLockfile(r reporter.Reporter, path string, parseAs string, compareOffline bool) ([]scannedPackage, error) { +func scanLockfile(r reporter.Reporter, path string, parseAs string, compareOffline bool, transitiveAct TransitiveScanningActions) ([]scannedPackage, error) { var err error var parsedLockfile lockfile.Lockfile @@ -365,7 +371,7 @@ func scanLockfile(r reporter.Reporter, path string, parseAs string, compareOffli parsedLockfile, err = lockfile.FromOSVScannerResults(path) default: if !compareOffline && (parseAs == "pom.xml" || filepath.Base(path) == "pom.xml") { - parsedLockfile, err = extractMavenDeps(f) + parsedLockfile, err = extractMavenDeps(f, transitiveAct) } else { parsedLockfile, err = lockfile.ExtractDeps(f, parseAs) } @@ -408,14 +414,26 @@ func scanLockfile(r reporter.Reporter, path string, parseAs string, compareOffli return packages, nil } -func extractMavenDeps(f lockfile.DepFile) (lockfile.Lockfile, error) { - depClient, err := client.NewDepsDevClient(depsdev.DepsdevAPI) +func extractMavenDeps(f lockfile.DepFile, actions TransitiveScanningActions) (lockfile.Lockfile, error) { + var depClient client.DependencyClient + var err error + if actions.NativeDataSource { + depClient, err = client.NewMavenRegistryClient(actions.MavenRegistry) + } else { + depClient, err = client.NewDepsDevClient(depsdev.DepsdevAPI) + } if err != nil { return lockfile.Lockfile{}, err } + + mavenClient, err := datasource.NewMavenRegistryAPIClient(actions.MavenRegistry) + if err != nil { + return lockfile.Lockfile{}, err + } + extractor := manifest.MavenResolverExtractor{ DependencyClient: depClient, - MavenRegistryAPIClient: datasource.NewMavenRegistryAPIClient(datasource.MavenCentral), + MavenRegistryAPIClient: mavenClient, } packages, err := extractor.Extract(f) if err != nil { @@ -845,7 +863,7 @@ func DoScan(actions ScannerActions, r reporter.Reporter) (models.VulnerabilityRe r.Errorf("Failed to resolved path with error %s\n", err) return models.VulnerabilityResults{}, err } - pkgs, err := scanLockfile(r, lockfilePath, parseAs, actions.CompareOffline) + pkgs, err := scanLockfile(r, lockfilePath, parseAs, actions.CompareOffline, actions.TransitiveScanningActions) if err != nil { return models.VulnerabilityResults{}, err } @@ -870,7 +888,7 @@ func DoScan(actions ScannerActions, r reporter.Reporter) (models.VulnerabilityRe for _, dir := range actions.DirectoryPaths { r.Infof("Scanning dir %s\n", dir) - pkgs, err := scanDir(r, dir, actions.SkipGit, actions.Recursive, !actions.NoIgnore, actions.CompareOffline) + pkgs, err := scanDir(r, dir, actions.SkipGit, actions.Recursive, !actions.NoIgnore, actions.CompareOffline, actions.TransitiveScanningActions) if err != nil { return models.VulnerabilityResults{}, err } diff --git a/scripts/generate_mock_resolution_universe/main.go b/scripts/generate_mock_resolution_universe/main.go index cb035a60c14..11b73fe2b6f 100644 --- a/scripts/generate_mock_resolution_universe/main.go +++ b/scripts/generate_mock_resolution_universe/main.go @@ -290,7 +290,7 @@ func main() { group := &errgroup.Group{} for _, filename := range os.Args[1:] { - if io, err := manifest.GetManifestIO(filename); err == nil { + if io, err := manifest.GetManifestIO(filename, ""); err == nil { if remediation.SupportsRelax(io) { group.Go(func() error { err := doRelockRelax(cl, io, filename) From 3ec9e0dbb7fd40047cead62ef48eb033652b7b09 Mon Sep 17 00:00:00 2001 From: Xueqin Cui Date: Mon, 30 Sep 2024 13:00:12 +1000 Subject: [PATCH 2/9] lint --- cmd/osv-scanner/scan/main.go | 2 +- internal/resolution/client/depsdev_client.go | 2 +- .../resolution/client/npm_registry_client.go | 2 +- .../clienttest/mock_resolution_client.go | 6 +++--- internal/resolution/manifest/manifest.go | 4 ++-- internal/resolution/manifest/maven.go | 17 +++++++++-------- internal/resolution/manifest/maven_test.go | 3 +-- .../generate_mock_resolution_universe/main.go | 2 +- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/cmd/osv-scanner/scan/main.go b/cmd/osv-scanner/scan/main.go index 77897b91b37..97e74d600f9 100644 --- a/cmd/osv-scanner/scan/main.go +++ b/cmd/osv-scanner/scan/main.go @@ -136,7 +136,7 @@ func Command(stdout, stderr io.Writer, r *reporter.Reporter) *cli.Command { Name: "experimental-resolution-data-source", Usage: "source to fetch package information from; value can be: deps.dev, native", Value: "deps.dev", - Action: func(ctx *cli.Context, s string) error { + Action: func(_ *cli.Context, s string) error { if s != "deps.dev" && s != "native" { return fmt.Errorf("unsupported data-source \"%s\" - must be one of: deps.dev, native", s) } diff --git a/internal/resolution/client/depsdev_client.go b/internal/resolution/client/depsdev_client.go index c6730168be3..ef490140d2e 100644 --- a/internal/resolution/client/depsdev_client.go +++ b/internal/resolution/client/depsdev_client.go @@ -25,7 +25,7 @@ func NewDepsDevClient(addr string) (*DepsDevClient, error) { return &DepsDevClient{APIClient: *resolve.NewAPIClient(c), c: c}, nil } -func (d *DepsDevClient) UpdateRegistries(registries []string) {} +func (d *DepsDevClient) UpdateRegistries(_ []string) {} func (d *DepsDevClient) WriteCache(path string) error { f, err := os.Create(path + depsDevCacheExt) diff --git a/internal/resolution/client/npm_registry_client.go b/internal/resolution/client/npm_registry_client.go index fef22e0ecd7..70455b126cb 100644 --- a/internal/resolution/client/npm_registry_client.go +++ b/internal/resolution/client/npm_registry_client.go @@ -229,7 +229,7 @@ func isNpmBundle(pk resolve.PackageKey) bool { return strings.Contains(pk.Name, ">") } -func (c *NpmRegistryClient) UpdateRegistries(registries []string) {} +func (c *NpmRegistryClient) UpdateRegistries(_ []string) {} func (c *NpmRegistryClient) WriteCache(path string) error { f, err := os.Create(path + npmRegistryCacheExt) diff --git a/internal/resolution/clienttest/mock_resolution_client.go b/internal/resolution/clienttest/mock_resolution_client.go index 825af3e3c07..76f60b6dbdb 100644 --- a/internal/resolution/clienttest/mock_resolution_client.go +++ b/internal/resolution/clienttest/mock_resolution_client.go @@ -42,9 +42,9 @@ type mockDependencyClient struct { *resolve.LocalClient } -func (mdc mockDependencyClient) LoadCache(string) error { return nil } -func (mdc mockDependencyClient) WriteCache(string) error { return nil } -func (mdc mockDependencyClient) UpdateRegistries(registries []string) {} +func (mdc mockDependencyClient) LoadCache(string) error { return nil } +func (mdc mockDependencyClient) WriteCache(string) error { return nil } +func (mdc mockDependencyClient) UpdateRegistries(_ []string) {} func NewMockResolutionClient(t *testing.T, universeYAML string) client.ResolutionClient { t.Helper() diff --git a/internal/resolution/manifest/manifest.go b/internal/resolution/manifest/manifest.go index d9741662033..4df28c141b4 100644 --- a/internal/resolution/manifest/manifest.go +++ b/internal/resolution/manifest/manifest.go @@ -92,11 +92,11 @@ func Overwrite(rw ReadWriter, filename string, p Patch) error { return nil } -func GetReadWriter(pathToManifest string, mavenRegistry string) (ReadWriter, error) { +func GetReadWriter(pathToManifest string, registry string) (ReadWriter, error) { base := filepath.Base(pathToManifest) switch { case base == "pom.xml": - return NewMavenReadWriter(mavenRegistry), nil + return NewMavenReadWriter(registry) case base == "package.json": return NpmReadWriter{}, nil default: diff --git a/internal/resolution/manifest/maven.go b/internal/resolution/manifest/maven.go index a191f271345..cc1790ecf8a 100644 --- a/internal/resolution/manifest/maven.go +++ b/internal/resolution/manifest/maven.go @@ -36,17 +36,18 @@ func mavenRequirementKey(requirement resolve.RequirementVersion) RequirementKey } type MavenReadWriter struct { - client *datasource.MavenRegistryAPIClient + *datasource.MavenRegistryAPIClient } func (MavenReadWriter) System() resolve.System { return resolve.Maven } -func NewMavenReadWriter(registry string) MavenReadWriter { - return MavenReadWriter{ - MavenRegistryAPIClient: datasource.NewMavenRegistryAPIClient(datasource.MavenCentral), +func NewMavenReadWriter(registry string) (MavenReadWriter, error) { + client, err := datasource.NewMavenRegistryAPIClient(registry) + if err != nil { + return MavenReadWriter{}, err } - return MavenManifestIO{client: client}, nil + return MavenReadWriter{MavenRegistryAPIClient: client}, nil } type MavenManifestSpecific struct { @@ -98,11 +99,11 @@ func (m MavenReadWriter) Read(df lockfile.DepFile) (Manifest, error) { return Manifest{}, fmt.Errorf("failed to merge profiles: %w", err) } for _, repo := range project.Repositories { - m.client.Add(string(repo.URL)) + m.MavenRegistryAPIClient.Add(string(repo.URL)) } // Merging parents data by parsing local parent pom.xml or fetching from upstream. - if err := mavenutil.MergeParents(ctx, m.client, &project, project.Parent, 1, df.Path(), true); err != nil { + if err := mavenutil.MergeParents(ctx, m.MavenRegistryAPIClient, &project, project.Parent, 1, df.Path(), true); err != nil { return Manifest{}, fmt.Errorf("failed to merge parents: %w", err) } @@ -125,7 +126,7 @@ func (m MavenReadWriter) Read(df lockfile.DepFile) (Manifest, error) { // To get dependency management from another project, we need the // project with parents merged, so we call mergeParents by passing // an empty project. - if err := mavenutil.MergeParents(ctx, m.client, &result, root, 0, "", false); err != nil { + if err := mavenutil.MergeParents(ctx, m.MavenRegistryAPIClient, &result, root, 0, "", false); err != nil { return maven.DependencyManagement{}, err } diff --git a/internal/resolution/manifest/maven_test.go b/internal/resolution/manifest/maven_test.go index 8bcee5b7980..d2f6c6f06bf 100644 --- a/internal/resolution/manifest/maven_test.go +++ b/internal/resolution/manifest/maven_test.go @@ -109,9 +109,8 @@ func TestMavenReadWrite(t *testing.T) { } defer df.Close() - client, _ := datasource.NewMavenRegistryAPIClient(srv.URL) - mavenRW := MavenReadWriter{client: client} + mavenRW := MavenReadWriter{MavenRegistryAPIClient: client} got, err := mavenRW.Read(df) if err != nil { diff --git a/scripts/generate_mock_resolution_universe/main.go b/scripts/generate_mock_resolution_universe/main.go index 18146777458..ee472ebbbb4 100644 --- a/scripts/generate_mock_resolution_universe/main.go +++ b/scripts/generate_mock_resolution_universe/main.go @@ -290,7 +290,7 @@ func main() { group := &errgroup.Group{} for _, filename := range os.Args[1:] { - if io, err := manifest.GetReadWriter(filename, ""); err == nil { + if io, err := manifest.GetReadWriter(filename, ""); err == nil { if remediation.SupportsRelax(io) { group.Go(func() error { err := doRelockRelax(cl, io, filename) From db6ca1c7d863bc52d80088d36fd91011b187f28c Mon Sep 17 00:00:00 2001 From: Xueqin Cui Date: Tue, 1 Oct 2024 17:23:40 +1000 Subject: [PATCH 3/9] make registry a struct --- cmd/osv-scanner/fix/noninteractive.go | 8 +++++--- internal/manifest/maven.go | 14 ++++++++++++-- internal/resolution/client/client.go | 6 +++++- internal/resolution/client/depsdev_client.go | 2 +- .../resolution/client/maven_registry_client.go | 12 +++++++++--- internal/resolution/client/npm_registry_client.go | 2 +- .../clienttest/mock_resolution_client.go | 6 +++--- internal/resolution/datasource/maven_registry.go | 9 ++++++--- .../resolution/datasource/maven_registry_test.go | 4 +++- internal/resolution/manifest/maven.go | 4 +++- internal/utility/maven/maven.go | 6 ++++-- 11 files changed, 52 insertions(+), 21 deletions(-) diff --git a/cmd/osv-scanner/fix/noninteractive.go b/cmd/osv-scanner/fix/noninteractive.go index ce36c590664..da6ac62a1ff 100644 --- a/cmd/osv-scanner/fix/noninteractive.go +++ b/cmd/osv-scanner/fix/noninteractive.go @@ -299,11 +299,13 @@ func autoOverride(ctx context.Context, r reporter.Reporter, opts osvFixOptions, // Update Maven registries based on the pom.xml specific, ok := manif.EcosystemSpecific.(manifest.MavenManifestSpecific) if ok { - registries := make([]string, len(specific.Repositories)) + registries := make([]client.Registry, len(specific.Repositories)) for i, repo := range specific.Repositories { - registries[i] = string(repo.URL) + registries[i] = client.Registry{URL: string(repo.URL)} + } + if err := opts.Client.DependencyClient.UpdateRegistries(registries); err != nil { + return err } - opts.Client.DependencyClient.UpdateRegistries(registries) } } client.PreFetch(ctx, opts.Client, manif.Requirements, manif.FilePath) diff --git a/internal/manifest/maven.go b/internal/manifest/maven.go index 55aac6b1118..039ddd36a2a 100644 --- a/internal/manifest/maven.go +++ b/internal/manifest/maven.go @@ -39,7 +39,9 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD return nil, fmt.Errorf("failed to merge profiles: %w", err) } for _, repo := range project.Repositories { - e.MavenRegistryAPIClient.Add(string(repo.URL)) + if err := e.MavenRegistryAPIClient.AddRegistry(string(repo.URL)); err != nil { + return nil, fmt.Errorf("failed to add registry %s: %w", repo.URL, err) + } } // Merging parents data by parsing local parent pom.xml or fetching from upstream. if err := mavenutil.MergeParents(ctx, e.MavenRegistryAPIClient, &project, project.Parent, 1, f.Path(), true); err != nil { @@ -59,7 +61,15 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD return result.DependencyManagement, nil }) - e.DependencyClient.UpdateRegistries(e.MavenRegistryAPIClient.GetRegistries()) + if registries := e.MavenRegistryAPIClient.GetRegistries(); len(registries) > 0 { + cleintRegs := make([]client.Registry, len(registries)) + for i, reg := range registries { + cleintRegs[i] = client.Registry{URL: reg} + } + if err := e.DependencyClient.UpdateRegistries(cleintRegs); err != nil { + return nil, err + } + } overrideClient := client.NewOverrideClient(e.DependencyClient) resolver := mavenresolve.NewResolver(overrideClient) diff --git a/internal/resolution/client/client.go b/internal/resolution/client/client.go index f1bc77fa7b4..91e48b6c1a2 100644 --- a/internal/resolution/client/client.go +++ b/internal/resolution/client/client.go @@ -31,7 +31,11 @@ type DependencyClient interface { // LoadCache loads a manifest-specific resolution cache. LoadCache(filepath string) error // UpdateRegistries updates the registries to fetch data. - UpdateRegistries(registries []string) + UpdateRegistries(registries []Registry) error +} + +type Registry struct { + URL string } // PreFetch loads cache, then makes and caches likely queries needed for resolving a package with a list of requirements diff --git a/internal/resolution/client/depsdev_client.go b/internal/resolution/client/depsdev_client.go index ef490140d2e..ceb49025140 100644 --- a/internal/resolution/client/depsdev_client.go +++ b/internal/resolution/client/depsdev_client.go @@ -25,7 +25,7 @@ func NewDepsDevClient(addr string) (*DepsDevClient, error) { return &DepsDevClient{APIClient: *resolve.NewAPIClient(c), c: c}, nil } -func (d *DepsDevClient) UpdateRegistries(_ []string) {} +func (d *DepsDevClient) UpdateRegistries(_ []Registry) error { return nil } func (d *DepsDevClient) WriteCache(path string) error { f, err := os.Create(path + depsDevCacheExt) diff --git a/internal/resolution/client/maven_registry_client.go b/internal/resolution/client/maven_registry_client.go index 3814c431225..d5966d8075a 100644 --- a/internal/resolution/client/maven_registry_client.go +++ b/internal/resolution/client/maven_registry_client.go @@ -107,7 +107,9 @@ func (c *MavenRegistryClient) Requirements(ctx context.Context, vk resolve.Versi return nil, err } for _, repo := range proj.Repositories { - c.api.Add(string(repo.URL)) + if err := c.api.AddRegistry(string(repo.URL)); err != nil { + return nil, err + } } // We need to merge parents for potential dependencies in parents. if err := mavenutil.MergeParents(ctx, c.api, &proj, proj.Parent, 1, "", false); err != nil { @@ -154,10 +156,14 @@ func (c *MavenRegistryClient) MatchingVersions(ctx context.Context, vk resolve.V return resolve.MatchRequirement(vk, versions), nil } -func (c *MavenRegistryClient) UpdateRegistries(registries []string) { +func (c *MavenRegistryClient) UpdateRegistries(registries []Registry) error { for _, reg := range registries { - c.api.Add(reg) + if err := c.api.AddRegistry(reg.URL); err != nil { + return err + } } + + return nil } func (c *MavenRegistryClient) WriteCache(path string) error { diff --git a/internal/resolution/client/npm_registry_client.go b/internal/resolution/client/npm_registry_client.go index 70455b126cb..c64a075d3bf 100644 --- a/internal/resolution/client/npm_registry_client.go +++ b/internal/resolution/client/npm_registry_client.go @@ -229,7 +229,7 @@ func isNpmBundle(pk resolve.PackageKey) bool { return strings.Contains(pk.Name, ">") } -func (c *NpmRegistryClient) UpdateRegistries(_ []string) {} +func (c *NpmRegistryClient) UpdateRegistries(_ []Registry) error { return nil } func (c *NpmRegistryClient) WriteCache(path string) error { f, err := os.Create(path + npmRegistryCacheExt) diff --git a/internal/resolution/clienttest/mock_resolution_client.go b/internal/resolution/clienttest/mock_resolution_client.go index 76f60b6dbdb..af02ada63f4 100644 --- a/internal/resolution/clienttest/mock_resolution_client.go +++ b/internal/resolution/clienttest/mock_resolution_client.go @@ -42,9 +42,9 @@ type mockDependencyClient struct { *resolve.LocalClient } -func (mdc mockDependencyClient) LoadCache(string) error { return nil } -func (mdc mockDependencyClient) WriteCache(string) error { return nil } -func (mdc mockDependencyClient) UpdateRegistries(_ []string) {} +func (mdc mockDependencyClient) LoadCache(string) error { return nil } +func (mdc mockDependencyClient) WriteCache(string) error { return nil } +func (mdc mockDependencyClient) UpdateRegistries(_ []client.Registry) error { return nil } func NewMockResolutionClient(t *testing.T, universeYAML string) client.ResolutionClient { t.Helper() diff --git a/internal/resolution/datasource/maven_registry.go b/internal/resolution/datasource/maven_registry.go index 01bfb56c3e1..579bb0eb6e5 100644 --- a/internal/resolution/datasource/maven_registry.go +++ b/internal/resolution/datasource/maven_registry.go @@ -48,12 +48,15 @@ func NewMavenRegistryAPIClient(registry string) (*MavenRegistryAPIClient, error) } // Add adds the given registry to the list of registries if it has not been added. -func (m *MavenRegistryAPIClient) Add(registry string) { +func (m *MavenRegistryAPIClient) AddRegistry(registry string) error { if !slices.Contains(m.registries, registry) { - if _, err := url.Parse(registry); err == nil { - m.registries = append(m.registries, registry) + if _, err := url.Parse(registry); err != nil { + return err } + m.registries = append(m.registries, registry) } + + return nil } func (m *MavenRegistryAPIClient) GetRegistries() []string { diff --git a/internal/resolution/datasource/maven_registry_test.go b/internal/resolution/datasource/maven_registry_test.go index d526ca57f39..12ab60a91af 100644 --- a/internal/resolution/datasource/maven_registry_test.go +++ b/internal/resolution/datasource/maven_registry_test.go @@ -233,7 +233,9 @@ func TestMultipleRegistry(t *testing.T) { `)) srv := testutility.NewMockHTTPServer(t) - client.Add(srv.URL) + if err := client.AddRegistry(srv.URL); err != nil { + t.Fatalf("failed to add registry %s: %v", srv.URL, err) + } srv.SetResponse(t, "org/example/x.y.z/maven-metadata.xml", []byte(` org.example diff --git a/internal/resolution/manifest/maven.go b/internal/resolution/manifest/maven.go index cc1790ecf8a..a35a8d17f33 100644 --- a/internal/resolution/manifest/maven.go +++ b/internal/resolution/manifest/maven.go @@ -99,7 +99,9 @@ func (m MavenReadWriter) Read(df lockfile.DepFile) (Manifest, error) { return Manifest{}, fmt.Errorf("failed to merge profiles: %w", err) } for _, repo := range project.Repositories { - m.MavenRegistryAPIClient.Add(string(repo.URL)) + if err := m.MavenRegistryAPIClient.AddRegistry(string(repo.URL)); err != nil { + return Manifest{}, fmt.Errorf("failed to add registry %s: %w", repo.URL, err) + } } // Merging parents data by parsing local parent pom.xml or fetching from upstream. diff --git a/internal/utility/maven/maven.go b/internal/utility/maven/maven.go index 6230b43d054..51cd3dbc182 100644 --- a/internal/utility/maven/maven.go +++ b/internal/utility/maven/maven.go @@ -82,10 +82,12 @@ func MergeParents(ctx context.Context, mavenClient *datasource.MavenRegistryAPIC } // Empty JDK and ActivationOS indicates merging the default profiles. if err := result.MergeProfiles("", maven.ActivationOS{}); err != nil { - return err + return fmt.Errorf("failed to merge profiles: %w", err) } for _, repo := range proj.Repositories { - mavenClient.Add(string(repo.URL)) + if err := mavenClient.AddRegistry(string(repo.URL)); err != nil { + return fmt.Errorf("failed to add registry %s: %w", repo.URL, err) + } } result.MergeParent(proj) current = proj.Parent From 0d5058d02a2fc1971b206941424437dfb87e9f97 Mon Sep 17 00:00:00 2001 From: Xueqin Cui Date: Fri, 4 Oct 2024 11:51:55 +1000 Subject: [PATCH 4/9] do not add repositories from dependencies --- internal/resolution/client/maven_registry_client.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/internal/resolution/client/maven_registry_client.go b/internal/resolution/client/maven_registry_client.go index d5966d8075a..696c2f5f125 100644 --- a/internal/resolution/client/maven_registry_client.go +++ b/internal/resolution/client/maven_registry_client.go @@ -106,11 +106,6 @@ func (c *MavenRegistryClient) Requirements(ctx context.Context, vk resolve.Versi if err := proj.MergeProfiles("", maven.ActivationOS{}); err != nil { return nil, err } - for _, repo := range proj.Repositories { - if err := c.api.AddRegistry(string(repo.URL)); err != nil { - return nil, err - } - } // We need to merge parents for potential dependencies in parents. if err := mavenutil.MergeParents(ctx, c.api, &proj, proj.Parent, 1, "", false); err != nil { return nil, err From 5a89b47ead04ed9f3bbbf02d3494cffda3d6cb15 Mon Sep 17 00:00:00 2001 From: Xueqin Cui Date: Thu, 10 Oct 2024 10:47:27 +1100 Subject: [PATCH 5/9] clients --- cmd/osv-scanner/fix/noninteractive.go | 2 +- cmd/osv-scanner/fixtures/maven-transitive/parent.xml | 2 +- internal/manifest/maven.go | 6 +++--- internal/resolution/client/client.go | 4 ++-- internal/resolution/client/depsdev_client.go | 2 +- internal/resolution/client/maven_registry_client.go | 2 +- internal/resolution/client/npm_registry_client.go | 2 +- .../resolution/clienttest/mock_resolution_client.go | 6 +++--- internal/resolution/datasource/maven_registry.go | 12 +++++++----- 9 files changed, 20 insertions(+), 18 deletions(-) diff --git a/cmd/osv-scanner/fix/noninteractive.go b/cmd/osv-scanner/fix/noninteractive.go index da6ac62a1ff..95170f28cfb 100644 --- a/cmd/osv-scanner/fix/noninteractive.go +++ b/cmd/osv-scanner/fix/noninteractive.go @@ -303,7 +303,7 @@ func autoOverride(ctx context.Context, r reporter.Reporter, opts osvFixOptions, for i, repo := range specific.Repositories { registries[i] = client.Registry{URL: string(repo.URL)} } - if err := opts.Client.DependencyClient.UpdateRegistries(registries); err != nil { + if err := opts.Client.DependencyClient.AddRegistries(registries); err != nil { return err } } diff --git a/cmd/osv-scanner/fixtures/maven-transitive/parent.xml b/cmd/osv-scanner/fixtures/maven-transitive/parent.xml index d31cbe88038..f287727fc3b 100644 --- a/cmd/osv-scanner/fixtures/maven-transitive/parent.xml +++ b/cmd/osv-scanner/fixtures/maven-transitive/parent.xml @@ -22,7 +22,7 @@ - google-andriod + google-android https://dl.google.com/dl/android/maven2 diff --git a/internal/manifest/maven.go b/internal/manifest/maven.go index 039ddd36a2a..7d77ba2ffd2 100644 --- a/internal/manifest/maven.go +++ b/internal/manifest/maven.go @@ -62,11 +62,11 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD }) if registries := e.MavenRegistryAPIClient.GetRegistries(); len(registries) > 0 { - cleintRegs := make([]client.Registry, len(registries)) + clientRegs := make([]client.Registry, len(registries)) for i, reg := range registries { - cleintRegs[i] = client.Registry{URL: reg} + clientRegs[i] = client.Registry{URL: reg} } - if err := e.DependencyClient.UpdateRegistries(cleintRegs); err != nil { + if err := e.DependencyClient.AddRegistries(clientRegs); err != nil { return nil, err } } diff --git a/internal/resolution/client/client.go b/internal/resolution/client/client.go index 91e48b6c1a2..b35e3778704 100644 --- a/internal/resolution/client/client.go +++ b/internal/resolution/client/client.go @@ -30,8 +30,8 @@ type DependencyClient interface { WriteCache(filepath string) error // LoadCache loads a manifest-specific resolution cache. LoadCache(filepath string) error - // UpdateRegistries updates the registries to fetch data. - UpdateRegistries(registries []Registry) error + // AddRegistries adds the specified registries to fetch data. + AddRegistries(registries []Registry) error } type Registry struct { diff --git a/internal/resolution/client/depsdev_client.go b/internal/resolution/client/depsdev_client.go index ceb49025140..ffd0d912573 100644 --- a/internal/resolution/client/depsdev_client.go +++ b/internal/resolution/client/depsdev_client.go @@ -25,7 +25,7 @@ func NewDepsDevClient(addr string) (*DepsDevClient, error) { return &DepsDevClient{APIClient: *resolve.NewAPIClient(c), c: c}, nil } -func (d *DepsDevClient) UpdateRegistries(_ []Registry) error { return nil } +func (d *DepsDevClient) AddRegistries(_ []Registry) error { return nil } func (d *DepsDevClient) WriteCache(path string) error { f, err := os.Create(path + depsDevCacheExt) diff --git a/internal/resolution/client/maven_registry_client.go b/internal/resolution/client/maven_registry_client.go index 696c2f5f125..95e0223f02c 100644 --- a/internal/resolution/client/maven_registry_client.go +++ b/internal/resolution/client/maven_registry_client.go @@ -151,7 +151,7 @@ func (c *MavenRegistryClient) MatchingVersions(ctx context.Context, vk resolve.V return resolve.MatchRequirement(vk, versions), nil } -func (c *MavenRegistryClient) UpdateRegistries(registries []Registry) error { +func (c *MavenRegistryClient) AddRegistries(registries []Registry) error { for _, reg := range registries { if err := c.api.AddRegistry(reg.URL); err != nil { return err diff --git a/internal/resolution/client/npm_registry_client.go b/internal/resolution/client/npm_registry_client.go index c64a075d3bf..e12a01b2328 100644 --- a/internal/resolution/client/npm_registry_client.go +++ b/internal/resolution/client/npm_registry_client.go @@ -229,7 +229,7 @@ func isNpmBundle(pk resolve.PackageKey) bool { return strings.Contains(pk.Name, ">") } -func (c *NpmRegistryClient) UpdateRegistries(_ []Registry) error { return nil } +func (c *NpmRegistryClient) AddRegistries(_ []Registry) error { return nil } func (c *NpmRegistryClient) WriteCache(path string) error { f, err := os.Create(path + npmRegistryCacheExt) diff --git a/internal/resolution/clienttest/mock_resolution_client.go b/internal/resolution/clienttest/mock_resolution_client.go index af02ada63f4..27e4c40d228 100644 --- a/internal/resolution/clienttest/mock_resolution_client.go +++ b/internal/resolution/clienttest/mock_resolution_client.go @@ -42,9 +42,9 @@ type mockDependencyClient struct { *resolve.LocalClient } -func (mdc mockDependencyClient) LoadCache(string) error { return nil } -func (mdc mockDependencyClient) WriteCache(string) error { return nil } -func (mdc mockDependencyClient) UpdateRegistries(_ []client.Registry) error { return nil } +func (mdc mockDependencyClient) LoadCache(string) error { return nil } +func (mdc mockDependencyClient) WriteCache(string) error { return nil } +func (mdc mockDependencyClient) AddRegistries(_ []client.Registry) error { return nil } func NewMockResolutionClient(t *testing.T, universeYAML string) client.ResolutionClient { t.Helper() diff --git a/internal/resolution/datasource/maven_registry.go b/internal/resolution/datasource/maven_registry.go index 579bb0eb6e5..a1153684bed 100644 --- a/internal/resolution/datasource/maven_registry.go +++ b/internal/resolution/datasource/maven_registry.go @@ -49,12 +49,14 @@ func NewMavenRegistryAPIClient(registry string) (*MavenRegistryAPIClient, error) // Add adds the given registry to the list of registries if it has not been added. func (m *MavenRegistryAPIClient) AddRegistry(registry string) error { - if !slices.Contains(m.registries, registry) { - if _, err := url.Parse(registry); err != nil { - return err - } - m.registries = append(m.registries, registry) + if slices.Contains(m.registries, registry) { + return nil + } + + if _, err := url.Parse(registry); err != nil { + return err } + m.registries = append(m.registries, registry) return nil } From ae6c318b7d91718fd10ff23f266019e6eba6759e Mon Sep 17 00:00:00 2001 From: Xueqin Cui Date: Thu, 10 Oct 2024 11:53:39 +1100 Subject: [PATCH 6/9] comment --- cmd/osv-scanner/fix/noninteractive.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/osv-scanner/fix/noninteractive.go b/cmd/osv-scanner/fix/noninteractive.go index 95170f28cfb..fceff98a4cc 100644 --- a/cmd/osv-scanner/fix/noninteractive.go +++ b/cmd/osv-scanner/fix/noninteractive.go @@ -296,7 +296,10 @@ func autoOverride(ctx context.Context, r reporter.Reporter, opts osvFixOptions, } if opts.ManifestRW.System() == resolve.Maven { - // Update Maven registries based on the pom.xml + // Update Maven registries based on the repositories defined in pom.xml, + // as well as the repositories merged from parent pom.xml. + // TODO: add registries defined in settings.xml + // https://github.com/google/osv-scanner/issues/1269 specific, ok := manif.EcosystemSpecific.(manifest.MavenManifestSpecific) if ok { registries := make([]client.Registry, len(specific.Repositories)) From ddf53bcf54e80e3cd506578d8ac3a8c4b539e1d9 Mon Sep 17 00:00:00 2001 From: Xueqin Cui Date: Fri, 11 Oct 2024 16:43:13 +1100 Subject: [PATCH 7/9] does allow updating registires when importing dependencies --- cmd/osv-scanner/__snapshots__/main_test.snap | 40 +++++++++---------- .../fixtures/maven-transitive/parent.xml | 8 ++-- internal/manifest/maven.go | 13 +++--- .../client/maven_registry_client.go | 8 +--- .../resolution/datasource/maven_registry.go | 14 ++++++- internal/resolution/manifest/maven.go | 11 +---- internal/utility/maven/maven.go | 14 +++++++ 7 files changed, 60 insertions(+), 48 deletions(-) diff --git a/cmd/osv-scanner/__snapshots__/main_test.snap b/cmd/osv-scanner/__snapshots__/main_test.snap index 6c77340d213..e7b2f61ed9f 100755 --- a/cmd/osv-scanner/__snapshots__/main_test.snap +++ b/cmd/osv-scanner/__snapshots__/main_test.snap @@ -2359,16 +2359,16 @@ No issues found --- [TestRun_MavenTransitive/resolve_transitive_dependencies_with_native_datda_source - 1] -Scanned /fixtures/maven-transitive/registry.xml file as a pom.xml and found 13 packages -+-------------------------------------+------+-----------+-------------------------------------+---------+----------------------------------------+ -| OSV URL | CVSS | ECOSYSTEM | PACKAGE | VERSION | SOURCE | -+-------------------------------------+------+-----------+-------------------------------------+---------+----------------------------------------+ -| https://osv.dev/GHSA-735f-pc8j-v9w8 | 8.7 | Maven | com.google.protobuf:protobuf-java | 4.28.0 | fixtures/maven-transitive/registry.xml | -| https://osv.dev/GHSA-7rjr-3q55-vv33 | 9.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | -| https://osv.dev/GHSA-8489-44mv-ggj8 | 6.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | -| https://osv.dev/GHSA-jfh8-c2jp-5v3q | 10.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | -| https://osv.dev/GHSA-p6xc-xr62-6r2g | 8.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | -+-------------------------------------+------+-----------+-------------------------------------+---------+----------------------------------------+ +Scanned /fixtures/maven-transitive/registry.xml file as a pom.xml and found 59 packages ++-------------------------------------+------+-----------+-----------------------------------------------+---------+----------------------------------------+ +| OSV URL | CVSS | ECOSYSTEM | PACKAGE | VERSION | SOURCE | ++-------------------------------------+------+-----------+-----------------------------------------------+---------+----------------------------------------+ +| https://osv.dev/GHSA-cm6r-892j-jv2g | 6.1 | Maven | com.google.android.gms:play-services-basement | 10.0.0 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-7rjr-3q55-vv33 | 9.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-8489-44mv-ggj8 | 6.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-jfh8-c2jp-5v3q | 10.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-p6xc-xr62-6r2g | 8.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | ++-------------------------------------+------+-----------+-----------------------------------------------+---------+----------------------------------------+ --- @@ -2377,16 +2377,16 @@ Scanned /fixtures/maven-transitive/registry.xml file as a pom.xml and f --- [TestRun_MavenTransitive/scans_dependencies_from_multiple_registries - 1] -Scanned /fixtures/maven-transitive/registry.xml file as a pom.xml and found 13 packages -+-------------------------------------+------+-----------+-------------------------------------+---------+----------------------------------------+ -| OSV URL | CVSS | ECOSYSTEM | PACKAGE | VERSION | SOURCE | -+-------------------------------------+------+-----------+-------------------------------------+---------+----------------------------------------+ -| https://osv.dev/GHSA-735f-pc8j-v9w8 | 8.7 | Maven | com.google.protobuf:protobuf-java | 4.28.0 | fixtures/maven-transitive/registry.xml | -| https://osv.dev/GHSA-7rjr-3q55-vv33 | 9.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | -| https://osv.dev/GHSA-8489-44mv-ggj8 | 6.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | -| https://osv.dev/GHSA-jfh8-c2jp-5v3q | 10.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | -| https://osv.dev/GHSA-p6xc-xr62-6r2g | 8.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | -+-------------------------------------+------+-----------+-------------------------------------+---------+----------------------------------------+ +Scanned /fixtures/maven-transitive/registry.xml file as a pom.xml and found 59 packages ++-------------------------------------+------+-----------+-----------------------------------------------+---------+----------------------------------------+ +| OSV URL | CVSS | ECOSYSTEM | PACKAGE | VERSION | SOURCE | ++-------------------------------------+------+-----------+-----------------------------------------------+---------+----------------------------------------+ +| https://osv.dev/GHSA-cm6r-892j-jv2g | 6.1 | Maven | com.google.android.gms:play-services-basement | 10.0.0 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-7rjr-3q55-vv33 | 9.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-8489-44mv-ggj8 | 6.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-jfh8-c2jp-5v3q | 10.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | +| https://osv.dev/GHSA-p6xc-xr62-6r2g | 8.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | fixtures/maven-transitive/registry.xml | ++-------------------------------------+------+-----------+-----------------------------------------------+---------+----------------------------------------+ --- diff --git a/cmd/osv-scanner/fixtures/maven-transitive/parent.xml b/cmd/osv-scanner/fixtures/maven-transitive/parent.xml index f287727fc3b..4aed395c187 100644 --- a/cmd/osv-scanner/fixtures/maven-transitive/parent.xml +++ b/cmd/osv-scanner/fixtures/maven-transitive/parent.xml @@ -12,11 +12,13 @@ pom + - com.google.protobuf - protobuf-java-util - 4.28.0 + + com.google.android.gms + play-services + 10.0.0 diff --git a/internal/manifest/maven.go b/internal/manifest/maven.go index 7d77ba2ffd2..657d6527c2a 100644 --- a/internal/manifest/maven.go +++ b/internal/manifest/maven.go @@ -52,13 +52,7 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD // - import dependency management // - fill in missing dependency version requirement project.ProcessDependencies(func(groupID, artifactID, version maven.String) (maven.DependencyManagement, error) { - root := maven.Parent{ProjectKey: maven.ProjectKey{GroupID: groupID, ArtifactID: artifactID, Version: version}} - var result maven.Project - if err := mavenutil.MergeParents(ctx, e.MavenRegistryAPIClient, &result, root, 0, f.Path(), false); err != nil { - return maven.DependencyManagement{}, err - } - - return result.DependencyManagement, nil + return mavenutil.GetDependencyManagement(ctx, e.MavenRegistryAPIClient, groupID, artifactID, version) }) if registries := e.MavenRegistryAPIClient.GetRegistries(); len(registries) > 0 { @@ -112,6 +106,7 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD } overrideClient.AddVersion(root, reqs) + client.PreFetch(ctx, overrideClient, reqs, f.Path()) g, err := resolver.Resolve(ctx, root.VersionKey) if err != nil { return nil, fmt.Errorf("failed resolving %v: %w", root, err) @@ -121,6 +116,10 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD g.Edges[i] = e } + if err := overrideClient.WriteCache(f.Path()); err != nil { + return nil, fmt.Errorf("failed to write resolution cache: %w", err) + } + details := map[string]lockfile.PackageDetails{} for i := 1; i < len(g.Nodes); i++ { // Ignore the first node which is the root. diff --git a/internal/resolution/client/maven_registry_client.go b/internal/resolution/client/maven_registry_client.go index 95e0223f02c..34683607c9c 100644 --- a/internal/resolution/client/maven_registry_client.go +++ b/internal/resolution/client/maven_registry_client.go @@ -111,13 +111,7 @@ func (c *MavenRegistryClient) Requirements(ctx context.Context, vk resolve.Versi return nil, err } proj.ProcessDependencies(func(groupID, artifactID, version maven.String) (maven.DependencyManagement, error) { - root := maven.Parent{ProjectKey: maven.ProjectKey{GroupID: groupID, ArtifactID: artifactID, Version: version}} - var result maven.Project - if err := mavenutil.MergeParents(ctx, c.api, &result, root, 0, "", false); err != nil { - return maven.DependencyManagement{}, err - } - - return result.DependencyManagement, nil + return mavenutil.GetDependencyManagement(ctx, c.api, groupID, artifactID, version) }) reqs := make([]resolve.RequirementVersion, 0, len(proj.Dependencies)) diff --git a/internal/resolution/datasource/maven_registry.go b/internal/resolution/datasource/maven_registry.go index a1153684bed..f8b75956495 100644 --- a/internal/resolution/datasource/maven_registry.go +++ b/internal/resolution/datasource/maven_registry.go @@ -27,7 +27,7 @@ type MavenRegistryAPIClient struct { registries []string // URLs of the registries to fetch projects // Cache fields - mu sync.Mutex + mu *sync.Mutex cacheTimestamp *time.Time // If set, this means we loaded from a cache projects *RequestCache[string, maven.Project] metadata *RequestCache[string, maven.Metadata] @@ -42,11 +42,23 @@ func NewMavenRegistryAPIClient(registry string) (*MavenRegistryAPIClient, error) return &MavenRegistryAPIClient{ defaultRegistry: registry, + mu: &sync.Mutex{}, projects: NewRequestCache[string, maven.Project](), metadata: NewRequestCache[string, maven.Metadata](), }, nil } +// CloneWithoutRegistries copies MavenRegistryAPIClient including its cache but not registries. +func (m *MavenRegistryAPIClient) CloneWithoutRegistries() *MavenRegistryAPIClient { + return &MavenRegistryAPIClient{ + defaultRegistry: m.defaultRegistry, + mu: m.mu, + cacheTimestamp: m.cacheTimestamp, + projects: m.projects, + metadata: m.metadata, + } +} + // Add adds the given registry to the list of registries if it has not been added. func (m *MavenRegistryAPIClient) AddRegistry(registry string) error { if slices.Contains(m.registries, registry) { diff --git a/internal/resolution/manifest/maven.go b/internal/resolution/manifest/maven.go index a35a8d17f33..4fe3124f256 100644 --- a/internal/resolution/manifest/maven.go +++ b/internal/resolution/manifest/maven.go @@ -123,16 +123,7 @@ func (m MavenReadWriter) Read(df lockfile.DepFile) (Manifest, error) { // - import dependency management // - fill in missing dependency version requirement project.ProcessDependencies(func(groupID, artifactID, version maven.String) (maven.DependencyManagement, error) { - root := maven.Parent{ProjectKey: maven.ProjectKey{GroupID: groupID, ArtifactID: artifactID, Version: version}} - var result maven.Project - // To get dependency management from another project, we need the - // project with parents merged, so we call mergeParents by passing - // an empty project. - if err := mavenutil.MergeParents(ctx, m.MavenRegistryAPIClient, &result, root, 0, "", false); err != nil { - return maven.DependencyManagement{}, err - } - - return result.DependencyManagement, nil + return mavenutil.GetDependencyManagement(ctx, m.MavenRegistryAPIClient, groupID, artifactID, version) }) groups := make(map[RequirementKey][]string) diff --git a/internal/utility/maven/maven.go b/internal/utility/maven/maven.go index 51cd3dbc182..ce1aac60370 100644 --- a/internal/utility/maven/maven.go +++ b/internal/utility/maven/maven.go @@ -130,3 +130,17 @@ func ParentPOMPath(currentPath, relativePath string) string { return "" } + +// GetDependencyManagement returns managed dependencies in the specified Maven project by fetching remote pom.xml. +func GetDependencyManagement(ctx context.Context, client *datasource.MavenRegistryAPIClient, groupID, artifactID, version maven.String) (maven.DependencyManagement, error) { + root := maven.Parent{ProjectKey: maven.ProjectKey{GroupID: groupID, ArtifactID: artifactID, Version: version}} + var result maven.Project + // To get dependency management from another project, we need the + // project with parents merged, so we call MergeParents by passing + // an empty project. + if err := MergeParents(ctx, client.CloneWithoutRegistries(), &result, root, 0, "", false); err != nil { + return maven.DependencyManagement{}, err + } + + return result.DependencyManagement, nil +} From 6eea90de166814a031c798ef15129ae453d62873 Mon Sep 17 00:00:00 2001 From: Xueqin Cui Date: Mon, 14 Oct 2024 15:43:25 +1100 Subject: [PATCH 8/9] snap --- cmd/osv-scanner/__snapshots__/main_test.snap | 3 +++ internal/resolution/datasource/maven_registry.go | 4 ++-- internal/utility/maven/maven.go | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cmd/osv-scanner/__snapshots__/main_test.snap b/cmd/osv-scanner/__snapshots__/main_test.snap index be7123fc333..38bd9128337 100755 --- a/cmd/osv-scanner/__snapshots__/main_test.snap +++ b/cmd/osv-scanner/__snapshots__/main_test.snap @@ -2391,6 +2391,9 @@ Scanned /fixtures/maven-transitive/registry.xml file as a pom.xml and f --- [TestRun_MavenTransitive/scans_dependencies_from_multiple_registries - 2] + +--- + [TestRun_MavenTransitive/scans_pom.xml_with_non_UTF-8_encoding - 1] Scanned /fixtures/maven-transitive/encoding.xml file as a pom.xml and found 2 packages +-------------------------------------+------+-----------+-------------+---------+----------------------------------------+ diff --git a/internal/resolution/datasource/maven_registry.go b/internal/resolution/datasource/maven_registry.go index 8cb77c0873e..343ac8025e0 100644 --- a/internal/resolution/datasource/maven_registry.go +++ b/internal/resolution/datasource/maven_registry.go @@ -49,8 +49,8 @@ func NewMavenRegistryAPIClient(registry string) (*MavenRegistryAPIClient, error) }, nil } -// CloneWithoutRegistries copies MavenRegistryAPIClient including its cache but not registries. -func (m *MavenRegistryAPIClient) CloneWithoutRegistries() *MavenRegistryAPIClient { +// CopyWithoutRegistries copies MavenRegistryAPIClient including its cache but not registries. +func (m *MavenRegistryAPIClient) CopyWithoutRegistries() *MavenRegistryAPIClient { return &MavenRegistryAPIClient{ defaultRegistry: m.defaultRegistry, mu: m.mu, diff --git a/internal/utility/maven/maven.go b/internal/utility/maven/maven.go index 8ab4272b792..e8ffce73882 100644 --- a/internal/utility/maven/maven.go +++ b/internal/utility/maven/maven.go @@ -137,7 +137,7 @@ func GetDependencyManagement(ctx context.Context, client *datasource.MavenRegist // To get dependency management from another project, we need the // project with parents merged, so we call MergeParents by passing // an empty project. - if err := MergeParents(ctx, client.CloneWithoutRegistries(), &result, root, 0, "", false); err != nil { + if err := MergeParents(ctx, client.CopyWithoutRegistries(), &result, root, 0, "", false); err != nil { return maven.DependencyManagement{}, err } From 20310f023c98ef1b609912711698ed6bd8495026 Mon Sep 17 00:00:00 2001 From: Xueqin Cui Date: Mon, 21 Oct 2024 11:19:06 +1100 Subject: [PATCH 9/9] does not write cache --- internal/manifest/maven.go | 4 ---- internal/resolution/datasource/maven_registry.go | 4 ++-- internal/utility/maven/maven.go | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/internal/manifest/maven.go b/internal/manifest/maven.go index 30a7da4e4bb..e326dfa60f7 100644 --- a/internal/manifest/maven.go +++ b/internal/manifest/maven.go @@ -115,10 +115,6 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD g.Edges[i] = e } - if err := overrideClient.WriteCache(f.Path()); err != nil { - return nil, fmt.Errorf("failed to write resolution cache: %w", err) - } - details := map[string]lockfile.PackageDetails{} for i := 1; i < len(g.Nodes); i++ { // Ignore the first node which is the root. diff --git a/internal/resolution/datasource/maven_registry.go b/internal/resolution/datasource/maven_registry.go index 343ac8025e0..2e5b06d019c 100644 --- a/internal/resolution/datasource/maven_registry.go +++ b/internal/resolution/datasource/maven_registry.go @@ -49,8 +49,8 @@ func NewMavenRegistryAPIClient(registry string) (*MavenRegistryAPIClient, error) }, nil } -// CopyWithoutRegistries copies MavenRegistryAPIClient including its cache but not registries. -func (m *MavenRegistryAPIClient) CopyWithoutRegistries() *MavenRegistryAPIClient { +// WithoutRegistries makes MavenRegistryAPIClient including its cache but not registries. +func (m *MavenRegistryAPIClient) WithoutRegistries() *MavenRegistryAPIClient { return &MavenRegistryAPIClient{ defaultRegistry: m.defaultRegistry, mu: m.mu, diff --git a/internal/utility/maven/maven.go b/internal/utility/maven/maven.go index e8ffce73882..d38060eb8b9 100644 --- a/internal/utility/maven/maven.go +++ b/internal/utility/maven/maven.go @@ -137,7 +137,7 @@ func GetDependencyManagement(ctx context.Context, client *datasource.MavenRegist // To get dependency management from another project, we need the // project with parents merged, so we call MergeParents by passing // an empty project. - if err := MergeParents(ctx, client.CopyWithoutRegistries(), &result, root, 0, "", false); err != nil { + if err := MergeParents(ctx, client.WithoutRegistries(), &result, root, 0, "", false); err != nil { return maven.DependencyManagement{}, err }