Skip to content

Commit

Permalink
⭐️ add container-proxy flag for scanning containers
Browse files Browse the repository at this point in the history
Signed-off-by: Ivan Milchev <[email protected]>
  • Loading branch information
imilchev committed May 14, 2024
1 parent f15d2d8 commit 326a7a8
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 17 deletions.
12 changes: 12 additions & 0 deletions providers/os/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ var Config = plugin.Provider{
Default: "false",
Desc: "Disable the in-memory cache for images. WARNING: This will slow down scans significantly.",
},
{
Long: "container-proxy",
Type: plugin.FlagType_String,
Default: "",
Desc: "HTTP proxy to use for container pulls",
},
},
},
{
Expand Down Expand Up @@ -231,6 +237,12 @@ var Config = plugin.Provider{
Default: "false",
Desc: "Disable the in-memory cache for images. WARNING: This will slow down scans significantly.",
},
{
Long: "container-proxy",
Type: plugin.FlagType_String,
Default: "",
Desc: "HTTP proxy to use for container pulls",
},
},
},
{
Expand Down
8 changes: 6 additions & 2 deletions providers/os/connection/container/image_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/google/go-containerregistry/pkg/v1/tarball"
"github.com/rs/zerolog/log"
"go.mondoo.com/cnquery/v11/providers-sdk/v1/inventory"
Expand All @@ -20,6 +19,7 @@ import (
"go.mondoo.com/cnquery/v11/providers/os/connection/container/image"
"go.mondoo.com/cnquery/v11/providers/os/connection/tar"
"go.mondoo.com/cnquery/v11/providers/os/id/containerid"
"go.mondoo.com/cnquery/v11/providers/os/resources/discovery/container_registry"
)

// NewImageConnection uses a container image reference as input and creates a tar connection
Expand Down Expand Up @@ -63,7 +63,11 @@ func NewRegistryImage(id uint32, conf *inventory.Config, asset *inventory.Asset)
}
log.Debug().Str("ref", ref.Name()).Msg("found valid container registry reference")

registryOpts := []remote.Option{auth.TransportOption(conf.Insecure), auth.AuthOption(ref.Name(), conf.Credentials)}
registryOpts, err := container_registry.RemoteOptionsFromConfigOptions(conf)
if err != nil {
return nil, err
}
registryOpts = append(registryOpts, auth.AuthOption(ref.Name(), conf.Credentials))
img, err := image.LoadImageFromRegistry(ref, registryOpts...)
if err != nil {
return nil, err
Expand Down
7 changes: 6 additions & 1 deletion providers/os/connection/container/registry_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,12 @@ func (r *RegistryConnection) Asset() *inventory.Asset {
}

func (r *RegistryConnection) DiscoverImages() (*inventory.Inventory, error) {
resolver := container_registry.NewContainerRegistryResolver()
opts, err := container_registry.RemoteOptionsFromConfigOptions(r.asset.Connections[0])
if err != nil {
return nil, err
}

resolver := container_registry.NewContainerRegistryResolver(opts...)
host := r.asset.Connections[0].Host
assets, err := resolver.ListRegistry(host)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions providers/os/connection/shared/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ const (
Type_DockerSnapshot ConnectionType = "docker-snapshot"
Type_ContainerRegistry ConnectionType = "container-registry"
Type_RegistryImage ConnectionType = "registry-image"

ContainerProxyOption string = "container-proxy"
)

type Connection interface {
Expand Down
14 changes: 11 additions & 3 deletions providers/os/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,21 @@ func (s *Service) ParseCLI(req *plugin.ParseCLIReq) (*plugin.ParseCLIRes, error)
asset.IdDetector = []string{idDetector}
}

if conf.Options == nil {
conf.Options = map[string]string{}
}

if disableCache, ok := flags["disable-cache"]; ok {
if conf.Options == nil {
conf.Options = map[string]string{}
}
conf.Options["disable-cache"] = strconv.FormatBool(disableCache.RawData().Value.(bool))
}

if containerProxy, ok := flags[shared.ContainerProxyOption]; ok {
proxyVal := containerProxy.RawData().Value.(string)
if proxyVal != "" {
conf.Options[shared.ContainerProxyOption] = proxyVal
}
}

res := plugin.ParseCLIRes{
Asset: asset,
}
Expand Down
38 changes: 38 additions & 0 deletions providers/os/resources/discovery/container_registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
package container_registry

import (
"crypto/tls"
"fmt"
"net"
"net/http"
"net/url"
"time"

"github.com/cockroachdb/errors"
"github.com/google/go-containerregistry/pkg/name"
Expand All @@ -19,6 +23,40 @@ import (
"go.mondoo.com/cnquery/v11/providers/os/id/containerid"
)

func RemoteOptionsFromConfigOptions(cfg *inventory.Config) ([]remote.Option, error) {
opts := []remote.Option{}

transport := &http.Transport{
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
// We usually are dealing with 2 hosts (at most), split MaxIdleConns between them.
MaxIdleConnsPerHost: 50,
}
if containerProxy, ok := cfg.Options[shared.ContainerProxyOption]; ok {
urlParsed, err := url.Parse(containerProxy)
if err != nil {
return nil, err
}
transport.Proxy = http.ProxyURL(urlParsed)

}

if cfg.Insecure {
transport.TLSClientConfig = &tls.Config{
InsecureSkipVerify: true,
}
}
opts = append(opts, remote.WithTransport(transport))
return opts, nil
}

func NewContainerRegistryResolver(opts ...remote.Option) *DockerRegistryImages {
return &DockerRegistryImages{
opts: opts,
Expand Down
22 changes: 11 additions & 11 deletions providers/os/resources/discovery/container_registry/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"errors"

"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/rs/zerolog/log"
"go.mondoo.com/cnquery/v11/providers-sdk/v1/inventory"
"go.mondoo.com/cnquery/v11/providers-sdk/v1/vault"
Expand All @@ -33,26 +32,27 @@ func (r *Resolver) AvailableDiscoveryTargets() []string {
func (r *Resolver) Resolve(ctx context.Context, root *inventory.Asset, conf *inventory.Config, credsResolver vault.Resolver) ([]*inventory.Asset, error) {
resolved := []*inventory.Asset{}

imageFetcher := NewContainerRegistryResolver()
opts, err := RemoteOptionsFromConfigOptions(conf)
if err != nil {
return nil, err
}

imageFetcher := NewContainerRegistryResolver(opts...)

// check if the reference is an image
// NOTE: we use strict validation here otherwise urls like cr://index.docker.io/mondoo/client are converted
// to index.docker.io/mondoo/client:latest
opts := name.StrictValidation
nameOpts := name.StrictValidation
if r.NoStrictValidation {
opts = name.WeakValidation
nameOpts = name.WeakValidation
}

ref, err := name.ParseReference(conf.Host, opts)
ref, err := name.ParseReference(conf.Host, nameOpts)
if err == nil {
log.Debug().Str("image", conf.Host).Msg("detected container image in container registry")

remoteOpts := []remote.Option{
auth.AuthOption(ref.Name(), conf.Credentials),
// to support self-signed certs
auth.TransportOption(conf.Insecure),
}
a, err := imageFetcher.GetImage(ref, conf.Credentials, remoteOpts...)
opts = append(opts, auth.AuthOption(ref.Name(), conf.Credentials))
a, err := imageFetcher.GetImage(ref, conf.Credentials, opts...)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 326a7a8

Please sign in to comment.