mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-21 23:00:42 -08:00
refactor: use google/wire for cache (#7024)
Signed-off-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
167
pkg/cache/client.go
vendored
167
pkg/cache/client.go
vendored
@@ -1,166 +1,65 @@
|
||||
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"
|
||||
TypeUnknown Type = "unknown"
|
||||
TypeFS Type = "fs"
|
||||
TypeRedis Type = "redis"
|
||||
)
|
||||
|
||||
type Type string
|
||||
|
||||
type Options struct {
|
||||
Type Type
|
||||
TTL time.Duration
|
||||
Redis RedisOptions
|
||||
Backend string
|
||||
CacheDir string
|
||||
RedisCACert string
|
||||
RedisCert string
|
||||
RedisKey string
|
||||
RedisTLS bool
|
||||
TTL time.Duration
|
||||
}
|
||||
|
||||
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) {
|
||||
func NewType(backend string) Type {
|
||||
// "redis://" or "fs" are allowed for now
|
||||
// An empty value is also allowed for testability
|
||||
switch {
|
||||
case strings.HasPrefix(backend, "redis://"):
|
||||
return TypeRedis, nil
|
||||
return TypeRedis
|
||||
case backend == "fs", backend == "":
|
||||
return TypeFS, nil
|
||||
return TypeFS
|
||||
default:
|
||||
return "", xerrors.Errorf("unknown cache backend: %s", backend)
|
||||
return TypeUnknown
|
||||
}
|
||||
}
|
||||
|
||||
// New returns a new cache client
|
||||
func New(dir string, opts Options) (Cache, error) {
|
||||
if opts.Type == TypeRedis {
|
||||
log.Info("Redis cache", log.String("url", opts.Redis.BackendMasked()))
|
||||
options, err := redis.ParseURL(opts.Redis.Backend)
|
||||
func New(opts Options) (Cache, func(), error) {
|
||||
cleanup := func() {} // To avoid panic
|
||||
|
||||
var cache Cache
|
||||
t := NewType(opts.Backend)
|
||||
switch t {
|
||||
case TypeRedis:
|
||||
redisCache, err := NewRedisCache(opts.Backend, opts.RedisCACert, opts.RedisCert, opts.RedisKey, opts.RedisTLS, opts.TTL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, cleanup, xerrors.Errorf("unable to initialize redis cache: %w", 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,
|
||||
}
|
||||
cache = redisCache
|
||||
case TypeFS:
|
||||
// standalone mode
|
||||
fsCache, err := NewFSCache(opts.CacheDir)
|
||||
if err != nil {
|
||||
return nil, cleanup, xerrors.Errorf("unable to initialize fs cache: %w", err)
|
||||
}
|
||||
|
||||
return NewRedisCache(options, opts.TTL), nil
|
||||
cache = fsCache
|
||||
default:
|
||||
return nil, cleanup, xerrors.Errorf("unknown cache type: %s", t)
|
||||
}
|
||||
|
||||
// standalone mode
|
||||
fsCache, err := NewFSCache(dir)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("unable to initialize fs cache: %w", err)
|
||||
}
|
||||
return fsCache, 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
|
||||
return cache, func() { _ = cache.Close() }, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user