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

     1  package jar
     2  
     3  import (
     4  	"context"
     5  	"io/fs"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"golang.org/x/xerrors"
    11  
    12  	dio "github.com/aquasecurity/go-dep-parser/pkg/io"
    13  	"github.com/aquasecurity/go-dep-parser/pkg/java/jar"
    14  	"github.com/devseccon/trivy/pkg/fanal/analyzer"
    15  	"github.com/devseccon/trivy/pkg/fanal/analyzer/language"
    16  	"github.com/devseccon/trivy/pkg/fanal/types"
    17  	"github.com/devseccon/trivy/pkg/javadb"
    18  	"github.com/devseccon/trivy/pkg/parallel"
    19  )
    20  
    21  func init() {
    22  	analyzer.RegisterPostAnalyzer(analyzer.TypeJar, newJavaLibraryAnalyzer)
    23  }
    24  
    25  const version = 1
    26  
    27  var requiredExtensions = []string{
    28  	".jar",
    29  	".war",
    30  	".ear",
    31  	".par",
    32  }
    33  
    34  // javaLibraryAnalyzer analyzes jar/war/ear/par files
    35  type javaLibraryAnalyzer struct {
    36  	parallel int
    37  }
    38  
    39  func newJavaLibraryAnalyzer(options analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) {
    40  	return &javaLibraryAnalyzer{
    41  		parallel: options.Parallel,
    42  	}, nil
    43  }
    44  
    45  func (a *javaLibraryAnalyzer) PostAnalyze(ctx context.Context, input analyzer.PostAnalysisInput) (*analyzer.AnalysisResult, error) {
    46  	// TODO: think about the sonatype API and "--offline"
    47  	client, err := javadb.NewClient()
    48  	if err != nil {
    49  		return nil, xerrors.Errorf("Unable to initialize the Java DB: %s", err)
    50  	}
    51  	defer func() { _ = client.Close() }()
    52  
    53  	// Skip analyzing JAR files as the nil client means the Java DB was not downloaded successfully.
    54  	if client == nil {
    55  		return nil, nil
    56  	}
    57  
    58  	// It will be called on each JAR file
    59  	onFile := func(path string, info fs.FileInfo, r dio.ReadSeekerAt) (*types.Application, error) {
    60  		p := jar.NewParser(client, jar.WithSize(info.Size()), jar.WithFilePath(path))
    61  		return language.ParsePackage(types.Jar, path, r, p, input.Options.FileChecksum)
    62  	}
    63  
    64  	var apps []types.Application
    65  	onResult := func(app *types.Application) error {
    66  		if app == nil {
    67  			return nil
    68  		}
    69  		apps = append(apps, *app)
    70  		return nil
    71  	}
    72  
    73  	if err = parallel.WalkDir(ctx, input.FS, ".", a.parallel, onFile, onResult); err != nil {
    74  		return nil, xerrors.Errorf("walk dir error: %w", err)
    75  	}
    76  
    77  	return &analyzer.AnalysisResult{
    78  		Applications: apps,
    79  	}, nil
    80  }
    81  
    82  func (a *javaLibraryAnalyzer) Required(filePath string, _ os.FileInfo) bool {
    83  	ext := filepath.Ext(filePath)
    84  	for _, required := range requiredExtensions {
    85  		if strings.EqualFold(ext, required) {
    86  			return true
    87  		}
    88  	}
    89  	return false
    90  }
    91  
    92  func (a *javaLibraryAnalyzer) Type() analyzer.Type {
    93  	return analyzer.TypeJar
    94  }
    95  
    96  func (a *javaLibraryAnalyzer) Version() int {
    97  	return version
    98  }