feat!: add clean subcommand (#6993)

Signed-off-by: knqyf263 <knqyf263@gmail.com>
Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com>
Co-authored-by: DmitriyLewen <dmitriy.lewen@smartforce.io>
This commit is contained in:
Teppei Fukuda
2024-06-25 13:06:27 +04:00
committed by GitHub
parent de201dc772
commit 8d0ae1f5de
35 changed files with 496 additions and 210 deletions

View File

@@ -116,7 +116,7 @@ body:
label: Checklist label: Checklist
description: Have you tried the following? description: Have you tried the following?
options: options:
- label: Run `trivy image --reset` - label: Run `trivy clean --all`
- label: Read [the troubleshooting](https://aquasecurity.github.io/trivy/latest/docs/references/troubleshooting/) - label: Read [the troubleshooting](https://aquasecurity.github.io/trivy/latest/docs/references/troubleshooting/)
- type: markdown - type: markdown
attributes: attributes:

View File

@@ -9,24 +9,25 @@ The cache directory includes
The cache option is common to all scanners. The cache option is common to all scanners.
## Clear Caches ## Clear Caches
The `--clear-cache` option removes caches. `trivy clean` subcommand removes caches.
**The scan is not performed.**
``` ```
$ trivy image --clear-cache $ trivy clean --scan-cache
``` ```
<details> <details>
<summary>Result</summary> <summary>Result</summary>
``` ```
2019-11-15T15:13:26.209+0200 INFO Reopening vulnerability DB 2024-06-21T21:58:21+04:00 INFO Removing scan cache...
2019-11-15T15:13:26.209+0200 INFO Removing image caches...
``` ```
</details> </details>
If you want to delete cached vulnerability databases, use `--vuln-db`.
You can also delete all caches with `--all`.
See `trivy clean --help` for details.
## Cache Directory ## Cache Directory
Specify where the cache is stored with `--cache-dir`. Specify where the cache is stored with `--cache-dir`.

View File

@@ -78,8 +78,10 @@ $ trivy image --java-db-repository registry.gitlab.com/gitlab-org/security-produ
`java-db-registry:latest` => `java-db-registry:latest`, but `java-db-registry` => `java-db-registry:1`. `java-db-registry:latest` => `java-db-registry:latest`, but `java-db-registry` => `java-db-registry:1`.
## Remove DBs ## Remove DBs
The `--reset` flag removes all caches and databases. "trivy clean" command removes caches and databases.
``` ```
$ trivy image --reset $ trivy clean --vuln-db --java-db
2024-06-24T11:42:31+06:00 INFO Removing vulnerability database...
2024-06-24T11:42:31+06:00 INFO Removing Java database...
``` ```

View File

@@ -43,6 +43,7 @@ trivy [global flags] command [flags] target
### SEE ALSO ### SEE ALSO
* [trivy clean](trivy_clean.md) - Remove cached files
* [trivy config](trivy_config.md) - Scan config files for misconfigurations * [trivy config](trivy_config.md) - Scan config files for misconfigurations
* [trivy convert](trivy_convert.md) - Convert Trivy JSON report into a different format * [trivy convert](trivy_convert.md) - Convert Trivy JSON report into a different format
* [trivy filesystem](trivy_filesystem.md) - Scan local filesystem * [trivy filesystem](trivy_filesystem.md) - Scan local filesystem

View File

@@ -0,0 +1,50 @@
## trivy clean
Remove cached files
```
trivy clean [flags]
```
### Examples
```
# Remove all caches
$ trivy clean --all
# Remove scan cache
$ trivy clean --scan-cache
# Remove vulnerability database
$ trivy clean --vuln-db
```
### Options
```
-a, --all remove all caches
--checks-bundle remove checks bundle
-h, --help help for clean
--java-db remove Java database
--scan-cache remove scan cache (container and VM image analysis results)
--vuln-db remove vulnerability database
```
### Options inherited from parent commands
```
--cache-dir string cache directory (default "/path/to/cache")
-c, --config string config path (default "trivy.yaml")
-d, --debug debug mode
--generate-default-config write the default config to trivy-default.yaml
--insecure allow insecure server connections
-q, --quiet suppress progress bar and log output
--timeout duration timeout (default 5m0s)
-v, --version show version
```
### SEE ALSO
* [trivy](trivy.md) - Unified security scanner

View File

@@ -14,7 +14,6 @@ trivy config [flags] DIR
--cf-params strings specify paths to override the CloudFormation parameters files --cf-params strings specify paths to override the CloudFormation parameters files
--check-namespaces strings Rego namespaces --check-namespaces strings Rego namespaces
--checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0")
--clear-cache clear image caches without scanning
--compliance string compliance report to generate --compliance string compliance report to generate
--config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files --config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files
--config-data strings specify paths from which data for the Rego checks will be recursively loaded --config-data strings specify paths from which data for the Rego checks will be recursively loaded
@@ -45,7 +44,6 @@ trivy config [flags] DIR
--redis-tls enable redis TLS with public certificates, if using redis as cache backend --redis-tls enable redis TLS with public certificates, if using redis as cache backend
--registry-token string registry token --registry-token string registry token
--report string specify a compliance report format for the output (all,summary) (default "all") --report string specify a compliance report format for the output (all,summary) (default "all")
--reset-checks-bundle remove checks bundle
-s, --severity strings severities of security issues to be displayed (UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL) (default [UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL]) -s, --severity strings severities of security issues to be displayed (UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL) (default [UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL])
--skip-check-update skip fetching rego check updates --skip-check-update skip fetching rego check updates
--skip-dirs strings specify the directories or glob patterns to skip --skip-dirs strings specify the directories or glob patterns to skip

View File

@@ -24,7 +24,6 @@ trivy filesystem [flags] PATH
--cf-params strings specify paths to override the CloudFormation parameters files --cf-params strings specify paths to override the CloudFormation parameters files
--check-namespaces strings Rego namespaces --check-namespaces strings Rego namespaces
--checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0")
--clear-cache clear image caches without scanning
--compliance string compliance report to generate --compliance string compliance report to generate
--config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files --config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files
--config-data strings specify paths from which data for the Rego checks will be recursively loaded --config-data strings specify paths from which data for the Rego checks will be recursively loaded
@@ -71,8 +70,6 @@ trivy filesystem [flags] PATH
--registry-token string registry token --registry-token string registry token
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
--report string specify a compliance report format for the output (all,summary) (default "all") --report string specify a compliance report format for the output (all,summary) (default "all")
--reset remove all caches and database
--reset-checks-bundle remove checks bundle
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor) --sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor)
--scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret]) --scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret])
--secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml") --secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml")

View File

@@ -38,7 +38,6 @@ trivy image [flags] IMAGE_NAME
--cache-ttl duration cache TTL when using redis as cache backend --cache-ttl duration cache TTL when using redis as cache backend
--check-namespaces strings Rego namespaces --check-namespaces strings Rego namespaces
--checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0")
--clear-cache clear image caches without scanning
--compliance string compliance report to generate (docker-cis) --compliance string compliance report to generate (docker-cis)
--config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files --config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files
--config-data strings specify paths from which data for the Rego checks will be recursively loaded --config-data strings specify paths from which data for the Rego checks will be recursively loaded
@@ -92,8 +91,6 @@ trivy image [flags] IMAGE_NAME
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
--removed-pkgs detect vulnerabilities of removed packages (only for Alpine) --removed-pkgs detect vulnerabilities of removed packages (only for Alpine)
--report string specify a format for the compliance report. (all,summary) (default "summary") --report string specify a format for the compliance report. (all,summary) (default "summary")
--reset remove all caches and database
--reset-checks-bundle remove checks bundle
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor) --sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor)
--scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret]) --scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret])
--secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml") --secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml")

View File

@@ -34,7 +34,6 @@ trivy kubernetes [flags] [CONTEXT]
--cache-ttl duration cache TTL when using redis as cache backend --cache-ttl duration cache TTL when using redis as cache backend
--check-namespaces strings Rego namespaces --check-namespaces strings Rego namespaces
--checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0")
--clear-cache clear image caches without scanning
--compliance string compliance report to generate (k8s-nsa,k8s-cis,k8s-pss-baseline,k8s-pss-restricted) --compliance string compliance report to generate (k8s-nsa,k8s-cis,k8s-pss-baseline,k8s-pss-restricted)
--config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files --config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files
--config-data strings specify paths from which data for the Rego checks will be recursively loaded --config-data strings specify paths from which data for the Rego checks will be recursively loaded
@@ -87,8 +86,6 @@ trivy kubernetes [flags] [CONTEXT]
--registry-token string registry token --registry-token string registry token
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
--report string specify a report format for the output (all,summary) (default "all") --report string specify a report format for the output (all,summary) (default "all")
--reset remove all caches and database
--reset-checks-bundle remove checks bundle
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor) --sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor)
--scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,rbac) (default [vuln,misconfig,secret,rbac]) --scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,rbac) (default [vuln,misconfig,secret,rbac])
--secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml") --secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml")

View File

@@ -24,7 +24,6 @@ trivy repository [flags] (REPO_PATH | REPO_URL)
--cf-params strings specify paths to override the CloudFormation parameters files --cf-params strings specify paths to override the CloudFormation parameters files
--check-namespaces strings Rego namespaces --check-namespaces strings Rego namespaces
--checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0")
--clear-cache clear image caches without scanning
--commit string pass the commit hash to be scanned --commit string pass the commit hash to be scanned
--config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files --config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files
--config-data strings specify paths from which data for the Rego checks will be recursively loaded --config-data strings specify paths from which data for the Rego checks will be recursively loaded
@@ -70,8 +69,6 @@ trivy repository [flags] (REPO_PATH | REPO_URL)
--redis-tls enable redis TLS with public certificates, if using redis as cache backend --redis-tls enable redis TLS with public certificates, if using redis as cache backend
--registry-token string registry token --registry-token string registry token
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
--reset remove all caches and database
--reset-checks-bundle remove checks bundle
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor) --sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor)
--scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret]) --scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret])
--secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml") --secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml")

View File

@@ -27,7 +27,6 @@ trivy rootfs [flags] ROOTDIR
--cf-params strings specify paths to override the CloudFormation parameters files --cf-params strings specify paths to override the CloudFormation parameters files
--check-namespaces strings Rego namespaces --check-namespaces strings Rego namespaces
--checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0")
--clear-cache clear image caches without scanning
--config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files --config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files
--config-data strings specify paths from which data for the Rego checks will be recursively loaded --config-data strings specify paths from which data for the Rego checks will be recursively loaded
--custom-headers strings custom headers in client mode --custom-headers strings custom headers in client mode
@@ -72,8 +71,6 @@ trivy rootfs [flags] ROOTDIR
--redis-tls enable redis TLS with public certificates, if using redis as cache backend --redis-tls enable redis TLS with public certificates, if using redis as cache backend
--registry-token string registry token --registry-token string registry token
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
--reset remove all caches and database
--reset-checks-bundle remove checks bundle
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor) --sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor)
--scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret]) --scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret])
--secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml") --secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml")

View File

@@ -22,7 +22,6 @@ trivy sbom [flags] SBOM_PATH
``` ```
--cache-backend string cache backend (e.g. redis://localhost:6379) (default "fs") --cache-backend string cache backend (e.g. redis://localhost:6379) (default "fs")
--cache-ttl duration cache TTL when using redis as cache backend --cache-ttl duration cache TTL when using redis as cache backend
--clear-cache clear image caches without scanning
--compliance string compliance report to generate --compliance string compliance report to generate
--custom-headers strings custom headers in client mode --custom-headers strings custom headers in client mode
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2") --db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2")
@@ -49,7 +48,6 @@ trivy sbom [flags] SBOM_PATH
--redis-key string redis key file location, if using redis as cache backend --redis-key string redis key file location, if using redis as cache backend
--redis-tls enable redis TLS with public certificates, if using redis as cache backend --redis-tls enable redis TLS with public certificates, if using redis as cache backend
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
--reset remove all caches and database
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor) --sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor)
--scanners strings comma-separated list of what security issues to detect (vuln,license) (default [vuln]) --scanners strings comma-separated list of what security issues to detect (vuln,license) (default [vuln])
--server string server address in client mode --server string server address in client mode

View File

@@ -22,7 +22,6 @@ trivy server [flags]
``` ```
--cache-backend string cache backend (e.g. redis://localhost:6379) (default "fs") --cache-backend string cache backend (e.g. redis://localhost:6379) (default "fs")
--cache-ttl duration cache TTL when using redis as cache backend --cache-ttl duration cache TTL when using redis as cache backend
--clear-cache clear image caches without scanning
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2") --db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2")
--download-db-only download/update vulnerability database but don't run a scan --download-db-only download/update vulnerability database but don't run a scan
--enable-modules strings [EXPERIMENTAL] module names to enable --enable-modules strings [EXPERIMENTAL] module names to enable
@@ -36,7 +35,6 @@ trivy server [flags]
--redis-key string redis key file location, if using redis as cache backend --redis-key string redis key file location, if using redis as cache backend
--redis-tls enable redis TLS with public certificates, if using redis as cache backend --redis-tls enable redis TLS with public certificates, if using redis as cache backend
--registry-token string registry token --registry-token string registry token
--reset remove all caches and database
--skip-db-update skip updating vulnerability database --skip-db-update skip updating vulnerability database
--token string for authentication in client/server mode --token string for authentication in client/server mode
--token-header string specify a header name for token in client/server mode (default "Trivy-Token") --token-header string specify a header name for token in client/server mode (default "Trivy-Token")

View File

@@ -24,7 +24,6 @@ trivy vm [flags] VM_IMAGE
--cache-backend string cache backend (e.g. redis://localhost:6379) (default "fs") --cache-backend string cache backend (e.g. redis://localhost:6379) (default "fs")
--cache-ttl duration cache TTL when using redis as cache backend --cache-ttl duration cache TTL when using redis as cache backend
--checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0")
--clear-cache clear image caches without scanning
--compliance string compliance report to generate --compliance string compliance report to generate
--custom-headers strings custom headers in client mode --custom-headers strings custom headers in client mode
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2") --db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2")
@@ -62,8 +61,6 @@ trivy vm [flags] VM_IMAGE
--redis-key string redis key file location, if using redis as cache backend --redis-key string redis key file location, if using redis as cache backend
--redis-tls enable redis TLS with public certificates, if using redis as cache backend --redis-tls enable redis TLS with public certificates, if using redis as cache backend
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
--reset remove all caches and database
--reset-checks-bundle remove checks bundle
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor) --sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor)
--scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret]) --scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret])
--secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml") --secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml")

View File

@@ -264,10 +264,10 @@ $ brew install aquasecurity/trivy/trivy
## Others ## Others
### Unknown error ### Unknown error
Try again with `--reset` option: Try again after running `trivy clean --all`:
``` ```
$ trivy image --reset $ trivy clean --all
``` ```
[air-gapped]: ../advanced/air-gap.md [air-gapped]: ../advanced/air-gap.md

View File

@@ -85,8 +85,6 @@ container_scanning:
FULL_IMAGE_NAME: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG FULL_IMAGE_NAME: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
script: script:
- trivy --version - trivy --version
# cache cleanup is needed when scanning images with the same tags, it does not remove the database
- time trivy image --clear-cache
# update vulnerabilities db # update vulnerabilities db
- time trivy image --download-db-only - time trivy image --download-db-only
# Builds report and puts it in the default workdir $CI_PROJECT_DIR, so `artifacts:` can take it from there # Builds report and puts it in the default workdir $CI_PROJECT_DIR, so `artifacts:` can take it from there

View File

@@ -152,6 +152,7 @@ nav:
- Configuration: - Configuration:
- CLI: - CLI:
- Overview: docs/references/configuration/cli/trivy.md - Overview: docs/references/configuration/cli/trivy.md
- Clean: docs/references/configuration/cli/trivy_clean.md
- Config: docs/references/configuration/cli/trivy_config.md - Config: docs/references/configuration/cli/trivy_config.md
- Convert: docs/references/configuration/cli/trivy_convert.md - Convert: docs/references/configuration/cli/trivy_convert.md
- Filesystem: docs/references/configuration/cli/trivy_filesystem.md - Filesystem: docs/references/configuration/cli/trivy_filesystem.md

39
pkg/cache/client.go vendored
View File

@@ -20,11 +20,6 @@ const (
TypeRedis Type = "redis" TypeRedis Type = "redis"
) )
type Client struct {
dir string
Cache
}
type Type string type Type string
type Options struct { type Options struct {
@@ -115,9 +110,8 @@ func NewType(backend string) (Type, error) {
} }
} }
// NewClient returns a new cache client // New returns a new cache client
func NewClient(dir string, opts Options) (*Client, error) { func New(dir string, opts Options) (Cache, error) {
client := &Client{dir: dir}
if opts.Type == TypeRedis { if opts.Type == TypeRedis {
log.Info("Redis cache", log.String("url", opts.Redis.BackendMasked())) log.Info("Redis cache", log.String("url", opts.Redis.BackendMasked()))
options, err := redis.ParseURL(opts.Redis.Backend) options, err := redis.ParseURL(opts.Redis.Backend)
@@ -142,38 +136,15 @@ func NewClient(dir string, opts Options) (*Client, error) {
} }
} }
client.Cache = NewRedisCache(options, opts.TTL) return NewRedisCache(options, opts.TTL), nil
return client, nil
} }
// standalone mode // standalone mode
var err error fsCache, err := NewFSCache(dir)
client.Cache, err = NewFSCache(dir)
if err != nil { if err != nil {
return nil, xerrors.Errorf("unable to initialize fs cache: %w", err) return nil, xerrors.Errorf("unable to initialize fs cache: %w", err)
} }
return client, nil return fsCache, nil
}
// Reset resets the cache
func (c *Client) Reset() error {
log.Info("Removing all caches...")
if err := c.Clear(); err != nil {
return xerrors.Errorf("failed to remove the cache: %w", err)
}
if err := os.RemoveAll(c.dir); err != nil {
return xerrors.Errorf("failed to remove the directory (%s) : %w", c.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 // GetTLSConfig gets tls config from CA, Cert and Key file

View File

@@ -1,8 +1,6 @@
package cache_test package cache_test
import ( import (
"os"
"path/filepath"
"testing" "testing"
"time" "time"
@@ -129,51 +127,3 @@ func TestRedisOptions_BackendMasked(t *testing.T) {
}) })
} }
} }
func TestClient_Reset(t *testing.T) {
// Create a temporary directory for testing
tempDir := t.TempDir()
// Create test files and subdirectories
subDir := filepath.Join(tempDir, "subdir")
err := os.MkdirAll(subDir, 0755)
require.NoError(t, err)
testFile := filepath.Join(tempDir, "testfile.txt")
err = os.WriteFile(testFile, []byte("test content"), 0644)
require.NoError(t, err)
// Create a cache client
client, err := cache.NewClient(tempDir, cache.Options{Type: cache.TypeFS})
require.NoError(t, err)
// Call Reset method
err = client.Reset()
require.NoError(t, err)
// Verify that the subdirectory no longer exists
require.NoDirExists(t, subDir, "Subdirectory should not exist after Reset")
// Verify that the test file no longer exists
require.NoFileExists(t, testFile, "Test file should not exist after Reset")
// Verify that the cache directory no longer exists
require.NoDirExists(t, tempDir, "Cache directory should not exist after Reset")
}
func TestClient_ClearArtifacts(t *testing.T) {
// Create a temporary directory for testing
tempDir := t.TempDir()
// Create a client
client, err := cache.NewClient(tempDir, cache.Options{Type: cache.TypeFS})
require.NoError(t, err)
require.FileExists(t, filepath.Join(tempDir, "fanal", "fanal.db"), "Database file should exist")
// Call ClearArtifacts method
err = client.ClearArtifacts()
require.NoError(t, err)
require.NoDirExists(t, filepath.Join(tempDir, "fanal"), "Artifact cache should not exist after ClearArtifacts")
}

View File

@@ -14,6 +14,7 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/commands/artifact" "github.com/aquasecurity/trivy/pkg/commands/artifact"
"github.com/aquasecurity/trivy/pkg/commands/clean"
"github.com/aquasecurity/trivy/pkg/commands/convert" "github.com/aquasecurity/trivy/pkg/commands/convert"
"github.com/aquasecurity/trivy/pkg/commands/server" "github.com/aquasecurity/trivy/pkg/commands/server"
"github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/analyzer"
@@ -94,6 +95,7 @@ func NewApp() *cobra.Command {
NewSBOMCommand(globalFlags), NewSBOMCommand(globalFlags),
NewVersionCommand(globalFlags), NewVersionCommand(globalFlags),
NewVMCommand(globalFlags), NewVMCommand(globalFlags),
NewCleanCommand(globalFlags),
) )
if plugins := loadPluginCommands(); len(plugins) > 0 { if plugins := loadPluginCommands(); len(plugins) > 0 {
@@ -1160,6 +1162,47 @@ func NewSBOMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
return cmd return cmd
} }
func NewCleanCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
cleanFlags := &flag.Flags{
GlobalFlagGroup: globalFlags,
CleanFlagGroup: flag.NewCleanFlagGroup(),
}
cmd := &cobra.Command{
Use: "clean [flags]",
GroupID: groupUtility,
Short: "Remove cached files",
Example: ` # Remove all caches
$ trivy clean --all
# Remove scan cache
$ trivy clean --scan-cache
# Remove vulnerability database
$ trivy clean --vuln-db
`,
PreRunE: func(cmd *cobra.Command, args []string) error {
if err := cleanFlags.Bind(cmd); err != nil {
return xerrors.Errorf("flag bind error: %w", err)
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
opts, err := cleanFlags.ToOptions(args)
if err != nil {
return xerrors.Errorf("flag error: %w", err)
}
return clean.Run(cmd.Context(), opts)
},
SilenceErrors: true,
SilenceUsage: true,
}
cmd.SetFlagErrorFunc(flagErrorFunc)
cleanFlags.AddFlags(cmd)
cmd.SetUsageTemplate(fmt.Sprintf(usageTemplate, cleanFlags.Usages(cmd)))
return cmd
}
func NewVersionCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { func NewVersionCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
var versionFormat string var versionFormat string
cmd := &cobra.Command{ cmd := &cobra.Command{
@@ -1199,7 +1242,8 @@ func showVersion(cacheDir, outputFormat string, w io.Writer) error {
} }
func validateArgs(cmd *cobra.Command, args []string) error { func validateArgs(cmd *cobra.Command, args []string) error {
// '--clear-cache', '--download-db-only', '--download-java-db-only', '--reset', '--reset-checks-bundle' and '--generate-default-config' don't conduct the subsequent scanning // '--clear-cache' (removed), '--download-db-only', '--download-java-db-only', '--reset' (removed),
// '--reset-checks-bundle' (removed) and '--generate-default-config' don't conduct the subsequent scanning
if viper.GetBool(flag.ClearCacheFlag.ConfigName) || viper.GetBool(flag.DownloadDBOnlyFlag.ConfigName) || if viper.GetBool(flag.ClearCacheFlag.ConfigName) || viper.GetBool(flag.DownloadDBOnlyFlag.ConfigName) ||
viper.GetBool(flag.ResetFlag.ConfigName) || viper.GetBool(flag.GenerateDefaultConfigFlag.ConfigName) || viper.GetBool(flag.ResetFlag.ConfigName) || viper.GetBool(flag.GenerateDefaultConfigFlag.ConfigName) ||
viper.GetBool(flag.DownloadJavaDBOnlyFlag.ConfigName) || viper.GetBool(flag.ResetChecksBundleFlag.ConfigName) { viper.GetBool(flag.DownloadJavaDBOnlyFlag.ConfigName) || viper.GetBool(flag.ResetChecksBundleFlag.ConfigName) {

View File

@@ -24,7 +24,6 @@ import (
"github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/misconf" "github.com/aquasecurity/trivy/pkg/misconf"
"github.com/aquasecurity/trivy/pkg/module" "github.com/aquasecurity/trivy/pkg/module"
"github.com/aquasecurity/trivy/pkg/policy"
pkgReport "github.com/aquasecurity/trivy/pkg/report" pkgReport "github.com/aquasecurity/trivy/pkg/report"
"github.com/aquasecurity/trivy/pkg/result" "github.com/aquasecurity/trivy/pkg/result"
"github.com/aquasecurity/trivy/pkg/rpc/client" "github.com/aquasecurity/trivy/pkg/rpc/client"
@@ -350,41 +349,14 @@ func (r *runner) initCache(opts flag.Options) error {
} }
// standalone mode // standalone mode
cacheClient, err := cache.NewClient(opts.CacheDir, opts.CacheOptions.CacheBackendOptions) cacheClient, err := cache.New(opts.CacheDir, opts.CacheOptions.CacheBackendOptions)
if err != nil { if err != nil {
return xerrors.Errorf("unable to initialize the cache: %w", err) return xerrors.Errorf("unable to initialize the cache: %w", err)
} }
log.Debug("Cache dir", log.String("dir", opts.CacheDir)) log.Debug("Cache dir", log.String("dir", opts.CacheDir))
if opts.Reset { r.cache = cacheClient
defer cacheClient.Close() r.localCache = cacheClient
if err = cacheClient.Reset(); err != nil {
return xerrors.Errorf("cache reset error: %w", err)
}
return SkipScan
}
if opts.ResetChecksBundle {
c, err := policy.NewClient(opts.CacheDir, true, opts.MisconfOptions.ChecksBundleRepository)
if err != nil {
return xerrors.Errorf("failed to instantiate check client: %w", err)
}
if err := c.Clear(); err != nil {
return xerrors.Errorf("failed to remove the cache: %w", err)
}
return SkipScan
}
if opts.ClearCache {
defer cacheClient.Close()
if err = cacheClient.ClearArtifacts(); err != nil {
return xerrors.Errorf("cache clear error: %w", err)
}
return SkipScan
}
r.cache = cacheClient.Cache
r.localCache = cacheClient.Cache
return nil return nil
} }

102
pkg/commands/clean/run.go Normal file
View File

@@ -0,0 +1,102 @@
package clean
import (
"context"
"os"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/cache"
"github.com/aquasecurity/trivy/pkg/db"
"github.com/aquasecurity/trivy/pkg/flag"
"github.com/aquasecurity/trivy/pkg/javadb"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/policy"
)
func Run(ctx context.Context, opts flag.Options) error {
ctx, cancel := context.WithTimeout(ctx, opts.Timeout)
defer cancel()
if !opts.CleanAll && !opts.CleanScanCache && !opts.CleanVulnerabilityDB && !opts.CleanJavaDB && !opts.CleanChecksBundle {
return xerrors.New("no clean option is specified")
}
if opts.CleanAll {
return cleanAll(ctx, opts)
}
if opts.CleanScanCache {
if err := cleanScanCache(ctx, opts); err != nil {
return xerrors.Errorf("failed to remove scan cache : %w", err)
}
}
if opts.CleanVulnerabilityDB {
if err := cleanVulnerabilityDB(ctx, opts); err != nil {
return xerrors.Errorf("vuln db clean error: %w", err)
}
}
if opts.CleanJavaDB {
if err := cleanJavaDB(ctx, opts); err != nil {
return xerrors.Errorf("java db clean error: %w", err)
}
}
if opts.CleanChecksBundle {
if err := cleanCheckBundle(opts); err != nil {
return xerrors.Errorf("check bundle clean error: %w", err)
}
}
return nil
}
func cleanAll(ctx context.Context, opts flag.Options) error {
log.InfoContext(ctx, "Removing all caches...")
if err := os.RemoveAll(opts.CacheDir); err != nil {
return xerrors.Errorf("failed to remove the directory (%s) : %w", opts.CacheDir, err)
}
return nil
}
func cleanScanCache(ctx context.Context, opts flag.Options) error {
log.InfoContext(ctx, "Removing scan cache...")
c, err := cache.New(opts.CacheDir, opts.CacheBackendOptions)
if err != nil {
return xerrors.Errorf("failed to instantiate cache client: %w", err)
}
if err = c.Clear(); err != nil {
return xerrors.Errorf("clear scan cache: %w", err)
}
return nil
}
func cleanVulnerabilityDB(ctx context.Context, opts flag.Options) error {
log.InfoContext(ctx, "Removing vulnerability database...")
if err := db.NewClient(opts.CacheDir, true).Clear(ctx); err != nil {
return xerrors.Errorf("clear vulnerability database: %w", err)
}
return nil
}
func cleanJavaDB(ctx context.Context, opts flag.Options) error {
log.InfoContext(ctx, "Removing Java database...")
if err := javadb.Clear(ctx, opts.CacheDir); err != nil {
return xerrors.Errorf("clear Java database: %w", err)
}
return nil
}
func cleanCheckBundle(opts flag.Options) error {
log.Info("Removing check bundle...")
c, err := policy.NewClient(opts.CacheDir, true, opts.MisconfOptions.ChecksBundleRepository)
if err != nil {
return xerrors.Errorf("failed to instantiate check client: %w", err)
}
if err := c.Clear(); err != nil {
return xerrors.Errorf("clear check bundle: %w", err)
}
return nil
}

View File

@@ -0,0 +1,135 @@
package clean_test
import (
"context"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/commands/clean"
"github.com/aquasecurity/trivy/pkg/flag"
)
func TestRun(t *testing.T) {
tests := []struct {
name string
cleanOpts flag.CleanOptions
wantErr bool
checkFunc func(*testing.T, string)
}{
{
name: "clean all",
cleanOpts: flag.CleanOptions{
CleanAll: true,
},
wantErr: false,
checkFunc: func(t *testing.T, dir string) {
assert.NoDirExists(t, dir)
},
},
{
name: "clean scan cache",
cleanOpts: flag.CleanOptions{
CleanScanCache: true,
},
wantErr: false,
checkFunc: func(t *testing.T, dir string) {
assert.NoDirExists(t, filepath.Join(dir, "fanal"))
assert.DirExists(t, filepath.Join(dir, "db"))
assert.DirExists(t, filepath.Join(dir, "java-db"))
assert.DirExists(t, filepath.Join(dir, "policy"))
},
},
{
name: "clean vulnerability DB",
cleanOpts: flag.CleanOptions{
CleanVulnerabilityDB: true,
},
wantErr: false,
checkFunc: func(t *testing.T, dir string) {
assert.NoDirExists(t, filepath.Join(dir, "db"))
assert.DirExists(t, filepath.Join(dir, "fanal"))
assert.DirExists(t, filepath.Join(dir, "java-db"))
assert.DirExists(t, filepath.Join(dir, "policy"))
},
},
{
name: "clean Java DB",
cleanOpts: flag.CleanOptions{
CleanJavaDB: true,
},
wantErr: false,
checkFunc: func(t *testing.T, dir string) {
assert.NoDirExists(t, filepath.Join(dir, "java-db"))
assert.DirExists(t, filepath.Join(dir, "fanal"))
assert.DirExists(t, filepath.Join(dir, "db"))
assert.DirExists(t, filepath.Join(dir, "policy"))
},
},
{
name: "clean check bundle",
cleanOpts: flag.CleanOptions{
CleanChecksBundle: true,
},
wantErr: false,
checkFunc: func(t *testing.T, dir string) {
assert.NoDirExists(t, filepath.Join(dir, "policy"))
assert.DirExists(t, filepath.Join(dir, "fanal"))
assert.DirExists(t, filepath.Join(dir, "db"))
assert.DirExists(t, filepath.Join(dir, "java-db"))
},
},
{
name: "no clean option specified",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Create a temporary directory for testing
tempDir := t.TempDir()
// Create test directories and files
createTestFiles(t, tempDir)
opts := flag.Options{
GlobalOptions: flag.GlobalOptions{
CacheDir: tempDir,
},
CleanOptions: tt.cleanOpts,
}
err := clean.Run(context.Background(), opts)
if tt.wantErr {
assert.Error(t, err)
return
}
require.NoError(t, err)
if tt.checkFunc != nil {
tt.checkFunc(t, tempDir)
}
})
}
}
func createTestFiles(t *testing.T, dir string) {
subdirs := []string{
"fanal",
"db",
"java-db",
"policy",
}
for _, subdir := range subdirs {
err := os.MkdirAll(filepath.Join(dir, subdir), 0755)
require.NoError(t, err)
testFile := filepath.Join(dir, subdir, "testfile.txt")
err = os.WriteFile(testFile, []byte("test content"), 0644)
require.NoError(t, err)
}
}

View File

@@ -19,17 +19,13 @@ func Run(ctx context.Context, opts flag.Options) (err error) {
log.InitLogger(opts.Debug, opts.Quiet) log.InitLogger(opts.Debug, opts.Quiet)
// configure cache dir // configure cache dir
cacheClient, err := cache.NewClient(opts.CacheDir, opts.CacheOptions.CacheBackendOptions) cacheClient, err := cache.New(opts.CacheDir, opts.CacheOptions.CacheBackendOptions)
if err != nil { if err != nil {
return xerrors.Errorf("server cache error: %w", err) return xerrors.Errorf("server cache error: %w", err)
} }
defer cacheClient.Close() defer cacheClient.Close()
log.Debug("Cache", log.String("dir", opts.CacheDir)) log.Debug("Cache", log.String("dir", opts.CacheDir))
if opts.Reset {
return cacheClient.Reset()
}
// download the database file // download the database file
if err = operation.DownloadDB(ctx, opts.AppVersion, opts.CacheDir, opts.DBRepository, if err = operation.DownloadDB(ctx, opts.AppVersion, opts.CacheDir, opts.DBRepository,
true, opts.SkipDBUpdate, opts.RegistryOpts()); err != nil { true, opts.SkipDBUpdate, opts.RegistryOpts()); err != nil {

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"os"
"time" "time"
"github.com/google/go-containerregistry/pkg/name" "github.com/google/go-containerregistry/pkg/name"
@@ -158,6 +159,13 @@ func (c *Client) Download(ctx context.Context, dst string, opt types.RegistryOpt
return nil return nil
} }
func (c *Client) Clear(ctx context.Context) error {
if err := os.RemoveAll(db.Dir(c.cacheDir)); err != nil {
return xerrors.Errorf("failed to remove vulnerability database: %w", err)
}
return nil
}
func (c *Client) updateDownloadedAt(ctx context.Context, dst string) error { func (c *Client) updateDownloadedAt(ctx context.Context, dst string) error {
log.Debug("Updating database metadata...") log.Debug("Updating database metadata...")

View File

@@ -18,10 +18,12 @@ import (
// cert: cert.pem // cert: cert.pem
// key: key.pem // key: key.pem
var ( var (
// Deprecated
ClearCacheFlag = Flag[bool]{ ClearCacheFlag = Flag[bool]{
Name: "clear-cache", Name: "clear-cache",
ConfigName: "cache.clear", ConfigName: "cache.clear",
Usage: "clear image caches without scanning", Usage: "clear image caches without scanning",
Removed: `Use "trivy clean --scan-cache" instead`,
} }
CacheBackendFlag = Flag[string]{ CacheBackendFlag = Flag[string]{
Name: "cache-backend", Name: "cache-backend",

84
pkg/flag/clean_flags.go Normal file
View File

@@ -0,0 +1,84 @@
package flag
var (
CleanAll = Flag[bool]{
Name: "all",
Shorthand: "a",
ConfigName: "clean.all",
Usage: "remove all caches",
}
CleanScanCache = Flag[bool]{
Name: "scan-cache",
ConfigName: "clean.scan-cache",
Usage: "remove scan cache (container and VM image analysis results)",
}
CleanVulnerabilityDB = Flag[bool]{
Name: "vuln-db",
ConfigName: "clean.vuln-db",
Usage: "remove vulnerability database",
}
CleanJavaDB = Flag[bool]{
Name: "java-db",
ConfigName: "clean.java-db",
Usage: "remove Java database",
}
CleanChecksBundle = Flag[bool]{
Name: "checks-bundle",
ConfigName: "clean.checks-bundle",
Usage: "remove checks bundle",
}
)
type CleanFlagGroup struct {
CleanAll *Flag[bool]
CleanVulnerabilityDB *Flag[bool]
CleanJavaDB *Flag[bool]
CleanChecksBundle *Flag[bool]
CleanScanCache *Flag[bool]
}
type CleanOptions struct {
CleanAll bool
CleanVulnerabilityDB bool
CleanJavaDB bool
CleanChecksBundle bool
CleanScanCache bool
}
func NewCleanFlagGroup() *CleanFlagGroup {
return &CleanFlagGroup{
CleanAll: CleanAll.Clone(),
CleanVulnerabilityDB: CleanVulnerabilityDB.Clone(),
CleanJavaDB: CleanJavaDB.Clone(),
CleanChecksBundle: CleanChecksBundle.Clone(),
CleanScanCache: CleanScanCache.Clone(),
}
}
func (fg *CleanFlagGroup) Name() string {
return "Clean"
}
func (fg *CleanFlagGroup) Flags() []Flagger {
return []Flagger{
fg.CleanAll,
fg.CleanVulnerabilityDB,
fg.CleanJavaDB,
fg.CleanChecksBundle,
fg.CleanScanCache,
}
}
func (fg *CleanFlagGroup) ToOptions() (CleanOptions, error) {
if err := parseFlags(fg); err != nil {
return CleanOptions{}, err
}
return CleanOptions{
CleanAll: fg.CleanAll.Value(),
CleanVulnerabilityDB: fg.CleanVulnerabilityDB.Value(),
CleanJavaDB: fg.CleanJavaDB.Value(),
CleanChecksBundle: fg.CleanChecksBundle.Value(),
CleanScanCache: fg.CleanScanCache.Value(),
}, nil
}

View File

@@ -12,10 +12,12 @@ import (
) )
var ( var (
// Deprecated
ResetFlag = Flag[bool]{ ResetFlag = Flag[bool]{
Name: "reset", Name: "reset",
ConfigName: "reset", ConfigName: "reset",
Usage: "remove all caches and database", Usage: "remove all caches and database",
Removed: `Use "trivy clean --all" instead.`,
} }
DownloadDBOnlyFlag = Flag[bool]{ DownloadDBOnlyFlag = Flag[bool]{
Name: "download-db-only", Name: "download-db-only",
@@ -64,7 +66,7 @@ var (
Name: "light", Name: "light",
ConfigName: "db.light", ConfigName: "db.light",
Usage: "deprecated", Usage: "deprecated",
Deprecated: true, Deprecated: `This flag is ignored.`,
} }
) )
@@ -90,7 +92,6 @@ type DBOptions struct {
NoProgress bool NoProgress bool
DBRepository name.Reference DBRepository name.Reference
JavaDBRepository name.Reference JavaDBRepository name.Reference
Light bool // deprecated
} }
// NewDBFlagGroup returns a default DBFlagGroup // NewDBFlagGroup returns a default DBFlagGroup
@@ -135,7 +136,6 @@ func (f *DBFlagGroup) ToOptions() (DBOptions, error) {
skipJavaDBUpdate := f.SkipJavaDBUpdate.Value() skipJavaDBUpdate := f.SkipJavaDBUpdate.Value()
downloadDBOnly := f.DownloadDBOnly.Value() downloadDBOnly := f.DownloadDBOnly.Value()
downloadJavaDBOnly := f.DownloadJavaDBOnly.Value() downloadJavaDBOnly := f.DownloadJavaDBOnly.Value()
light := f.Light.Value()
if downloadDBOnly && skipDBUpdate { if downloadDBOnly && skipDBUpdate {
return DBOptions{}, xerrors.New("--skip-db-update and --download-db-only options can not be specified both") return DBOptions{}, xerrors.New("--skip-db-update and --download-db-only options can not be specified both")
@@ -143,9 +143,6 @@ func (f *DBFlagGroup) ToOptions() (DBOptions, error) {
if downloadJavaDBOnly && skipJavaDBUpdate { if downloadJavaDBOnly && skipJavaDBUpdate {
return DBOptions{}, xerrors.New("--skip-java-db-update and --download-java-db-only options can not be specified both") return DBOptions{}, xerrors.New("--skip-java-db-update and --download-java-db-only options can not be specified both")
} }
if light {
log.Warn("'--light' option is deprecated and will be removed. See also: https://github.com/aquasecurity/trivy/discussions/1649")
}
var dbRepository, javaDBRepository name.Reference var dbRepository, javaDBRepository name.Reference
var err error var err error
@@ -179,7 +176,6 @@ func (f *DBFlagGroup) ToOptions() (DBOptions, error) {
SkipDBUpdate: skipDBUpdate, SkipDBUpdate: skipDBUpdate,
DownloadJavaDBOnly: downloadJavaDBOnly, DownloadJavaDBOnly: downloadJavaDBOnly,
SkipJavaDBUpdate: skipJavaDBUpdate, SkipJavaDBUpdate: skipJavaDBUpdate,
Light: light,
NoProgress: f.NoProgress.Value(), NoProgress: f.NoProgress.Value(),
DBRepository: dbRepository, DBRepository: dbRepository,
JavaDBRepository: javaDBRepository, JavaDBRepository: javaDBRepository,

View File

@@ -43,23 +43,6 @@ func TestDBFlagGroup_ToOptions(t *testing.T) {
}, },
assertion: require.NoError, assertion: require.NoError,
}, },
{
name: "light",
fields: fields{
Light: true,
DBRepository: "ghcr.io/aquasecurity/trivy-db",
JavaDBRepository: "ghcr.io/aquasecurity/trivy-java-db",
},
want: flag.DBOptions{
Light: true,
DBRepository: name.Tag{}, // All fields are unexported
JavaDBRepository: name.Tag{}, // All fields are unexported
},
wantLogs: []string{
"'--light' option is deprecated and will be removed. See also: https://github.com/aquasecurity/trivy/discussions/1649",
},
assertion: require.NoError,
},
{ {
name: "sad", name: "sad",
fields: fields{ fields: fields{
@@ -88,7 +71,6 @@ func TestDBFlagGroup_ToOptions(t *testing.T) {
viper.Set(flag.SkipDBUpdateFlag.ConfigName, tt.fields.SkipDBUpdate) viper.Set(flag.SkipDBUpdateFlag.ConfigName, tt.fields.SkipDBUpdate)
viper.Set(flag.DownloadDBOnlyFlag.ConfigName, tt.fields.DownloadDBOnly) viper.Set(flag.DownloadDBOnlyFlag.ConfigName, tt.fields.DownloadDBOnly)
viper.Set(flag.LightFlag.ConfigName, tt.fields.Light)
viper.Set(flag.DBRepositoryFlag.ConfigName, tt.fields.DBRepository) viper.Set(flag.DBRepositoryFlag.ConfigName, tt.fields.DBRepository)
viper.Set(flag.JavaDBRepositoryFlag.ConfigName, tt.fields.JavaDBRepository) viper.Set(flag.JavaDBRepositoryFlag.ConfigName, tt.fields.JavaDBRepository)
@@ -96,7 +78,6 @@ func TestDBFlagGroup_ToOptions(t *testing.T) {
f := &flag.DBFlagGroup{ f := &flag.DBFlagGroup{
DownloadDBOnly: flag.DownloadDBOnlyFlag.Clone(), DownloadDBOnly: flag.DownloadDBOnlyFlag.Clone(),
SkipDBUpdate: flag.SkipDBUpdateFlag.Clone(), SkipDBUpdate: flag.SkipDBUpdateFlag.Clone(),
Light: flag.LightFlag.Clone(),
DBRepository: flag.DBRepositoryFlag.Clone(), DBRepository: flag.DBRepositoryFlag.Clone(),
JavaDBRepository: flag.JavaDBRepositoryFlag.Clone(), JavaDBRepository: flag.JavaDBRepositoryFlag.Clone(),
} }

View File

@@ -15,10 +15,12 @@ import (
// config-policy: "custom-policy/policy" // config-policy: "custom-policy/policy"
// policy-namespaces: "user" // policy-namespaces: "user"
var ( var (
// Deprecated
ResetChecksBundleFlag = Flag[bool]{ ResetChecksBundleFlag = Flag[bool]{
Name: "reset-checks-bundle", Name: "reset-checks-bundle",
ConfigName: "misconfiguration.reset-checks-bundle", ConfigName: "misconfiguration.reset-checks-bundle",
Usage: "remove checks bundle", Usage: "remove checks bundle",
Removed: `Use "trivy clean --checks-bundle" instead`,
Aliases: []Alias{ Aliases: []Alias{
{ {
Name: "reset-policy-bundle", Name: "reset-policy-bundle",

View File

@@ -59,7 +59,10 @@ type Flag[T FlagType] struct {
Persistent bool Persistent bool
// Deprecated represents if the flag is deprecated // Deprecated represents if the flag is deprecated
Deprecated bool Deprecated string
// Removed represents if the flag is removed and no longer works
Removed string
// Aliases represents aliases // Aliases represents aliases
Aliases []Alias Aliases []Alias
@@ -107,6 +110,14 @@ func (f *Flag[T]) Parse() error {
return xerrors.Errorf(`invalid argument "%s" for "--%s" flag: must be one of %q`, value, f.Name, f.Values) return xerrors.Errorf(`invalid argument "%s" for "--%s" flag: must be one of %q`, value, f.Name, f.Values)
} }
if f.Deprecated != "" && f.isSet() {
log.Warnf(`"--%s" is deprecated. %s`, f.Name, f.Deprecated)
}
if f.Removed != "" && f.isSet() {
log.Errorf(`"--%s" was removed. %s`, f.Name, f.Removed)
return xerrors.Errorf(`removed flag ("--%s")`, f.Name)
}
f.value = value f.value = value
return nil return nil
} }
@@ -229,8 +240,8 @@ func (f *Flag[T]) Add(cmd *cobra.Command) {
flags.Float64P(f.Name, f.Shorthand, v, f.Usage) flags.Float64P(f.Name, f.Shorthand, v, f.Usage)
} }
if f.Deprecated { if f.Deprecated != "" || f.Removed != "" {
flags.MarkHidden(f.Name) // nolint: gosec _ = flags.MarkHidden(f.Name)
} }
} }
@@ -301,6 +312,7 @@ type Flags struct {
GlobalFlagGroup *GlobalFlagGroup GlobalFlagGroup *GlobalFlagGroup
AWSFlagGroup *AWSFlagGroup AWSFlagGroup *AWSFlagGroup
CacheFlagGroup *CacheFlagGroup CacheFlagGroup *CacheFlagGroup
CleanFlagGroup *CleanFlagGroup
DBFlagGroup *DBFlagGroup DBFlagGroup *DBFlagGroup
ImageFlagGroup *ImageFlagGroup ImageFlagGroup *ImageFlagGroup
K8sFlagGroup *K8sFlagGroup K8sFlagGroup *K8sFlagGroup
@@ -323,6 +335,7 @@ type Options struct {
GlobalOptions GlobalOptions
AWSOptions AWSOptions
CacheOptions CacheOptions
CleanOptions
DBOptions DBOptions
ImageOptions ImageOptions
K8sOptions K8sOptions
@@ -495,6 +508,9 @@ func (f *Flags) groups() []FlagGroup {
if f.CacheFlagGroup != nil { if f.CacheFlagGroup != nil {
groups = append(groups, f.CacheFlagGroup) groups = append(groups, f.CacheFlagGroup)
} }
if f.CleanFlagGroup != nil {
groups = append(groups, f.CleanFlagGroup)
}
if f.DBFlagGroup != nil { if f.DBFlagGroup != nil {
groups = append(groups, f.DBFlagGroup) groups = append(groups, f.DBFlagGroup)
} }
@@ -621,6 +637,13 @@ func (f *Flags) ToOptions(args []string) (Options, error) {
} }
} }
if f.CleanFlagGroup != nil {
opts.CleanOptions, err = f.CleanFlagGroup.ToOptions()
if err != nil {
return Options{}, xerrors.Errorf("clean flag error: %w", err)
}
}
if f.DBFlagGroup != nil { if f.DBFlagGroup != nil {
opts.DBOptions, err = f.DBFlagGroup.ToOptions() opts.DBOptions, err = f.DBFlagGroup.ToOptions()
if err != nil { if err != nil {

View File

@@ -1,23 +1,17 @@
package flag package flag
import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/log"
)
var ( var (
ArtifactTypeFlag = Flag[string]{ ArtifactTypeFlag = Flag[string]{
Name: "artifact-type", Name: "artifact-type",
ConfigName: "sbom.artifact-type", ConfigName: "sbom.artifact-type",
Usage: "deprecated", Usage: "deprecated",
Deprecated: true, Removed: `Use 'trivy image' or other subcommands. See also https://github.com/aquasecurity/trivy/discussions/2407`,
} }
SBOMFormatFlag = Flag[string]{ SBOMFormatFlag = Flag[string]{
Name: "sbom-format", Name: "sbom-format",
ConfigName: "sbom.format", ConfigName: "sbom.format",
Usage: "deprecated", Usage: "deprecated",
Deprecated: true, Removed: `Use 'trivy image' or other subcommands. See also https://github.com/aquasecurity/trivy/discussions/2407`,
} }
) )
@@ -26,8 +20,7 @@ type SBOMFlagGroup struct {
SBOMFormat *Flag[string] // deprecated SBOMFormat *Flag[string] // deprecated
} }
type SBOMOptions struct { type SBOMOptions struct{}
}
func NewSBOMFlagGroup() *SBOMFlagGroup { func NewSBOMFlagGroup() *SBOMFlagGroup {
return &SBOMFlagGroup{ return &SBOMFlagGroup{
@@ -52,14 +45,5 @@ func (f *SBOMFlagGroup) ToOptions() (SBOMOptions, error) {
return SBOMOptions{}, err return SBOMOptions{}, err
} }
artifactType := f.ArtifactType.Value()
sbomFormat := f.SBOMFormat.Value()
if artifactType != "" || sbomFormat != "" {
log.Error("'trivy sbom' is now for scanning SBOM. " +
"See https://github.com/aquasecurity/trivy/discussions/2407 for the detail")
return SBOMOptions{}, xerrors.New("'--artifact-type' and '--sbom-format' are no longer available")
}
return SBOMOptions{}, nil return SBOMOptions{}, nil
} }

View File

@@ -73,7 +73,7 @@ var (
ConfigName: "scan.slow", ConfigName: "scan.slow",
Default: false, Default: false,
Usage: "scan over time with lower CPU and memory utilization", Usage: "scan over time with lower CPU and memory utilization",
Deprecated: true, Deprecated: `Use "--parallel 1" instead.`,
} }
ParallelFlag = Flag[int]{ ParallelFlag = Flag[int]{
Name: "parallel", Name: "parallel",

View File

@@ -79,7 +79,7 @@ func (u *Updater) Update() error {
return xerrors.Errorf("Java DB metadata update error: %w", err) return xerrors.Errorf("Java DB metadata update error: %w", err)
} }
log.Info("The Java DB is cached for 3 days. If you want to update the database more frequently, " + log.Info("The Java DB is cached for 3 days. If you want to update the database more frequently, " +
"the '--reset' flag clears the DB cache.") `"trivy clean --java-db" command clears the DB cache.`)
} }
return nil return nil
@@ -88,7 +88,7 @@ func (u *Updater) Update() error {
func Init(cacheDir string, javaDBRepository name.Reference, skip, quiet bool, registryOption ftypes.RegistryOptions) { func Init(cacheDir string, javaDBRepository name.Reference, skip, quiet bool, registryOption ftypes.RegistryOptions) {
updater = &Updater{ updater = &Updater{
repo: javaDBRepository, repo: javaDBRepository,
dbDir: filepath.Join(cacheDir, "java-db"), dbDir: dbDir(cacheDir),
skip: skip, skip: skip,
quiet: quiet, quiet: quiet,
registryOption: registryOption, registryOption: registryOption,
@@ -107,6 +107,14 @@ func Update() error {
return err return err
} }
func Clear(ctx context.Context, cacheDir string) error {
return os.RemoveAll(dbDir(cacheDir))
}
func dbDir(cacheDir string) string {
return filepath.Join(cacheDir, "java-db")
}
type DB struct { type DB struct {
driver db.DB driver db.DB
} }

View File

@@ -237,7 +237,6 @@ func (c *Client) GetMetadata() (*Metadata, error) {
} }
func (c *Client) Clear() error { func (c *Client) Clear() error {
log.Info("Removing check bundle...")
if err := os.RemoveAll(c.policyDir); err != nil { if err := os.RemoveAll(c.policyDir); err != nil {
return xerrors.Errorf("failed to remove check bundle: %w", err) return xerrors.Errorf("failed to remove check bundle: %w", err)
} }