-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
lockfile.go
120 lines (99 loc) · 2.87 KB
/
lockfile.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package gradle
import (
"context"
"fmt"
"io"
"io/fs"
"os"
"sort"
"strings"
"github.com/samber/lo"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/parser/gradle/lockfile"
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
"github.com/aquasecurity/trivy/pkg/fanal/analyzer/language"
"github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/utils/fsutils"
)
func init() {
analyzer.RegisterPostAnalyzer(analyzer.TypeGradleLock, newGradleLockAnalyzer)
}
const (
version = 2
fileNameSuffix = "gradle.lockfile"
)
// gradleLockAnalyzer analyzes '*gradle.lockfile'
type gradleLockAnalyzer struct {
logger *log.Logger
parser language.Parser
}
func newGradleLockAnalyzer(_ analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) {
return &gradleLockAnalyzer{
logger: log.WithPrefix("gradle"),
parser: lockfile.NewParser(),
}, nil
}
func (a gradleLockAnalyzer) PostAnalyze(_ context.Context, input analyzer.PostAnalysisInput) (*analyzer.AnalysisResult, error) {
poms, err := a.parsePoms()
if err != nil {
a.logger.Warn("Unable to get licenses and dependencies", log.Err(err))
}
required := func(path string, d fs.DirEntry) bool {
return a.Required(path, nil)
}
var apps []types.Application
err = fsutils.WalkDir(input.FS, ".", required, func(filePath string, _ fs.DirEntry, r io.Reader) error {
var app *types.Application
app, err = language.Parse(types.Gradle, filePath, r, a.parser)
if err != nil {
return xerrors.Errorf("%s parse error: %w", filePath, err)
}
if app == nil {
return nil
}
pkgs := lo.SliceToMap(app.Packages, func(lib types.Package) (string, struct{}) {
return lib.ID, struct{}{}
})
for i, lib := range app.Packages {
pom := poms[lib.ID]
// Fill licenses from pom file
if len(pom.Licenses.License) > 0 {
app.Packages[i].Licenses = lo.Map(pom.Licenses.License, func(license License, _ int) string {
return license.Name
})
}
// File child deps from pom file
var deps []string
for _, dep := range pom.Dependencies.Dependency {
id := packageID(dep.GroupID, dep.ArtifactID, dep.Version)
if _, ok := pkgs[id]; ok {
deps = append(deps, id)
}
}
sort.Strings(deps)
app.Packages[i].DependsOn = deps
}
sort.Sort(app.Packages)
apps = append(apps, *app)
return nil
})
if err != nil {
return nil, xerrors.Errorf("walk error: %w", err)
}
return &analyzer.AnalysisResult{
Applications: apps,
}, nil
}
func (a gradleLockAnalyzer) Required(filePath string, _ os.FileInfo) bool {
return strings.HasSuffix(filePath, fileNameSuffix)
}
func (a gradleLockAnalyzer) Type() analyzer.Type {
return analyzer.TypeGradleLock
}
func (a gradleLockAnalyzer) Version() int {
return version
}
func packageID(groupId, artifactId, ver string) string {
return fmt.Sprintf("%s:%s:%s", groupId, artifactId, ver)
}