fix(report): tidy dependencies for multiple repo on integration with GSA (#1593)
* initialize dependencyGraphManifests out of loop * remove GitHubSecurityAlert.PackageName * tidy dependency map for multi repo * set repo name into SBOM components & purl for multi repo
This commit is contained in:
		@@ -291,6 +291,8 @@ func DetectGitHubCves(r *models.ScanResult, githubConfs map[string]config.GitHub
 | 
			
		||||
	if len(githubConfs) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r.GitHubManifests = models.DependencyGraphManifests{}
 | 
			
		||||
	for ownerRepo, setting := range githubConfs {
 | 
			
		||||
		ss := strings.Split(ownerRepo, "/")
 | 
			
		||||
		if len(ss) != 2 {
 | 
			
		||||
 
 | 
			
		||||
@@ -79,12 +79,8 @@ func DetectGitHubSecurityAlerts(r *models.ScanResult, owner, repo, token string,
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			repoURLPkgName := fmt.Sprintf("%s %s",
 | 
			
		||||
				alerts.Data.Repository.URL, v.Node.SecurityVulnerability.Package.Name)
 | 
			
		||||
 | 
			
		||||
			m := models.GitHubSecurityAlert{
 | 
			
		||||
				PackageName: repoURLPkgName,
 | 
			
		||||
				Repository:  alerts.Data.Repository.URL,
 | 
			
		||||
				Repository: alerts.Data.Repository.URL,
 | 
			
		||||
				Package: models.GSAVulnerablePackage{
 | 
			
		||||
					Name:             v.Node.SecurityVulnerability.Package.Name,
 | 
			
		||||
					Ecosystem:        v.Node.SecurityVulnerability.Package.Ecosystem,
 | 
			
		||||
@@ -219,7 +215,6 @@ func DetectGitHubDependencyGraph(r *models.ScanResult, owner, repo, token string
 | 
			
		||||
	)
 | 
			
		||||
	//TODO Proxy
 | 
			
		||||
	httpClient := oauth2.NewClient(context.Background(), src)
 | 
			
		||||
	r.GitHubManifests = models.DependencyGraphManifests{}
 | 
			
		||||
 | 
			
		||||
	return fetchDependencyGraph(r, httpClient, owner, repo, "", "")
 | 
			
		||||
}
 | 
			
		||||
@@ -268,9 +263,10 @@ func fetchDependencyGraph(r *models.ScanResult, httpClient *http.Client, owner,
 | 
			
		||||
 | 
			
		||||
	dependenciesAfter = ""
 | 
			
		||||
	for _, m := range graph.Data.Repository.DependencyGraphManifests.Edges {
 | 
			
		||||
		manifest, ok := r.GitHubManifests[m.Node.Filename]
 | 
			
		||||
		manifest, ok := r.GitHubManifests[m.Node.BlobPath]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			manifest = models.DependencyGraphManifest{
 | 
			
		||||
				BlobPath:     m.Node.BlobPath,
 | 
			
		||||
				Filename:     m.Node.Filename,
 | 
			
		||||
				Repository:   m.Node.Repository.URL,
 | 
			
		||||
				Dependencies: []models.Dependency{},
 | 
			
		||||
@@ -284,7 +280,7 @@ func fetchDependencyGraph(r *models.ScanResult, httpClient *http.Client, owner,
 | 
			
		||||
				Requirements:   d.Node.Requirements,
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
		r.GitHubManifests[m.Node.Filename] = manifest
 | 
			
		||||
		r.GitHubManifests[m.Node.BlobPath] = manifest
 | 
			
		||||
 | 
			
		||||
		if m.Node.Dependencies.PageInfo.HasNextPage {
 | 
			
		||||
			dependenciesAfter = fmt.Sprintf(`(after: \"%s\")`, m.Node.Dependencies.PageInfo.EndCursor)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,28 @@
 | 
			
		||||
package models
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DependencyGraphManifests has a map of DependencyGraphManifest
 | 
			
		||||
// key: Filename
 | 
			
		||||
// key: BlobPath
 | 
			
		||||
type DependencyGraphManifests map[string]DependencyGraphManifest
 | 
			
		||||
 | 
			
		||||
type DependencyGraphManifest struct {
 | 
			
		||||
	BlobPath     string       `json:"blobPath"`
 | 
			
		||||
	Filename     string       `json:"filename"`
 | 
			
		||||
	Repository   string       `json:"repository"`
 | 
			
		||||
	Dependencies []Dependency `json:"dependencies"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RepoURLFilename should be same format with GitHubSecurityAlert.RepoURLManifestPath()
 | 
			
		||||
func (m DependencyGraphManifest) RepoURLFilename() string {
 | 
			
		||||
	return fmt.Sprintf("%s/%s", m.Repository, m.Filename)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Ecosystem returns a name of ecosystem(or package manager) of manifest(lock) file in trivy way
 | 
			
		||||
// https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-the-dependency-graph#supported-package-ecosystems
 | 
			
		||||
func (m DependencyGraphManifest) Ecosystem() string {
 | 
			
		||||
 
 | 
			
		||||
@@ -299,10 +299,8 @@ func (g GitHubSecurityAlerts) Names() (names []string) {
 | 
			
		||||
	return names
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GitHubSecurityAlert has detected CVE-ID, PackageName, Status fetched via GitHub API
 | 
			
		||||
// GitHubSecurityAlert has detected CVE-ID, GSAVulnerablePackage, Status fetched via GitHub API
 | 
			
		||||
type GitHubSecurityAlert struct {
 | 
			
		||||
	// TODO: PackageName deprecated. it will be removed next time.
 | 
			
		||||
	PackageName   string               `json:"packageName"`
 | 
			
		||||
	Repository    string               `json:"repository"`
 | 
			
		||||
	Package       GSAVulnerablePackage `json:"package,omitempty"`
 | 
			
		||||
	FixedIn       string               `json:"fixedIn"`
 | 
			
		||||
@@ -316,6 +314,11 @@ func (a GitHubSecurityAlert) RepoURLPackageName() string {
 | 
			
		||||
	return fmt.Sprintf("%s %s", a.Repository, a.Package.Name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RepoURLManifestPath should be same format with DependencyGraphManifest.RepoURLFilename()
 | 
			
		||||
func (a GitHubSecurityAlert) RepoURLManifestPath() string {
 | 
			
		||||
	return fmt.Sprintf("%s/%s", a.Repository, a.Package.ManifestPath)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type GSAVulnerablePackage struct {
 | 
			
		||||
	Name             string `json:"name"`
 | 
			
		||||
	Ecosystem        string `json:"ecosystem"`
 | 
			
		||||
 
 | 
			
		||||
@@ -86,7 +86,7 @@ func cdxComponents(result models.ScanResult, metaBomRef string) (*[]cdx.Componen
 | 
			
		||||
 | 
			
		||||
	ghpkgToPURL := map[string]map[string]string{}
 | 
			
		||||
	for _, ghm := range result.GitHubManifests {
 | 
			
		||||
		ghpkgToPURL[ghm.Filename] = map[string]string{}
 | 
			
		||||
		ghpkgToPURL[ghm.RepoURLFilename()] = map[string]string{}
 | 
			
		||||
 | 
			
		||||
		ghpkgComps := ghpkgToCdxComponents(ghm, ghpkgToPURL)
 | 
			
		||||
		bomRefs[metaBomRef] = append(bomRefs[metaBomRef], ghpkgComps[0].BOMRef)
 | 
			
		||||
@@ -275,7 +275,7 @@ func ghpkgToCdxComponents(m models.DependencyGraphManifest, ghpkgToPURL map[stri
 | 
			
		||||
		{
 | 
			
		||||
			BOMRef: uuid.NewString(),
 | 
			
		||||
			Type:   cdx.ComponentTypeApplication,
 | 
			
		||||
			Name:   m.Filename,
 | 
			
		||||
			Name:   m.BlobPath,
 | 
			
		||||
			Properties: &[]cdx.Property{
 | 
			
		||||
				{
 | 
			
		||||
					Name:  "future-architect:vuls:Type",
 | 
			
		||||
@@ -286,7 +286,7 @@ func ghpkgToCdxComponents(m models.DependencyGraphManifest, ghpkgToPURL map[stri
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, dep := range m.Dependencies {
 | 
			
		||||
		purl := packageurl.NewPackageURL(m.Ecosystem(), "", dep.PackageName, dep.Version(), packageurl.Qualifiers{{Key: "file_path", Value: m.Filename}}, "").ToString()
 | 
			
		||||
		purl := packageurl.NewPackageURL(m.Ecosystem(), "", dep.PackageName, dep.Version(), packageurl.Qualifiers{{Key: "repo_url", Value: m.Repository}, {Key: "file_path", Value: m.Filename}}, "").ToString()
 | 
			
		||||
		components = append(components, cdx.Component{
 | 
			
		||||
			BOMRef:     purl,
 | 
			
		||||
			Type:       cdx.ComponentTypeLibrary,
 | 
			
		||||
@@ -295,7 +295,7 @@ func ghpkgToCdxComponents(m models.DependencyGraphManifest, ghpkgToPURL map[stri
 | 
			
		||||
			PackageURL: purl,
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		ghpkgToPURL[m.Filename][dep.PackageName] = purl
 | 
			
		||||
		ghpkgToPURL[m.RepoURLFilename()][dep.PackageName] = purl
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return components
 | 
			
		||||
@@ -496,7 +496,7 @@ func cdxAffects(cve models.VulnInfo, ospkgToPURL map[string]string, libpkgToPURL
 | 
			
		||||
	}
 | 
			
		||||
	for _, alert := range cve.GitHubSecurityAlerts {
 | 
			
		||||
		// TODO: not in dependency graph
 | 
			
		||||
		if purl, ok := ghpkgToPURL[alert.Package.ManifestPath][alert.Package.Name]; ok {
 | 
			
		||||
		if purl, ok := ghpkgToPURL[alert.RepoURLManifestPath()][alert.Package.Name]; ok {
 | 
			
		||||
			affects = append(affects, cdx.Affects{
 | 
			
		||||
				Ref: purl,
 | 
			
		||||
			})
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user