github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/fanal/analyzer/config_analyzer.go (about)

     1  package analyzer
     2  
     3  import (
     4  	"context"
     5  
     6  	v1 "github.com/google/go-containerregistry/pkg/v1"
     7  	"golang.org/x/exp/slices"
     8  	"golang.org/x/xerrors"
     9  
    10  	"github.com/devseccon/trivy/pkg/fanal/types"
    11  	"github.com/devseccon/trivy/pkg/log"
    12  	"github.com/devseccon/trivy/pkg/misconf"
    13  )
    14  
    15  var configAnalyzerConstructors = make(map[Type]configAnalyzerConstructor)
    16  
    17  type configAnalyzerConstructor func(ConfigAnalyzerOptions) (ConfigAnalyzer, error)
    18  
    19  // RegisterConfigAnalyzer adds a constructor of config analyzer
    20  func RegisterConfigAnalyzer(t Type, init configAnalyzerConstructor) {
    21  	configAnalyzerConstructors[t] = init
    22  }
    23  
    24  // DeregisterConfigAnalyzer is mainly for testing
    25  func DeregisterConfigAnalyzer(t Type) {
    26  	delete(configAnalyzerConstructors, t)
    27  }
    28  
    29  // ConfigAnalyzer defines an interface for analyzer of container image config
    30  type ConfigAnalyzer interface {
    31  	Type() Type
    32  	Version() int
    33  	Analyze(ctx context.Context, input ConfigAnalysisInput) (*ConfigAnalysisResult, error)
    34  	Required(osFound types.OS) bool
    35  }
    36  
    37  // ConfigAnalyzerOptions is used to initialize config analyzers
    38  type ConfigAnalyzerOptions struct {
    39  	FilePatterns         []string
    40  	DisabledAnalyzers    []Type
    41  	MisconfScannerOption misconf.ScannerOption
    42  	SecretScannerOption  SecretScannerOption
    43  }
    44  
    45  type ConfigAnalysisInput struct {
    46  	OS     types.OS
    47  	Config *v1.ConfigFile
    48  }
    49  
    50  type ConfigAnalysisResult struct {
    51  	Misconfiguration *types.Misconfiguration
    52  	Secret           *types.Secret
    53  	HistoryPackages  types.Packages
    54  }
    55  
    56  func (r *ConfigAnalysisResult) Merge(newResult *ConfigAnalysisResult) {
    57  	if newResult == nil {
    58  		return
    59  	}
    60  	if newResult.Misconfiguration != nil {
    61  		r.Misconfiguration = newResult.Misconfiguration
    62  	}
    63  	if newResult.Secret != nil {
    64  		r.Secret = newResult.Secret
    65  	}
    66  	if newResult.HistoryPackages != nil {
    67  		r.HistoryPackages = newResult.HistoryPackages
    68  	}
    69  }
    70  
    71  type ConfigAnalyzerGroup struct {
    72  	configAnalyzers []ConfigAnalyzer
    73  }
    74  
    75  func NewConfigAnalyzerGroup(opts ConfigAnalyzerOptions) (ConfigAnalyzerGroup, error) {
    76  	var g ConfigAnalyzerGroup
    77  	for t, newConfigAnalyzer := range configAnalyzerConstructors {
    78  		// Skip the handler if it is disabled
    79  		if slices.Contains(opts.DisabledAnalyzers, t) {
    80  			continue
    81  		}
    82  		a, err := newConfigAnalyzer(opts)
    83  		if err != nil {
    84  			return ConfigAnalyzerGroup{}, xerrors.Errorf("config analyzer %s initialize error: %w", t, err)
    85  		}
    86  
    87  		g.configAnalyzers = append(g.configAnalyzers, a)
    88  	}
    89  
    90  	return g, nil
    91  }
    92  
    93  // AnalyzerVersions returns analyzer version identifier used for cache keys.
    94  func (ag *ConfigAnalyzerGroup) AnalyzerVersions() Versions {
    95  	versions := make(map[string]int)
    96  	for _, ca := range ag.configAnalyzers {
    97  		versions[string(ca.Type())] = ca.Version()
    98  	}
    99  	return Versions{
   100  		Analyzers: versions,
   101  	}
   102  }
   103  
   104  func (ag *ConfigAnalyzerGroup) AnalyzeImageConfig(ctx context.Context, targetOS types.OS, config *v1.ConfigFile) *ConfigAnalysisResult {
   105  	input := ConfigAnalysisInput{
   106  		OS:     targetOS,
   107  		Config: config,
   108  	}
   109  	result := new(ConfigAnalysisResult)
   110  	for _, a := range ag.configAnalyzers {
   111  		if !a.Required(targetOS) {
   112  			continue
   113  		}
   114  
   115  		r, err := a.Analyze(ctx, input)
   116  		if err != nil {
   117  			log.Logger.Debugf("Image config analysis error: %s", err)
   118  			continue
   119  		}
   120  
   121  		result.Merge(r)
   122  	}
   123  	return result
   124  }