Skip to content
Open
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
3 changes: 2 additions & 1 deletion artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"os"
"slices"
"strings"
"sync"

"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
_ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/all"
Expand All @@ -27,6 +26,8 @@ import (
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/samber/lo"
"github.com/sirupsen/logrus"
"sync"

"golang.org/x/sync/semaphore"
)

Expand Down
407 changes: 212 additions & 195 deletions go.mod

Large diffs are not rendered by default.

2,593 changes: 587 additions & 2,006 deletions go.sum

Large diffs are not rendered by default.

56 changes: 21 additions & 35 deletions image/daemon/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,14 @@ import (

itypes "github.com/castai/image-analyzer/image/types"

"github.com/containerd/containerd"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/images/archive"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/reference/docker"
refdocker "github.com/containerd/containerd/reference/docker"
"github.com/containerd/containerd/v2/client"
"github.com/containerd/containerd/v2/core/content"
"github.com/containerd/containerd/v2/core/images/archive"
"github.com/containerd/containerd/v2/pkg/namespaces"
"github.com/containerd/platforms"
"github.com/distribution/reference"
api "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/go-connections/nat"
dockerspec "github.com/moby/docker-image-spec/specs-go/v1"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
Expand All @@ -38,17 +36,17 @@ const (
defaultContainerdNamespace = "k8s.io"
)

func imageWriter(client *containerd.Client, img containerd.Image) imageSave {
func imageWriter(c *client.Client, img client.Image) imageSave {
return func(ctx context.Context, ref []string) (io.ReadCloser, error) {
if len(ref) < 1 {
return nil, errors.New("no image reference")
}
imgOpts := archive.WithImage(client.ImageService(), ref[0])
imgOpts := archive.WithImage(c.ImageService(), ref[0])
manifestOpts := archive.WithManifest(img.Target())
platOpts := archive.WithPlatform(platforms.DefaultStrict())
pr, pw := io.Pipe()
go func() {
pw.CloseWithError(archive.Export(ctx, client.ContentStore(), pw, imgOpts, manifestOpts, platOpts))
pw.CloseWithError(archive.Export(ctx, c.ContentStore(), pw, imgOpts, manifestOpts, platOpts))
}()
return pr, nil
}
Expand All @@ -69,20 +67,20 @@ func ContainerdImage(ctx context.Context, imageName string) (itypes.ImageWithInd
}

// Parse the image name
ref, err := refdocker.ParseDockerRef(imageName)
ref, err := reference.ParseDockerRef(imageName)
if err != nil {
return nil, cleanup, fmt.Errorf("parse error: %w", err)
}

client, err := containerd.New(addr)
c, err := client.New(addr)
if err != nil {
return nil, cleanup, fmt.Errorf("failed to initialize a containerd client: %w", err)
}

// Need to specify a namespace
ctx = namespaces.WithNamespace(ctx, defaultContainerdNamespace)

img, err := client.GetImage(ctx, ref.String())
img, err := c.GetImage(ctx, ref.String())
if err != nil {
return nil, cleanup, fmt.Errorf("failed to get %s: %w", imageName, err)
}
Expand All @@ -93,7 +91,7 @@ func ContainerdImage(ctx context.Context, imageName string) (itypes.ImageWithInd
}

cleanup = func() {
_ = client.Close()
_ = c.Close()
_ = f.Close()
_ = os.Remove(f.Name())
}
Expand All @@ -104,15 +102,15 @@ func ContainerdImage(ctx context.Context, imageName string) (itypes.ImageWithInd
}

return &image{
opener: imageOpener(ctx, ref.String(), f, imageWriter(client, img)),
opener: imageOpener(ctx, ref.String(), f, imageWriter(c, img)),
inspect: insp,
history: history,
}, cleanup, nil
}

// readImageConfig reads the config spec (`application/vnd.oci.image.config.v1+json`) for img.platform from content store.
// ported from https://github.com/containerd/nerdctl/blob/7dfbaa2122628921febeb097e7a8a86074dc931d/pkg/imgutil/imgutil.go#L377-L393
func readImageConfig(ctx context.Context, img containerd.Image) (ocispec.Image, ocispec.Descriptor, error) {
func readImageConfig(ctx context.Context, img client.Image) (ocispec.Image, ocispec.Descriptor, error) {
var config ocispec.Image

configDesc, err := img.Config(ctx) // aware of img.platform
Expand All @@ -130,12 +128,12 @@ func readImageConfig(ctx context.Context, img containerd.Image) (ocispec.Image,
}

// ported from https://github.com/containerd/nerdctl/blob/d110fea18018f13c3f798fa6565e482f3ff03591/pkg/inspecttypes/dockercompat/dockercompat.go#L279-L321
func inspect(ctx context.Context, img containerd.Image, ref docker.Named) (api.ImageInspect, []v1.History, error) {
func inspect(ctx context.Context, img client.Image, ref reference.Named) (api.ImageInspect, []v1.History, error) {
var tag string
if tagged, ok := ref.(refdocker.Tagged); ok {
if tagged, ok := ref.(reference.Tagged); ok {
tag = tagged.Tag()
}
repository := refdocker.FamiliarName(ref)
repository := reference.FamiliarName(ref)

imgConfig, imgConfigDesc, err := readImageConfig(ctx, img)
if err != nil {
Expand Down Expand Up @@ -165,27 +163,15 @@ func inspect(ctx context.Context, img containerd.Image, ref docker.Named) (api.I
history = append(history, hist)
}

portSet := make(nat.PortSet)
for k := range imgConfig.Config.ExposedPorts {
portSet[nat.Port(k)] = struct{}{}
}

return api.ImageInspect{
ID: imgConfigDesc.Digest.String(),
RepoTags: []string{fmt.Sprintf("%s:%s", repository, tag)},
RepoDigests: []string{fmt.Sprintf("%s@%s", repository, img.Target().Digest)},
Comment: lastHistory.Comment,
Created: lastCreated,
Author: lastHistory.Author,
Config: &container.Config{
User: imgConfig.Config.User,
ExposedPorts: portSet,
Env: imgConfig.Config.Env,
Cmd: imgConfig.Config.Cmd,
Volumes: imgConfig.Config.Volumes,
WorkingDir: imgConfig.Config.WorkingDir,
Entrypoint: imgConfig.Config.Entrypoint,
Labels: imgConfig.Config.Labels,
Config: &dockerspec.DockerOCIImageConfig{
ImageConfig: imgConfig.Config,
},
Architecture: imgConfig.Architecture,
Os: imgConfig.OS,
Expand Down
5 changes: 4 additions & 1 deletion image/daemon/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package daemon
import (
"context"
"fmt"
"io"
"os"

itypes "github.com/castai/image-analyzer/image/types"
Expand Down Expand Up @@ -64,7 +65,9 @@ func DockerImage(ref name.Reference) (itypes.ImageWithIndex, func(), error) {
}

return &image{
opener: imageOpener(context.Background(), imageID, f, c.ImageSave),
opener: imageOpener(context.Background(), imageID, f, func(ctx context.Context, ids []string) (io.ReadCloser, error) {
return c.ImageSave(ctx, ids)
}),
inspect: inspect,
history: configHistory(history),
}, cleanup, nil
Expand Down
39 changes: 14 additions & 25 deletions image/daemon/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import (
"time"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
dimage "github.com/docker/docker/api/types/image"
dockerspec "github.com/moby/docker-image-spec/specs-go/v1"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/tarball"
)
Expand Down Expand Up @@ -180,34 +180,23 @@ func (img *image) diffIDs() ([]v1.Hash, error) {
return diffIDs, nil
}

func (img *image) imageConfig(config *container.Config) v1.Config {
func (img *image) imageConfig(config *dockerspec.DockerOCIImageConfig) v1.Config {
if config == nil {
return v1.Config{}
}

c := v1.Config{
AttachStderr: config.AttachStderr,
AttachStdin: config.AttachStdin,
AttachStdout: config.AttachStdout,
Cmd: config.Cmd,
Domainname: config.Domainname,
Entrypoint: config.Entrypoint,
Env: config.Env,
Hostname: config.Hostname,
Image: config.Image,
Labels: config.Labels,
OnBuild: config.OnBuild,
OpenStdin: config.OpenStdin,
StdinOnce: config.StdinOnce,
Tty: config.Tty,
User: config.User,
Volumes: config.Volumes,
WorkingDir: config.WorkingDir,
ArgsEscaped: config.ArgsEscaped,
NetworkDisabled: config.NetworkDisabled,
MacAddress: config.MacAddress,
StopSignal: config.StopSignal,
Shell: config.Shell,
Cmd: config.Cmd,
Entrypoint: config.Entrypoint,
Env: config.Env,
Labels: config.Labels,
OnBuild: config.OnBuild,
User: config.User,
Volumes: config.Volumes,
WorkingDir: config.WorkingDir,
ArgsEscaped: config.ArgsEscaped,
StopSignal: config.StopSignal,
Shell: config.Shell,
}

if config.Healthcheck != nil {
Expand All @@ -222,7 +211,7 @@ func (img *image) imageConfig(config *container.Config) v1.Config {

if len(config.ExposedPorts) > 0 {
c.ExposedPorts = map[string]struct{}{}
for port := range c.ExposedPorts {
for port := range config.ExposedPorts {
c.ExposedPorts[port] = struct{}{}
}
}
Expand Down
Loading