github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/pkg/scanners/terraform/parser/resolvers/cache.go (about)

     1  package resolvers
     2  
     3  import (
     4  	"context"
     5  	"crypto/md5" // nolint
     6  	"fmt"
     7  	"io/fs"
     8  	"os"
     9  	"path/filepath"
    10  )
    11  
    12  type cacheResolver struct{}
    13  
    14  var Cache = &cacheResolver{}
    15  
    16  const tempDirName = ".khulnasoft"
    17  
    18  func locateCacheFS() (fs.FS, error) {
    19  	dir, err := locateCacheDir()
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  	return os.DirFS(dir), nil
    24  }
    25  
    26  func locateCacheDir() (string, error) {
    27  	cacheDir := filepath.Join(os.TempDir(), tempDirName, "cache")
    28  	if err := os.MkdirAll(cacheDir, 0o755); err != nil {
    29  		return "", err
    30  	}
    31  	if !isWritable(cacheDir) {
    32  		return "", fmt.Errorf("cache directory is not writable")
    33  	}
    34  	return cacheDir, nil
    35  }
    36  
    37  func (r *cacheResolver) Resolve(_ context.Context, _ fs.FS, opt Options) (filesystem fs.FS, prefix string, downloadPath string, applies bool, err error) {
    38  	if !opt.AllowCache {
    39  		opt.Debug("Cache is disabled.")
    40  		return nil, "", "", false, nil
    41  	}
    42  	cacheFS, err := locateCacheFS()
    43  	if err != nil {
    44  		opt.Debug("No cache filesystem is available on this machine.")
    45  		return nil, "", "", false, nil
    46  	}
    47  	key := cacheKey(opt.Source, opt.Version, opt.RelativePath)
    48  	opt.Debug("Trying to resolve: %s", key)
    49  	if info, err := fs.Stat(cacheFS, filepath.ToSlash(key)); err == nil && info.IsDir() {
    50  		opt.Debug("Module '%s' resolving via cache...", opt.Name)
    51  		cacheDir, err := locateCacheDir()
    52  		if err != nil {
    53  			return nil, "", "", true, err
    54  		}
    55  		return os.DirFS(filepath.Join(cacheDir, key)), opt.OriginalSource, ".", true, nil
    56  	}
    57  	return nil, "", "", false, nil
    58  }
    59  
    60  func cacheKey(source, version, relativePath string) string {
    61  	return fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%s:%s:%s", source, version, relativePath)))) // nolint
    62  }