diff --git a/go.mod b/go.mod index b12cdf30855a..71f2d1628f7e 100644 --- a/go.mod +++ b/go.mod @@ -30,13 +30,12 @@ require ( github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240516051533-4c5a4aad13b7 github.com/aws/aws-sdk-go-v2 v1.27.2 - github.com/aws/aws-sdk-go-v2/config v1.27.15 - github.com/aws/aws-sdk-go-v2/credentials v1.17.15 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.20 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.161.3 - github.com/aws/aws-sdk-go-v2/service/ecr v1.28.2 - github.com/aws/aws-sdk-go-v2/service/s3 v1.54.2 - github.com/aws/aws-sdk-go-v2/service/sts v1.28.9 // indirect + github.com/aws/aws-sdk-go-v2/config v1.27.18 + github.com/aws/aws-sdk-go-v2/credentials v1.17.18 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.163.1 + github.com/aws/aws-sdk-go-v2/service/ecr v1.28.5 + github.com/aws/aws-sdk-go-v2/service/s3 v1.55.1 + github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 // indirect github.com/aws/smithy-go v1.20.2 github.com/bitnami/go-version v0.0.0-20231130084017-bb00604d650c github.com/bmatcuk/doublestar/v4 v4.6.1 @@ -169,19 +168,15 @@ require ( github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go v1.53.0 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.7 // indirect github.com/aws/aws-sdk-go-v2/service/ebs v1.21.7 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.9 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.7 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.20.8 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/briandowns/spinner v1.23.0 // indirect diff --git a/go.sum b/go.sum index 93c0f75b63ea..17d31b547023 100644 --- a/go.sum +++ b/go.sum @@ -791,46 +791,36 @@ github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go-v2 v1.27.2 h1:pLsTXqX93rimAOZG2FIYraDQstZaaGVVN4tNw65v0h8= github.com/aws/aws-sdk-go-v2 v1.27.2/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg= -github.com/aws/aws-sdk-go-v2/config v1.27.15 h1:uNnGLZ+DutuNEkuPh6fwqK7LpEiPmzb7MIMA1mNWEUc= -github.com/aws/aws-sdk-go-v2/config v1.27.15/go.mod h1:7j7Kxx9/7kTmL7z4LlhwQe63MYEE5vkVV6nWg4ZAI8M= -github.com/aws/aws-sdk-go-v2/credentials v1.17.15 h1:YDexlvDRCA8ems2T5IP1xkMtOZ1uLJOCJdTr0igs5zo= -github.com/aws/aws-sdk-go-v2/credentials v1.17.15/go.mod h1:vxHggqW6hFNaeNC0WyXS3VdyjcV0a4KMUY4dKJ96buU= +github.com/aws/aws-sdk-go-v2/config v1.27.18 h1:wFvAnwOKKe7QAyIxziwSKjmer9JBMH1vzIL6W+fYuKk= +github.com/aws/aws-sdk-go-v2/config v1.27.18/go.mod h1:0xz6cgdX55+kmppvPm2IaKzIXOheGJhAufacPJaXZ7c= +github.com/aws/aws-sdk-go-v2/credentials v1.17.18 h1:D/ALDWqK4JdY3OFgA2thcPO1c9aYTT5STS/CvnkqY1c= +github.com/aws/aws-sdk-go-v2/credentials v1.17.18/go.mod h1:JuitCWq+F5QGUrmMPsk945rop6bB57jdscu+Glozdnc= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 h1:dDgptDO9dxeFkXy+tEgVkzSClHZje/6JkPW5aZyEvrQ= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5/go.mod h1:gjvE2KBUgUQhcv89jqxrIxH9GaKs1JbZzWejj/DaHGA= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.20 h1:NCM9wYaJCmlIWZSO/JwUEveKf0NCvsSgo9V9BwOAolo= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.20/go.mod h1:dmxIx3qriuepxqZgFeFMitFuftWPB94+MZv/6Btpth4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 h1:cy8ahBJuhtM8GTTSyOkfy6WVPV1IE+SS5/wfXUYuulw= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9/go.mod h1:CZBXGLaJnEZI6EVNcPd7a6B5IC5cA/GkRWtu9fp3S6Y= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 h1:A4SYk07ef04+vxZToz9LWvAXl9LW0NClpPpMsi31cz0= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9/go.mod h1:5jJcHuwDagxN+ErjQ3PU3ocf6Ylc/p9x+BLO/+X4iXw= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.7 h1:/FUtT3xsoHO3cfh+I/kCbcMCN98QZRsiFet/V8QkWSs= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.7/go.mod h1:MaCAgWpGooQoCWZnMur97rGn5dp350w2+CeiV5406wE= github.com/aws/aws-sdk-go-v2/service/ebs v1.21.7 h1:CRzzXjmgx9p362yO39D6hbZULdMI23gaKqSxijJCXHM= github.com/aws/aws-sdk-go-v2/service/ebs v1.21.7/go.mod h1:wnsHqpi3RgDwklS5SPHUgjcUUpontGPKJ+GJYOdV7pY= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.161.3 h1:l0mvKOGm25yo/Fy+Y/08Cm4aTA4XmnIuq4ppy+shfMI= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.161.3/go.mod h1:iJ2sQeUTkjNp3nL7kE/Bav0xXYhtiRCRP5ZXk4jFhCQ= -github.com/aws/aws-sdk-go-v2/service/ecr v1.28.2 h1:xUpMnRZonKfrHaNLC77IMpWZSUMRRXIi6IU5EhAPsrM= -github.com/aws/aws-sdk-go-v2/service/ecr v1.28.2/go.mod h1:X52zjAVRaXklEU1TE/wO8kyyJSr9cJx9ZsqliWbyRys= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.163.1 h1:0RiDkJO1veM6/FQ+GJcGiIhZgPwXlscX29B0zFE4Ulo= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.163.1/go.mod h1:gYk1NtyvkH1SxPcndDtfro3lwbiE5t0tW4eRki5YnOQ= +github.com/aws/aws-sdk-go-v2/service/ecr v1.28.5 h1:dvvTFXpWSv9+8lTNPl1EPNZL6BCUV6MgVckEMvXaOgk= +github.com/aws/aws-sdk-go-v2/service/ecr v1.28.5/go.mod h1:Ogt6AOZ/sPBlJZpVFJgOK+jGGREuo8DMjNg+O/7gpjI= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.9 h1:UXqEWQI0n+q0QixzU0yUUQBZXRd5037qdInTIHFTl98= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.9/go.mod h1:xP6Gq6fzGZT8w/ZN+XvGMZ2RU1LeEs7b2yUP5DN8NY4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9 h1:Wx0rlZoEJR7JwlSZcHnEa7CNjrSIyVxMFWGAaXy4fJY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9/go.mod h1:aVMHdE0aHO3v+f/iw01fmXV/5DbfQ3Bi9nN7nd9bE9Y= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.7 h1:uO5XR6QGBcmPyo2gxofYJLFkcVQ4izOoGDNenlZhTEk= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.7/go.mod h1:feeeAYfAcwTReM6vbwjEyDmiGho+YgBhaFULuXDW8kc= -github.com/aws/aws-sdk-go-v2/service/s3 v1.54.2 h1:gYSJhNiOF6J9xaYxu2NFNstoiNELwt0T9w29FxSfN+Y= -github.com/aws/aws-sdk-go-v2/service/s3 v1.54.2/go.mod h1:739CllldowZiPPsDFcJHNF4FXrVxaSGVnZ9Ez9Iz9hc= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.8 h1:Kv1hwNG6jHC/sxMTe5saMjH6t6ZLkgfvVxyEjfWL1ks= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.8/go.mod h1:c1qtZUWtygI6ZdvKppzCSXsDOq5I4luJPZ0Ud3juFCA= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.2 h1:nWBZ1xHCF+A7vv9sDzJOq4NWIdzFYm0kH7Pr4OjHYsQ= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.2/go.mod h1:9lmoVDVLz/yUZwLaQ676TK02fhCu4+PgRSmMaKR1ozk= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.9 h1:Qp6Boy0cGDloOE3zI6XhNLNZgjNS8YmiFQFHe71SaW0= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.9/go.mod h1:0Aqn1MnEuitqfsCNyKsdKLhDUOr4txD/g19EfiUqgws= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 h1:o4T+fKxA3gTMcluBNZZXE9DNaMkJuUL1O3mffCUjoJo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11/go.mod h1:84oZdJ+VjuJKs9v1UTC9NaodRZRseOXCTgku+vQJWR8= +github.com/aws/aws-sdk-go-v2/service/s3 v1.55.1 h1:UAxBuh0/8sFJk1qOkvOKewP5sWeWaTPDknbQz0ZkDm0= +github.com/aws/aws-sdk-go-v2/service/s3 v1.55.1/go.mod h1:hWjsYGjVuqCgfoveVcVFPXIWgz0aByzwaxKlN1StKcM= +github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 h1:gEYM2GSpr4YNWc6hCd5nod4+d4kd9vWIAWrmGuLdlMw= +github.com/aws/aws-sdk-go-v2/service/sso v1.20.11/go.mod h1:gVvwPdPNYehHSP9Rs7q27U1EU+3Or2ZpXvzAYJNh63w= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 h1:iXjh3uaH3vsVcnyZX7MqCoCfcyxIrVE9iOQruRaWPrQ= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5/go.mod h1:5ZXesEuy/QcO0WUnt+4sDkxhdXRHTu2yG0uCSH8B6os= +github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 h1:M/1u4HBpwLuMtjlxuI2y6HoVLzF5e2mfxHCg7ZVMYmk= +github.com/aws/aws-sdk-go-v2/service/sts v1.28.12/go.mod h1:kcfd+eTdEi/40FIbLq4Hif3XMXnl5b/+t/KTfLt9xIk= github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= diff --git a/pkg/fanal/cache/cache.go b/pkg/cache/cache.go similarity index 100% rename from pkg/fanal/cache/cache.go rename to pkg/cache/cache.go diff --git a/pkg/cache/client.go b/pkg/cache/client.go new file mode 100644 index 000000000000..fea9395770c7 --- /dev/null +++ b/pkg/cache/client.go @@ -0,0 +1,200 @@ +package cache + +import ( + "crypto/tls" + "crypto/x509" + "fmt" + "os" + "strings" + "time" + + "github.com/go-redis/redis/v8" + "github.com/samber/lo" + "golang.org/x/xerrors" + + "github.com/aquasecurity/trivy/pkg/log" +) + +const ( + TypeFS Type = "fs" + TypeRedis Type = "redis" +) + +type Client struct { + Cache +} + +type Type string + +type Options struct { + Type Type + TTL time.Duration + Redis RedisOptions +} + +func NewOptions(backend, redisCACert, redisCert, redisKey string, redisTLS bool, ttl time.Duration) (Options, error) { + t, err := NewType(backend) + if err != nil { + return Options{}, xerrors.Errorf("cache type error: %w", err) + } + + var redisOpts RedisOptions + if t == TypeRedis { + redisTLSOpts, err := NewRedisTLSOptions(redisCACert, redisCert, redisKey) + if err != nil { + return Options{}, xerrors.Errorf("redis TLS option error: %w", err) + } + redisOpts = RedisOptions{ + Backend: backend, + TLS: redisTLS, + TLSOptions: redisTLSOpts, + } + } else if ttl != 0 { + log.Warn("'--cache-ttl' is only available with Redis cache backend") + } + + return Options{ + Type: t, + TTL: ttl, + Redis: redisOpts, + }, nil +} + +type RedisOptions struct { + Backend string + TLS bool + TLSOptions RedisTLSOptions +} + +// BackendMasked returns the redis connection string masking credentials +func (o *RedisOptions) BackendMasked() string { + endIndex := strings.Index(o.Backend, "@") + if endIndex == -1 { + return o.Backend + } + + startIndex := strings.Index(o.Backend, "//") + + return fmt.Sprintf("%s****%s", o.Backend[:startIndex+2], o.Backend[endIndex:]) +} + +// RedisTLSOptions holds the options for redis cache +type RedisTLSOptions struct { + CACert string + Cert string + Key string +} + +func NewRedisTLSOptions(caCert, cert, key string) (RedisTLSOptions, error) { + opts := RedisTLSOptions{ + CACert: caCert, + Cert: cert, + Key: key, + } + + // If one of redis option not nil, make sure CA, cert, and key provided + if !lo.IsEmpty(opts) { + if opts.CACert == "" || opts.Cert == "" || opts.Key == "" { + return RedisTLSOptions{}, xerrors.Errorf("you must provide Redis CA, cert and key file path when using TLS") + } + } + return opts, nil +} + +func NewType(backend string) (Type, error) { + // "redis://" or "fs" are allowed for now + // An empty value is also allowed for testability + switch { + case strings.HasPrefix(backend, "redis://"): + return TypeRedis, nil + case backend == "fs", backend == "": + return TypeFS, nil + default: + return "", xerrors.Errorf("unknown cache backend: %s", backend) + } +} + +// NewClient returns a new cache client +func NewClient(opts Options) (*Client, error) { + if opts.Type == TypeRedis { + log.Info("Redis cache", log.String("url", opts.Redis.BackendMasked())) + options, err := redis.ParseURL(opts.Redis.Backend) + if err != nil { + return nil, err + } + + if tlsOpts := opts.Redis.TLSOptions; !lo.IsEmpty(tlsOpts) { + caCert, cert, err := GetTLSConfig(tlsOpts.CACert, tlsOpts.Cert, tlsOpts.Key) + if err != nil { + return nil, err + } + + options.TLSConfig = &tls.Config{ + RootCAs: caCert, + Certificates: []tls.Certificate{cert}, + MinVersion: tls.VersionTLS12, + } + } else if opts.Redis.TLS { + options.TLSConfig = &tls.Config{ + MinVersion: tls.VersionTLS12, + } + } + + redisCache := NewRedisCache(options, opts.TTL) + return &Client{Cache: redisCache}, nil + } + + // standalone mode + fsCache, err := NewFSCache(Dir()) + if err != nil { + return nil, xerrors.Errorf("unable to initialize fs cache: %w", err) + } + return &Client{Cache: fsCache}, nil +} + +// Reset resets the cache +func (c *Client) Reset() (err error) { + if err := c.ClearDB(); err != nil { + return xerrors.Errorf("failed to clear the database: %w", err) + } + if err := c.ClearArtifacts(); err != nil { + return xerrors.Errorf("failed to clear the artifact cache: %w", err) + } + return nil +} + +// ClearDB clears the DB cache +func (c *Client) ClearDB() (err error) { + log.Info("Removing DB file...") + if err = os.RemoveAll(Dir()); err != nil { + return xerrors.Errorf("failed to remove the directory (%s) : %w", Dir(), err) + } + return nil +} + +// ClearArtifacts clears the artifact cache +func (c *Client) ClearArtifacts() error { + log.Info("Removing artifact caches...") + if err := c.Clear(); err != nil { + return xerrors.Errorf("failed to remove the cache: %w", err) + } + return nil +} + +// GetTLSConfig gets tls config from CA, Cert and Key file +func GetTLSConfig(caCertPath, certPath, keyPath string) (*x509.CertPool, tls.Certificate, error) { + cert, err := tls.LoadX509KeyPair(certPath, keyPath) + if err != nil { + return nil, tls.Certificate{}, err + } + + caCert, err := os.ReadFile(caCertPath) + if err != nil { + return nil, tls.Certificate{}, err + } + + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + return caCertPool, cert, nil +} diff --git a/pkg/cache/client_test.go b/pkg/cache/client_test.go new file mode 100644 index 000000000000..f22ce4f93e2f --- /dev/null +++ b/pkg/cache/client_test.go @@ -0,0 +1,129 @@ +package cache_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/aquasecurity/trivy/pkg/cache" +) + +func TestNewOptions(t *testing.T) { + type args struct { + backend string + redisCACert string + redisCert string + redisKey string + redisTLS bool + ttl time.Duration + } + tests := []struct { + name string + args args + want cache.Options + assertion require.ErrorAssertionFunc + }{ + { + name: "fs", + args: args{backend: "fs"}, + want: cache.Options{Type: cache.TypeFS}, + assertion: require.NoError, + }, + { + name: "redis", + args: args{backend: "redis://localhost:6379"}, + want: cache.Options{ + Type: cache.TypeRedis, + Redis: cache.RedisOptions{Backend: "redis://localhost:6379"}, + }, + assertion: require.NoError, + }, + { + name: "redis tls", + args: args{ + backend: "redis://localhost:6379", + redisCACert: "ca-cert.pem", + redisCert: "cert.pem", + redisKey: "key.pem", + }, + want: cache.Options{ + Type: cache.TypeRedis, + Redis: cache.RedisOptions{ + Backend: "redis://localhost:6379", + TLSOptions: cache.RedisTLSOptions{ + CACert: "ca-cert.pem", + Cert: "cert.pem", + Key: "key.pem", + }, + }, + }, + assertion: require.NoError, + }, + { + name: "redis tls with public certificates", + args: args{ + backend: "redis://localhost:6379", + redisTLS: true, + }, + want: cache.Options{ + Type: cache.TypeRedis, + Redis: cache.RedisOptions{ + Backend: "redis://localhost:6379", + TLS: true, + }, + }, + assertion: require.NoError, + }, + { + name: "unknown backend", + args: args{backend: "unknown"}, + assertion: func(t require.TestingT, err error, msgs ...any) { + require.ErrorContains(t, err, "unknown cache backend") + }, + }, + { + name: "sad redis tls", + args: args{ + backend: "redis://localhost:6379", + redisCACert: "ca-cert.pem", + }, + assertion: func(t require.TestingT, err error, msgs ...any) { + require.ErrorContains(t, err, "you must provide Redis CA, cert and key file path when using TLS") + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := cache.NewOptions(tt.args.backend, tt.args.redisCACert, tt.args.redisCert, tt.args.redisKey, tt.args.redisTLS, tt.args.ttl) + tt.assertion(t, err) + assert.Equal(t, tt.want, got) + }) + } +} + +func TestRedisOptions_BackendMasked(t *testing.T) { + tests := []struct { + name string + fields cache.RedisOptions + want string + }{ + { + name: "redis cache backend masked", + fields: cache.RedisOptions{Backend: "redis://root:password@localhost:6379"}, + want: "redis://****@localhost:6379", + }, + { + name: "redis cache backend masked does nothing", + fields: cache.RedisOptions{Backend: "redis://localhost:6379"}, + want: "redis://localhost:6379", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, tt.fields.BackendMasked()) + }) + } +} diff --git a/pkg/cache/dir.go b/pkg/cache/dir.go new file mode 100644 index 000000000000..b687017c9faf --- /dev/null +++ b/pkg/cache/dir.go @@ -0,0 +1,30 @@ +package cache + +import ( + "os" + "path/filepath" +) + +var cacheDir string + +// defaultDir returns/creates the cache-dir to be used for trivy operations +func defaultDir() string { + tmpDir, err := os.UserCacheDir() + if err != nil { + tmpDir = os.TempDir() + } + return filepath.Join(tmpDir, "trivy") +} + +// Dir returns the directory used for caching +func Dir() string { + if cacheDir == "" { + return defaultDir() + } + return cacheDir +} + +// SetDir sets the trivy cache dir +func SetDir(dir string) { + cacheDir = dir +} diff --git a/pkg/fanal/cache/fs.go b/pkg/cache/fs.go similarity index 100% rename from pkg/fanal/cache/fs.go rename to pkg/cache/fs.go diff --git a/pkg/fanal/cache/fs_test.go b/pkg/cache/fs_test.go similarity index 100% rename from pkg/fanal/cache/fs_test.go rename to pkg/cache/fs_test.go diff --git a/pkg/fanal/cache/key.go b/pkg/cache/key.go similarity index 100% rename from pkg/fanal/cache/key.go rename to pkg/cache/key.go diff --git a/pkg/fanal/cache/key_test.go b/pkg/cache/key_test.go similarity index 100% rename from pkg/fanal/cache/key_test.go rename to pkg/cache/key_test.go diff --git a/pkg/fanal/cache/mock_artifact_cache.go b/pkg/cache/mock_artifact_cache.go similarity index 100% rename from pkg/fanal/cache/mock_artifact_cache.go rename to pkg/cache/mock_artifact_cache.go diff --git a/pkg/fanal/cache/mock_cache.go b/pkg/cache/mock_cache.go similarity index 100% rename from pkg/fanal/cache/mock_cache.go rename to pkg/cache/mock_cache.go diff --git a/pkg/fanal/cache/mock_local_artifact_cache.go b/pkg/cache/mock_local_artifact_cache.go similarity index 100% rename from pkg/fanal/cache/mock_local_artifact_cache.go rename to pkg/cache/mock_local_artifact_cache.go diff --git a/pkg/cache/nop.go b/pkg/cache/nop.go index 6b52e91108c6..4a76cd84e414 100644 --- a/pkg/cache/nop.go +++ b/pkg/cache/nop.go @@ -1,16 +1,11 @@ package cache -import "github.com/aquasecurity/trivy/pkg/fanal/cache" +import "github.com/aquasecurity/trivy/pkg/fanal/types" -func NopCache(ac cache.ArtifactCache) cache.Cache { - return nopCache{ArtifactCache: ac} -} +type NopCache struct{} -type nopCache struct { - cache.ArtifactCache - cache.LocalArtifactCache -} - -func (nopCache) Close() error { - return nil -} +func NewNopCache() NopCache { return NopCache{} } +func (NopCache) GetArtifact(string) (types.ArtifactInfo, error) { return types.ArtifactInfo{}, nil } +func (NopCache) GetBlob(string) (types.BlobInfo, error) { return types.BlobInfo{}, nil } +func (NopCache) Close() error { return nil } +func (NopCache) Clear() error { return nil } diff --git a/pkg/fanal/cache/redis.go b/pkg/cache/redis.go similarity index 100% rename from pkg/fanal/cache/redis.go rename to pkg/cache/redis.go diff --git a/pkg/fanal/cache/redis_test.go b/pkg/cache/redis_test.go similarity index 99% rename from pkg/fanal/cache/redis_test.go rename to pkg/cache/redis_test.go index 335e272890f2..46716a7d7bfe 100644 --- a/pkg/fanal/cache/redis_test.go +++ b/pkg/cache/redis_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/aquasecurity/trivy/pkg/fanal/cache" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/types" ) diff --git a/pkg/cache/remote.go b/pkg/cache/remote.go index 5900bf7a3b91..f55d877d5f3d 100644 --- a/pkg/cache/remote.go +++ b/pkg/cache/remote.go @@ -7,7 +7,6 @@ import ( "golang.org/x/xerrors" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/rpc" "github.com/aquasecurity/trivy/pkg/rpc/client" @@ -21,7 +20,7 @@ type RemoteCache struct { } // NewRemoteCache is the factory method for RemoteCache -func NewRemoteCache(url string, customHeaders http.Header, insecure bool) cache.ArtifactCache { +func NewRemoteCache(url string, customHeaders http.Header, insecure bool) ArtifactCache { ctx := client.WithCustomHeaders(context.Background(), customHeaders) httpClient := &http.Client{ @@ -33,7 +32,10 @@ func NewRemoteCache(url string, customHeaders http.Header, insecure bool) cache. }, } c := rpcCache.NewCacheProtobufClient(url, httpClient) - return &RemoteCache{ctx: ctx, client: c} + return &RemoteCache{ + ctx: ctx, + client: c, + } } // PutArtifact sends artifact to remote client diff --git a/pkg/cache/remote_test.go b/pkg/cache/remote_test.go index a7a8e27dbaa9..bbfd72e3b20d 100644 --- a/pkg/cache/remote_test.go +++ b/pkg/cache/remote_test.go @@ -15,14 +15,13 @@ import ( "google.golang.org/protobuf/types/known/emptypb" "github.com/aquasecurity/trivy/pkg/cache" - fcache "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/types" rpcCache "github.com/aquasecurity/trivy/rpc/cache" rpcScanner "github.com/aquasecurity/trivy/rpc/scanner" ) type mockCacheServer struct { - cache fcache.Cache + cache cache.Cache } func (s *mockCacheServer) PutArtifact(_ context.Context, in *rpcCache.PutArtifactRequest) (*emptypb.Empty, error) { @@ -47,7 +46,10 @@ func (s *mockCacheServer) MissingBlobs(_ context.Context, in *rpcCache.MissingBl } layerIDs = append(layerIDs, layerID) } - return &rpcCache.MissingBlobsResponse{MissingArtifact: true, MissingBlobIds: layerIDs}, nil + return &rpcCache.MissingBlobsResponse{ + MissingArtifact: true, + MissingBlobIds: layerIDs, + }, nil } func (s *mockCacheServer) DeleteBlobs(_ context.Context, in *rpcCache.DeleteBlobsRequest) (*emptypb.Empty, error) { diff --git a/pkg/fanal/cache/testdata/broken-image.db b/pkg/cache/testdata/broken-image.db similarity index 100% rename from pkg/fanal/cache/testdata/broken-image.db rename to pkg/cache/testdata/broken-image.db diff --git a/pkg/fanal/cache/testdata/broken-layer.db b/pkg/cache/testdata/broken-layer.db similarity index 100% rename from pkg/fanal/cache/testdata/broken-layer.db rename to pkg/cache/testdata/broken-layer.db diff --git a/pkg/fanal/cache/testdata/different-image-schema.db b/pkg/cache/testdata/different-image-schema.db similarity index 100% rename from pkg/fanal/cache/testdata/different-image-schema.db rename to pkg/cache/testdata/different-image-schema.db diff --git a/pkg/fanal/cache/testdata/fanal.db b/pkg/cache/testdata/fanal.db similarity index 100% rename from pkg/fanal/cache/testdata/fanal.db rename to pkg/cache/testdata/fanal.db diff --git a/pkg/fanal/cache/testdata/policy/test.rego b/pkg/cache/testdata/policy/test.rego similarity index 100% rename from pkg/fanal/cache/testdata/policy/test.rego rename to pkg/cache/testdata/policy/test.rego diff --git a/pkg/fanal/cache/testdata/trivy-secret.yaml b/pkg/cache/testdata/trivy-secret.yaml similarity index 100% rename from pkg/fanal/cache/testdata/trivy-secret.yaml rename to pkg/cache/testdata/trivy-secret.yaml diff --git a/pkg/commands/artifact/inject.go b/pkg/commands/artifact/inject.go index f0538efdbce3..174af5045f74 100644 --- a/pkg/commands/artifact/inject.go +++ b/pkg/commands/artifact/inject.go @@ -5,10 +5,11 @@ package artifact import ( "context" + "github.com/google/wire" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/artifact" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/rpc/client" "github.com/aquasecurity/trivy/pkg/scanner" diff --git a/pkg/commands/artifact/run.go b/pkg/commands/artifact/run.go index b430fdc1efc9..3a22f762c71c 100644 --- a/pkg/commands/artifact/run.go +++ b/pkg/commands/artifact/run.go @@ -12,11 +12,10 @@ import ( "golang.org/x/xerrors" "github.com/aquasecurity/trivy-db/pkg/db" - tcache "github.com/aquasecurity/trivy/pkg/cache" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/commands/operation" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/artifact" - "github.com/aquasecurity/trivy/pkg/fanal/cache" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/fanal/walker" "github.com/aquasecurity/trivy/pkg/flag" @@ -31,7 +30,6 @@ import ( "github.com/aquasecurity/trivy/pkg/rpc/client" "github.com/aquasecurity/trivy/pkg/scanner" "github.com/aquasecurity/trivy/pkg/types" - "github.com/aquasecurity/trivy/pkg/utils/fsutils" "github.com/aquasecurity/trivy/pkg/version/doc" ) @@ -92,8 +90,9 @@ type Runner interface { } type runner struct { - cache cache.Cache - dbOpen bool + cache cache.ArtifactCache + localCache cache.LocalArtifactCache + dbOpen bool // WASM modules module *module.Manager @@ -106,6 +105,7 @@ type runnerOption func(*runner) func WithCacheClient(c cache.Cache) runnerOption { return func(r *runner) { r.cache = c + r.localCache = c } } @@ -143,7 +143,7 @@ func NewRunner(ctx context.Context, cliOptions flag.Options, opts ...runnerOptio // Close closes everything func (r *runner) Close(ctx context.Context) error { var errs error - if err := r.cache.Close(); err != nil { + if err := r.localCache.Close(); err != nil { errs = multierror.Append(errs, err) } @@ -259,7 +259,7 @@ func (r *runner) ScanVM(ctx context.Context, opts flag.Options) (types.Report, e } func (r *runner) scanArtifact(ctx context.Context, opts flag.Options, initializeScanner InitializeScanner) (types.Report, error) { - report, err := scan(ctx, opts, initializeScanner, r.cache) + report, err := r.scan(ctx, opts, initializeScanner) if err != nil { return types.Report{}, xerrors.Errorf("scan error: %w", err) } @@ -344,18 +344,18 @@ func (r *runner) initCache(opts flag.Options) error { // client/server mode if opts.ServerAddr != "" { - remoteCache := tcache.NewRemoteCache(opts.ServerAddr, opts.CustomHeaders, opts.Insecure) - r.cache = tcache.NopCache(remoteCache) + r.cache = cache.NewRemoteCache(opts.ServerAddr, opts.CustomHeaders, opts.Insecure) + r.localCache = cache.NewNopCache() // No need to use local cache in client/server mode return nil } // standalone mode - fsutils.SetCacheDir(opts.CacheDir) - cacheClient, err := operation.NewCache(opts.CacheOptions) + cache.SetDir(opts.CacheDir) + cacheClient, err := cache.NewClient(opts.CacheOptions.CacheBackendOptions) if err != nil { return xerrors.Errorf("unable to initialize the cache: %w", err) } - log.Debug("Cache dir", log.String("dir", fsutils.CacheDir())) + log.Debug("Cache dir", log.String("dir", cache.Dir())) if opts.Reset { defer cacheClient.Close() @@ -366,7 +366,7 @@ func (r *runner) initCache(opts flag.Options) error { } if opts.ResetChecksBundle { - c, err := policy.NewClient(fsutils.CacheDir(), true, opts.MisconfOptions.ChecksBundleRepository) + c, err := policy.NewClient(cache.Dir(), true, opts.MisconfOptions.ChecksBundleRepository) if err != nil { return xerrors.Errorf("failed to instantiate check client: %w", err) } @@ -384,7 +384,8 @@ func (r *runner) initCache(opts flag.Options) error { return SkipScan } - r.cache = cacheClient + r.cache = cacheClient.Cache + r.localCache = cacheClient.Cache return nil } @@ -526,7 +527,7 @@ func filterMisconfigAnalyzers(included, all []analyzer.Type) ([]analyzer.Type, e return lo.Without(all, included...), nil } -func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfig, types.ScanOptions, error) { +func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.ScanOptions, error) { target := opts.Target if opts.Input != "" { target = opts.Input @@ -616,8 +617,8 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi return ScannerConfig{ Target: target, - ArtifactCache: cacheClient, - LocalArtifactCache: cacheClient, + ArtifactCache: r.cache, + LocalArtifactCache: r.localCache, ServerOption: client.ScannerOption{ RemoteURL: opts.ServerAddr, CustomHeaders: opts.CustomHeaders, @@ -675,9 +676,8 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi }, scanOptions, nil } -func scan(ctx context.Context, opts flag.Options, initializeScanner InitializeScanner, cacheClient cache.Cache) ( - types.Report, error) { - scannerConfig, scanOptions, err := initScannerConfig(opts, cacheClient) +func (r *runner) scan(ctx context.Context, opts flag.Options, initializeScanner InitializeScanner) (types.Report, error) { + scannerConfig, scanOptions, err := r.initScannerConfig(opts) if err != nil { return types.Report{}, err } diff --git a/pkg/commands/artifact/wire_gen.go b/pkg/commands/artifact/wire_gen.go index 5e12c10e54d8..85e66b8214f2 100644 --- a/pkg/commands/artifact/wire_gen.go +++ b/pkg/commands/artifact/wire_gen.go @@ -16,7 +16,7 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/artifact/repo" "github.com/aquasecurity/trivy/pkg/fanal/artifact/sbom" "github.com/aquasecurity/trivy/pkg/fanal/artifact/vm" - "github.com/aquasecurity/trivy/pkg/fanal/cache" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/image" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/fanal/walker" diff --git a/pkg/commands/operation/operation.go b/pkg/commands/operation/operation.go index e315405b50b9..63946710f1b2 100644 --- a/pkg/commands/operation/operation.go +++ b/pkg/commands/operation/operation.go @@ -2,114 +2,22 @@ package operation import ( "context" - "crypto/tls" - "crypto/x509" - "os" - "strings" "sync" - "github.com/go-redis/redis/v8" "github.com/google/go-containerregistry/pkg/name" - "github.com/google/wire" - "github.com/samber/lo" "golang.org/x/xerrors" "github.com/aquasecurity/trivy-db/pkg/metadata" "github.com/aquasecurity/trivy/pkg/db" - "github.com/aquasecurity/trivy/pkg/fanal/cache" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/flag" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/policy" "github.com/aquasecurity/trivy/pkg/types" - "github.com/aquasecurity/trivy/pkg/utils/fsutils" ) var mu sync.Mutex -// SuperSet binds cache dependencies -var SuperSet = wire.NewSet( - cache.NewFSCache, - wire.Bind(new(cache.LocalArtifactCache), new(cache.FSCache)), - NewCache, -) - -// Cache implements the local cache -type Cache struct { - cache.Cache -} - -// NewCache is the factory method for Cache -func NewCache(c flag.CacheOptions) (Cache, error) { - if strings.HasPrefix(c.CacheBackend, "redis://") { - log.Info("Redis cache", log.String("url", c.CacheBackendMasked())) - options, err := redis.ParseURL(c.CacheBackend) - if err != nil { - return Cache{}, err - } - - if !lo.IsEmpty(c.RedisOptions) { - caCert, cert, err := GetTLSConfig(c.RedisCACert, c.RedisCert, c.RedisKey) - if err != nil { - return Cache{}, err - } - - options.TLSConfig = &tls.Config{ - RootCAs: caCert, - Certificates: []tls.Certificate{cert}, - MinVersion: tls.VersionTLS12, - } - } else if c.RedisTLS { - options.TLSConfig = &tls.Config{ - MinVersion: tls.VersionTLS12, - } - } - - redisCache := cache.NewRedisCache(options, c.CacheTTL) - return Cache{Cache: redisCache}, nil - } - - if c.CacheTTL != 0 { - log.Warn("'--cache-ttl' is only available with Redis cache backend") - } - - // standalone mode - fsCache, err := cache.NewFSCache(fsutils.CacheDir()) - if err != nil { - return Cache{}, xerrors.Errorf("unable to initialize fs cache: %w", err) - } - return Cache{Cache: fsCache}, nil -} - -// Reset resets the cache -func (c Cache) Reset() (err error) { - if err := c.ClearDB(); err != nil { - return xerrors.Errorf("failed to clear the database: %w", err) - } - if err := c.ClearArtifacts(); err != nil { - return xerrors.Errorf("failed to clear the artifact cache: %w", err) - } - return nil -} - -// ClearDB clears the DB cache -func (c Cache) ClearDB() (err error) { - log.Info("Removing DB file...") - if err = os.RemoveAll(fsutils.CacheDir()); err != nil { - return xerrors.Errorf("failed to remove the directory (%s) : %w", fsutils.CacheDir(), err) - } - return nil -} - -// ClearArtifacts clears the artifact cache -func (c Cache) ClearArtifacts() error { - log.Info("Removing artifact caches...") - if err := c.Clear(); err != nil { - return xerrors.Errorf("failed to remove the cache: %w", err) - } - return nil -} - // DownloadDB downloads the DB func DownloadDB(ctx context.Context, appVersion, cacheDir string, dbRepository name.Reference, quiet, skipUpdate bool, opt ftypes.RegistryOptions) error { @@ -186,24 +94,6 @@ func InitBuiltinPolicies(ctx context.Context, cacheDir string, quiet, skipUpdate return policyPaths, nil } -// GetTLSConfig gets tls config from CA, Cert and Key file -func GetTLSConfig(caCertPath, certPath, keyPath string) (*x509.CertPool, tls.Certificate, error) { - cert, err := tls.LoadX509KeyPair(certPath, keyPath) - if err != nil { - return nil, tls.Certificate{}, err - } - - caCert, err := os.ReadFile(caCertPath) - if err != nil { - return nil, tls.Certificate{}, err - } - - caCertPool := x509.NewCertPool() - caCertPool.AppendCertsFromPEM(caCert) - - return caCertPool, cert, nil -} - func Exit(opts flag.Options, failedResults bool, m types.Metadata) error { if opts.ExitOnEOL != 0 && m.OS != nil && m.OS.Eosl { log.Error("Detected EOL OS", log.String("family", string(m.OS.Family)), diff --git a/pkg/commands/server/run.go b/pkg/commands/server/run.go index 70788db6a6f3..eeef097990ce 100644 --- a/pkg/commands/server/run.go +++ b/pkg/commands/server/run.go @@ -6,12 +6,12 @@ import ( "golang.org/x/xerrors" "github.com/aquasecurity/trivy-db/pkg/db" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/commands/operation" "github.com/aquasecurity/trivy/pkg/flag" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/module" rpcServer "github.com/aquasecurity/trivy/pkg/rpc/server" - "github.com/aquasecurity/trivy/pkg/utils/fsutils" ) // Run runs the scan @@ -19,16 +19,16 @@ func Run(ctx context.Context, opts flag.Options) (err error) { log.InitLogger(opts.Debug, opts.Quiet) // configure cache dir - fsutils.SetCacheDir(opts.CacheDir) - cache, err := operation.NewCache(opts.CacheOptions) + cache.SetDir(opts.CacheDir) + cacheClient, err := cache.NewClient(opts.CacheOptions.CacheBackendOptions) if err != nil { return xerrors.Errorf("server cache error: %w", err) } - defer cache.Close() - log.Debug("Cache", log.String("dir", fsutils.CacheDir())) + defer cacheClient.Close() + log.Debug("Cache", log.String("dir", cache.Dir())) if opts.Reset { - return cache.ClearDB() + return cacheClient.ClearDB() } // download the database file @@ -57,5 +57,5 @@ func Run(ctx context.Context, opts flag.Options) (err error) { server := rpcServer.NewServer(opts.AppVersion, opts.Listen, opts.CacheDir, opts.Token, opts.TokenHeader, opts.DBRepository, opts.RegistryOpts()) - return server.ListenAndServe(ctx, cache, opts.SkipDBUpdate) + return server.ListenAndServe(ctx, cacheClient, opts.SkipDBUpdate) } diff --git a/pkg/fanal/applier/applier.go b/pkg/fanal/applier/applier.go index 192c9d2184f2..0ddeef11eba2 100644 --- a/pkg/fanal/applier/applier.go +++ b/pkg/fanal/applier/applier.go @@ -3,8 +3,8 @@ package applier import ( "golang.org/x/xerrors" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" - "github.com/aquasecurity/trivy/pkg/fanal/cache" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" ) diff --git a/pkg/fanal/applier/applier_test.go b/pkg/fanal/applier/applier_test.go index ac8915f2dad6..b2a992f80012 100644 --- a/pkg/fanal/applier/applier_test.go +++ b/pkg/fanal/applier/applier_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/applier" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/types" ) diff --git a/pkg/fanal/artifact/image/image.go b/pkg/fanal/artifact/image/image.go index c4491eaa90ab..b4350b25b866 100644 --- a/pkg/fanal/artifact/image/image.go +++ b/pkg/fanal/artifact/image/image.go @@ -14,9 +14,9 @@ import ( "github.com/samber/lo" "golang.org/x/xerrors" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/artifact" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/handler" "github.com/aquasecurity/trivy/pkg/fanal/image" "github.com/aquasecurity/trivy/pkg/fanal/types" diff --git a/pkg/fanal/artifact/image/image_test.go b/pkg/fanal/artifact/image/image_test.go index 05fc6b229105..6ce36846868a 100644 --- a/pkg/fanal/artifact/image/image_test.go +++ b/pkg/fanal/artifact/image/image_test.go @@ -11,10 +11,10 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/xerrors" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/artifact" image2 "github.com/aquasecurity/trivy/pkg/fanal/artifact/image" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/image" "github.com/aquasecurity/trivy/pkg/fanal/types" diff --git a/pkg/fanal/artifact/image/remote_sbom_test.go b/pkg/fanal/artifact/image/remote_sbom_test.go index 1fd29fe2c69a..29fcc10f52fc 100644 --- a/pkg/fanal/artifact/image/remote_sbom_test.go +++ b/pkg/fanal/artifact/image/remote_sbom_test.go @@ -14,9 +14,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/artifact" image2 "github.com/aquasecurity/trivy/pkg/fanal/artifact/image" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/rekortest" diff --git a/pkg/fanal/artifact/local/fs.go b/pkg/fanal/artifact/local/fs.go index b807db2c6733..2f5ef7fe4ecd 100644 --- a/pkg/fanal/artifact/local/fs.go +++ b/pkg/fanal/artifact/local/fs.go @@ -14,9 +14,9 @@ import ( "github.com/opencontainers/go-digest" "golang.org/x/xerrors" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/artifact" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/handler" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/fanal/walker" diff --git a/pkg/fanal/artifact/local/fs_test.go b/pkg/fanal/artifact/local/fs_test.go index 2cee794c85b2..d27b5ffb4366 100644 --- a/pkg/fanal/artifact/local/fs_test.go +++ b/pkg/fanal/artifact/local/fs_test.go @@ -10,9 +10,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/artifact" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/fanal/walker" "github.com/aquasecurity/trivy/pkg/misconf" diff --git a/pkg/fanal/artifact/repo/git.go b/pkg/fanal/artifact/repo/git.go index 4ce1c990c925..8eb3d9af7f9d 100644 --- a/pkg/fanal/artifact/repo/git.go +++ b/pkg/fanal/artifact/repo/git.go @@ -12,9 +12,9 @@ import ( "github.com/hashicorp/go-multierror" "golang.org/x/xerrors" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/artifact" "github.com/aquasecurity/trivy/pkg/fanal/artifact/local" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/walker" ) diff --git a/pkg/fanal/artifact/repo/git_test.go b/pkg/fanal/artifact/repo/git_test.go index 0e4c8ee39d4b..8de1f3d8864b 100644 --- a/pkg/fanal/artifact/repo/git_test.go +++ b/pkg/fanal/artifact/repo/git_test.go @@ -12,8 +12,8 @@ import ( "github.com/stretchr/testify/require" "github.com/aquasecurity/trivy/internal/gittest" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/artifact" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/walker" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/config/all" diff --git a/pkg/fanal/artifact/sbom/sbom.go b/pkg/fanal/artifact/sbom/sbom.go index 979c5c5a8517..a5b646c18889 100644 --- a/pkg/fanal/artifact/sbom/sbom.go +++ b/pkg/fanal/artifact/sbom/sbom.go @@ -11,9 +11,9 @@ import ( "github.com/samber/lo" "golang.org/x/xerrors" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/artifact" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/handler" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" diff --git a/pkg/fanal/artifact/sbom/sbom_test.go b/pkg/fanal/artifact/sbom/sbom_test.go index 37ea39380b43..1dffa52f68c4 100644 --- a/pkg/fanal/artifact/sbom/sbom_test.go +++ b/pkg/fanal/artifact/sbom/sbom_test.go @@ -11,9 +11,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/artifact" "github.com/aquasecurity/trivy/pkg/fanal/artifact/sbom" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/types" ) diff --git a/pkg/fanal/artifact/vm/ebs.go b/pkg/fanal/artifact/vm/ebs.go index 64e1cc6a6b5a..280236cb371f 100644 --- a/pkg/fanal/artifact/vm/ebs.go +++ b/pkg/fanal/artifact/vm/ebs.go @@ -8,9 +8,9 @@ import ( ebsfile "github.com/masahiro331/go-ebs-file" "golang.org/x/xerrors" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/cloud/aws/config" "github.com/aquasecurity/trivy/pkg/fanal/artifact" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/log" ) diff --git a/pkg/fanal/artifact/vm/file.go b/pkg/fanal/artifact/vm/file.go index 7968cf44681b..a3cb262a98c8 100644 --- a/pkg/fanal/artifact/vm/file.go +++ b/pkg/fanal/artifact/vm/file.go @@ -12,8 +12,8 @@ import ( "github.com/opencontainers/go-digest" "golang.org/x/xerrors" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/artifact" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/fanal/vm" "github.com/aquasecurity/trivy/pkg/fanal/vm/disk" diff --git a/pkg/fanal/artifact/vm/vm.go b/pkg/fanal/artifact/vm/vm.go index 5b9aae130f4c..56f7a0f5fa88 100644 --- a/pkg/fanal/artifact/vm/vm.go +++ b/pkg/fanal/artifact/vm/vm.go @@ -10,9 +10,9 @@ import ( "github.com/google/wire" "golang.org/x/xerrors" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/artifact" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/handler" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/fanal/walker" diff --git a/pkg/fanal/artifact/vm/vm_test.go b/pkg/fanal/artifact/vm/vm_test.go index d1becf0f7067..c1331554f5cc 100644 --- a/pkg/fanal/artifact/vm/vm_test.go +++ b/pkg/fanal/artifact/vm/vm_test.go @@ -14,10 +14,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/artifact" "github.com/aquasecurity/trivy/pkg/fanal/artifact/vm" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/fanal/walker" "github.com/aquasecurity/trivy/pkg/misconf" diff --git a/pkg/fanal/cache/s3.go b/pkg/fanal/cache/s3.go deleted file mode 100644 index 0176d2cf80d8..000000000000 --- a/pkg/fanal/cache/s3.go +++ /dev/null @@ -1,180 +0,0 @@ -package cache - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/feature/s3/manager" - "github.com/aws/aws-sdk-go-v2/service/s3" - "github.com/hashicorp/go-multierror" - "golang.org/x/xerrors" - - "github.com/aquasecurity/trivy/pkg/fanal/types" -) - -var _ Cache = &S3Cache{} - -type s3API interface { - HeadObject(ctx context.Context, params *s3.HeadObjectInput, optFns ...func(*s3.Options)) (*s3.HeadObjectOutput, error) - PutObject(ctx context.Context, params *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error) - DeleteBucket(ctx context.Context, params *s3.DeleteBucketInput, optFns ...func(*s3.Options)) (*s3.DeleteBucketOutput, error) -} - -type S3Cache struct { - s3Client s3API - downloader *manager.Downloader - bucketName string - prefix string -} - -func NewS3Cache(bucketName, prefix string, api s3API, downloaderAPI *manager.Downloader) S3Cache { - return S3Cache{ - s3Client: api, - downloader: downloaderAPI, - bucketName: bucketName, - prefix: prefix, - } -} - -func (c S3Cache) PutArtifact(artifactID string, artifactConfig types.ArtifactInfo) (err error) { - key := fmt.Sprintf("%s/%s/%s", artifactBucket, c.prefix, artifactID) - if err := c.put(key, artifactConfig); err != nil { - return xerrors.Errorf("unable to store artifact information in cache (%s): %w", artifactID, err) - } - return nil -} - -func (c S3Cache) DeleteBlobs(blobIDs []string) error { - var errs error - for _, blobID := range blobIDs { - key := fmt.Sprintf("%s/%s/%s", blobBucket, c.prefix, blobID) - input := &s3.DeleteBucketInput{Bucket: aws.String(key)} - if _, err := c.s3Client.DeleteBucket(context.TODO(), input); err != nil { - errs = multierror.Append(errs, err) - } - } - return errs -} - -func (c S3Cache) PutBlob(blobID string, blobInfo types.BlobInfo) error { - key := fmt.Sprintf("%s/%s/%s", blobBucket, c.prefix, blobID) - if err := c.put(key, blobInfo); err != nil { - return xerrors.Errorf("unable to store blob information in cache (%s): %w", blobID, err) - } - return nil -} - -func (c S3Cache) put(key string, body any) (err error) { - b, err := json.Marshal(body) - if err != nil { - return err - } - params := &s3.PutObjectInput{ - Bucket: aws.String(c.bucketName), - Key: aws.String(key), - Body: bytes.NewReader(b), - } - _, err = c.s3Client.PutObject(context.TODO(), params) - if err != nil { - return xerrors.Errorf("unable to put object: %w", err) - } - // Index file due S3 caveat read after write consistency - _, err = c.s3Client.PutObject(context.TODO(), &s3.PutObjectInput{ - Bucket: aws.String(c.bucketName), - Key: aws.String(fmt.Sprintf("%s.index", key)), - }) - if err != nil { - return xerrors.Errorf("unable to put index object: %w", err) - } - return nil -} - -func (c S3Cache) GetBlob(blobID string) (types.BlobInfo, error) { - var blobInfo types.BlobInfo - buf := manager.NewWriteAtBuffer([]byte{}) - _, err := c.downloader.Download(context.TODO(), buf, &s3.GetObjectInput{ - Bucket: aws.String(c.bucketName), - Key: aws.String(fmt.Sprintf("%s/%s/%s", blobBucket, c.prefix, blobID)), - }) - if err != nil { - return types.BlobInfo{}, xerrors.Errorf("failed to get blob from the cache: %w", err) - } - err = json.Unmarshal(buf.Bytes(), &blobInfo) - if err != nil { - return types.BlobInfo{}, xerrors.Errorf("JSON unmarshal error: %w", err) - } - return blobInfo, nil -} - -func (c S3Cache) GetArtifact(artifactID string) (types.ArtifactInfo, error) { - var info types.ArtifactInfo - buf := manager.NewWriteAtBuffer([]byte{}) - _, err := c.downloader.Download(context.TODO(), buf, &s3.GetObjectInput{ - Bucket: aws.String(c.bucketName), - Key: aws.String(fmt.Sprintf("%s/%s/%s", artifactBucket, c.prefix, artifactID)), - }) - if err != nil { - return types.ArtifactInfo{}, xerrors.Errorf("failed to get artifact from the cache: %w", err) - } - err = json.Unmarshal(buf.Bytes(), &info) - if err != nil { - return types.ArtifactInfo{}, xerrors.Errorf("JSON unmarshal error: %w", err) - } - return info, nil -} - -func (c S3Cache) getIndex(key, keyType string) error { - _, err := c.s3Client.HeadObject(context.TODO(), &s3.HeadObjectInput{ - Key: aws.String(fmt.Sprintf("%s/%s/%s.index", keyType, c.prefix, key)), - Bucket: &c.bucketName, - }) - if err != nil { - return xerrors.Errorf("failed to get index from the cache: %w", err) - } - return nil -} - -func (c S3Cache) MissingBlobs(artifactID string, blobIDs []string) (bool, []string, error) { - var missingArtifact bool - var missingBlobIDs []string - for _, blobID := range blobIDs { - err := c.getIndex(blobID, blobBucket) - if err != nil { - // error means cache missed blob info - missingBlobIDs = append(missingBlobIDs, blobID) - continue - } - blobInfo, err := c.GetBlob(blobID) - if err != nil { - return true, missingBlobIDs, xerrors.Errorf("the blob object (%s) doesn't exist in S3 even though the index file exists: %w", blobID, err) - } - if blobInfo.SchemaVersion != types.BlobJSONSchemaVersion { - missingBlobIDs = append(missingBlobIDs, blobID) - } - } - // get artifact info - err := c.getIndex(artifactID, artifactBucket) - // error means cache missed artifact info - if err != nil { - return true, missingBlobIDs, nil - } - artifactInfo, err := c.GetArtifact(artifactID) - if err != nil { - return true, missingBlobIDs, xerrors.Errorf("the artifact object (%s) doesn't exist in S3 even though the index file exists: %w", artifactID, err) - } - if artifactInfo.SchemaVersion != types.ArtifactJSONSchemaVersion { - missingArtifact = true - } - return missingArtifact, missingBlobIDs, nil -} - -func (c S3Cache) Close() error { - return nil -} - -func (c S3Cache) Clear() error { - return nil -} diff --git a/pkg/fanal/cache/s3_test.go b/pkg/fanal/cache/s3_test.go deleted file mode 100644 index ed3da27b974f..000000000000 --- a/pkg/fanal/cache/s3_test.go +++ /dev/null @@ -1,312 +0,0 @@ -package cache - -import ( - "context" - "errors" - "reflect" - "testing" - "time" - - "github.com/aws/aws-sdk-go-v2/feature/s3/manager" - "github.com/aws/aws-sdk-go-v2/service/s3" - "golang.org/x/xerrors" - - "github.com/aquasecurity/trivy/pkg/fanal/types" -) - -type mockS3Client struct { - s3API -} - -const ( - correctHash = "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7" -) - -func (m *mockS3Client) PutObject(ctx context.Context, in *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error) { - return &s3.PutObjectOutput{}, nil -} - -func (m *mockS3Client) HeadObject(ctx context.Context, params *s3.HeadObjectInput, optFns ...func(*s3.Options)) (*s3.HeadObjectOutput, error) { - return &s3.HeadObjectOutput{}, nil -} - -func (m *mockS3Client) DeleteBucket(ctx context.Context, in *s3.DeleteBucketInput, optFns ...func(*s3.Options)) (*s3.DeleteBucketOutput, error) { - if in != nil && *in.Bucket == blobBucket+"/prefix/"+correctHash { - return &s3.DeleteBucketOutput{}, nil - } - return nil, errors.New("unknown bucket") -} - -func TestS3Cache_PutBlob(t *testing.T) { - mockSvc := &mockS3Client{} - - type fields struct { - S3 s3API - Downloader *manager.Downloader - BucketName string - Prefix string - } - type args struct { - blobID string - blobInfo types.BlobInfo - } - tests := []struct { - name string - fields fields - args args - wantErr bool - }{ - { - name: "happy path", - fields: fields{ - S3: mockSvc, - BucketName: "test", - Prefix: "prefix", - }, - args: args{ - blobID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7", - blobInfo: types.BlobInfo{ - SchemaVersion: 1, - OS: types.OS{ - Family: "alpine", - Name: "3.10", - }, - }}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := NewS3Cache(tt.fields.BucketName, tt.fields.Prefix, tt.fields.S3, tt.fields.Downloader) - if err := c.PutBlob(tt.args.blobID, tt.args.blobInfo); (err != nil) != tt.wantErr { - t.Errorf("S3Cache.PutBlob() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestS3Cache_PutArtifact(t *testing.T) { - mockSvc := &mockS3Client{} - - type fields struct { - S3 s3API - Downloader *manager.Downloader - BucketName string - Prefix string - } - type args struct { - artifactID string - artifactConfig types.ArtifactInfo - } - tests := []struct { - name string - fields fields - args args - wantErr bool - }{ - { - name: "happy path", - fields: fields{ - S3: mockSvc, - BucketName: "test", - Prefix: "prefix", - }, - args: args{ - artifactID: "sha256:58701fd185bda36cab0557bb6438661831267aa4a9e0b54211c4d5317a48aff4", - artifactConfig: types.ArtifactInfo{ - SchemaVersion: 1, - Architecture: "amd64", - Created: time.Date(2020, 1, 2, 3, 4, 5, 0, time.UTC), - DockerVersion: "18.06.1-ce", - OS: "linux", - HistoryPackages: []types.Package{ - { - Name: "musl", - Version: "1.2.3", - }, - }, - }}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := NewS3Cache(tt.fields.BucketName, tt.fields.Prefix, tt.fields.S3, tt.fields.Downloader) - if err := c.PutArtifact(tt.args.artifactID, tt.args.artifactConfig); (err != nil) != tt.wantErr { - t.Errorf("S3Cache.PutArtifact() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestS3Cache_getIndex(t *testing.T) { - mockSvc := &mockS3Client{} - - type fields struct { - S3 s3API - Downloader *manager.Downloader - BucketName string - Prefix string - } - type args struct { - key string - keyType string - } - tests := []struct { - name string - fields fields - args args - wantErr bool - }{ - { - name: "happy path", - fields: fields{ - S3: mockSvc, - BucketName: "test", - Prefix: "prefix", - }, - args: args{ - key: "key", - keyType: "artifactBucket", - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := NewS3Cache(tt.fields.BucketName, tt.fields.Prefix, tt.fields.S3, tt.fields.Downloader) - if err := c.getIndex(tt.args.key, tt.args.keyType); (err != nil) != tt.wantErr { - t.Errorf("S3Cache.getIndex() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -type mockS3ClientMissingBlobs struct { - s3API -} - -func (m *mockS3ClientMissingBlobs) PutObject(ctx context.Context, in *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error) { - return &s3.PutObjectOutput{}, nil -} - -func (m *mockS3ClientMissingBlobs) HeadObject(ctx context.Context, params *s3.HeadObjectInput, optFns ...func(*s3.Options)) (*s3.HeadObjectOutput, error) { - return &s3.HeadObjectOutput{}, xerrors.Errorf("the object doesn't exist in S3") -} - -func TestS3Cache_MissingBlobs(t *testing.T) { - mockSvc := &mockS3ClientMissingBlobs{} - - type fields struct { - S3 s3API - Downloader *manager.Downloader - BucketName string - Prefix string - } - type args struct { - artifactID string - blobIDs []string - analyzerVersions map[string]int - configAnalyzerVersions map[string]int - } - tests := []struct { - name string - fields fields - args args - want bool - wantStringSlice []string - wantErr bool - }{{ - name: "happy path", - fields: fields{ - S3: mockSvc, - BucketName: "test", - Prefix: "prefix", - }, - args: args{ - artifactID: "sha256:58701fd185bda36cab0557bb6438661831267aa4a9e0b54211c4d5317a48aff4/1", - blobIDs: []string{"sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7/10011"}, - }, - want: true, - wantStringSlice: []string{"sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7/10011"}, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := NewS3Cache(tt.fields.BucketName, tt.fields.Prefix, tt.fields.S3, tt.fields.Downloader) - got, got1, err := c.MissingBlobs(tt.args.artifactID, tt.args.blobIDs) - if (err != nil) != tt.wantErr { - t.Errorf("S3Cache.MissingBlobs() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("S3Cache.MissingBlobs() got = %v, want %v", got, tt.want) - } - if !reflect.DeepEqual(got1, tt.wantStringSlice) { - t.Errorf("S3Cache.MissingBlobs() got1 = %v, want %v", got1, tt.wantStringSlice) - } - }) - } -} - -func TestS3Cache_DeleteBlobs(t *testing.T) { - mockSvc := &mockS3Client{} - - type fields struct { - S3 s3API - Downloader *manager.Downloader - BucketName string - Prefix string - } - type args struct { - blobIDs []string - } - tests := []struct { - name string - fields fields - args args - wantErr bool - }{ - { - name: "happy path", - fields: fields{ - S3: mockSvc, - BucketName: "test", - Prefix: "prefix", - }, - args: args{ - blobIDs: []string{correctHash}, - }, - }, - { - name: "delete blob with bad ID", - fields: fields{ - S3: mockSvc, - BucketName: "test", - Prefix: "prefix", - }, - args: args{ - blobIDs: []string{"unde"}, - }, - wantErr: true, - }, - { - name: "delete blobs with bad ID", - fields: fields{ - S3: mockSvc, - BucketName: "test", - Prefix: "prefix", - }, - args: args{ - blobIDs: []string{correctHash}, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := NewS3Cache(tt.fields.BucketName, tt.fields.Prefix, tt.fields.S3, tt.fields.Downloader) - if err := c.DeleteBlobs(tt.args.blobIDs); (err != nil) != tt.wantErr { - t.Errorf("S3Cache.PutBlob() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} diff --git a/pkg/fanal/test/integration/containerd_test.go b/pkg/fanal/test/integration/containerd_test.go index e0fdd7602e32..d16ad3dac059 100644 --- a/pkg/fanal/test/integration/containerd_test.go +++ b/pkg/fanal/test/integration/containerd_test.go @@ -27,11 +27,11 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/applier" "github.com/aquasecurity/trivy/pkg/fanal/artifact" aimage "github.com/aquasecurity/trivy/pkg/fanal/artifact/image" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/image" "github.com/aquasecurity/trivy/pkg/fanal/types" ) diff --git a/pkg/fanal/test/integration/library_test.go b/pkg/fanal/test/integration/library_test.go index 9e2073185c60..f06a8c3f5c6c 100644 --- a/pkg/fanal/test/integration/library_test.go +++ b/pkg/fanal/test/integration/library_test.go @@ -20,11 +20,11 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/analyzer" + "github.com/aquasecurity/trivy/pkg/cache" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/all" "github.com/aquasecurity/trivy/pkg/fanal/applier" "github.com/aquasecurity/trivy/pkg/fanal/artifact" aimage "github.com/aquasecurity/trivy/pkg/fanal/artifact/image" - "github.com/aquasecurity/trivy/pkg/fanal/cache" _ "github.com/aquasecurity/trivy/pkg/fanal/handler/all" "github.com/aquasecurity/trivy/pkg/fanal/image" "github.com/aquasecurity/trivy/pkg/fanal/types" diff --git a/pkg/fanal/test/integration/registry_test.go b/pkg/fanal/test/integration/registry_test.go index 081f9df20d95..5b062e425729 100644 --- a/pkg/fanal/test/integration/registry_test.go +++ b/pkg/fanal/test/integration/registry_test.go @@ -20,12 +20,12 @@ import ( testcontainers "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/all" "github.com/aquasecurity/trivy/pkg/fanal/applier" "github.com/aquasecurity/trivy/pkg/fanal/artifact" aimage "github.com/aquasecurity/trivy/pkg/fanal/artifact/image" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/image" testdocker "github.com/aquasecurity/trivy/pkg/fanal/test/integration/docker" "github.com/aquasecurity/trivy/pkg/fanal/types" diff --git a/pkg/flag/cache_flags.go b/pkg/flag/cache_flags.go index c259d5b9e963..75b7a1837371 100644 --- a/pkg/flag/cache_flags.go +++ b/pkg/flag/cache_flags.go @@ -1,12 +1,11 @@ package flag import ( - "fmt" - "strings" "time" - "github.com/samber/lo" "golang.org/x/xerrors" + + "github.com/aquasecurity/trivy/pkg/cache" ) // e.g. config yaml: @@ -70,18 +69,8 @@ type CacheFlagGroup struct { } type CacheOptions struct { - ClearCache bool - CacheBackend string - CacheTTL time.Duration - RedisTLS bool - RedisOptions -} - -// RedisOptions holds the options for redis cache -type RedisOptions struct { - RedisCACert string - RedisCert string - RedisKey string + ClearCache bool + CacheBackendOptions cache.Options } // NewCacheFlagGroup returns a default CacheFlagGroup @@ -118,43 +107,14 @@ func (fg *CacheFlagGroup) ToOptions() (CacheOptions, error) { return CacheOptions{}, err } - cacheBackend := fg.CacheBackend.Value() - redisOptions := RedisOptions{ - RedisCACert: fg.RedisCACert.Value(), - RedisCert: fg.RedisCert.Value(), - RedisKey: fg.RedisKey.Value(), - } - - // "redis://" or "fs" are allowed for now - // An empty value is also allowed for testability - if !strings.HasPrefix(cacheBackend, "redis://") && - cacheBackend != "fs" && cacheBackend != "" { - return CacheOptions{}, xerrors.Errorf("unsupported cache backend: %s", cacheBackend) - } - // if one of redis option not nil, make sure CA, cert, and key provided - if !lo.IsEmpty(redisOptions) { - if redisOptions.RedisCACert == "" || redisOptions.RedisCert == "" || redisOptions.RedisKey == "" { - return CacheOptions{}, xerrors.Errorf("you must provide Redis CA, cert and key file path when using TLS") - } + backendOpts, err := cache.NewOptions(fg.CacheBackend.Value(), fg.RedisCACert.Value(), fg.RedisCert.Value(), + fg.RedisKey.Value(), fg.RedisTLS.Value(), fg.CacheTTL.Value()) + if err != nil { + return CacheOptions{}, xerrors.Errorf("failed to initialize cache options: %w", err) } return CacheOptions{ - ClearCache: fg.ClearCache.Value(), - CacheBackend: cacheBackend, - CacheTTL: fg.CacheTTL.Value(), - RedisTLS: fg.RedisTLS.Value(), - RedisOptions: redisOptions, + ClearCache: fg.ClearCache.Value(), + CacheBackendOptions: backendOpts, }, nil } - -// CacheBackendMasked returns the redis connection string masking credentials -func (o *CacheOptions) CacheBackendMasked() string { - endIndex := strings.Index(o.CacheBackend, "@") - if endIndex == -1 { - return o.CacheBackend - } - - startIndex := strings.Index(o.CacheBackend, "//") - - return fmt.Sprintf("%s****%s", o.CacheBackend[:startIndex+2], o.CacheBackend[endIndex:]) -} diff --git a/pkg/flag/cache_flags_test.go b/pkg/flag/cache_flags_test.go deleted file mode 100644 index c795cdbd6715..000000000000 --- a/pkg/flag/cache_flags_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package flag_test - -import ( - "testing" - "time" - - "github.com/spf13/viper" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/aquasecurity/trivy/pkg/flag" -) - -func TestCacheFlagGroup_ToOptions(t *testing.T) { - type fields struct { - ClearCache bool - CacheBackend string - CacheTTL time.Duration - RedisTLS bool - RedisCACert string - RedisCert string - RedisKey string - } - tests := []struct { - name string - fields fields - want flag.CacheOptions - assertion require.ErrorAssertionFunc - }{ - { - name: "fs", - fields: fields{ - CacheBackend: "fs", - }, - want: flag.CacheOptions{ - CacheBackend: "fs", - }, - assertion: require.NoError, - }, - { - name: "redis", - fields: fields{ - CacheBackend: "redis://localhost:6379", - }, - want: flag.CacheOptions{ - CacheBackend: "redis://localhost:6379", - }, - assertion: require.NoError, - }, - { - name: "redis tls", - fields: fields{ - CacheBackend: "redis://localhost:6379", - RedisCACert: "ca-cert.pem", - RedisCert: "cert.pem", - RedisKey: "key.pem", - }, - want: flag.CacheOptions{ - CacheBackend: "redis://localhost:6379", - RedisOptions: flag.RedisOptions{ - RedisCACert: "ca-cert.pem", - RedisCert: "cert.pem", - RedisKey: "key.pem", - }, - }, - assertion: require.NoError, - }, - { - name: "redis tls with public certificates", - fields: fields{ - CacheBackend: "redis://localhost:6379", - RedisTLS: true, - }, - want: flag.CacheOptions{ - CacheBackend: "redis://localhost:6379", - RedisTLS: true, - }, - assertion: require.NoError, - }, - { - name: "unknown backend", - fields: fields{ - CacheBackend: "unknown", - }, - assertion: func(t require.TestingT, err error, msgs ...any) { - require.ErrorContains(t, err, "unsupported cache backend") - }, - }, - { - name: "sad redis tls", - fields: fields{ - CacheBackend: "redis://localhost:6379", - RedisCACert: "ca-cert.pem", - }, - assertion: func(t require.TestingT, err error, msgs ...any) { - require.ErrorContains(t, err, "you must provide Redis CA") - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - viper.Set(flag.ClearCacheFlag.ConfigName, tt.fields.ClearCache) - viper.Set(flag.CacheBackendFlag.ConfigName, tt.fields.CacheBackend) - viper.Set(flag.CacheTTLFlag.ConfigName, tt.fields.CacheTTL) - viper.Set(flag.RedisTLSFlag.ConfigName, tt.fields.RedisTLS) - viper.Set(flag.RedisCACertFlag.ConfigName, tt.fields.RedisCACert) - viper.Set(flag.RedisCertFlag.ConfigName, tt.fields.RedisCert) - viper.Set(flag.RedisKeyFlag.ConfigName, tt.fields.RedisKey) - - f := &flag.CacheFlagGroup{ - ClearCache: flag.ClearCacheFlag.Clone(), - CacheBackend: flag.CacheBackendFlag.Clone(), - CacheTTL: flag.CacheTTLFlag.Clone(), - RedisTLS: flag.RedisTLSFlag.Clone(), - RedisCACert: flag.RedisCACertFlag.Clone(), - RedisCert: flag.RedisCertFlag.Clone(), - RedisKey: flag.RedisKeyFlag.Clone(), - } - - got, err := f.ToOptions() - tt.assertion(t, err) - assert.Equalf(t, tt.want, got, "ToOptions()") - }) - } -} - -func TestCacheOptions_CacheBackendMasked(t *testing.T) { - type fields struct { - backend string - } - tests := []struct { - name string - fields fields - want string - }{ - { - name: "redis cache backend masked", - fields: fields{ - backend: "redis://root:password@localhost:6379", - }, - want: "redis://****@localhost:6379", - }, - { - name: "redis cache backend masked does nothing", - fields: fields{ - backend: "redis://localhost:6379", - }, - want: "redis://localhost:6379", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &flag.CacheOptions{ - CacheBackend: tt.fields.backend, - } - - assert.Equal(t, tt.want, c.CacheBackendMasked()) - }) - } -} diff --git a/pkg/flag/global_flags.go b/pkg/flag/global_flags.go index aa4851c657f0..eb34e2f589dc 100644 --- a/pkg/flag/global_flags.go +++ b/pkg/flag/global_flags.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" - "github.com/aquasecurity/trivy/pkg/utils/fsutils" + "github.com/aquasecurity/trivy/pkg/cache" ) var ( @@ -55,7 +55,7 @@ var ( CacheDirFlag = Flag[string]{ Name: "cache-dir", ConfigName: "cache.dir", - Default: fsutils.CacheDir(), + Default: cache.Dir(), Usage: "cache directory", Persistent: true, } diff --git a/pkg/k8s/inject.go b/pkg/k8s/inject.go index 31ffd2afffa7..e71b11fe57d9 100644 --- a/pkg/k8s/inject.go +++ b/pkg/k8s/inject.go @@ -6,7 +6,7 @@ package k8s import ( "github.com/google/wire" - "github.com/aquasecurity/trivy/pkg/fanal/cache" + "github.com/aquasecurity/trivy/pkg/cache" ) func initializeScanK8s(localArtifactCache cache.LocalArtifactCache) *ScanKubernetes { diff --git a/pkg/k8s/wire_gen.go b/pkg/k8s/wire_gen.go index 2b2343a654b7..134fa8c1ec49 100644 --- a/pkg/k8s/wire_gen.go +++ b/pkg/k8s/wire_gen.go @@ -9,7 +9,7 @@ package k8s import ( "github.com/aquasecurity/trivy-db/pkg/db" "github.com/aquasecurity/trivy/pkg/fanal/applier" - "github.com/aquasecurity/trivy/pkg/fanal/cache" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/scanner/langpkg" "github.com/aquasecurity/trivy/pkg/scanner/local" "github.com/aquasecurity/trivy/pkg/scanner/ospkg" diff --git a/pkg/oci/artifact_test.go b/pkg/oci/artifact_test.go index d28dbe55bc1e..479c607af425 100644 --- a/pkg/oci/artifact_test.go +++ b/pkg/oci/artifact_test.go @@ -14,9 +14,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/cache" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/oci" - "github.com/aquasecurity/trivy/pkg/utils/fsutils" ) type fakeLayer struct { @@ -97,7 +97,7 @@ func TestArtifact_Download(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tempDir := t.TempDir() - fsutils.SetCacheDir(tempDir) + cache.SetDir(tempDir) // Mock image img := new(fakei.FakeImage) diff --git a/pkg/plugin/index_test.go b/pkg/plugin/index_test.go index 7e5621d5ca1c..e420dfaa6d08 100644 --- a/pkg/plugin/index_test.go +++ b/pkg/plugin/index_test.go @@ -12,13 +12,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/plugin" - "github.com/aquasecurity/trivy/pkg/utils/fsutils" ) func TestManager_Update(t *testing.T) { tempDir := t.TempDir() - fsutils.SetCacheDir(tempDir) + cache.SetDir(tempDir) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, err := w.Write([]byte(`this is index`)) @@ -73,7 +73,7 @@ bar A bar plugin } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - fsutils.SetCacheDir(tt.dir) + cache.SetDir(tt.dir) var got bytes.Buffer m := plugin.NewManager(plugin.WithWriter(&got)) diff --git a/pkg/plugin/manager.go b/pkg/plugin/manager.go index 949c87525be7..70ae3758fbdc 100644 --- a/pkg/plugin/manager.go +++ b/pkg/plugin/manager.go @@ -14,6 +14,7 @@ import ( "gopkg.in/yaml.v3" "github.com/aquasecurity/go-version/pkg/semver" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/downloader" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" @@ -63,7 +64,7 @@ func NewManager(opts ...ManagerOption) *Manager { indexURL: indexURL, logger: log.WithPrefix("plugin"), pluginRoot: filepath.Join(fsutils.HomeDir(), pluginsRelativeDir), - indexPath: filepath.Join(fsutils.CacheDir(), "plugin", "index.yaml"), + indexPath: filepath.Join(cache.Dir(), "plugin", "index.yaml"), } for _, opt := range opts { opt(m) diff --git a/pkg/plugin/manager_unix_test.go b/pkg/plugin/manager_unix_test.go index 0250a80d7907..dd59109f94ee 100644 --- a/pkg/plugin/manager_unix_test.go +++ b/pkg/plugin/manager_unix_test.go @@ -20,11 +20,11 @@ import ( "github.com/stretchr/testify/require" "github.com/aquasecurity/trivy/internal/gittest" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/clock" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/plugin" - "github.com/aquasecurity/trivy/pkg/utils/fsutils" ) func setupGitRepository(t *testing.T, repo, dir string) *httptest.Server { @@ -200,7 +200,7 @@ func TestManager_Install(t *testing.T) { t.Setenv("XDG_DATA_HOME", dst) // For plugin index - fsutils.SetCacheDir("testdata") + cache.SetDir("testdata") if tt.installed != nil { setupInstalledPlugin(t, dst, *tt.installed) diff --git a/pkg/rpc/server/inject.go b/pkg/rpc/server/inject.go index 453e4e80a892..4c05df08b15e 100644 --- a/pkg/rpc/server/inject.go +++ b/pkg/rpc/server/inject.go @@ -6,7 +6,7 @@ package server import ( "github.com/google/wire" - "github.com/aquasecurity/trivy/pkg/fanal/cache" + "github.com/aquasecurity/trivy/pkg/cache" ) func initializeScanServer(localArtifactCache cache.LocalArtifactCache) *ScanServer { diff --git a/pkg/rpc/server/listen.go b/pkg/rpc/server/listen.go index 78edb5a21876..7e2ebc6b8227 100644 --- a/pkg/rpc/server/listen.go +++ b/pkg/rpc/server/listen.go @@ -15,8 +15,8 @@ import ( "github.com/aquasecurity/trivy-db/pkg/db" "github.com/aquasecurity/trivy-db/pkg/metadata" + "github.com/aquasecurity/trivy/pkg/cache" dbc "github.com/aquasecurity/trivy/pkg/db" - "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/utils/fsutils" diff --git a/pkg/rpc/server/listen_test.go b/pkg/rpc/server/listen_test.go index 02cf8d0c59fd..82c8b2669bc4 100644 --- a/pkg/rpc/server/listen_test.go +++ b/pkg/rpc/server/listen_test.go @@ -17,9 +17,9 @@ import ( trivydb "github.com/aquasecurity/trivy-db/pkg/db" "github.com/aquasecurity/trivy-db/pkg/metadata" "github.com/aquasecurity/trivy/internal/dbtest" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/clock" "github.com/aquasecurity/trivy/pkg/db" - "github.com/aquasecurity/trivy/pkg/fanal/cache" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/policy" "github.com/aquasecurity/trivy/pkg/version" diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index 79801b3bd212..eb29683942f5 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -8,7 +8,7 @@ import ( "golang.org/x/xerrors" "google.golang.org/protobuf/types/known/emptypb" - "github.com/aquasecurity/trivy/pkg/fanal/cache" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/rpc" "github.com/aquasecurity/trivy/pkg/scanner" diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index 956db45249e3..78db0c06aac3 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -15,7 +15,7 @@ import ( dbTypes "github.com/aquasecurity/trivy-db/pkg/types" "github.com/aquasecurity/trivy-db/pkg/utils" "github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability" - "github.com/aquasecurity/trivy/pkg/fanal/cache" + "github.com/aquasecurity/trivy/pkg/cache" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/scanner" "github.com/aquasecurity/trivy/pkg/types" diff --git a/pkg/rpc/server/wire_gen.go b/pkg/rpc/server/wire_gen.go index 81f5ba451a72..4d667cbe9dfd 100644 --- a/pkg/rpc/server/wire_gen.go +++ b/pkg/rpc/server/wire_gen.go @@ -9,7 +9,7 @@ package server import ( "github.com/aquasecurity/trivy-db/pkg/db" "github.com/aquasecurity/trivy/pkg/fanal/applier" - "github.com/aquasecurity/trivy/pkg/fanal/cache" + "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/scanner/langpkg" "github.com/aquasecurity/trivy/pkg/scanner/local" "github.com/aquasecurity/trivy/pkg/scanner/ospkg" diff --git a/pkg/utils/fsutils/fs.go b/pkg/utils/fsutils/fs.go index c4f9c75cc9fc..b8efbf1cbc60 100644 --- a/pkg/utils/fsutils/fs.go +++ b/pkg/utils/fsutils/fs.go @@ -18,30 +18,6 @@ const ( xdgDataHome = "XDG_DATA_HOME" ) -var cacheDir string - -// defaultCacheDir returns/creates the cache-dir to be used for trivy operations -func defaultCacheDir() string { - tmpDir, err := os.UserCacheDir() - if err != nil { - tmpDir = os.TempDir() - } - return filepath.Join(tmpDir, "trivy") -} - -// CacheDir returns the directory used for caching -func CacheDir() string { - if cacheDir == "" { - return defaultCacheDir() - } - return cacheDir -} - -// SetCacheDir sets the trivy cacheDir -func SetCacheDir(dir string) { - cacheDir = dir -} - func HomeDir() string { dataHome := os.Getenv(xdgDataHome) if dataHome != "" {