From b37426066f5ff824190d54d979efdfca194baa6d Mon Sep 17 00:00:00 2001 From: aidenwang Date: Thu, 21 Jul 2022 21:47:08 -0700 Subject: [PATCH 1/6] save --- dependencydiff/dependencydiff.go | 93 ++++++++++++------ dependencydiff/dependencydiff_test.go | 68 ++++++++++++- dependencydiff/errors.go | 23 +++++ dependencydiff/mapping.go | 131 ++++++++++++++++++++++++++ dependencydiff/raw_dependencies.go | 7 +- e2e/dependencydiff_test.go | 29 +++--- pkg/dependencydiff_result.go | 31 +++--- 7 files changed, 319 insertions(+), 63 deletions(-) create mode 100644 dependencydiff/errors.go create mode 100644 dependencydiff/mapping.go diff --git a/dependencydiff/dependencydiff.go b/dependencydiff/dependencydiff.go index 3c18f0cb87e..8d6028cc0ef 100644 --- a/dependencydiff/dependencydiff.go +++ b/dependencydiff/dependencydiff.go @@ -17,12 +17,14 @@ package dependencydiff import ( "context" "fmt" + "strings" "github.com/ossf/scorecard/v4/checker" "github.com/ossf/scorecard/v4/checks" "github.com/ossf/scorecard/v4/clients" sce "github.com/ossf/scorecard/v4/errors" "github.com/ossf/scorecard/v4/log" + sclog "github.com/ossf/scorecard/v4/log" "github.com/ossf/scorecard/v4/pkg" "github.com/ossf/scorecard/v4/policy" ) @@ -31,44 +33,56 @@ import ( const Depdiff = "Dependency-diff" type dependencydiffContext struct { - logger *log.Logger - ownerName, repoName, baseSHA, headSHA string - ctx context.Context - ghRepo clients.Repo - ghRepoClient clients.RepoClient - ossFuzzClient clients.RepoClient - vulnsClient clients.VulnerabilitiesClient - ciiClient clients.CIIBestPracticesClient - changeTypesToCheck map[pkg.ChangeType]bool - checkNamesToRun []string - dependencydiffs []dependency - results []pkg.DependencyCheckResult + logger *sclog.Logger + ownerName, repoName, base, head string + ctx context.Context + ghRepo clients.Repo + ghRepoClient clients.RepoClient + ossFuzzClient clients.RepoClient + vulnsClient clients.VulnerabilitiesClient + ciiClient clients.CIIBestPracticesClient + changeTypesToCheck map[pkg.ChangeType]bool + checkNamesToRun []string + dependencydiffs []dependency + results []pkg.DependencyCheckResult } // GetDependencyDiffResults gets dependency changes between two given code commits BASE and HEAD // along with the Scorecard check results of the dependencies, and returns a slice of DependencyCheckResult. -// TO use this API, an access token must be set following https://github.com/ossf/scorecard#authentication. +// TO use this API, an access token must be set. See https://github.com/ossf/scorecard#authentication. func GetDependencyDiffResults( - ctx context.Context, ownerName, repoName, baseSHA, headSHA string, scorecardChecksNames []string, - changeTypesToCheck map[pkg.ChangeType]bool) ([]pkg.DependencyCheckResult, error) { - // Fetch the raw dependency diffs. + ctx context.Context, + repoURI string, /* Use the format "ownerName/repoName" as the repo URI, such as "ossf/scorecard". */ + base, head string, /* Two code commits base and head, can use either SHAs or branch names. */ + checksToRun []string, /* A list of enabled check names to run. */ + changeTypesToCheck map[pkg.ChangeType]bool, /* A list of change types for which to surface scorecard results. */ +) ([]pkg.DependencyCheckResult, error) { + + logger := log.NewLogger(log.DefaultLevel) + ownerAndRepo := strings.Split(repoURI, "/") + if len(ownerAndRepo) != 2 { + return nil, fmt.Errorf("%w: repo uri input", errInvalid) + } + owner, repo := ownerAndRepo[0], ownerAndRepo[1] dCtx := dependencydiffContext{ - logger: log.NewLogger(log.InfoLevel), - ownerName: ownerName, - repoName: repoName, - baseSHA: baseSHA, - headSHA: headSHA, + logger: logger, + ownerName: owner, + repoName: repo, + base: base, + head: head, ctx: ctx, changeTypesToCheck: changeTypesToCheck, - checkNamesToRun: scorecardChecksNames, + checkNamesToRun: checksToRun, } + // Fetch the raw dependency diffs. This API will also handle error cases such as invalid base or head. err := fetchRawDependencyDiffData(&dCtx) + // Map the ecosystem naming convention from GitHub to OSV. if err != nil { return nil, fmt.Errorf("error in fetchRawDependencyDiffData: %w", err) } - + err = mapDependencyEcosystemNaming(dCtx.dependencydiffs) if err != nil { - return nil, fmt.Errorf("error in initRepoAndClientByChecks: %w", err) + return nil, fmt.Errorf("error in mapDependencyEcosystemNaming: %w", err) } err = getScorecardCheckResults(&dCtx) if err != nil { @@ -77,6 +91,24 @@ func GetDependencyDiffResults( return dCtx.results, nil } +func mapDependencyEcosystemNaming(deps []dependency) error { + for i := range deps { + if deps[i].Ecosystem != nil { + ghEcosys := ecosystemGitHub(*deps[i].Ecosystem) + if !ghEcosys.isValid() { + return fmt.Errorf("%w: github ecosystem", errInvalid) + } + osvEcosys, err := ghEcosys.toOSV() + if err != nil { + wrappedErr := fmt.Errorf("error mapping dependency ecosystem: %w:", err) + return wrappedErr + } + deps[i].Ecosystem = asPointer(string(osvEcosys)) + } + } + return nil +} + func initRepoAndClientByChecks(dCtx *dependencydiffContext, dSrcRepo string) error { repo, repoClient, ossFuzzClient, ciiClient, vulnsClient, err := checker.GetClients( dCtx.ctx, dSrcRepo, "", dCtx.logger, @@ -150,13 +182,20 @@ func getScorecardCheckResults(dCtx *dependencydiffContext) error { // If the run fails, we leave the current dependency scorecard result empty and record the error // rather than letting the entire API return nil since we still expect results for other dependencies. if err != nil { - depCheckResult.ScorecardResultsWithError.Error = sce.WithMessage(sce.ErrScorecardInternal, - fmt.Sprintf("error running the scorecard checks: %v", err)) + wrappedErr := sce.WithMessage(sce.ErrScorecardInternal, + fmt.Sprintf("scorecard running failed for %s: %v", d.Name, err)) + dCtx.logger.Error(wrappedErr, "") + depCheckResult.ScorecardResultWithError.Error = wrappedErr + } else { // Otherwise, we record the scorecard check results for this dependency. - depCheckResult.ScorecardResultsWithError.ScorecardResults = &scorecardResult + depCheckResult.ScorecardResultWithError.ScorecardResult = &scorecardResult } } dCtx.results = append(dCtx.results, depCheckResult) } return nil } + +func asPointer(s string) *string { + return &s +} diff --git a/dependencydiff/dependencydiff_test.go b/dependencydiff/dependencydiff_test.go index 768d3dc46a1..d8f4694351b 100644 --- a/dependencydiff/dependencydiff_test.go +++ b/dependencydiff/dependencydiff_test.go @@ -16,6 +16,7 @@ package dependencydiff import ( "context" + "errors" "path" "testing" @@ -40,8 +41,8 @@ func Test_fetchRawDependencyDiffData(t *testing.T) { ctx: context.Background(), ownerName: "no_such_owner", repoName: "repo_not_exist", - baseSHA: "base", - headSHA: clients.HeadSHA, + base: "main", + head: clients.HeadSHA, }, wantEmpty: true, wantErr: true, @@ -158,3 +159,66 @@ func Test_getScorecardCheckResults(t *testing.T) { }) } } + +func Test_mapDependencyEcosystemNaming(t *testing.T) { + t.Parallel() + //nolint + tests := []struct { + name string + deps []dependency + errWanted error + }{ + { + name: "error invalid github ecosystem", + deps: []dependency{ + { + Name: "dependency_1", + Ecosystem: asPointer("not_supported"), + }, + { + Name: "dependency_2", + Ecosystem: asPointer("gomod"), + }, + }, + errWanted: errInvalid, + }, + { + name: "error cannot find mapping", + deps: []dependency{ + { + Name: "dependency_3", + Ecosystem: asPointer("actions"), + }, + }, + errWanted: errInvalid, + }, + { + name: "correct mapping", + deps: []dependency{ + { + Name: "dependency_4", + Ecosystem: asPointer("gomod"), + }, + { + Name: "dependency_5", + Ecosystem: asPointer("pip"), + }, + { + Name: "dependency_6", + Ecosystem: asPointer("cargo"), + }, + }, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + err := mapDependencyEcosystemNaming(tt.deps) + if tt.errWanted != nil && errors.Is(tt.errWanted, err) { + t.Errorf("not a wanted error, want:%v, got:%v", tt.errWanted, err) + return + } + }) + } +} diff --git a/dependencydiff/errors.go b/dependencydiff/errors.go new file mode 100644 index 00000000000..6541cc53964 --- /dev/null +++ b/dependencydiff/errors.go @@ -0,0 +1,23 @@ +// Copyright 2022 Security Scorecard Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dependencydiff + +import "errors" + +// static Errors for mapping +var ( + errMappingNotFound = errors.New("ecosystem mapping not found") + errInvalid = errors.New("invalid") +) diff --git a/dependencydiff/mapping.go b/dependencydiff/mapping.go new file mode 100644 index 00000000000..0eb59ac29bf --- /dev/null +++ b/dependencydiff/mapping.go @@ -0,0 +1,131 @@ +// Copyright 2022 Security Scorecard Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dependencydiff + +import ( + "fmt" +) + +// EcosystemOSV is a package ecosystem supported by OSV. +type ecosystemOSV string + +// Data source: https://ossf.github.io/osv-schema/#affectedpackage-field +const ( + // The Go ecosystem. + goOSV ecosystemOSV = "Go" + + // The NPM ecosystem. + npmOSV = "npm" + + // The Android ecosystem. + androidOSV = "Android" + + // The crates.io ecosystem for RUST. + cratesOSV = "crates.io" + + // For reports from the OSS-Fuzz project that have no more appropriate ecosystem. + ossFuzzOSV = "OSS-Fuzz" + + // The Python PyPI ecosystem. PyPI is the main package source of pip. + pyPIOSV = "PyPI" + + // The RubyGems ecosystem. + rubyGemsOSV = "RubyGems" + + // The PHP package manager ecosystem. Packagist is the main Composer repository. + packagistOSV = "Packagist" + + // The Maven Java package ecosystem. + mavenOSV = "Maven" + + // The NuGet package ecosystem. + nuGetOSV = "Nuget" + + // The Linux kernel. + linuxOSV = "Linux" + + // The Debian package ecosystem. + debianOSV = "Debian" + + // Hex is the package manager of Erlang. + // TODO: GitHub doesn't support hex as the ecosystem for Erlang yet. Add this mapping in the future. + hexOSV = "Hex" +) + +// ecosystemGitHub is a package ecosystem supported by GitHub. +type ecosystemGitHub string + +// Data source: https://docs.github.com/en/code-security/supply-chain-security/understanding- +// your-software-supply-chain/about-the-dependency-graph#supported-package-ecosystems +const ( + // The Go ecosystem on GitHub includes go.mod and go.sum, but both use gomod as the ecosystem name. + goGitHub ecosystemGitHub = "gomod" + + // Npm is the package manager of JavaScript. + // Yarn is another package manager of JavaScript, GitHub also uses "npm" as its ecosys name. + npmGitHub ecosystemGitHub = "npm" + + // RubyGems is the package manager of Ruby. + rubyGemsGitHub ecosystemGitHub = "rubygems" + + // Pip is the package manager of Python. + // Poetry is another package manager of Python, GitHub also uses "pip" as its ecosys name. + pipGitHub ecosystemGitHub = "pip" + + // Action is the GitHub Action. + actionGitHub ecosystemGitHub = "actions" + + // Cargo is the package manager of RUST. + cargoGitHub ecosystemGitHub = "cargo" + + // Composer is the package manager of PHP, there is currently no mapping to the OSV. + composerGitHub ecosystemGitHub = "composer" + + // NuGet is the package manager of .NET languages (C#, F#, VB), C++. + nuGetGitHub ecosystemGitHub = "nuget" + + // Maven is the package manager of Java and Scala. + mavenGitHub ecosystemGitHub = "maven" +) + +func (e ecosystemGitHub) isValid() bool { + switch e { + case goGitHub, npmGitHub, rubyGemsGitHub, pipGitHub, actionGitHub, + cargoGitHub, composerGitHub, nuGetGitHub, mavenGitHub: + return true + default: + return false + } +} + +var ( + gitHubToOSV = map[ecosystemGitHub]ecosystemOSV{ + goGitHub: goOSV, /* go.mod and go.sum */ + cargoGitHub: cratesOSV, + pipGitHub: pyPIOSV, /* pip and poetry */ + npmGitHub: npmOSV, /* npm and yarn */ + mavenGitHub: mavenOSV, + composerGitHub: packagistOSV, + rubyGemsGitHub: rubyGemsOSV, + nuGetGitHub: nuGetOSV, + } +) + +func (e ecosystemGitHub) toOSV() (ecosystemOSV, error) { + if ecosystemOSV, found := gitHubToOSV[e]; found { + return ecosystemOSV, nil + } + return "", fmt.Errorf("%w for github entry %s", errMappingNotFound, e) +} diff --git a/dependencydiff/raw_dependencies.go b/dependencydiff/raw_dependencies.go index 519e560217c..39194535d51 100644 --- a/dependencydiff/raw_dependencies.go +++ b/dependencydiff/raw_dependencies.go @@ -58,7 +58,7 @@ func fetchRawDependencyDiffData(dCtx *dependencydiffContext) error { req, err := ghClient.NewRequest( "GET", path.Join("repos", dCtx.ownerName, dCtx.repoName, - "dependency-graph", "compare", dCtx.baseSHA+"..."+dCtx.headSHA), + "dependency-graph", "compare", dCtx.base+"..."+dCtx.head), nil, ) if err != nil { @@ -68,5 +68,10 @@ func fetchRawDependencyDiffData(dCtx *dependencydiffContext) error { if err != nil { return fmt.Errorf("error parsing the dependency-diff reponse: %w", err) } + for _, d := range dCtx.dependencydiffs { + if !d.ChangeType.IsValid() { + return fmt.Errorf("%w: change type", errInvalid) + } + } return nil } diff --git a/e2e/dependencydiff_test.go b/e2e/dependencydiff_test.go index d0246293537..2e1d7d236aa 100644 --- a/e2e/dependencydiff_test.go +++ b/e2e/dependencydiff_test.go @@ -19,26 +19,22 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/ossf/scorecard/v4/checks" "github.com/ossf/scorecard/v4/dependencydiff" "github.com/ossf/scorecard/v4/pkg" ) const ( - OWNER = "ossf-tests" - REPO = "scorecard-depdiff" - BASE = "fd2a82b3b735fffbc2d782ed5f50301b879ecc51" - HEAD = "1989568f93e484f6a86f8b276b170e3d6962ce12" + repoURI = "ossf-tests/scorecard-depdiff" + base = "fd2a82b3b735fffbc2d782ed5f50301b879ecc51" + head = "1989568f93e484f6a86f8b276b170e3d6962ce12" ) var _ = Describe("E2E TEST:"+dependencydiff.Depdiff, func() { Context("E2E TEST:Validating use of the dependency-diff API", func() { It("Should return a slice of dependency-diff checking results", func() { ctx := context.Background() - ownerName, repoName := OWNER, REPO - baseSHA, headSHA := BASE, HEAD - scorecardChecksNames := []string{ + checks := []string{ checks.CheckBranchProtection, } changeTypesToCheck := map[pkg.ChangeType]bool{ @@ -46,8 +42,9 @@ var _ = Describe("E2E TEST:"+dependencydiff.Depdiff, func() { } results, err := dependencydiff.GetDependencyDiffResults( ctx, - ownerName, repoName, baseSHA, headSHA, - scorecardChecksNames, + repoURI, + base, head, + checks, changeTypesToCheck, ) Expect(err).Should(BeNil()) @@ -55,9 +52,6 @@ var _ = Describe("E2E TEST:"+dependencydiff.Depdiff, func() { }) It("Should return a valid empty result", func() { ctx := context.Background() - ownerName, repoName := OWNER, REPO - baseSHA, headSHA := BASE, BASE - scorecardChecksNames := []string{ checks.CheckBranchProtection, } @@ -66,7 +60,8 @@ var _ = Describe("E2E TEST:"+dependencydiff.Depdiff, func() { } results, err := dependencydiff.GetDependencyDiffResults( ctx, - ownerName, repoName, baseSHA, headSHA, + repoURI, + base, head, scorecardChecksNames, changeTypesToCheck, ) @@ -75,16 +70,14 @@ var _ = Describe("E2E TEST:"+dependencydiff.Depdiff, func() { }) It("Should initialize clients corresponding to the checks to run and do not crash", func() { ctx := context.Background() - ownerName, repoName := OWNER, REPO - baseSHA, headSHA := BASE, HEAD - scorecardChecksNames := []string{} changeTypesToCheck := map[pkg.ChangeType]bool{ pkg.Removed: true, } _, err := dependencydiff.GetDependencyDiffResults( ctx, - ownerName, repoName, baseSHA, headSHA, + repoURI, + base, head, scorecardChecksNames, changeTypesToCheck, ) diff --git a/pkg/dependencydiff_result.go b/pkg/dependencydiff_result.go index 5208d9812ce..b92ed2af7fd 100644 --- a/pkg/dependencydiff_result.go +++ b/pkg/dependencydiff_result.go @@ -35,8 +35,8 @@ const ( ) // IsValid determines if a ChangeType is valid. -func (ct *ChangeType) IsValid() bool { - switch *ct { +func (ct ChangeType) IsValid() bool { + switch ct { case Added, Updated, Removed: return true default: @@ -44,40 +44,41 @@ func (ct *ChangeType) IsValid() bool { } } -// ScorecardResultsWithError is used for the dependency-diff module to record scorecard results and their errors. -type ScorecardResultsWithError struct { +// ScorecardResultWithError is used for the dependency-diff module to record the scorecard result and the error. +type ScorecardResultWithError struct { // ScorecardResults is the scorecard result for the dependency repo. - ScorecardResults *ScorecardResult `json:"scorecardResults"` + ScorecardResult *ScorecardResult // Error is an error returned when running the scorecard checks. A nil Error indicates the run succeeded. - Error error `json:"scorecardRunTimeError"` + Error error } // DependencyCheckResult is the dependency structure used in the returned results. type DependencyCheckResult struct { // ChangeType indicates whether the dependency is added, updated, or removed. - ChangeType *ChangeType `json:"changeType"` + ChangeType *ChangeType // Package URL is a short link for a package. - PackageURL *string `json:"packageUrl"` + PackageURL *string // SourceRepository is the source repository URL of the dependency. - SourceRepository *string `json:"sourceRepository"` + SourceRepository *string // ManifestPath is the path of the manifest file of the dependency, such as go.mod for Go. - ManifestPath *string `json:"manifestPath"` + ManifestPath *string // Ecosystem is the name of the package management system, such as NPM, GO, PYPI. - Ecosystem *string `json:"ecosystem"` + Ecosystem *string // Version is the package version of the dependency. - Version *string `json:"version"` + Version *string - // ScorecardResultsWithError is the scorecard checking results of the dependency. - ScorecardResultsWithError ScorecardResultsWithError `json:"scorecardResultsWithError"` + // ScorecardResultWithError contains the scorecard checking result of the dependency + // and an error field to record potential failing scorecard runs. + ScorecardResultWithError ScorecardResultWithError // Name is the name of the dependency. - Name string `json:"name"` + Name string } // AsJSON for DependencyCheckResult exports the DependencyCheckResult as a JSON object. From 7ac60bfddb853ba15484836d93fffca9f6c6aa1a Mon Sep 17 00:00:00 2001 From: aidenwang Date: Thu, 21 Jul 2022 22:12:51 -0700 Subject: [PATCH 2/6] save --- dependencydiff/dependencydiff.go | 27 ++++++++++++++------------- dependencydiff/mapping.go | 14 +++++++------- e2e/dependencydiff_test.go | 1 + 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/dependencydiff/dependencydiff.go b/dependencydiff/dependencydiff.go index 8d6028cc0ef..343e3acd56f 100644 --- a/dependencydiff/dependencydiff.go +++ b/dependencydiff/dependencydiff.go @@ -23,7 +23,6 @@ import ( "github.com/ossf/scorecard/v4/checks" "github.com/ossf/scorecard/v4/clients" sce "github.com/ossf/scorecard/v4/errors" - "github.com/ossf/scorecard/v4/log" sclog "github.com/ossf/scorecard/v4/log" "github.com/ossf/scorecard/v4/pkg" "github.com/ossf/scorecard/v4/policy" @@ -58,7 +57,7 @@ func GetDependencyDiffResults( changeTypesToCheck map[pkg.ChangeType]bool, /* A list of change types for which to surface scorecard results. */ ) ([]pkg.DependencyCheckResult, error) { - logger := log.NewLogger(log.DefaultLevel) + logger := sclog.NewLogger(sclog.DefaultLevel) ownerAndRepo := strings.Split(repoURI, "/") if len(ownerAndRepo) != 2 { return nil, fmt.Errorf("%w: repo uri input", errInvalid) @@ -93,18 +92,20 @@ func GetDependencyDiffResults( func mapDependencyEcosystemNaming(deps []dependency) error { for i := range deps { - if deps[i].Ecosystem != nil { - ghEcosys := ecosystemGitHub(*deps[i].Ecosystem) - if !ghEcosys.isValid() { - return fmt.Errorf("%w: github ecosystem", errInvalid) - } - osvEcosys, err := ghEcosys.toOSV() - if err != nil { - wrappedErr := fmt.Errorf("error mapping dependency ecosystem: %w:", err) - return wrappedErr - } - deps[i].Ecosystem = asPointer(string(osvEcosys)) + if deps[i].Ecosystem == nil { + continue } + ghEcosys := ecosystemGitHub(*deps[i].Ecosystem) + if !ghEcosys.isValid() { + return fmt.Errorf("%w: github ecosystem", errInvalid) + } + osvEcosys, err := ghEcosys.toOSV() + if err != nil { + wrappedErr := fmt.Errorf("error mapping dependency ecosystem: %w", err) + return wrappedErr + } + deps[i].Ecosystem = asPointer(string(osvEcosys)) + } return nil } diff --git a/dependencydiff/mapping.go b/dependencydiff/mapping.go index 0eb59ac29bf..7c3337aad13 100644 --- a/dependencydiff/mapping.go +++ b/dependencydiff/mapping.go @@ -29,14 +29,14 @@ const ( // The NPM ecosystem. npmOSV = "npm" - // The Android ecosystem. - androidOSV = "Android" + // The Android ecosystem + androidOSV = "Android" // nolint: since this is not used in the map for now. // The crates.io ecosystem for RUST. cratesOSV = "crates.io" // For reports from the OSS-Fuzz project that have no more appropriate ecosystem. - ossFuzzOSV = "OSS-Fuzz" + ossFuzzOSV = "OSS-Fuzz" // nolint: since this is not used in the map for now. // The Python PyPI ecosystem. PyPI is the main package source of pip. pyPIOSV = "PyPI" @@ -54,14 +54,14 @@ const ( nuGetOSV = "Nuget" // The Linux kernel. - linuxOSV = "Linux" + linuxOSV = "Linux" // nolint: since this is not used in the map for now. // The Debian package ecosystem. - debianOSV = "Debian" + debianOSV = "Debian" // nolint: since this is not used in the map for now. // Hex is the package manager of Erlang. // TODO: GitHub doesn't support hex as the ecosystem for Erlang yet. Add this mapping in the future. - hexOSV = "Hex" + hexOSV = "Hex" // nolint: since this is not used in the map for now. ) // ecosystemGitHub is a package ecosystem supported by GitHub. @@ -85,7 +85,7 @@ const ( pipGitHub ecosystemGitHub = "pip" // Action is the GitHub Action. - actionGitHub ecosystemGitHub = "actions" + actionGitHub ecosystemGitHub = "actions" // nolint: since this is not used in the map for now. // Cargo is the package manager of RUST. cargoGitHub ecosystemGitHub = "cargo" diff --git a/e2e/dependencydiff_test.go b/e2e/dependencydiff_test.go index 2e1d7d236aa..5eb41be2906 100644 --- a/e2e/dependencydiff_test.go +++ b/e2e/dependencydiff_test.go @@ -19,6 +19,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "github.com/ossf/scorecard/v4/checks" "github.com/ossf/scorecard/v4/dependencydiff" "github.com/ossf/scorecard/v4/pkg" From c90d3041cf5319008b7104b422beadeb792a3c7f Mon Sep 17 00:00:00 2001 From: aidenwang Date: Thu, 21 Jul 2022 22:23:30 -0700 Subject: [PATCH 3/6] save --- dependencydiff/mapping.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/dependencydiff/mapping.go b/dependencydiff/mapping.go index 7c3337aad13..6bdae8722b8 100644 --- a/dependencydiff/mapping.go +++ b/dependencydiff/mapping.go @@ -30,13 +30,13 @@ const ( npmOSV = "npm" // The Android ecosystem - androidOSV = "Android" // nolint: since this is not used in the map for now. + androidOSV = "Android" // nolint:unused // The crates.io ecosystem for RUST. cratesOSV = "crates.io" // For reports from the OSS-Fuzz project that have no more appropriate ecosystem. - ossFuzzOSV = "OSS-Fuzz" // nolint: since this is not used in the map for now. + ossFuzzOSV = "OSS-Fuzz" // nolint:unused // The Python PyPI ecosystem. PyPI is the main package source of pip. pyPIOSV = "PyPI" @@ -54,14 +54,14 @@ const ( nuGetOSV = "Nuget" // The Linux kernel. - linuxOSV = "Linux" // nolint: since this is not used in the map for now. + linuxOSV = "Linux" // nolint:unused // The Debian package ecosystem. - debianOSV = "Debian" // nolint: since this is not used in the map for now. + debianOSV = "Debian" // nolint:unused // Hex is the package manager of Erlang. // TODO: GitHub doesn't support hex as the ecosystem for Erlang yet. Add this mapping in the future. - hexOSV = "Hex" // nolint: since this is not used in the map for now. + hexOSV = "Hex" // nolint:unused ) // ecosystemGitHub is a package ecosystem supported by GitHub. @@ -69,6 +69,7 @@ type ecosystemGitHub string // Data source: https://docs.github.com/en/code-security/supply-chain-security/understanding- // your-software-supply-chain/about-the-dependency-graph#supported-package-ecosystems +// nolint const ( // The Go ecosystem on GitHub includes go.mod and go.sum, but both use gomod as the ecosystem name. goGitHub ecosystemGitHub = "gomod" @@ -85,7 +86,7 @@ const ( pipGitHub ecosystemGitHub = "pip" // Action is the GitHub Action. - actionGitHub ecosystemGitHub = "actions" // nolint: since this is not used in the map for now. + actionGitHub ecosystemGitHub = "actions" // nolint:unused // Cargo is the package manager of RUST. cargoGitHub ecosystemGitHub = "cargo" From f50fcc0499d08e1a84bc0d52e9f1f336160e08c0 Mon Sep 17 00:00:00 2001 From: aidenwang Date: Fri, 22 Jul 2022 11:34:47 -0700 Subject: [PATCH 4/6] save --- dependencydiff/dependencydiff.go | 8 +-- dependencydiff/mapping.go | 105 +++++++++---------------------- 2 files changed, 33 insertions(+), 80 deletions(-) diff --git a/dependencydiff/dependencydiff.go b/dependencydiff/dependencydiff.go index 343e3acd56f..a06004da725 100644 --- a/dependencydiff/dependencydiff.go +++ b/dependencydiff/dependencydiff.go @@ -95,16 +95,12 @@ func mapDependencyEcosystemNaming(deps []dependency) error { if deps[i].Ecosystem == nil { continue } - ghEcosys := ecosystemGitHub(*deps[i].Ecosystem) - if !ghEcosys.isValid() { - return fmt.Errorf("%w: github ecosystem", errInvalid) - } - osvEcosys, err := ghEcosys.toOSV() + mappedEcosys, err := toEcosystem(*deps[i].Ecosystem) if err != nil { wrappedErr := fmt.Errorf("error mapping dependency ecosystem: %w", err) return wrappedErr } - deps[i].Ecosystem = asPointer(string(osvEcosys)) + deps[i].Ecosystem = asPointer(string(mappedEcosys)) } return nil diff --git a/dependencydiff/mapping.go b/dependencydiff/mapping.go index 6bdae8722b8..445676b3b6b 100644 --- a/dependencydiff/mapping.go +++ b/dependencydiff/mapping.go @@ -18,113 +18,70 @@ import ( "fmt" ) -// EcosystemOSV is a package ecosystem supported by OSV. -type ecosystemOSV string +// Ecosystem is a package ecosystem supported by OSV, GitHub, etc. +type ecosystem string -// Data source: https://ossf.github.io/osv-schema/#affectedpackage-field +// OSV ecosystem naming data source: https://ossf.github.io/osv-schema/#affectedpackage-field +// nolint const ( // The Go ecosystem. - goOSV ecosystemOSV = "Go" + ecosystemGo ecosystem = "Go" // The NPM ecosystem. - npmOSV = "npm" + ecosystemNpm ecosystem = "npm" // The Android ecosystem - androidOSV = "Android" // nolint:unused + ecosystemAndroid ecosystem = "Android" // nolint:unused // The crates.io ecosystem for RUST. - cratesOSV = "crates.io" + ecosystemCrates ecosystem = "crates.io" // For reports from the OSS-Fuzz project that have no more appropriate ecosystem. - ossFuzzOSV = "OSS-Fuzz" // nolint:unused + ecosystemOssFuzz ecosystem = "OSS-Fuzz" // nolint:unused // The Python PyPI ecosystem. PyPI is the main package source of pip. - pyPIOSV = "PyPI" + ecosystemPyPI ecosystem = "PyPI" // The RubyGems ecosystem. - rubyGemsOSV = "RubyGems" + ecosystemRubyGems ecosystem = "RubyGems" // The PHP package manager ecosystem. Packagist is the main Composer repository. - packagistOSV = "Packagist" + ecosystemPackagist ecosystem = "Packagist" // The Maven Java package ecosystem. - mavenOSV = "Maven" + ecosystemMaven ecosystem = "Maven" // The NuGet package ecosystem. - nuGetOSV = "Nuget" + ecosystemNuGet ecosystem = "Nuget" // The Linux kernel. - linuxOSV = "Linux" // nolint:unused + ecosystemLinux ecosystem = "Linux" // nolint:unused // The Debian package ecosystem. - debianOSV = "Debian" // nolint:unused + ecosystemDebian ecosystem = "Debian" // nolint:unused // Hex is the package manager of Erlang. - // TODO: GitHub doesn't support hex as the ecosystem for Erlang yet. Add this mapping in the future. - hexOSV = "Hex" // nolint:unused + // TODO: GitHub doesn't support hex as the ecosystem for Erlang yet. Add this to the map in the future. + ecosystemHex ecosystem = "Hex" // nolint:unused ) -// ecosystemGitHub is a package ecosystem supported by GitHub. -type ecosystemGitHub string - -// Data source: https://docs.github.com/en/code-security/supply-chain-security/understanding- -// your-software-supply-chain/about-the-dependency-graph#supported-package-ecosystems -// nolint -const ( - // The Go ecosystem on GitHub includes go.mod and go.sum, but both use gomod as the ecosystem name. - goGitHub ecosystemGitHub = "gomod" - - // Npm is the package manager of JavaScript. - // Yarn is another package manager of JavaScript, GitHub also uses "npm" as its ecosys name. - npmGitHub ecosystemGitHub = "npm" - - // RubyGems is the package manager of Ruby. - rubyGemsGitHub ecosystemGitHub = "rubygems" - - // Pip is the package manager of Python. - // Poetry is another package manager of Python, GitHub also uses "pip" as its ecosys name. - pipGitHub ecosystemGitHub = "pip" - - // Action is the GitHub Action. - actionGitHub ecosystemGitHub = "actions" // nolint:unused - - // Cargo is the package manager of RUST. - cargoGitHub ecosystemGitHub = "cargo" - - // Composer is the package manager of PHP, there is currently no mapping to the OSV. - composerGitHub ecosystemGitHub = "composer" - - // NuGet is the package manager of .NET languages (C#, F#, VB), C++. - nuGetGitHub ecosystemGitHub = "nuget" - - // Maven is the package manager of Java and Scala. - mavenGitHub ecosystemGitHub = "maven" -) - -func (e ecosystemGitHub) isValid() bool { - switch e { - case goGitHub, npmGitHub, rubyGemsGitHub, pipGitHub, actionGitHub, - cargoGitHub, composerGitHub, nuGetGitHub, mavenGitHub: - return true - default: - return false - } -} - var ( - gitHubToOSV = map[ecosystemGitHub]ecosystemOSV{ - goGitHub: goOSV, /* go.mod and go.sum */ - cargoGitHub: cratesOSV, - pipGitHub: pyPIOSV, /* pip and poetry */ - npmGitHub: npmOSV, /* npm and yarn */ - mavenGitHub: mavenOSV, - composerGitHub: packagistOSV, - rubyGemsGitHub: rubyGemsOSV, - nuGetGitHub: nuGetOSV, + //gitHubToOSV defines the ecosystem naming mapping relationship between GitHub and others. + gitHubToOSV = map[string]ecosystem{ + // GitHub ecosystem naming data source: https://docs.github.com/en/code-security/supply-chain-security/ + // understanding-your-software-supply-chain/about-the-dependency-graph#supported-package-ecosystems + "gomod": ecosystemGo, /* go.mod and go.sum */ + "cargo": ecosystemCrates, + "pip": ecosystemPyPI, /* pip and poetry */ + "npm": ecosystemNpm, /* npm and yarn */ + "maven": ecosystemMaven, + "composer": ecosystemPackagist, + "rubygems": ecosystemRubyGems, + "nuget": ecosystemNuGet, } ) -func (e ecosystemGitHub) toOSV() (ecosystemOSV, error) { +func toEcosystem(e string) (ecosystem, error) { if ecosystemOSV, found := gitHubToOSV[e]; found { return ecosystemOSV, nil } From 75cbea03a0dbc257b7e03449ae5b3367d737218d Mon Sep 17 00:00:00 2001 From: aidenwang Date: Fri, 22 Jul 2022 13:17:20 -0700 Subject: [PATCH 5/6] save --- e2e/dependencydiff_test.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/e2e/dependencydiff_test.go b/e2e/dependencydiff_test.go index 5eb41be2906..7df0c3b8222 100644 --- a/e2e/dependencydiff_test.go +++ b/e2e/dependencydiff_test.go @@ -35,7 +35,7 @@ var _ = Describe("E2E TEST:"+dependencydiff.Depdiff, func() { Context("E2E TEST:Validating use of the dependency-diff API", func() { It("Should return a slice of dependency-diff checking results", func() { ctx := context.Background() - checks := []string{ + checksToRun := []string{ checks.CheckBranchProtection, } changeTypesToCheck := map[pkg.ChangeType]bool{ @@ -44,8 +44,8 @@ var _ = Describe("E2E TEST:"+dependencydiff.Depdiff, func() { results, err := dependencydiff.GetDependencyDiffResults( ctx, repoURI, - base, head, - checks, + base, base, + checksToRun, changeTypesToCheck, ) Expect(err).Should(BeNil()) @@ -53,7 +53,7 @@ var _ = Describe("E2E TEST:"+dependencydiff.Depdiff, func() { }) It("Should return a valid empty result", func() { ctx := context.Background() - scorecardChecksNames := []string{ + checksToRun := []string{ checks.CheckBranchProtection, } changeTypesToCheck := map[pkg.ChangeType]bool{ @@ -63,7 +63,7 @@ var _ = Describe("E2E TEST:"+dependencydiff.Depdiff, func() { ctx, repoURI, base, head, - scorecardChecksNames, + checksToRun, changeTypesToCheck, ) Expect(err).Should(BeNil()) @@ -71,7 +71,9 @@ var _ = Describe("E2E TEST:"+dependencydiff.Depdiff, func() { }) It("Should initialize clients corresponding to the checks to run and do not crash", func() { ctx := context.Background() - scorecardChecksNames := []string{} + checksToRun := []string{ + checks.CheckFuzzing, + } changeTypesToCheck := map[pkg.ChangeType]bool{ pkg.Removed: true, } @@ -79,7 +81,7 @@ var _ = Describe("E2E TEST:"+dependencydiff.Depdiff, func() { ctx, repoURI, base, head, - scorecardChecksNames, + checksToRun, changeTypesToCheck, ) Expect(err).Should(BeNil()) From 4b9e13892ee0b9ec410c2dd05b4fb23496f401c0 Mon Sep 17 00:00:00 2001 From: aidenwang Date: Fri, 22 Jul 2022 13:58:25 -0700 Subject: [PATCH 6/6] save --- e2e/dependencydiff_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/dependencydiff_test.go b/e2e/dependencydiff_test.go index 7df0c3b8222..fa388ba8efd 100644 --- a/e2e/dependencydiff_test.go +++ b/e2e/dependencydiff_test.go @@ -44,7 +44,7 @@ var _ = Describe("E2E TEST:"+dependencydiff.Depdiff, func() { results, err := dependencydiff.GetDependencyDiffResults( ctx, repoURI, - base, base, + base, head, checksToRun, changeTypesToCheck, ) @@ -62,7 +62,7 @@ var _ = Describe("E2E TEST:"+dependencydiff.Depdiff, func() { results, err := dependencydiff.GetDependencyDiffResults( ctx, repoURI, - base, head, + base, base, checksToRun, changeTypesToCheck, )