mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-23 07:29:00 -08:00
feat(image): customer podman host or socket option (#6256)
Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Co-authored-by: DmitriyLewen <dmitriy.lewen@smartforce.io>
This commit is contained in:
@@ -78,6 +78,7 @@ trivy image [flags] IMAGE_NAME
|
||||
--parallel int number of goroutines enabled for parallel scanning, set 0 to auto-detect parallelism (default 5)
|
||||
--password strings password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons.
|
||||
--platform string set platform in the form os/arch if image is multi-platform capable
|
||||
--podman-host string unix podman socket path to use for podman scanning
|
||||
--policy-bundle-repository string OCI registry URL to retrieve policy bundle from (default "ghcr.io/aquasecurity/trivy-policies:0")
|
||||
--policy-namespaces strings Rego namespaces
|
||||
--redis-ca string redis ca file location, if using redis as cache backend
|
||||
|
||||
@@ -203,6 +203,11 @@ image:
|
||||
# Same as '--docker-host'
|
||||
# Default is empty
|
||||
host:
|
||||
|
||||
podman:
|
||||
# Same as '--podman-host'
|
||||
# Default is empty
|
||||
host:
|
||||
```
|
||||
|
||||
## Vulnerability Options
|
||||
|
||||
@@ -500,3 +500,10 @@ 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
|
||||
```
|
||||
|
||||
### Configure Podman daemon socket to connect to.
|
||||
You can configure Podman daemon socket with `--podman-host`.
|
||||
|
||||
```shell
|
||||
$ trivy image --podman-host /run/user/1000/podman/podman.sock YOUR_IMAGE
|
||||
```
|
||||
@@ -670,6 +670,9 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
|
||||
DockerOptions: ftypes.DockerOptions{
|
||||
Host: opts.DockerHost,
|
||||
},
|
||||
PodmanOptions: ftypes.PodmanOptions{
|
||||
Host: opts.PodmanHost,
|
||||
},
|
||||
ImageSources: opts.ImageSources,
|
||||
},
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ func tryDockerDaemon(_ context.Context, imageName string, ref name.Reference, op
|
||||
|
||||
}
|
||||
|
||||
func tryPodmanDaemon(_ context.Context, imageName string, _ name.Reference, _ types.ImageOptions) (types.Image, func(), error) {
|
||||
img, cleanup, err := daemon.PodmanImage(imageName)
|
||||
func tryPodmanDaemon(_ context.Context, imageName string, _ name.Reference, opts types.ImageOptions) (types.Image, func(), error) {
|
||||
img, cleanup, err := daemon.PodmanImage(imageName, opts.PodmanOptions.Host)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@@ -115,6 +115,46 @@ func Test_image_ConfigNameWithCustomDockerHost(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func Test_image_ConfigNameWithCustomPodmanHost(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("podman.sock is not available for Windows CI")
|
||||
}
|
||||
|
||||
ref, err := name.ParseReference("alpine:3.11")
|
||||
require.NoError(t, err)
|
||||
|
||||
eo := engine.Option{
|
||||
APIVersion: opt.APIVersion,
|
||||
ImagePaths: map[string]string{
|
||||
"index.docker.io/library/alpine:3.11": "../../test/testdata/alpine-311.tar.gz",
|
||||
},
|
||||
}
|
||||
|
||||
runtimeDir, err := os.MkdirTemp("", "daemon")
|
||||
require.NoError(t, err)
|
||||
|
||||
dir := filepath.Join(runtimeDir, "image")
|
||||
err = os.MkdirAll(dir, os.ModePerm)
|
||||
require.NoError(t, err)
|
||||
|
||||
podmanSocket := filepath.Join(dir, "image-test-podman-socket.sock")
|
||||
eo.UnixDomainSocket = podmanSocket
|
||||
|
||||
te := engine.NewDockerEngine(eo)
|
||||
defer te.Close()
|
||||
|
||||
img, cleanup, err := PodmanImage(ref.Name(), podmanSocket)
|
||||
require.NoError(t, err)
|
||||
defer cleanup()
|
||||
|
||||
conf, err := img.ConfigName()
|
||||
assert.Equal(t, v1.Hash{
|
||||
Algorithm: "sha256",
|
||||
Hex: "a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72",
|
||||
}, conf)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func Test_image_ConfigFile(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -25,10 +25,13 @@ type podmanClient struct {
|
||||
c http.Client
|
||||
}
|
||||
|
||||
func newPodmanClient() (podmanClient, error) {
|
||||
func newPodmanClient(host string) (podmanClient, error) {
|
||||
// Get Podman socket location
|
||||
sockDir := os.Getenv("XDG_RUNTIME_DIR")
|
||||
socket := filepath.Join(sockDir, "podman", "podman.sock")
|
||||
if host != "" {
|
||||
socket = host
|
||||
}
|
||||
|
||||
if _, err := os.Stat(socket); err != nil {
|
||||
return podmanClient{}, xerrors.Errorf("no podman socket found: %w", err)
|
||||
@@ -109,10 +112,10 @@ func (p podmanClient) imageSave(_ context.Context, imageNames []string) (io.Read
|
||||
|
||||
// PodmanImage implements v1.Image by extending daemon.Image.
|
||||
// The caller must call cleanup() to remove a temporary file.
|
||||
func PodmanImage(ref string) (Image, func(), error) {
|
||||
func PodmanImage(ref, host string) (Image, func(), error) {
|
||||
cleanup := func() {}
|
||||
|
||||
c, err := newPodmanClient()
|
||||
c, err := newPodmanClient(host)
|
||||
if err != nil {
|
||||
return nil, cleanup, xerrors.Errorf("unable to initialize Podman client: %w", err)
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ func TestPodmanImage(t *testing.T) {
|
||||
ref, err := name.ParseReference(tt.imageName)
|
||||
require.NoError(t, err)
|
||||
|
||||
img, cleanup, err := PodmanImage(ref.Name())
|
||||
img, cleanup, err := PodmanImage(ref.Name(), "")
|
||||
defer cleanup()
|
||||
|
||||
if tt.wantErr {
|
||||
|
||||
@@ -60,7 +60,7 @@ type DockerOptions struct {
|
||||
}
|
||||
|
||||
type PodmanOptions struct {
|
||||
// Add Podman-specific options
|
||||
Host string
|
||||
}
|
||||
|
||||
type ContainerdOptions struct {
|
||||
|
||||
@@ -45,6 +45,12 @@ var (
|
||||
Default: "",
|
||||
Usage: "unix domain socket path to use for docker scanning",
|
||||
}
|
||||
PodmanHostFlag = Flag[string]{
|
||||
Name: "podman-host",
|
||||
ConfigName: "image.podman.host",
|
||||
Default: "",
|
||||
Usage: "unix podman socket path to use for podman scanning",
|
||||
}
|
||||
SourceFlag = Flag[[]string]{
|
||||
Name: "image-src",
|
||||
ConfigName: "image.source",
|
||||
@@ -60,6 +66,7 @@ type ImageFlagGroup struct {
|
||||
ScanRemovedPkgs *Flag[bool]
|
||||
Platform *Flag[string]
|
||||
DockerHost *Flag[string]
|
||||
PodmanHost *Flag[string]
|
||||
ImageSources *Flag[[]string]
|
||||
}
|
||||
|
||||
@@ -69,6 +76,7 @@ type ImageOptions struct {
|
||||
ScanRemovedPkgs bool
|
||||
Platform ftypes.Platform
|
||||
DockerHost string
|
||||
PodmanHost string
|
||||
ImageSources ftypes.ImageSources
|
||||
}
|
||||
|
||||
@@ -79,6 +87,7 @@ func NewImageFlagGroup() *ImageFlagGroup {
|
||||
ScanRemovedPkgs: ScanRemovedPkgsFlag.Clone(),
|
||||
Platform: PlatformFlag.Clone(),
|
||||
DockerHost: DockerHostFlag.Clone(),
|
||||
PodmanHost: PodmanHostFlag.Clone(),
|
||||
ImageSources: SourceFlag.Clone(),
|
||||
}
|
||||
}
|
||||
@@ -94,6 +103,7 @@ func (f *ImageFlagGroup) Flags() []Flagger {
|
||||
f.ScanRemovedPkgs,
|
||||
f.Platform,
|
||||
f.DockerHost,
|
||||
f.PodmanHost,
|
||||
f.ImageSources,
|
||||
}
|
||||
}
|
||||
@@ -121,6 +131,7 @@ func (f *ImageFlagGroup) ToOptions() (ImageOptions, error) {
|
||||
ScanRemovedPkgs: f.ScanRemovedPkgs.Value(),
|
||||
Platform: platform,
|
||||
DockerHost: f.DockerHost.Value(),
|
||||
PodmanHost: f.PodmanHost.Value(),
|
||||
ImageSources: xstrings.ToTSlice[ftypes.ImageSource](f.ImageSources.Value()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user