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 }