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

Use node's arch during image scan #200

Merged
merged 3 commits into from
Dec 6, 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
12 changes: 8 additions & 4 deletions cmd/imgcollector/collector/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ import (
"strings"
"time"

"github.com/castai/image-analyzer/image"
"github.com/castai/image-analyzer/image/hostfs"
fanalyzer "github.com/aquasecurity/trivy/pkg/fanal/analyzer"
"github.com/cenkalti/backoff/v4"
"github.com/google/go-containerregistry/pkg/name"
"github.com/samber/lo"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"

fanalyzer "github.com/aquasecurity/trivy/pkg/fanal/analyzer"
analyzer "github.com/castai/image-analyzer"
"github.com/castai/image-analyzer/image"
"github.com/castai/image-analyzer/image/hostfs"
"github.com/castai/kvisor/castai"
"github.com/castai/kvisor/cmd/imgcollector/config"
)
Expand Down Expand Up @@ -86,7 +86,7 @@ func (c *Collector) Collect(ctx context.Context) error {
metadata := &castai.ImageMetadata{
ImageName: c.cfg.ImageName,
ImageID: c.cfg.ImageID,
Architecture: arRef.ArtifactInfo.Architecture,
Architecture: c.cfg.ImageArchitecture,
ImageDigest: digest.String(),
ResourceIDs: strings.Split(c.cfg.ResourceIDs, ","),
BlobsInfo: arRef.BlobsInfo,
Expand Down Expand Up @@ -147,6 +147,10 @@ func (c *Collector) getImage(ctx context.Context) (image.ImageWithIndex, func(),
return nil, nil, fmt.Errorf("unmarshaling docker options file: %w", err)
}
}
if c.cfg.ImageArchitecture != "" && c.cfg.ImageOS != "" {
opts.Architecture = c.cfg.ImageArchitecture
opts.OS = c.cfg.ImageOS
}
img, err := image.NewFromRemote(ctx, c.cfg.ImageName, opts)
return img, func() {}, err
}
Expand Down
18 changes: 10 additions & 8 deletions cmd/imgcollector/collector/collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import (
"testing"
"time"

"github.com/castai/image-analyzer/image"
"github.com/castai/image-analyzer/image/hostfs"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"

"github.com/castai/image-analyzer/image"
"github.com/castai/image-analyzer/image/hostfs"
mock_blobcache "github.com/castai/kvisor/blobscache/mock"
"github.com/castai/kvisor/castai"
"github.com/castai/kvisor/cmd/imgcollector/config"
Expand Down Expand Up @@ -50,12 +50,13 @@ func TestCollector(t *testing.T) {
p := path.Join(cwd, "testdata/amd64-linux/io.containerd.content.v1.content")

c := New(log, config.Config{
ApiURL: srv.URL,
ImageID: imgID,
ImageName: imgName,
Timeout: 5 * time.Minute,
Mode: config.ModeHostFS,
Runtime: config.RuntimeContainerd,
ApiURL: srv.URL,
ImageID: imgID,
ImageName: imgName,
Timeout: 5 * time.Minute,
Mode: config.ModeHostFS,
Runtime: config.RuntimeContainerd,
ImageArchitecture: "amd64",
}, mockCache, &hostfs.ContainerdHostFSConfig{
Platform: v1.Platform{
Architecture: "amd64",
Expand All @@ -71,6 +72,7 @@ func TestCollector(t *testing.T) {
b, err := os.ReadFile("./testdata/expected_image_scan_meta1.json")
r.NoError(err)
r.NoError(json.Unmarshal(b, &expected))
expected.Architecture = "amd64"

var receivedMeta castai.ImageMetadata
r.NoError(json.Unmarshal(receivedMetaBytes, &receivedMeta))
Expand Down
24 changes: 13 additions & 11 deletions cmd/imgcollector/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,19 @@ const (
)

type Config struct {
ApiURL string `envconfig:"KVISOR_SERVER_API_URL" required:"true"`
ImageID string `envconfig:"COLLECTOR_IMAGE_ID" required:"true"`
ImageName string `envconfig:"COLLECTOR_IMAGE_NAME" required:"true"`
ImagePullSecret string `envconfig:"COLLECTOR_PULL_SECRET" default:""`
Timeout time.Duration `envconfig:"COLLECTOR_TIMEOUT" default:"5m"`
Mode Mode `envconfig:"COLLECTOR_MODE"`
Runtime Runtime `envconfig:"COLLECTOR_RUNTIME" required:"true"`
ResourceIDs string `envconfig:"COLLECTOR_RESOURCE_IDS" required:"true"`
DockerOptionPath string `envconfig:"COLLECTOR_DOCKER_OPTION_PATH" default:""`
PprofAddr string `envconfig:"COLLECTOR_PPROF_ADDR" default:""`
SlowMode bool `envconfig:"SLOW_MODE" default:"true"`
ApiURL string `envconfig:"KVISOR_SERVER_API_URL" required:"true"`
ImageID string `envconfig:"COLLECTOR_IMAGE_ID" required:"true"`
ImageName string `envconfig:"COLLECTOR_IMAGE_NAME" required:"true"`
ImageArchitecture string `envconfig:"COLLECTOR_IMAGE_ARCHITECTURE" required:"true"`
ImageOS string `envconfig:"COLLECTOR_IMAGE_OS" required:"true"`
ImagePullSecret string `envconfig:"COLLECTOR_PULL_SECRET" default:""`
Timeout time.Duration `envconfig:"COLLECTOR_TIMEOUT" default:"5m"`
Mode Mode `envconfig:"COLLECTOR_MODE"`
Runtime Runtime `envconfig:"COLLECTOR_RUNTIME" required:"true"`
ResourceIDs string `envconfig:"COLLECTOR_RESOURCE_IDS" required:"true"`
DockerOptionPath string `envconfig:"COLLECTOR_DOCKER_OPTION_PATH" default:""`
PprofAddr string `envconfig:"COLLECTOR_PPROF_ADDR" default:""`
SlowMode bool `envconfig:"SLOW_MODE" default:"true"`
// ImageLocalTarPath is used only with ModeTarArchive for local dev.
ImageLocalTarPath string
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/eks v1.22.1
github.com/aws/smithy-go v1.13.4
github.com/bombsimon/logrusr/v4 v4.0.0
github.com/castai/image-analyzer v0.1.0
github.com/castai/image-analyzer v0.2.0
github.com/cenkalti/backoff/v4 v4.1.3
github.com/containerd/containerd v1.7.8
github.com/davecgh/go-spew v1.1.1
Expand Down
8 changes: 2 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,8 @@ github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXe
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/caarlos0/env/v6 v6.10.1 h1:t1mPSxNpei6M5yAeu1qtRdPAK29Nbcf/n3G7x+b3/II=
github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc=
github.com/castai/image-analyzer v0.1.0 h1:S4HaztzLacwICJv/EYSu6NjhBGNcL8tP/mLAo/iKHW0=
github.com/castai/image-analyzer v0.1.0/go.mod h1:HJ+p9mvz92DDC/eqrTrscnV7w7NdBZd9a/PQZZ03PdM=
github.com/castai/image-analyzer v0.2.0 h1:rAazxM063PDaxGA2y5IsDEI7Yt2B6xETYh9To9k+ICU=
github.com/castai/image-analyzer v0.2.0/go.mod h1:HJ+p9mvz92DDC/eqrTrscnV7w7NdBZd9a/PQZZ03PdM=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
Expand Down Expand Up @@ -1786,8 +1786,6 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.24.1/go.mod h1:JhoOvNiLXKTPQ60zh2g0ewpA+bnEYf5q44Flhquh4vQ=
k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ=
k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg=
k8s.io/api v0.26.11 h1:hLhTZRdYc3vBBOY4wbEyTLWgMyieOAk2Ws9NG57QqO4=
k8s.io/api v0.26.11/go.mod h1:bSr/A0TKRt5W2OMDdexkM/ER1NxOxiQqNNFXW2nMZrM=
k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI=
Expand All @@ -1802,8 +1800,6 @@ k8s.io/apiserver v0.26.1/go.mod h1:wr75z634Cv+sifswE9HlAo5FQ7UoUauIICRlOE+5dCg=
k8s.io/cli-runtime v0.25.3 h1:Zs7P7l7db/5J+KDePOVtDlArAa9pZXaDinGWGZl0aM8=
k8s.io/cli-runtime v0.25.3/go.mod h1:InHHsjkyW5hQsILJGpGjeruiDZT/R0OkROQgD6GzxO4=
k8s.io/client-go v0.24.1/go.mod h1:f1kIDqcEYmwXS/vTbbhopMUbhKp2JhOeVTfxgaCIlF8=
k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU=
k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE=
k8s.io/client-go v0.26.11 h1:RjfZr5+vQjjTRmk4oCqHyC0cgrZXPjw+X+ge35sk4GI=
k8s.io/client-go v0.26.11/go.mod h1:+emNszw9va/uRJIM5ALTBtFnlZMTjwBrNjRfEh0iuw8=
k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0=
Expand Down
2 changes: 2 additions & 0 deletions imagescan/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@ func (s *Controller) scanImage(ctx context.Context, img *image) (rerr error) {
DeleteFinishedJob: true,
WaitForCompletion: true,
WaitDurationAfterCompletion: 30 * time.Second,
Architecture: img.architecture,
Os: img.os,
})
}

Expand Down
2 changes: 2 additions & 0 deletions imagescan/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ func TestSubscriber(t *testing.T) {
DeleteFinishedJob: true,
WaitForCompletion: true,
WaitDurationAfterCompletion: 30 * time.Second,
Architecture: defaultImageArch,
Os: defaultImageOs,
}, ngnxImage)
r.Len(client.getImagesResourcesChanges(), 1)
r.Len(client.getImagesResourcesChanges()[0].Images, 3)
Expand Down
32 changes: 24 additions & 8 deletions imagescan/delta.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var (
errNoCandidates = errors.New("no candidates")
)

const defaultImageOs = "linux"
const defaultImageArch = "amd64"

type podOwnerGetter interface {
Expand Down Expand Up @@ -101,6 +102,7 @@ func (d *deltaState) updateNodeUsage(v *corev1.Node) {
n = &node{
name: v.GetName(),
architecture: v.Status.NodeInfo.Architecture,
os: v.Status.NodeInfo.OperatingSystem,
allocatableMem: &inf.Dec{},
allocatableCPU: &inf.Dec{},
pods: make(map[types.UID]*pod),
Expand Down Expand Up @@ -168,14 +170,15 @@ func (d *deltaState) upsertImages(pod *corev1.Pod) {
}

nodeName := pod.Spec.NodeName
arch := d.getPodArch(pod)
key := cs.ImageID + arch + cont.Image
platform := d.getPodPlatform(pod)
key := cs.ImageID + platform.architecture + cont.Image
img, found := d.images[key]
if !found {
img = newImage()
img.name = cont.Image
img.key = key
img.architecture = arch
img.architecture = platform.architecture
img.os = platform.os
}
img.id = cs.ImageID
img.containerRuntime = getContainerRuntime(cs.ContainerID)
Expand Down Expand Up @@ -209,7 +212,7 @@ func (d *deltaState) upsertImages(pod *corev1.Pod) {
func (d *deltaState) handlePodDelete(pod *corev1.Pod) {
now := time.Now().UTC()
for imgKey, img := range d.images {
if img.architecture != d.getPodArch(pod) {
if img.architecture != d.getPodPlatform(pod).architecture {
continue
}

Expand Down Expand Up @@ -320,12 +323,23 @@ func (d *deltaState) setImageScanned(scannedImg castai.ScannedImage) {
}
}

func (d *deltaState) getPodArch(pod *corev1.Pod) string {
type platform struct {
architecture string
os string
}

func (d *deltaState) getPodPlatform(pod *corev1.Pod) platform {
n, ok := d.nodes[pod.Spec.NodeName]
if ok && n.architecture != "" {
return n.architecture
if ok && n.architecture != "" && n.os != "" {
return platform{
architecture: n.architecture,
os: n.os,
}
}
return platform{
architecture: defaultImageArch,
os: defaultImageOs,
}
return defaultImageArch
}

func getContainerRuntime(containerID string) imgcollectorconfig.Runtime {
Expand All @@ -352,6 +366,7 @@ type pod struct {
type node struct {
name string
architecture string
os string
allocatableMem *inf.Dec
allocatableCPU *inf.Dec
pods map[types.UID]*pod
Expand Down Expand Up @@ -426,6 +441,7 @@ type image struct {
name string

architecture string
os string
containerRuntime imgcollectorconfig.Runtime

// owners map key points to higher level k8s resource for that image. (Image Affected resource in CAST AI console).
Expand Down
13 changes: 11 additions & 2 deletions imagescan/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ import (
"time"

"github.com/samber/lo"
"k8s.io/apimachinery/pkg/labels"

batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
batchv1typed "k8s.io/client-go/kubernetes/typed/batch/v1"
Expand Down Expand Up @@ -65,6 +64,8 @@ type ScanImageParams struct {
DeleteFinishedJob bool
WaitForCompletion bool
WaitDurationAfterCompletion time.Duration
Architecture string
Os string
}

func (s *Scanner) ScanImage(ctx context.Context, params ScanImageParams) (rerr error) {
Expand Down Expand Up @@ -202,6 +203,14 @@ func (s *Scanner) ScanImage(ctx context.Context, params ScanImageParams) (rerr e
Name: "KVISOR_SERVER_API_URL",
Value: s.cfg.ImageScan.APIUrl,
},
{
Name: "COLLECTOR_IMAGE_ARCHITECTURE",
Value: params.Architecture,
},
{
Name: "COLLECTOR_IMAGE_OS",
Value: params.Os,
},
}

if s.cfg.ImageScan.PullSecret != "" {
Expand Down
10 changes: 10 additions & 0 deletions imagescan/scanner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ func TestScanner(t *testing.T) {
Mode: "hostfs",
NodeName: "n1",
ResourceIDs: []string{"p1", "p2"},
Architecture: "amd64",
Os: "linux",
})
r.NoError(err)

Expand Down Expand Up @@ -162,6 +164,14 @@ func TestScanner(t *testing.T) {
Name: "KVISOR_SERVER_API_URL",
Value: "http://kvisor:6060",
},
{
Name: "COLLECTOR_IMAGE_ARCHITECTURE",
Value: "amd64",
},
{
Name: "COLLECTOR_IMAGE_OS",
Value: "linux",
},
{
Name: "COLLECTOR_PPROF_ADDR",
Value: ":6060",
Expand Down
Loading