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 1 commit
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
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, "")
aswath-s-tw marked this conversation as resolved.
Show resolved Hide resolved
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) {
aswath-s-tw marked this conversation as resolved.
Show resolved Hide resolved
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
aswath-s-tw marked this conversation as resolved.
Show resolved Hide resolved
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
}