-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
config_analyzer.go
124 lines (104 loc) · 3.1 KB
/
config_analyzer.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
121
122
123
124
package analyzer
import (
"context"
v1 "github.com/google/go-containerregistry/pkg/v1"
"golang.org/x/exp/slices"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/misconf"
)
var configAnalyzerConstructors = map[Type]configAnalyzerConstructor{}
type configAnalyzerConstructor func(ConfigAnalyzerOptions) (ConfigAnalyzer, error)
// RegisterConfigAnalyzer adds a constructor of config analyzer
func RegisterConfigAnalyzer(t Type, init configAnalyzerConstructor) {
configAnalyzerConstructors[t] = init
}
// DeregisterConfigAnalyzer is mainly for testing
func DeregisterConfigAnalyzer(t Type) {
delete(configAnalyzerConstructors, t)
}
// ConfigAnalyzer defines an interface for analyzer of container image config
type ConfigAnalyzer interface {
Type() Type
Version() int
Analyze(ctx context.Context, input ConfigAnalysisInput) (*ConfigAnalysisResult, error)
Required(osFound types.OS) bool
}
// ConfigAnalyzerOptions is used to initialize config analyzers
type ConfigAnalyzerOptions struct {
FilePatterns []string
DisabledAnalyzers []Type
MisconfScannerOption misconf.ScannerOption
SecretScannerOption SecretScannerOption
}
type ConfigAnalysisInput struct {
OS types.OS
Config *v1.ConfigFile
}
type ConfigAnalysisResult struct {
Misconfiguration *types.Misconfiguration
Secret *types.Secret
HistoryPackages types.Packages
}
func (r *ConfigAnalysisResult) Merge(new *ConfigAnalysisResult) {
if new == nil {
return
}
if new.Misconfiguration != nil {
r.Misconfiguration = new.Misconfiguration
}
if new.Secret != nil {
r.Secret = new.Secret
}
if new.HistoryPackages != nil {
r.HistoryPackages = new.HistoryPackages
}
}
type ConfigAnalyzerGroup struct {
configAnalyzers []ConfigAnalyzer
}
func NewConfigAnalyzerGroup(opts ConfigAnalyzerOptions) (ConfigAnalyzerGroup, error) {
var g ConfigAnalyzerGroup
for t, newConfigAnalyzer := range configAnalyzerConstructors {
// Skip the handler if it is disabled
if slices.Contains(opts.DisabledAnalyzers, t) {
continue
}
a, err := newConfigAnalyzer(opts)
if err != nil {
return ConfigAnalyzerGroup{}, xerrors.Errorf("config analyzer %s initialize error: %w", t, err)
}
g.configAnalyzers = append(g.configAnalyzers, a)
}
return g, nil
}
// AnalyzerVersions returns analyzer version identifier used for cache keys.
func (ag *ConfigAnalyzerGroup) AnalyzerVersions() Versions {
versions := map[string]int{}
for _, ca := range ag.configAnalyzers {
versions[string(ca.Type())] = ca.Version()
}
return Versions{
Analyzers: versions,
}
}
func (ag *ConfigAnalyzerGroup) AnalyzeImageConfig(ctx context.Context, targetOS types.OS, config *v1.ConfigFile) *ConfigAnalysisResult {
input := ConfigAnalysisInput{
OS: targetOS,
Config: config,
}
result := new(ConfigAnalysisResult)
for _, a := range ag.configAnalyzers {
if !a.Required(targetOS) {
continue
}
r, err := a.Analyze(ctx, input)
if err != nil {
log.Logger.Debugf("Image config analysis error: %s", err)
continue
}
result.Merge(r)
}
return result
}