mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-23 07:29:00 -08:00
98 lines
2.3 KiB
Go
98 lines
2.3 KiB
Go
package resolvers
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"sync/atomic"
|
|
|
|
"github.com/hashicorp/go-getter"
|
|
|
|
"github.com/aquasecurity/trivy/pkg/log"
|
|
)
|
|
|
|
type remoteResolver struct {
|
|
count int32
|
|
}
|
|
|
|
var Remote = &remoteResolver{
|
|
count: 0,
|
|
}
|
|
|
|
func (r *remoteResolver) incrementCount(o Options) {
|
|
|
|
atomic.CompareAndSwapInt32(&r.count, r.count, r.count+1)
|
|
o.Logger.Debug("Incrementing the download counter", log.Int("count", int(r.count)))
|
|
}
|
|
|
|
func (r *remoteResolver) GetDownloadCount() int {
|
|
return int(atomic.LoadInt32(&r.count))
|
|
}
|
|
|
|
func (r *remoteResolver) Resolve(ctx context.Context, _ fs.FS, opt Options) (filesystem fs.FS, prefix, downloadPath string, applies bool, err error) {
|
|
if !opt.hasPrefix("github.com/", "bitbucket.org/", "s3:", "git@", "git:", "hg:", "https:", "gcs:") {
|
|
return nil, "", "", false, nil
|
|
}
|
|
|
|
if !opt.AllowDownloads {
|
|
return nil, "", "", false, nil
|
|
}
|
|
|
|
src, subdir := splitPackageSubdirRaw(opt.OriginalSource)
|
|
key := cacheKey(src, opt.OriginalVersion)
|
|
opt.Logger.Debug("Caching module", log.String("key", key))
|
|
|
|
baseCacheDir, err := locateCacheDir(opt.CacheDir)
|
|
if err != nil {
|
|
return nil, "", "", true, fmt.Errorf("failed to locate cache directory: %w", err)
|
|
}
|
|
cacheDir := filepath.Join(baseCacheDir, key)
|
|
if err := r.download(ctx, opt, cacheDir); err != nil {
|
|
return nil, "", "", true, err
|
|
}
|
|
|
|
r.incrementCount(opt)
|
|
opt.Logger.Debug("Successfully resolve module via remote download",
|
|
log.String("name", opt.Name),
|
|
log.String("source", opt.Source),
|
|
)
|
|
return os.DirFS(cacheDir), opt.Source, subdir, true, nil
|
|
}
|
|
|
|
func (r *remoteResolver) download(ctx context.Context, opt Options, dst string) error {
|
|
_ = os.RemoveAll(dst)
|
|
if err := os.MkdirAll(filepath.Dir(dst), 0o750); err != nil {
|
|
return err
|
|
}
|
|
|
|
var opts []getter.ClientOption
|
|
|
|
// Overwrite the file getter so that a file will be copied
|
|
getter.Getters["file"] = &getter.FileGetter{Copy: true}
|
|
|
|
opt.Logger.Debug("Downloading module", log.String("source", opt.Source))
|
|
|
|
// Build the client
|
|
client := &getter.Client{
|
|
Ctx: ctx,
|
|
Src: opt.Source,
|
|
Dst: dst,
|
|
Pwd: opt.WorkingDir,
|
|
Getters: getter.Getters,
|
|
Mode: getter.ClientModeAny,
|
|
Options: opts,
|
|
}
|
|
|
|
if err := client.Get(); err != nil {
|
|
return fmt.Errorf("failed to download: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *remoteResolver) GetSourcePrefix(source string) string {
|
|
return source
|
|
}
|