github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/flag/cache_flags.go (about) 1 package flag 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "github.com/samber/lo" 9 "golang.org/x/xerrors" 10 ) 11 12 // e.g. config yaml: 13 // 14 // cache: 15 // clear: true 16 // backend: "redis://localhost:6379" 17 // redis: 18 // ca: ca-cert.pem 19 // cert: cert.pem 20 // key: key.pem 21 var ( 22 ClearCacheFlag = Flag{ 23 Name: "clear-cache", 24 ConfigName: "cache.clear", 25 Default: false, 26 Usage: "clear image caches without scanning", 27 } 28 CacheBackendFlag = Flag{ 29 Name: "cache-backend", 30 ConfigName: "cache.backend", 31 Default: "fs", 32 Usage: "cache backend (e.g. redis://localhost:6379)", 33 } 34 CacheTTLFlag = Flag{ 35 Name: "cache-ttl", 36 ConfigName: "cache.ttl", 37 Default: time.Duration(0), 38 Usage: "cache TTL when using redis as cache backend", 39 } 40 RedisTLSFlag = Flag{ 41 Name: "redis-tls", 42 ConfigName: "cache.redis.tls", 43 Default: false, 44 Usage: "enable redis TLS with public certificates, if using redis as cache backend", 45 } 46 RedisCACertFlag = Flag{ 47 Name: "redis-ca", 48 ConfigName: "cache.redis.ca", 49 Default: "", 50 Usage: "redis ca file location, if using redis as cache backend", 51 } 52 RedisCertFlag = Flag{ 53 Name: "redis-cert", 54 ConfigName: "cache.redis.cert", 55 Default: "", 56 Usage: "redis certificate file location, if using redis as cache backend", 57 } 58 RedisKeyFlag = Flag{ 59 Name: "redis-key", 60 ConfigName: "cache.redis.key", 61 Default: "", 62 Usage: "redis key file location, if using redis as cache backend", 63 } 64 ) 65 66 // CacheFlagGroup composes common printer flag structs used for commands requiring cache logic. 67 type CacheFlagGroup struct { 68 ClearCache *Flag 69 CacheBackend *Flag 70 CacheTTL *Flag 71 72 RedisTLS *Flag 73 RedisCACert *Flag 74 RedisCert *Flag 75 RedisKey *Flag 76 } 77 78 type CacheOptions struct { 79 ClearCache bool 80 CacheBackend string 81 CacheTTL time.Duration 82 RedisTLS bool 83 RedisOptions 84 } 85 86 // RedisOptions holds the options for redis cache 87 type RedisOptions struct { 88 RedisCACert string 89 RedisCert string 90 RedisKey string 91 } 92 93 // NewCacheFlagGroup returns a default CacheFlagGroup 94 func NewCacheFlagGroup() *CacheFlagGroup { 95 return &CacheFlagGroup{ 96 ClearCache: &ClearCacheFlag, 97 CacheBackend: &CacheBackendFlag, 98 CacheTTL: &CacheTTLFlag, 99 RedisTLS: &RedisTLSFlag, 100 RedisCACert: &RedisCACertFlag, 101 RedisCert: &RedisCertFlag, 102 RedisKey: &RedisKeyFlag, 103 } 104 } 105 106 func (fg *CacheFlagGroup) Name() string { 107 return "Cache" 108 } 109 110 func (fg *CacheFlagGroup) Flags() []*Flag { 111 return []*Flag{fg.ClearCache, fg.CacheBackend, fg.CacheTTL, fg.RedisTLS, fg.RedisCACert, fg.RedisCert, fg.RedisKey} 112 } 113 114 func (fg *CacheFlagGroup) ToOptions() (CacheOptions, error) { 115 cacheBackend := getString(fg.CacheBackend) 116 redisOptions := RedisOptions{ 117 RedisCACert: getString(fg.RedisCACert), 118 RedisCert: getString(fg.RedisCert), 119 RedisKey: getString(fg.RedisKey), 120 } 121 122 // "redis://" or "fs" are allowed for now 123 // An empty value is also allowed for testability 124 if !strings.HasPrefix(cacheBackend, "redis://") && 125 cacheBackend != "fs" && cacheBackend != "" { 126 return CacheOptions{}, xerrors.Errorf("unsupported cache backend: %s", cacheBackend) 127 } 128 // if one of redis option not nil, make sure CA, cert, and key provided 129 if !lo.IsEmpty(redisOptions) { 130 if redisOptions.RedisCACert == "" || redisOptions.RedisCert == "" || redisOptions.RedisKey == "" { 131 return CacheOptions{}, xerrors.Errorf("you must provide Redis CA, cert and key file path when using TLS") 132 } 133 } 134 135 return CacheOptions{ 136 ClearCache: getBool(fg.ClearCache), 137 CacheBackend: cacheBackend, 138 CacheTTL: getDuration(fg.CacheTTL), 139 RedisTLS: getBool(fg.RedisTLS), 140 RedisOptions: redisOptions, 141 }, nil 142 } 143 144 // CacheBackendMasked returns the redis connection string masking credentials 145 func (o *CacheOptions) CacheBackendMasked() string { 146 endIndex := strings.Index(o.CacheBackend, "@") 147 if endIndex == -1 { 148 return o.CacheBackend 149 } 150 151 startIndex := strings.Index(o.CacheBackend, "//") 152 153 return fmt.Sprintf("%s****%s", o.CacheBackend[:startIndex+2], o.CacheBackend[endIndex:]) 154 }