adjust logging for extracting oci artifacts with cosign bits (#575)

Signed-off-by: Adam Martin <adam.martin@ranchergovernment.com>
This commit is contained in:
Adam Martin
2026-04-22 12:57:51 -04:00
committed by GitHub
parent 2bf284e183
commit eca35ecb92
2 changed files with 89 additions and 0 deletions

View File

@@ -99,6 +99,21 @@ func ExtractCmd(ctx context.Context, o *flags.ExtractOpts, s *store.Layout, ref
if !strings.Contains(reference, repo) {
return nil
}
// Cosign sig/att/sbom/referrer descriptors are registry-only metadata —
// they are never extractable to disk. Skip them silently at debug level,
// mirroring the same guard in copy.go (directory-target path).
kind := desc.Annotations[consts.KindAnnotationName]
switch kind {
case consts.KindAnnotationSigs, consts.KindAnnotationAtts, consts.KindAnnotationSboms:
l.Debugf("skipping cosign artifact [%s] for extract", reference)
return nil
}
if strings.HasPrefix(kind, consts.KindAnnotationReferrers) {
l.Debugf("skipping OCI referrer [%s] for extract", reference)
return nil
}
found = true
rc, err := s.Fetch(ctx, desc)

View File

@@ -1,6 +1,8 @@
package store
import (
"bytes"
"context"
"os"
"path/filepath"
"strings"
@@ -14,6 +16,7 @@ import (
"github.com/google/go-containerregistry/pkg/v1/static"
gvtypes "github.com/google/go-containerregistry/pkg/v1/types"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/rs/zerolog"
"hauler.dev/go/hauler/internal/flags"
v1 "hauler.dev/go/hauler/pkg/apis/hauler.cattle.io/v1"
@@ -554,3 +557,74 @@ func TestExtractCmd_SubstringMatch(t *testing.T) {
t.Errorf("content mismatch: got %q, want %q", string(data), fileContent)
}
}
// newLogCaptureContext returns a context backed by a zerolog logger that writes
// JSON log lines to buf. Use buf.String() after the call to inspect log output.
func newLogCaptureContext(buf *bytes.Buffer) context.Context {
zl := zerolog.New(buf).With().Timestamp().Logger()
return zl.WithContext(context.Background())
}
func TestExtractCmd_CosignArtifactsProduceNoContainerImageWarning(t *testing.T) {
// Regression test: extracting a file ref whose store also contains cosign
// sig/att/sbom/referrer descriptors with the same repo prefix must not emit
// the "container images cannot be extracted" warning for those cosign descriptors.
//
// Before the fix, cosign manifests tripped isContainerImageManifest() and caused
// a misleading WRN line. The fix is a kind-annotation early-return in the Walk
// callback that mirrors the pattern in copy.go:49-58.
var logBuf bytes.Buffer
ctx := newLogCaptureContext(&logBuf)
s := newTestStore(t)
// Seed a real file artifact so ExtractCmd finds something to extract.
fileContent := "cosign-filter test file content"
url := seedFileInHTTPServer(t, "sigtest.txt", fileContent)
if err := storeFile(ctx, s, v1.File{Path: url}); err != nil {
t.Fatalf("storeFile: %v", err)
}
// The file is stored under "hauler/sigtest.txt:latest". Inject fake cosign
// sig/att/sbom/referrer descriptors sharing the same AnnotationRefName so the
// Walk callback's strings.Contains(reference, repo) filter matches them too.
baseRef := "hauler/sigtest.txt:latest"
for _, kind := range []string{
consts.KindAnnotationSigs,
consts.KindAnnotationAtts,
consts.KindAnnotationSboms,
consts.KindAnnotationReferrers + "/sha256" + strings.Repeat("a", 64),
} {
seedStoreDescriptor(t, s, map[string]string{
ocispec.AnnotationRefName: baseRef,
consts.KindAnnotationName: kind,
consts.ContainerdImageNameKey: "registry.example.com/" + baseRef,
})
}
destDir := t.TempDir()
eo := &flags.ExtractOpts{
StoreRootOpts: defaultRootOpts(s.Root),
DestinationDir: destDir,
}
if err := ExtractCmd(ctx, eo, s, baseRef); err != nil {
t.Fatalf("ExtractCmd: %v", err)
}
// The "container images cannot be extracted" warning must NOT appear for
// the cosign descriptors — they must be silently skipped at debug level.
if strings.Contains(logBuf.String(), "container images cannot be extracted") {
t.Errorf("unexpected warning in log output for cosign descriptors:\n%s", logBuf.String())
}
// The file artifact must still be extracted to the destination directory.
outPath := filepath.Join(destDir, "sigtest.txt")
data, err := os.ReadFile(outPath)
if err != nil {
t.Fatalf("expected extracted file at %s: %v", outPath, err)
}
if string(data) != fileContent {
t.Errorf("content mismatch: got %q, want %q", string(data), fileContent)
}
}