Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(image): custom docker host option #3599

Merged
merged 14 commits into from
Apr 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/docs/references/configuration/cli/trivy_image.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ trivy image [flags] IMAGE_NAME
--custom-headers strings custom headers in client mode
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db")
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
--docker-host string unix domain socket path to use for docker scanning
--download-db-only download/update vulnerability database but don't run a scan
--download-java-db-only download/update Java index database but don't run a scan
--enable-modules strings [EXPERIMENTAL] module names to enable
Expand Down
9 changes: 9 additions & 0 deletions docs/docs/references/configuration/config-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,15 @@ image:
# Same as '--removed-pkgs'
# Default is false
removed-pkgs: false

# Same as '--platform'
# Default is empty
platform:

docker:
# Same as '--docker-host'
# Default is empty
host:
```

## Vulnerability Options
Expand Down
6 changes: 6 additions & 0 deletions docs/docs/target/container_image.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,3 +482,9 @@ Total: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 1)

</details>

### Configure Docker daemon socket to connect to.
You can configure Docker daemon socket with `DOCKER_HOST` or `--docker-host`.

```shell
$ trivy image --docker-host tcp://127.0.0.1:2375 YOUR_IMAGE
```
2 changes: 1 addition & 1 deletion pkg/commands/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ func NewModuleCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
if err != nil {
return xerrors.Errorf("flag error: %w", err)
}
return module.Install(cmd.Context(), opts.ModuleDir, repo, opts.Quiet, opts.Remote())
return module.Install(cmd.Context(), opts.ModuleDir, repo, opts.Quiet, opts.Registry())
},
},
&cobra.Command{
Expand Down
4 changes: 2 additions & 2 deletions pkg/commands/artifact/inject.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
// initializeDockerScanner is for container image scanning in standalone mode
// e.g. dockerd, container registry, podman, etc.
func initializeDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache,
localArtifactCache cache.LocalArtifactCache, remoteOpt types.RemoteOptions, artifactOption artifact.Option) (
localArtifactCache cache.LocalArtifactCache, imageOpt types.ImageOptions, artifactOption artifact.Option) (
scanner.Scanner, func(), error) {
wire.Build(scanner.StandaloneDockerSet)
return scanner.Scanner{}, nil, nil
Expand Down Expand Up @@ -69,7 +69,7 @@ func initializeVMScanner(ctx context.Context, filePath string, artifactCache cac
// initializeRemoteDockerScanner is for container image scanning in client/server mode
// e.g. dockerd, container registry, podman, etc.
func initializeRemoteDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache,
remoteScanOptions client.ScannerOption, remoteOpt types.RemoteOptions, artifactOption artifact.Option) (
remoteScanOptions client.ScannerOption, imageOpt types.ImageOptions, artifactOption artifact.Option) (
scanner.Scanner, func(), error) {
wire.Build(scanner.RemoteDockerSet)
return scanner.Scanner{}, nil, nil
Expand Down
16 changes: 11 additions & 5 deletions pkg/commands/artifact/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/aquasecurity/trivy/pkg/fanal/analyzer/config"
"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/flag"
"github.com/aquasecurity/trivy/pkg/javadb"
"github.com/aquasecurity/trivy/pkg/log"
Expand Down Expand Up @@ -314,7 +315,7 @@ func (r *runner) initDB(ctx context.Context, opts flag.Options) error {

// download the database file
noProgress := opts.Quiet || opts.NoProgress
if err := operation.DownloadDB(ctx, opts.AppVersion, opts.CacheDir, opts.DBRepository, noProgress, opts.SkipDBUpdate, opts.Remote()); err != nil {
if err := operation.DownloadDB(ctx, opts.AppVersion, opts.CacheDir, opts.DBRepository, noProgress, opts.SkipDBUpdate, opts.Registry()); err != nil {
return err
}

Expand Down Expand Up @@ -615,8 +616,6 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
fileChecksum = true
}

remoteOpts := opts.Remote()

return ScannerConfig{
Target: target,
ArtifactCache: cacheClient,
Expand All @@ -633,18 +632,25 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
FilePatterns: opts.FilePatterns,
Offline: opts.OfflineScan,
NoProgress: opts.NoProgress || opts.Quiet,
Insecure: opts.Insecure,
RepoBranch: opts.RepoBranch,
RepoCommit: opts.RepoCommit,
RepoTag: opts.RepoTag,
SBOMSources: opts.SBOMSources,
RekorURL: opts.RekorURL,
Platform: opts.Platform,
DockerHost: opts.DockerHost,
Slow: opts.Slow,
AWSRegion: opts.Region,
FileChecksum: fileChecksum,

// For OCI registries
RemoteOptions: remoteOpts,
// For image scanning
ImageOption: ftypes.ImageOptions{
RegistryOptions: opts.Registry(),
DockerOptions: ftypes.DockerOptions{
Host: opts.DockerHost,
},
},

// For misconfiguration scanning
MisconfScannerOption: configScannerOptions,
Expand Down
4 changes: 2 additions & 2 deletions pkg/commands/artifact/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
// $ trivy image alpine:3.15
func imageStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
s, cleanup, err := initializeDockerScanner(ctx, conf.Target, conf.ArtifactCache, conf.LocalArtifactCache,
conf.ArtifactOption.RemoteOptions, conf.ArtifactOption)
conf.ArtifactOption.ImageOption, conf.ArtifactOption)
if err != nil {
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a docker scanner: %w", err)
}
Expand All @@ -34,7 +34,7 @@ func archiveStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.
func imageRemoteScanner(ctx context.Context, conf ScannerConfig) (
scanner.Scanner, func(), error) {
s, cleanup, err := initializeRemoteDockerScanner(ctx, conf.Target, conf.ArtifactCache, conf.ServerOption,
conf.ArtifactOption.RemoteOptions, conf.ArtifactOption)
conf.ArtifactOption.ImageOption, conf.ArtifactOption)
if err != nil {
return scanner.Scanner{}, nil, xerrors.Errorf("unable to initialize the remote docker scanner: %w", err)
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/commands/artifact/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/commands/operation/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func (c Cache) ClearArtifacts() error {
}

// DownloadDB downloads the DB
func DownloadDB(ctx context.Context, appVersion, cacheDir, dbRepository string, quiet, skipUpdate bool, opt types.RemoteOptions) error {
func DownloadDB(ctx context.Context, appVersion, cacheDir, dbRepository string, quiet, skipUpdate bool, opt types.RegistryOptions) error {
mu.Lock()
defer mu.Unlock()

Expand Down
4 changes: 2 additions & 2 deletions pkg/commands/server/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func Run(ctx context.Context, opts flag.Options) (err error) {

// download the database file
if err = operation.DownloadDB(ctx, opts.AppVersion, opts.CacheDir, opts.DBRepository,
true, opts.SkipDBUpdate, opts.Remote()); err != nil {
true, opts.SkipDBUpdate, opts.Registry()); err != nil {
return err
}

Expand All @@ -58,6 +58,6 @@ func Run(ctx context.Context, opts flag.Options) (err error) {
m.Register()

server := rpcServer.NewServer(opts.AppVersion, opts.Listen, opts.CacheDir, opts.Token, opts.TokenHeader,
opts.DBRepository, opts.Remote())
opts.DBRepository, opts.Registry())
return server.ListenAndServe(cache, opts.SkipDBUpdate)
}
6 changes: 3 additions & 3 deletions pkg/db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const (
// Operation defines the DB operations
type Operation interface {
NeedsUpdate(cliVersion string, skip bool) (need bool, err error)
Download(ctx context.Context, dst string, opt types.RemoteOptions) (err error)
Download(ctx context.Context, dst string, opt types.RegistryOptions) (err error)
}

type options struct {
Expand Down Expand Up @@ -143,7 +143,7 @@ func (c *Client) isNewDB(meta metadata.Metadata) bool {
}

// Download downloads the DB file
func (c *Client) Download(ctx context.Context, dst string, opt types.RemoteOptions) error {
func (c *Client) Download(ctx context.Context, dst string, opt types.RegistryOptions) error {
// Remove the metadata file under the cache directory before downloading DB
if err := c.metadata.Delete(); err != nil {
log.Logger.Debug("no metadata file")
Expand Down Expand Up @@ -183,7 +183,7 @@ func (c *Client) updateDownloadedAt(dst string) error {
return nil
}

func (c *Client) initOCIArtifact(opt types.RemoteOptions) (*oci.Artifact, error) {
func (c *Client) initOCIArtifact(opt types.RegistryOptions) (*oci.Artifact, error) {
if c.artifact != nil {
return c.artifact, nil
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/db/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ func TestClient_Download(t *testing.T) {
}, nil)

// Mock OCI artifact
opt := ftypes.RemoteOptions{
opt := ftypes.RegistryOptions{
Insecure: false,
}
art, err := oci.NewArtifact("db", true, opt, oci.WithImage(img))
Expand Down
2 changes: 1 addition & 1 deletion pkg/db/mock_operation.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions pkg/fanal/artifact/artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ type Option struct {
SkipDirs []string
FilePatterns []string
NoProgress bool
Insecure bool
Offline bool
AppDirs []string
SBOMSources []string
RekorURL string
Platform string
DockerHost string
Slow bool // Lower CPU and memory
AWSRegion string
FileChecksum bool // For SPDX
Expand All @@ -32,8 +34,8 @@ type Option struct {
RepoCommit string
RepoTag string

// For OCI registries
types.RemoteOptions
// For image scanning
ImageOption types.ImageOptions

MisconfScannerOption misconf.ScannerOption
SecretScannerOption analyzer.SecretScannerOption
Expand Down
4 changes: 2 additions & 2 deletions pkg/fanal/artifact/image/remote_sbom.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (a Artifact) inspectOCIReferrerSBOM(ctx context.Context) (ftypes.ArtifactRe
}

// Fetch referrers
index, err := remote.Referrers(ctx, digest, a.artifactOption.RemoteOptions)
index, err := remote.Referrers(ctx, digest, a.artifactOption.ImageOption.RegistryOptions)
if err != nil {
return ftypes.ArtifactReference{}, xerrors.Errorf("unable to fetch referrers: %w", err)
}
Expand All @@ -81,7 +81,7 @@ func (a Artifact) inspectOCIReferrerSBOM(ctx context.Context) (ftypes.ArtifactRe
func (a Artifact) parseReferrer(ctx context.Context, repo string, desc v1.Descriptor) (ftypes.ArtifactReference, error) {
const fileName string = "referrer.sbom"
repoName := fmt.Sprintf("%s@%s", repo, desc.Digest)
referrer, err := oci.NewArtifact(repoName, true, a.artifactOption.RemoteOptions)
referrer, err := oci.NewArtifact(repoName, true, a.artifactOption.ImageOption.RegistryOptions)
if err != nil {
return ftypes.ArtifactReference{}, xerrors.Errorf("OCI error: %w", err)
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/fanal/image/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"github.com/aquasecurity/trivy/pkg/fanal/types"
)

func tryDockerDaemon(imageName string, ref name.Reference) (types.Image, func(), error) {
img, cleanup, err := daemon.DockerImage(ref)
func tryDockerDaemon(imageName string, ref name.Reference, opt types.DockerOptions) (types.Image, func(), error) {
img, cleanup, err := daemon.DockerImage(ref, opt.Host)
if err != nil {
return nil, nil, err
}
Expand Down
13 changes: 11 additions & 2 deletions pkg/fanal/image/daemon/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,19 @@ import (

// DockerImage implements v1.Image by extending daemon.Image.
// The caller must call cleanup() to remove a temporary file.
func DockerImage(ref name.Reference) (Image, func(), error) {
func DockerImage(ref name.Reference, host string) (Image, func(), error) {
cleanup := func() {}

c, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
opts := []client.Opt{
client.FromEnv,
client.WithAPIVersionNegotiation(),
}
if host != "" {
// adding host parameter to the last assuming it will pick up more preference
opts = append(opts, client.WithHost(host))
}
c, err := client.NewClientWithOpts(opts...)

if err != nil {
return nil, cleanup, xerrors.Errorf("failed to initialize a docker client: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/fanal/image/daemon/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestDockerImage(t *testing.T) {
ref, err := name.ParseReference(tt.imageName)
require.NoError(t, err)

_, cleanup, err := DockerImage(ref)
_, cleanup, err := DockerImage(ref, "")
assert.Equal(t, tt.wantErr, err != nil, err)
defer func() {
if cleanup != nil {
Expand Down
Loading