Skip to content

Commit f14bed4

Browse files
authored
feat: add auth support for downloading OCI artifacts (#3915)
1 parent 1ee0518 commit f14bed4

File tree

22 files changed

+280
-215
lines changed

22 files changed

+280
-215
lines changed

docs/docs/vulnerability/db.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Database
2+
Trivy uses two types of databases for vulnerability detection:
3+
4+
- Vulnerability Database
5+
- Java Index Database
6+
7+
This page provides detailed information about these databases.
8+
9+
## Vulnerability Database
10+
Trivy utilizes a database containing vulnerability information.
11+
This database is built every six hours on [GitHub](https://github.com/aquasecurity/trivy-db) and is distributed via [GitHub Container registry (GHCR)](https://ghcr.io/aquasecurity/trivy-db).
12+
The database is cached and updated as needed.
13+
As Trivy updates the database automatically during execution, users don't need to be concerned about it.
14+
15+
For CLI flags related to the database, please refer to [this page](./examples/db.md).
16+
17+
### Private Hosting
18+
If you host the database on your own OCI registry, you can specify a different repository with the `--db-repository` flag.
19+
The default is `ghcr.io/aquasecurity/trivy-db`.
20+
21+
```shell
22+
$ trivy image --db-repository YOUR_REPO YOUR_IMAGE
23+
```
24+
25+
If authentication is required, it can be configured in the same way as for private images.
26+
Please refer to [the documentation](../advanced/private-registries/index.md) for more details.
27+
28+
## Java Index Database
29+
This database is only downloaded when scanning JAR files so that Trivy can identify the groupId, artifactId, and version of JAR files.
30+
It is built once a day on [GitHub](https://github.com/aquasecurity/trivy-java-db) and distributed via [GitHub Container registry (GHCR)](https://ghcr.io/aquasecurity/trivy-java-db).
31+
Like the vulnerability database, it is automatically downloaded and updated when needed, so users don't need to worry about it.
32+
33+
### Private Hosting
34+
If you host the database on your own OCI registry, you can specify a different repository with the `--java-db-repository` flag.
35+
The default is `ghcr.io/aquasecurity/trivy-java-db`.
36+
37+
If authentication is required, you need to run `docker login YOUR_REGISTRY`.
38+
Currently, specifying a username and password is not supported.

docs/docs/vulnerability/examples/db.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
# Vulnerability DB
22

33
## Skip update of vulnerability DB
4-
`Trivy` downloads its vulnerability database every 12 hours when it starts operating.
5-
This is usually fast, as the size of the DB is only 10~30MB.
6-
But if you want to skip even that, use the `--skip-db-update` option.
4+
If you want to skip downloading the vulnerability database, use the `--skip-db-update` option.
75

86
```
97
$ trivy image --skip-db-update python:3.4-alpine3.9

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ nav:
5252
- OS Packages: docs/vulnerability/detection/os.md
5353
- Language-specific Packages: docs/vulnerability/detection/language.md
5454
- Data Sources: docs/vulnerability/detection/data-source.md
55+
- Database: docs/vulnerability/db.md
5556
- Examples:
5657
- Vulnerability Filtering: docs/vulnerability/examples/filter.md
5758
- Report Formats: docs/vulnerability/examples/report.md

pkg/commands/app.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ func NewModuleCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
759759
if err != nil {
760760
return xerrors.Errorf("flag error: %w", err)
761761
}
762-
return module.Install(cmd.Context(), opts.ModuleDir, repo, opts.Quiet, opts.Insecure)
762+
return module.Install(cmd.Context(), opts.ModuleDir, repo, opts.Quiet, opts.Remote())
763763
},
764764
},
765765
&cobra.Command{

pkg/commands/artifact/run.go

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"github.com/aquasecurity/trivy/pkg/fanal/analyzer/config"
2020
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
2121
"github.com/aquasecurity/trivy/pkg/fanal/cache"
22-
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
2322
"github.com/aquasecurity/trivy/pkg/flag"
2423
"github.com/aquasecurity/trivy/pkg/javadb"
2524
"github.com/aquasecurity/trivy/pkg/log"
@@ -315,7 +314,7 @@ func (r *runner) initDB(opts flag.Options) error {
315314

316315
// download the database file
317316
noProgress := opts.Quiet || opts.NoProgress
318-
if err := operation.DownloadDB(opts.AppVersion, opts.CacheDir, opts.DBRepository, noProgress, opts.Insecure, opts.SkipDBUpdate); err != nil {
317+
if err := operation.DownloadDB(opts.AppVersion, opts.CacheDir, opts.DBRepository, noProgress, opts.SkipDBUpdate, opts.Remote()); err != nil {
319318
return err
320319
}
321320

@@ -610,13 +609,7 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
610609
}
611610
}
612611

613-
remoteOption := ftypes.RemoteOptions{
614-
Credentials: opts.Credentials,
615-
RegistryToken: opts.RegistryToken,
616-
Insecure: opts.Insecure,
617-
Platform: opts.Platform,
618-
AWSRegion: opts.AWSOptions.Region,
619-
}
612+
remoteOpts := opts.Remote()
620613

621614
return ScannerConfig{
622615
Target: target,
@@ -643,8 +636,8 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
643636
Slow: opts.Slow,
644637
AWSRegion: opts.Region,
645638

646-
// For container registries
647-
RemoteOptions: remoteOption,
639+
// For OCI registries
640+
RemoteOptions: remoteOpts,
648641

649642
// For misconfiguration scanning
650643
MisconfScannerOption: configScannerOptions,

pkg/commands/operation/operation.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/aquasecurity/trivy-db/pkg/metadata"
1616
"github.com/aquasecurity/trivy/pkg/db"
1717
"github.com/aquasecurity/trivy/pkg/fanal/cache"
18+
"github.com/aquasecurity/trivy/pkg/fanal/types"
1819
"github.com/aquasecurity/trivy/pkg/flag"
1920
"github.com/aquasecurity/trivy/pkg/log"
2021
"github.com/aquasecurity/trivy/pkg/policy"
@@ -101,8 +102,8 @@ func (c Cache) ClearArtifacts() error {
101102
}
102103

103104
// DownloadDB downloads the DB
104-
func DownloadDB(appVersion, cacheDir, dbRepository string, quiet, insecure, skipUpdate bool) error {
105-
client := db.NewClient(cacheDir, quiet, insecure, db.WithDBRepository(dbRepository))
105+
func DownloadDB(appVersion, cacheDir, dbRepository string, quiet, skipUpdate bool, opt types.RemoteOptions) error {
106+
client := db.NewClient(cacheDir, quiet, db.WithDBRepository(dbRepository))
106107
ctx := context.Background()
107108
needsUpdate, err := client.NeedsUpdate(appVersion, skipUpdate)
108109
if err != nil {
@@ -113,7 +114,7 @@ func DownloadDB(appVersion, cacheDir, dbRepository string, quiet, insecure, skip
113114
log.Logger.Info("Need to update DB")
114115
log.Logger.Infof("DB Repository: %s", dbRepository)
115116
log.Logger.Info("Downloading DB...")
116-
if err = client.Download(ctx, cacheDir); err != nil {
117+
if err = client.Download(ctx, cacheDir, opt); err != nil {
117118
return xerrors.Errorf("failed to download vulnerability DB: %w", err)
118119
}
119120
}
@@ -145,7 +146,7 @@ func InitBuiltinPolicies(ctx context.Context, cacheDir string, quiet, skipUpdate
145146

146147
needsUpdate := false
147148
if !skipUpdate {
148-
needsUpdate, err = client.NeedsUpdate()
149+
needsUpdate, err = client.NeedsUpdate(ctx)
149150
if err != nil {
150151
return nil, xerrors.Errorf("unable to check if built-in policies need to be updated: %w", err)
151152
}

pkg/commands/server/run.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func Run(ctx context.Context, opts flag.Options) (err error) {
3535

3636
// download the database file
3737
if err = operation.DownloadDB(opts.AppVersion, opts.CacheDir, opts.DBRepository,
38-
true, opts.Insecure, opts.SkipDBUpdate); err != nil {
38+
true, opts.SkipDBUpdate, opts.Remote()); err != nil {
3939
return err
4040
}
4141

@@ -57,6 +57,7 @@ func Run(ctx context.Context, opts flag.Options) (err error) {
5757
}
5858
m.Register()
5959

60-
server := rpcServer.NewServer(opts.AppVersion, opts.Listen, opts.CacheDir, opts.Token, opts.TokenHeader, opts.DBRepository)
61-
return server.ListenAndServe(cache, opts.Insecure, opts.SkipDBUpdate)
60+
server := rpcServer.NewServer(opts.AppVersion, opts.Listen, opts.CacheDir, opts.Token, opts.TokenHeader,
61+
opts.DBRepository, opts.Remote())
62+
return server.ListenAndServe(cache, opts.SkipDBUpdate)
6263
}

pkg/db/db.go

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/aquasecurity/trivy-db/pkg/db"
1414
"github.com/aquasecurity/trivy-db/pkg/metadata"
15+
"github.com/aquasecurity/trivy/pkg/fanal/types"
1516
"github.com/aquasecurity/trivy/pkg/log"
1617
"github.com/aquasecurity/trivy/pkg/oci"
1718
)
@@ -24,7 +25,7 @@ const (
2425
// Operation defines the DB operations
2526
type Operation interface {
2627
NeedsUpdate(cliVersion string, skip bool) (need bool, err error)
27-
Download(ctx context.Context, dst string) (err error)
28+
Download(ctx context.Context, dst string, opt types.RemoteOptions) (err error)
2829
}
2930

3031
type options struct {
@@ -61,14 +62,13 @@ func WithClock(clock clock.Clock) Option {
6162
type Client struct {
6263
*options
6364

64-
cacheDir string
65-
metadata metadata.Client
66-
quiet bool
67-
insecureSkipTLSVerify bool
65+
cacheDir string
66+
metadata metadata.Client
67+
quiet bool
6868
}
6969

7070
// NewClient is the factory method for DB client
71-
func NewClient(cacheDir string, quiet, insecure bool, opts ...Option) *Client {
71+
func NewClient(cacheDir string, quiet bool, opts ...Option) *Client {
7272
o := &options{
7373
clock: clock.RealClock{},
7474
dbRepository: defaultDBRepository,
@@ -79,11 +79,10 @@ func NewClient(cacheDir string, quiet, insecure bool, opts ...Option) *Client {
7979
}
8080

8181
return &Client{
82-
options: o,
83-
cacheDir: cacheDir,
84-
metadata: metadata.NewClient(cacheDir),
85-
quiet: quiet,
86-
insecureSkipTLSVerify: insecure, // insecure skip for download DB
82+
options: o,
83+
cacheDir: cacheDir,
84+
metadata: metadata.NewClient(cacheDir),
85+
quiet: quiet,
8786
}
8887
}
8988

@@ -144,18 +143,18 @@ func (c *Client) isNewDB(meta metadata.Metadata) bool {
144143
}
145144

146145
// Download downloads the DB file
147-
func (c *Client) Download(ctx context.Context, dst string) error {
146+
func (c *Client) Download(ctx context.Context, dst string, opt types.RemoteOptions) error {
148147
// Remove the metadata file under the cache directory before downloading DB
149148
if err := c.metadata.Delete(); err != nil {
150149
log.Logger.Debug("no metadata file")
151150
}
152151

153-
art, err := c.initOCIArtifact()
152+
art, err := c.initOCIArtifact(opt)
154153
if err != nil {
155154
return xerrors.Errorf("OCI artifact error: %w", err)
156155
}
157156

158-
if err = art.Download(ctx, db.Dir(dst)); err != nil {
157+
if err = art.Download(ctx, db.Dir(dst), oci.DownloadOption{MediaType: dbMediaType}); err != nil {
159158
return xerrors.Errorf("database download error: %w", err)
160159
}
161160

@@ -184,13 +183,13 @@ func (c *Client) updateDownloadedAt(dst string) error {
184183
return nil
185184
}
186185

187-
func (c *Client) initOCIArtifact() (*oci.Artifact, error) {
186+
func (c *Client) initOCIArtifact(opt types.RemoteOptions) (*oci.Artifact, error) {
188187
if c.artifact != nil {
189188
return c.artifact, nil
190189
}
191190

192191
repo := fmt.Sprintf("%s:%d", c.dbRepository, db.SchemaVersion)
193-
art, err := oci.NewArtifact(repo, dbMediaType, "", c.quiet, c.insecureSkipTLSVerify)
192+
art, err := oci.NewArtifact(repo, c.quiet, opt)
194193
if err != nil {
195194
var terr *transport.Error
196195
if errors.As(err, &terr) {

pkg/db/db_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
tdb "github.com/aquasecurity/trivy-db/pkg/db"
1919
"github.com/aquasecurity/trivy-db/pkg/metadata"
2020
"github.com/aquasecurity/trivy/pkg/db"
21+
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
2122
"github.com/aquasecurity/trivy/pkg/oci"
2223
)
2324

@@ -152,7 +153,7 @@ func TestClient_NeedsUpdate(t *testing.T) {
152153
require.NoError(t, err)
153154
}
154155

155-
client := db.NewClient(cacheDir, true, false, db.WithClock(tt.clock))
156+
client := db.NewClient(cacheDir, true, db.WithClock(tt.clock))
156157
needsUpdate, err := client.NeedsUpdate("test", tt.skip)
157158

158159
switch {
@@ -218,11 +219,14 @@ func TestClient_Download(t *testing.T) {
218219
}, nil)
219220

220221
// Mock OCI artifact
221-
art, err := oci.NewArtifact("db", mediaType, "", true, false, oci.WithImage(img))
222+
opt := ftypes.RemoteOptions{
223+
Insecure: false,
224+
}
225+
art, err := oci.NewArtifact("db", true, opt, oci.WithImage(img))
222226
require.NoError(t, err)
223227

224-
client := db.NewClient(cacheDir, true, false, db.WithOCIArtifact(art), db.WithClock(timeDownloadedAt))
225-
err = client.Download(context.Background(), cacheDir)
228+
client := db.NewClient(cacheDir, true, db.WithOCIArtifact(art), db.WithClock(timeDownloadedAt))
229+
err = client.Download(context.Background(), cacheDir, opt)
226230
if tt.wantErr != "" {
227231
require.Error(t, err)
228232
assert.Contains(t, err.Error(), tt.wantErr)

pkg/db/mock_operation.go

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)