github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/fanal/cache/key.go (about) 1 package cache 2 3 import ( 4 "crypto/sha256" 5 "encoding/json" 6 "fmt" 7 "io" 8 "os" 9 "path/filepath" 10 11 "golang.org/x/mod/sumdb/dirhash" 12 "golang.org/x/xerrors" 13 14 "github.com/devseccon/trivy/pkg/fanal/analyzer" 15 "github.com/devseccon/trivy/pkg/fanal/artifact" 16 ) 17 18 func CalcKey(id string, analyzerVersions analyzer.Versions, hookVersions map[string]int, artifactOpt artifact.Option) (string, error) { 19 // Sort options for consistent results 20 artifactOpt.Sort() 21 artifactOpt.MisconfScannerOption.Sort() 22 23 h := sha256.New() 24 25 // Write ID, analyzer/handler versions, skipped files/dirs and file patterns 26 keyBase := struct { 27 ID string 28 AnalyzerVersions analyzer.Versions 29 HookVersions map[string]int 30 SkipFiles []string 31 SkipDirs []string 32 FilePatterns []string `json:",omitempty"` 33 }{id, analyzerVersions, hookVersions, artifactOpt.SkipFiles, artifactOpt.SkipDirs, artifactOpt.FilePatterns} 34 35 if err := json.NewEncoder(h).Encode(keyBase); err != nil { 36 return "", xerrors.Errorf("json encode error: %w", err) 37 } 38 39 // Write policy, data contents and secret config file 40 paths := append(artifactOpt.MisconfScannerOption.PolicyPaths, artifactOpt.MisconfScannerOption.DataPaths...) 41 42 // Check if the secret config exists. 43 if _, err := os.Stat(artifactOpt.SecretScannerOption.ConfigPath); err == nil { 44 paths = append(paths, artifactOpt.SecretScannerOption.ConfigPath) 45 } 46 47 for _, p := range paths { 48 hash, err := hashContents(p) 49 if err != nil { 50 return "", err 51 } 52 53 if _, err := h.Write([]byte(hash)); err != nil { 54 return "", xerrors.Errorf("sha256 write error: %w", err) 55 } 56 } 57 58 return fmt.Sprintf("sha256:%x", h.Sum(nil)), nil 59 } 60 61 func hashContents(path string) (string, error) { 62 fi, err := os.Stat(path) 63 if err != nil { 64 return "", xerrors.Errorf("file %q stat error: %w", path, err) 65 } 66 67 var hash string 68 69 if fi.IsDir() { 70 hash, err = dirhash.HashDir(path, "", dirhash.DefaultHash) 71 if err != nil { 72 return "", xerrors.Errorf("hash dir error (%s): %w", path, err) 73 } 74 } else { 75 hash, err = dirhash.DefaultHash([]string{filepath.Base(path)}, func(_ string) (io.ReadCloser, error) { 76 return os.Open(path) 77 }) 78 if err != nil { 79 return "", xerrors.Errorf("hash file error (%s): %w", path, err) 80 } 81 } 82 return hash, nil 83 }