Skip to content

Commit

Permalink
feat(image): custom docker host option (#2997)
Browse files Browse the repository at this point in the history
  • Loading branch information
aswath-s-tw committed Feb 12, 2023
1 parent 12b563b commit 5cc4fdd
Show file tree
Hide file tree
Showing 12 changed files with 51 additions and 16 deletions.
2 changes: 2 additions & 0 deletions pkg/commands/artifact/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
ImageConfigScanners: opts.ImageConfigScanners, // this is valid only for 'image' subcommand
ScanRemovedPackages: opts.ScanRemovedPkgs, // this is valid only for 'image' subcommand
Platform: opts.Platform, // this is valid only for 'image' subcommand
DockerHost: opts.DockerHost, // this is valid only for 'image' subcommand
ListAllPackages: opts.ListAllPkgs,
LicenseCategories: opts.LicenseCategories,
FilePatterns: opts.FilePatterns,
Expand Down Expand Up @@ -617,6 +618,7 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
SBOMSources: opts.SBOMSources,
RekorURL: opts.RekorURL,
Platform: opts.Platform,
DockerHost: opts.DockerHost,
Slow: opts.Slow,
AWSRegion: opts.Region,

Expand Down
18 changes: 14 additions & 4 deletions pkg/commands/artifact/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,22 @@ import (
// imageStandaloneScanner initializes a container image scanner in standalone mode
// $ trivy image alpine:3.15
func imageStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
dockerOpt, err := types.GetDockerOption(conf.ArtifactOption.InsecureSkipTLS, conf.ArtifactOption.Platform)
dockerOpt, err := types.GetDockerOption(
conf.ArtifactOption.InsecureSkipTLS,
conf.ArtifactOption.Platform,
conf.ArtifactOption.DockerHost,
)
if err != nil {
return scanner.Scanner{}, nil, err
}
s, cleanup, err := initializeDockerScanner(ctx, conf.Target, conf.ArtifactCache, conf.LocalArtifactCache,
dockerOpt, conf.ArtifactOption)
s, cleanup, err := initializeDockerScanner(
ctx,
conf.Target,
conf.ArtifactCache,
conf.LocalArtifactCache,
dockerOpt,
conf.ArtifactOption,
)
if err != nil {
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a docker scanner: %w", err)
}
Expand All @@ -39,7 +49,7 @@ func archiveStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.
func imageRemoteScanner(ctx context.Context, conf ScannerConfig) (
scanner.Scanner, func(), error) {
// Scan an image in Docker Engine, Docker Registry, etc.
dockerOpt, err := types.GetDockerOption(conf.ArtifactOption.InsecureSkipTLS, conf.ArtifactOption.Platform)
dockerOpt, err := types.GetDockerOption(conf.ArtifactOption.InsecureSkipTLS, conf.ArtifactOption.Platform, "")
if err != nil {
return scanner.Scanner{}, nil, err
}
Expand Down
1 change: 1 addition & 0 deletions pkg/fanal/artifact/artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type Option struct {
SBOMSources []string
RekorURL string
Platform string
DockerHost string
Slow bool // Lower CPU and memory
AWSRegion string

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, host string) (types.Image, func(), error) {
img, cleanup, err := daemon.DockerImage(ref, host)
if err != nil {
return nil, nil, err
}
Expand Down
11 changes: 9 additions & 2 deletions pkg/fanal/image/daemon/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,17 @@ 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())
var c *client.Client
var err error
if host == "" {
c, err = client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
} else {
// adding host parameter to the last assuming it will pickup more preference
c, err = client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation(), client.WithHost(host))
}
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
8 changes: 4 additions & 4 deletions pkg/fanal/image/daemon/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func Test_image_ConfigName(t *testing.T) {
ref, err := name.ParseReference(tt.imageName)
require.NoError(t, err)

img, cleanup, err := DockerImage(ref)
img, cleanup, err := DockerImage(ref, "")
require.NoError(t, err)
defer cleanup()

Expand Down Expand Up @@ -156,7 +156,7 @@ func Test_image_ConfigFile(t *testing.T) {
ref, err := name.ParseReference(tt.imageName)
require.NoError(t, err)

img, cleanup, err := DockerImage(ref)
img, cleanup, err := DockerImage(ref, "")
require.NoError(t, err)
defer cleanup()

Expand Down Expand Up @@ -201,7 +201,7 @@ func Test_image_LayerByDiffID(t *testing.T) {
ref, err := name.ParseReference(tt.imageName)
require.NoError(t, err)

img, cleanup, err := DockerImage(ref)
img, cleanup, err := DockerImage(ref, "")
require.NoError(t, err)
defer cleanup()

Expand Down Expand Up @@ -230,7 +230,7 @@ func Test_image_RawConfigFile(t *testing.T) {
ref, err := name.ParseReference(tt.imageName)
require.NoError(t, err)

img, cleanup, err := DockerImage(ref)
img, cleanup, err := DockerImage(ref, "")
require.NoError(t, err)
defer cleanup()

Expand Down
2 changes: 1 addition & 1 deletion pkg/fanal/image/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func NewContainerImage(ctx context.Context, imageName string, option types.Docke

// Try accessing Docker Daemon
if o.dockerd {
img, cleanup, err := tryDockerDaemon(imageName, ref)
img, cleanup, err := tryDockerDaemon(imageName, ref, option.DockerHost)
if err == nil {
// Return v1.Image if the image is found in Docker Engine
return img, cleanup, nil
Expand Down
3 changes: 3 additions & 0 deletions pkg/fanal/types/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,7 @@ type DockerOption struct {

// Architecture
Platform string

// Unix domain socket path
DockerHost string
}
12 changes: 11 additions & 1 deletion pkg/flag/image_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,28 @@ var (
Value: "",
Usage: "set platform in the form os/arch if image is multi-platform capable",
}
DockerHostFlag = Flag{
Name: "docker-host",
ConfigName: "image.docker-host",
Value: "",
Usage: "unix domain socket path to use for docker standalone scanning",
}
)

type ImageFlagGroup struct {
Input *Flag // local image archive
ImageConfigScanners *Flag
ScanRemovedPkgs *Flag
Platform *Flag
DockerHost *Flag
}

type ImageOptions struct {
Input string
ImageConfigScanners types.Scanners
ScanRemovedPkgs bool
Platform string
DockerHost string
}

func NewImageFlagGroup() *ImageFlagGroup {
Expand All @@ -58,6 +66,7 @@ func NewImageFlagGroup() *ImageFlagGroup {
ImageConfigScanners: &ImageConfigScannersFlag,
ScanRemovedPkgs: &ScanRemovedPkgsFlag,
Platform: &PlatformFlag,
DockerHost: &DockerHostFlag,
}
}

Expand All @@ -66,7 +75,7 @@ func (f *ImageFlagGroup) Name() string {
}

func (f *ImageFlagGroup) Flags() []*Flag {
return []*Flag{f.Input, f.ImageConfigScanners, f.ScanRemovedPkgs, f.Platform}
return []*Flag{f.Input, f.ImageConfigScanners, f.ScanRemovedPkgs, f.Platform, f.DockerHost}
}

func (f *ImageFlagGroup) ToOptions() (ImageOptions, error) {
Expand All @@ -79,5 +88,6 @@ func (f *ImageFlagGroup) ToOptions() (ImageOptions, error) {
ImageConfigScanners: scanners,
ScanRemovedPkgs: getBool(f.ScanRemovedPkgs),
Platform: getString(f.Platform),
DockerHost: getString(f.DockerHost),
}, nil
}
3 changes: 2 additions & 1 deletion pkg/types/docker_conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type DockerConfig struct {
}

// GetDockerOption returns the Docker scanning options using DockerConfig
func GetDockerOption(insecureTlsSkip bool, Platform string) (types.DockerOption, error) {
func GetDockerOption(insecureTlsSkip bool, Platform string, DockerHost string) (types.DockerOption, error) {
cfg := DockerConfig{}
if err := env.Parse(&cfg); err != nil {
return types.DockerOption{}, xerrors.Errorf("unable to parse environment variables: %w", err)
Expand All @@ -29,5 +29,6 @@ func GetDockerOption(insecureTlsSkip bool, Platform string) (types.DockerOption,
InsecureSkipTLSVerify: insecureTlsSkip,
NonSSL: cfg.NonSSL,
Platform: Platform,
DockerHost: DockerHost,
}, nil
}
1 change: 1 addition & 0 deletions pkg/types/scanoptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ type ScanOptions struct {
ListAllPackages bool
LicenseCategories map[types.LicenseCategory][]string
FilePatterns []string
DockerHost string
}

0 comments on commit 5cc4fdd

Please sign in to comment.