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

     1  package resolvers
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/fs"
     7  	"os"
     8  	"path/filepath"
     9  	"sync/atomic"
    10  
    11  	"github.com/hashicorp/go-getter"
    12  )
    13  
    14  type remoteResolver struct {
    15  	count int32
    16  }
    17  
    18  var Remote = &remoteResolver{
    19  	count: 0,
    20  }
    21  
    22  func (r *remoteResolver) incrementCount(o Options) {
    23  	o.Debug("Incrementing the download counter")
    24  	atomic.CompareAndSwapInt32(&r.count, r.count, r.count+1)
    25  	o.Debug("Download counter is now %d", r.count)
    26  }
    27  
    28  func (r *remoteResolver) GetDownloadCount() int {
    29  	return int(atomic.LoadInt32(&r.count))
    30  }
    31  
    32  func (r *remoteResolver) Resolve(ctx context.Context, _ fs.FS, opt Options) (filesystem fs.FS, prefix string, downloadPath string, applies bool, err error) {
    33  	if !opt.hasPrefix("github.com/", "bitbucket.org/", "s3:", "git@", "git:", "hg:", "https:", "gcs:") {
    34  		return nil, "", "", false, nil
    35  	}
    36  
    37  	if !opt.AllowDownloads {
    38  		return nil, "", "", false, nil
    39  	}
    40  
    41  	key := cacheKey(opt.OriginalSource, opt.OriginalVersion, opt.RelativePath)
    42  	opt.Debug("Storing with cache key %s", key)
    43  
    44  	baseCacheDir, err := locateCacheDir()
    45  	if err != nil {
    46  		return nil, "", "", true, fmt.Errorf("failed to locate cache directory: %w", err)
    47  	}
    48  	cacheDir := filepath.Join(baseCacheDir, key)
    49  	if err := r.download(ctx, opt, cacheDir); err != nil {
    50  		return nil, "", "", true, err
    51  	}
    52  
    53  	r.incrementCount(opt)
    54  	opt.Debug("Successfully downloaded %s from %s", opt.Name, opt.Source)
    55  	opt.Debug("Module '%s' resolved via remote download.", opt.Name)
    56  	return os.DirFS(cacheDir), opt.Source, filepath.Join(".", opt.RelativePath), true, nil
    57  }
    58  
    59  func (r *remoteResolver) download(ctx context.Context, opt Options, dst string) error {
    60  	_ = os.RemoveAll(dst)
    61  	if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
    62  		return err
    63  	}
    64  
    65  	var opts []getter.ClientOption
    66  
    67  	// Overwrite the file getter so that a file will be copied
    68  	getter.Getters["file"] = &getter.FileGetter{Copy: true}
    69  
    70  	opt.Debug("Downloading %s...", opt.Source)
    71  
    72  	// Build the client
    73  	client := &getter.Client{
    74  		Ctx:     ctx,
    75  		Src:     opt.Source,
    76  		Dst:     dst,
    77  		Pwd:     opt.WorkingDir,
    78  		Getters: getter.Getters,
    79  		Mode:    getter.ClientModeAny,
    80  		Options: opts,
    81  	}
    82  
    83  	if err := client.Get(); err != nil {
    84  		return fmt.Errorf("failed to download: %w", err)
    85  	}
    86  
    87  	return nil
    88  }
    89  
    90  func (r *remoteResolver) GetSourcePrefix(source string) string {
    91  	return source
    92  }