From 98904396726c07aea7f8770ab0b292b1ba224f92 Mon Sep 17 00:00:00 2001 From: hectorj2f Date: Fri, 27 Sep 2024 17:20:58 +0200 Subject: [PATCH] remove previously deprecated attach/download sbom commands Signed-off-by: hectorj2f --- cmd/cosign/cli/attach.go | 30 ------- cmd/cosign/cli/attach/sbom.go | 149 ---------------------------------- cmd/cosign/cli/download.go | 29 ------- doc/cosign_attach.md | 1 - doc/cosign_download.md | 1 - test/e2e_attach_test.go | 93 --------------------- test/e2e_test.go | 76 ----------------- 7 files changed, 379 deletions(-) delete mode 100644 cmd/cosign/cli/attach/sbom.go diff --git a/cmd/cosign/cli/attach.go b/cmd/cosign/cli/attach.go index f8c384f97ac9..bfe33125ba12 100644 --- a/cmd/cosign/cli/attach.go +++ b/cmd/cosign/cli/attach.go @@ -16,9 +16,6 @@ package cli import ( - "fmt" - "os" - "github.com/sigstore/cosign/v2/cmd/cosign/cli/attach" "github.com/sigstore/cosign/v2/cmd/cosign/cli/options" "github.com/spf13/cobra" @@ -32,7 +29,6 @@ func Attach() *cobra.Command { cmd.AddCommand( attachSignature(), - attachSBOM(), attachAttestation(), ) @@ -75,32 +71,6 @@ func attachSignature() *cobra.Command { return cmd } -func attachSBOM() *cobra.Command { - o := &options.AttachSBOMOptions{} - - cmd := &cobra.Command{ - Use: "sbom", - Short: "DEPRECATED: Attach sbom to the supplied container image", - Long: "Attach sbom to the supplied container image\n\n" + options.SBOMAttachmentDeprecation, - Example: " cosign attach sbom ", - Args: cobra.ExactArgs(1), - PersistentPreRun: options.BindViper, - RunE: func(cmd *cobra.Command, args []string) error { - fmt.Fprintln(os.Stderr, options.SBOMAttachmentDeprecation) - mediaType, err := o.MediaType() - if err != nil { - return err - } - fmt.Fprintf(os.Stderr, "WARNING: Attaching SBOMs this way does not sign them. To sign them, use 'cosign attest --predicate %s --key '.\n", o.SBOM) - return attach.SBOMCmd(cmd.Context(), o.Registry, o.RegistryExperimental, o.SBOM, mediaType, args[0]) - }, - } - - o.AddFlags(cmd) - - return cmd -} - func attachAttestation() *cobra.Command { o := &options.AttachAttestationOptions{} diff --git a/cmd/cosign/cli/attach/sbom.go b/cmd/cosign/cli/attach/sbom.go deleted file mode 100644 index df651197f636..000000000000 --- a/cmd/cosign/cli/attach/sbom.go +++ /dev/null @@ -1,149 +0,0 @@ -// -// Copyright 2021 The Sigstore Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package attach - -import ( - "context" - "errors" - "fmt" - "io" - "net/http" - "os" - "path/filepath" - - "github.com/google/go-containerregistry/pkg/logs" - "github.com/google/go-containerregistry/pkg/name" - v1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/google/go-containerregistry/pkg/v1/empty" - "github.com/google/go-containerregistry/pkg/v1/mutate" - "github.com/google/go-containerregistry/pkg/v1/remote" - "github.com/google/go-containerregistry/pkg/v1/remote/transport" - ocistatic "github.com/google/go-containerregistry/pkg/v1/static" - ocitypes "github.com/google/go-containerregistry/pkg/v1/types" - "github.com/sigstore/cosign/v2/cmd/cosign/cli/options" - ociexperimental "github.com/sigstore/cosign/v2/internal/pkg/oci/remote" - "github.com/sigstore/cosign/v2/internal/ui" - ociremote "github.com/sigstore/cosign/v2/pkg/oci/remote" - "github.com/sigstore/cosign/v2/pkg/oci/static" -) - -func SBOMCmd(ctx context.Context, regOpts options.RegistryOptions, regExpOpts options.RegistryExperimentalOptions, sbomRef string, sbomType ocitypes.MediaType, imageRef string) error { - if regExpOpts.RegistryReferrersMode == options.RegistryReferrersModeOCI11 { - return sbomCmdOCIExperimental(ctx, regOpts, sbomRef, sbomType, imageRef) - } - - ref, err := name.ParseReference(imageRef, regOpts.NameOptions()...) - if err != nil { - return err - } - - b, err := sbomBytes(sbomRef) - if err != nil { - return err - } - - remoteOpts, err := regOpts.ClientOpts(ctx) - if err != nil { - return err - } - - dstRef, err := ociremote.SBOMTag(ref, remoteOpts...) - if err != nil { - return err - } - - ui.Infof(ctx, "Uploading SBOM file for [%s] to [%s] with mediaType [%s].\n", ref.Name(), dstRef.Name(), sbomType) - img, err := static.NewFile(b, static.WithLayerMediaType(sbomType)) - if err != nil { - return err - } - return remote.Write(dstRef, img, regOpts.GetRegistryClientOpts(ctx)...) -} - -func sbomCmdOCIExperimental(ctx context.Context, regOpts options.RegistryOptions, sbomRef string, sbomType ocitypes.MediaType, imageRef string) error { - var dig name.Digest - ref, err := name.ParseReference(imageRef, regOpts.NameOptions()...) - if err != nil { - return err - } - if digr, ok := ref.(name.Digest); ok { - dig = digr - } else { - desc, err := remote.Head(ref, regOpts.GetRegistryClientOpts(ctx)...) - if err != nil { - return err - } - dig = ref.Context().Digest(desc.Digest.String()) - } - - artifactType := ociexperimental.ArtifactType("sbom") - - desc, err := remote.Head(dig, regOpts.GetRegistryClientOpts(ctx)...) - var terr *transport.Error - if errors.As(err, &terr) && terr.StatusCode == http.StatusNotFound { - h, err := v1.NewHash(dig.DigestStr()) - if err != nil { - return err - } - // The subject doesn't exist, attach to it as if it's an empty OCI image. - logs.Progress.Println("subject doesn't exist, attaching to empty image") - desc = &v1.Descriptor{ - ArtifactType: artifactType, - MediaType: ocitypes.OCIManifestSchema1, - Size: 0, - Digest: h, - } - } else if err != nil { - return err - } - - b, err := sbomBytes(sbomRef) - if err != nil { - return err - } - - empty := mutate.MediaType( - mutate.ConfigMediaType(empty.Image, ocitypes.MediaType(artifactType)), - ocitypes.OCIManifestSchema1) - att, err := mutate.AppendLayers(empty, ocistatic.NewLayer(b, sbomType)) - if err != nil { - return err - } - att = mutate.Subject(att, *desc).(v1.Image) - attdig, err := att.Digest() - if err != nil { - return err - } - dstRef := ref.Context().Digest(attdig.String()) - - fmt.Fprintf(os.Stderr, "Uploading SBOM file for [%s] to [%s] with config.mediaType [%s] layers[0].mediaType [%s].\n", - ref.Name(), dstRef.String(), artifactType, sbomType) - return remote.Write(dstRef, att, regOpts.GetRegistryClientOpts(ctx)...) -} - -func sbomBytes(sbomRef string) ([]byte, error) { - // sbomRef can be "-", a string or a file. - switch signatureType(sbomRef) { - case StdinSignature: - return io.ReadAll(os.Stdin) - case RawSignature: - return []byte(sbomRef), nil - case FileSignature: - return os.ReadFile(filepath.Clean(sbomRef)) - default: - return nil, errors.New("unknown SBOM arg type") - } -} diff --git a/cmd/cosign/cli/download.go b/cmd/cosign/cli/download.go index a9d082705a2e..29e89cb35046 100644 --- a/cmd/cosign/cli/download.go +++ b/cmd/cosign/cli/download.go @@ -16,9 +16,6 @@ package cli import ( - "fmt" - "os" - "github.com/spf13/cobra" "github.com/sigstore/cosign/v2/cmd/cosign/cli/download" @@ -33,7 +30,6 @@ func Download() *cobra.Command { cmd.AddCommand( downloadSignature(), - downloadSBOM(), downloadAttestation(), ) @@ -59,31 +55,6 @@ func downloadSignature() *cobra.Command { return cmd } -func downloadSBOM() *cobra.Command { - o := &options.RegistryOptions{} - do := &options.SBOMDownloadOptions{} - - cmd := &cobra.Command{ - Use: "sbom", - Short: "DEPRECATED: Download SBOMs from the supplied container image", - Long: "Download SBOMs from the supplied container image\n\n" + options.SBOMAttachmentDeprecation, - Example: " cosign download sbom ", - Args: cobra.ExactArgs(1), - PersistentPreRun: options.BindViper, - RunE: func(cmd *cobra.Command, args []string) error { - fmt.Fprintln(os.Stderr, options.SBOMAttachmentDeprecation) - fmt.Fprintln(os.Stderr, "WARNING: Downloading SBOMs this way does not ensure its authenticity. If you want to ensure a tamper-proof SBOM, download it using 'cosign download attestation '.") - _, err := download.SBOMCmd(cmd.Context(), *o, *do, args[0], cmd.OutOrStdout()) - return err - }, - } - - do.AddFlags(cmd) - o.AddFlags(cmd) - - return cmd -} - func downloadAttestation() *cobra.Command { o := &options.RegistryOptions{} ao := &options.AttestationDownloadOptions{} diff --git a/doc/cosign_attach.md b/doc/cosign_attach.md index 181dcb60bdf7..3899f7e5d8ca 100644 --- a/doc/cosign_attach.md +++ b/doc/cosign_attach.md @@ -20,6 +20,5 @@ Provides utilities for attaching artifacts to other artifacts in a registry * [cosign](cosign.md) - A tool for Container Signing, Verification and Storage in an OCI registry. * [cosign attach attestation](cosign_attach_attestation.md) - Attach attestation to the supplied container image -* [cosign attach sbom](cosign_attach_sbom.md) - DEPRECATED: Attach sbom to the supplied container image * [cosign attach signature](cosign_attach_signature.md) - Attach signatures to the supplied container image diff --git a/doc/cosign_download.md b/doc/cosign_download.md index 0700d1930231..84dcebb7103e 100644 --- a/doc/cosign_download.md +++ b/doc/cosign_download.md @@ -20,6 +20,5 @@ Provides utilities for downloading artifacts and attached artifacts in a registr * [cosign](cosign.md) - A tool for Container Signing, Verification and Storage in an OCI registry. * [cosign download attestation](cosign_download_attestation.md) - Download in-toto attestations from the supplied container image -* [cosign download sbom](cosign_download_sbom.md) - DEPRECATED: Download SBOMs from the supplied container image * [cosign download signature](cosign_download_signature.md) - Download signatures from the supplied container image diff --git a/test/e2e_attach_test.go b/test/e2e_attach_test.go index 7385da4f4a65..a551257ea489 100644 --- a/test/e2e_attach_test.go +++ b/test/e2e_attach_test.go @@ -39,7 +39,6 @@ import ( "github.com/google/go-containerregistry/pkg/name" "github.com/google/go-containerregistry/pkg/v1/types" "github.com/sigstore/cosign/v2/cmd/cosign/cli/attach" - "github.com/sigstore/cosign/v2/cmd/cosign/cli/download" "github.com/sigstore/cosign/v2/cmd/cosign/cli/generate" "github.com/sigstore/cosign/v2/cmd/cosign/cli/options" cliverify "github.com/sigstore/cosign/v2/cmd/cosign/cli/verify" @@ -402,95 +401,3 @@ func TestUploadDownload(t *testing.T) { }) } } - -func TestAttachSBOM_bom_flag(t *testing.T) { - repo, stop := reg(t) - defer stop() - td := t.TempDir() - ctx := context.Background() - bomData, err := os.ReadFile("./testdata/bom-go-mod.spdx") - must(err, t) - - testCases := map[string]struct { - bom string - bomType attach.SignatureArgType - expectedErr bool - }{ - "stdin containing bom": { - bom: string(bomData), - bomType: attach.StdinSignature, - expectedErr: false, - }, - "file containing bom": { - bom: string(bomData), - bomType: attach.FileSignature, - expectedErr: false, - }, - "raw bom as argument": { - bom: string(bomData), - bomType: attach.RawSignature, - expectedErr: true, - }, - "empty bom as argument": { - bom: "", - bomType: attach.RawSignature, - expectedErr: true, - }, - } - - for testName, testCase := range testCases { - t.Run(testName, func(t *testing.T) { - imgName := path.Join(repo, "sbom-image") - img, _, cleanup := mkimage(t, imgName) - var sbomRef string - restoreStdin := func() {} - switch { - case testCase.bomType == attach.FileSignature: - sbomRef = mkfile(testCase.bom, td, t) - case testCase.bomType == attach.StdinSignature: - sbomRef = "-" - restoreStdin = mockStdin(testCase.bom, td, t) - default: - sbomRef = testCase.bom - } - - out := bytes.Buffer{} - _, errPl := download.SBOMCmd(ctx, options.RegistryOptions{}, options.SBOMDownloadOptions{Platform: "darwin/amd64"}, img.Name(), &out) - if errPl == nil { - t.Fatalf("Expected error when passing Platform to single arch image") - } - _, err := download.SBOMCmd(ctx, options.RegistryOptions{}, options.SBOMDownloadOptions{}, img.Name(), &out) - if err == nil { - t.Fatal("Expected error") - } - t.Log(out.String()) - out.Reset() - - // Upload it! - err = attach.SBOMCmd(ctx, options.RegistryOptions{}, options.RegistryExperimentalOptions{}, sbomRef, "spdx", imgName) - restoreStdin() - - if testCase.expectedErr { - mustErr(err, t) - } else { - sboms, err := download.SBOMCmd(ctx, options.RegistryOptions{}, options.SBOMDownloadOptions{}, imgName, &out) - if err != nil { - t.Fatal(err) - } - t.Log(out.String()) - if len(sboms) != 1 { - t.Fatalf("Expected one sbom, got %d", len(sboms)) - } - want, err := os.ReadFile("./testdata/bom-go-mod.spdx") - if err != nil { - t.Fatal(err) - } - if diff := cmp.Diff(string(want), sboms[0]); diff != "" { - t.Errorf("diff: %s", diff) - } - } - - cleanup() - }) - } -} diff --git a/test/e2e_test.go b/test/e2e_test.go index 598d7faa5c0e..715482113852 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -38,7 +38,6 @@ import ( "testing" "time" - "github.com/google/go-cmp/cmp" "github.com/google/go-containerregistry/pkg/name" "github.com/google/go-containerregistry/pkg/v1/remote" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -2023,81 +2022,6 @@ func TestSaveLoadAttestation(t *testing.T) { must(verifyAttestation.Exec(ctx, []string{imageDir}), t) } -func TestAttachSBOM(t *testing.T) { - td := t.TempDir() - err := downloadAndSetEnv(t, rekorURL+"/api/v1/log/publicKey", env.VariableSigstoreRekorPublicKey.String(), td) - if err != nil { - t.Fatal(err) - } - - repo, stop := reg(t) - defer stop() - ctx := context.Background() - - imgName := path.Join(repo, "sbom-image") - img, _, cleanup := mkimage(t, imgName) - defer cleanup() - - out := bytes.Buffer{} - - _, errPl := download.SBOMCmd(ctx, options.RegistryOptions{}, options.SBOMDownloadOptions{Platform: "darwin/amd64"}, img.Name(), &out) - if errPl == nil { - t.Fatalf("Expected error when passing Platform to single arch image") - } - _, err = download.SBOMCmd(ctx, options.RegistryOptions{}, options.SBOMDownloadOptions{}, img.Name(), &out) - if err == nil { - t.Fatal("Expected error") - } - t.Log(out.String()) - out.Reset() - - // Upload it! - must(attach.SBOMCmd(ctx, options.RegistryOptions{}, options.RegistryExperimentalOptions{}, "./testdata/bom-go-mod.spdx", "spdx", imgName), t) - - sboms, err := download.SBOMCmd(ctx, options.RegistryOptions{}, options.SBOMDownloadOptions{}, imgName, &out) - if err != nil { - t.Fatal(err) - } - t.Log(out.String()) - if len(sboms) != 1 { - t.Fatalf("Expected one sbom, got %d", len(sboms)) - } - want, err := os.ReadFile("./testdata/bom-go-mod.spdx") - if err != nil { - t.Fatal(err) - } - if diff := cmp.Diff(string(want), sboms[0]); diff != "" { - t.Errorf("diff: %s", diff) - } - - // Generate key pairs to sign the sbom - td1 := t.TempDir() - td2 := t.TempDir() - _, privKeyPath1, pubKeyPath1 := keypair(t, td1) - _, _, pubKeyPath2 := keypair(t, td2) - - // Verify should fail on a bad input - mustErr(verify(pubKeyPath1, imgName, true, nil, "sbom", false), t) - mustErr(verify(pubKeyPath2, imgName, true, nil, "sbom", false), t) - - // Now sign the sbom with one key - ko1 := options.KeyOpts{ - KeyRef: privKeyPath1, - PassFunc: passFunc, - RekorURL: rekorURL, - } - so := options.SignOptions{ - Upload: true, - TlogUpload: true, - Attachment: "sbom", - } - must(sign.SignCmd(ro, ko1, so, []string{imgName}), t) - - // Now verify should work with that one, but not the other - must(verify(pubKeyPath1, imgName, true, nil, "sbom", false), t) - mustErr(verify(pubKeyPath2, imgName, true, nil, "sbom", false), t) -} - func TestNoTlog(t *testing.T) { repo, stop := reg(t) defer stop()