Files
trivy/pkg/fanal/analyzer/language/dotnet/nuget/nuget.go
Teppei Fukuda 3eecfc6b6e refactor: unify Library and Package structs (#6633)
Signed-off-by: knqyf263 <knqyf263@gmail.com>
Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com>
Co-authored-by: DmitriyLewen <dmitriy.lewen@smartforce.io>
2024-05-07 12:25:52 +00:00

119 lines
2.8 KiB
Go

package nuget
import (
"context"
"errors"
"io"
"io/fs"
"os"
"path/filepath"
"sort"
"golang.org/x/exp/slices"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/parser/nuget/config"
"github.com/aquasecurity/trivy/pkg/dependency/parser/nuget/lock"
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
"github.com/aquasecurity/trivy/pkg/fanal/analyzer/language"
"github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/utils/fsutils"
)
func init() {
analyzer.RegisterPostAnalyzer(analyzer.TypeNuget, newNugetLibraryAnalyzer)
}
const (
version = 3
lockFile = types.NuGetPkgsLock
configFile = types.NuGetPkgsConfig
)
var requiredFiles = []string{
lockFile,
configFile,
}
type nugetLibraryAnalyzer struct {
lockParser language.Parser
configParser language.Parser
licenseParser nuspecParser
}
func newNugetLibraryAnalyzer(_ analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) {
return &nugetLibraryAnalyzer{
lockParser: lock.NewParser(),
configParser: config.NewParser(),
licenseParser: newNuspecParser(),
}, nil
}
func (a *nugetLibraryAnalyzer) PostAnalyze(_ context.Context, input analyzer.PostAnalysisInput) (*analyzer.AnalysisResult, error) {
var apps []types.Application
foundLicenses := make(map[string][]string)
// We saved only config and lock files in the FS,
// so we need to parse all saved files
required := func(path string, d fs.DirEntry) bool {
return true
}
err := fsutils.WalkDir(input.FS, ".", required, func(path string, d fs.DirEntry, r io.Reader) error {
// Set the default parser
parser := a.lockParser
targetFile := filepath.Base(path)
if targetFile == configFile {
parser = a.configParser
}
app, err := language.Parse(types.NuGet, path, r, parser)
if err != nil {
return xerrors.Errorf("NuGet parse error: %w", err)
}
// nuget file doesn't contain dependencies
if app == nil {
return nil
}
for i, lib := range app.Packages {
license, ok := foundLicenses[lib.ID]
if !ok {
license, err = a.licenseParser.findLicense(lib.Name, lib.Version)
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return xerrors.Errorf("license find error: %w", err)
}
foundLicenses[lib.ID] = license
}
app.Packages[i].Licenses = license
}
sort.Sort(app.Packages)
apps = append(apps, *app)
return nil
})
if err != nil {
return nil, xerrors.Errorf("NuGet walk error: %w", err)
}
return &analyzer.AnalysisResult{
Applications: apps,
}, nil
}
func (a *nugetLibraryAnalyzer) Required(filePath string, _ os.FileInfo) bool {
fileName := filepath.Base(filePath)
return slices.Contains(requiredFiles, fileName)
}
func (a *nugetLibraryAnalyzer) Type() analyzer.Type {
return analyzer.TypeNuget
}
func (a *nugetLibraryAnalyzer) Version() int {
return version
}