diff --git a/CHANGELOG.md b/CHANGELOG.md index a8c14b43e33..8127e480e51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * BREAKING: Move `cosign upload-blob` to `cosign upload blob`. * BREAKING: Move `cosign upload` to `cosign attach signature`. +* BREAKING: Move `cosign download` to `cosign download signature`. ### Bug Fixes diff --git a/EXAMPLES.md b/EXAMPLES.md index 38f478ec507..ceca0552467 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -14,7 +14,7 @@ $ cat gcpkms.sig | base64 | cosign attach signature -signature - us-central1-doc Now (on another machine) download the public key, payload, signatures and verify it! ```shell -$ cosign download us-central1-docker.pkg.dev/dlorenc-vmtest2/test/taskrun > signatures.json +$ cosign download signature us-central1-docker.pkg.dev/dlorenc-vmtest2/test/taskrun > signatures.json # There could be multiple signatures, let's pretend it's the last one. # Extract the payload and signature, base64 decoding them. $ cat signatures.json | tail -1 | jq -r .Payload | base64 -D > payload diff --git a/USAGE.md b/USAGE.md index abda97b2d9f..f60db0a9a35 100644 --- a/USAGE.md +++ b/USAGE.md @@ -205,7 +205,7 @@ invalid or missing annotation in claim: map[sig:original] Each signature is printed to stdout in a json format: ``` -$ cosign download us-central1-docker.pkg.dev/dlorenc-vmtest2/test/taskrun +$ cosign download signature us-central1-docker.pkg.dev/dlorenc-vmtest2/test/taskrun {"Base64Signature":"Ejy6ipGJjUzMDoQFePWixqPBYF0iSnIvpMWps3mlcYNSEcRRZelL7GzimKXaMjxfhy5bshNGvDT5QoUJ0tqUAg==","Payload":"eyJDcml0aWNhbCI6eyJJZGVudGl0eSI6eyJkb2NrZXItcmVmZXJlbmNlIjoiIn0sIkltYWdlIjp7IkRvY2tlci1tYW5pZmVzdC1kaWdlc3QiOiI4N2VmNjBmNTU4YmFkNzliZWVhNjQyNWEzYjI4OTg5ZjAxZGQ0MTcxNjQxNTBhYjNiYWFiOThkY2JmMDRkZWY4In0sIlR5cGUiOiIifSwiT3B0aW9uYWwiOm51bGx9"} ``` diff --git a/cmd/cosign/cli/attach/sig.go b/cmd/cosign/cli/attach/sig.go index 1708ceccf66..62c632ee6e4 100644 --- a/cmd/cosign/cli/attach/sig.go +++ b/cmd/cosign/cli/attach/sig.go @@ -80,7 +80,7 @@ func SignatureCmd(ctx context.Context, sigRef, payloadRef, imageRef string) erro repo := ref.Context() img := repo.Digest(get.Digest.String()) - sigRepo, err := cli.SignatureRepositoryForImage(ref) + sigRepo, err := cli.TargetRepositoryForImage(ref) if err != nil { return err } diff --git a/cmd/cosign/cli/clean.go b/cmd/cosign/cli/clean.go index f40167eb986..f720ec09549 100644 --- a/cmd/cosign/cli/clean.go +++ b/cmd/cosign/cli/clean.go @@ -58,7 +58,7 @@ func CleanCmd(_ context.Context, imageRef string) error { return err } - sigRepo, err := SignatureRepositoryForImage(ref) + sigRepo, err := TargetRepositoryForImage(ref) if err != nil { return err } diff --git a/cmd/cosign/cli/copy.go b/cmd/cosign/cli/copy.go index 3aab021a2bb..61ab5106958 100644 --- a/cmd/cosign/cli/copy.go +++ b/cmd/cosign/cli/copy.go @@ -76,7 +76,7 @@ func CopyCmd(ctx context.Context, srcImg, dstImg string, sigOnly, force bool) er return err } - srcSigRepo, err := SignatureRepositoryForImage(srcRef) + srcSigRepo, err := TargetRepositoryForImage(srcRef) if err != nil { return err } diff --git a/cmd/cosign/cli/download/download.go b/cmd/cosign/cli/download/download.go new file mode 100644 index 00000000000..22ac495e85b --- /dev/null +++ b/cmd/cosign/cli/download/download.go @@ -0,0 +1,40 @@ +// +// 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 download + +import ( + "context" + "flag" + + "github.com/peterbourgon/ff/v3/ffcli" +) + +func Download() *ffcli.Command { + var ( + flagset = flag.NewFlagSet("cosign download", flag.ExitOnError) + ) + + return &ffcli.Command{ + Name: "download", + ShortUsage: "cosign download", + ShortHelp: "download contains tools to download artifacts and attached artifacts in a registry", + FlagSet: flagset, + Subcommands: []*ffcli.Command{Signature()}, + Exec: func(ctx context.Context, args []string) error { + return flag.ErrHelp + }, + } +} diff --git a/cmd/cosign/cli/download.go b/cmd/cosign/cli/download/signature.go similarity index 79% rename from cmd/cosign/cli/download.go rename to cmd/cosign/cli/download/signature.go index 4cffd82cc91..97a16d85a72 100644 --- a/cmd/cosign/cli/download.go +++ b/cmd/cosign/cli/download/signature.go @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package cli +package download import ( "context" @@ -25,34 +25,34 @@ import ( "github.com/google/go-containerregistry/pkg/name" "github.com/google/go-containerregistry/pkg/v1/remote" "github.com/peterbourgon/ff/v3/ffcli" - + "github.com/sigstore/cosign/cmd/cosign/cli" "github.com/sigstore/cosign/pkg/cosign" ) -func Download() *ffcli.Command { +func Signature() *ffcli.Command { var ( - flagset = flag.NewFlagSet("cosign download", flag.ExitOnError) + flagset = flag.NewFlagSet("cosign download signature", flag.ExitOnError) ) return &ffcli.Command{ - Name: "download", - ShortUsage: "cosign download ", + Name: "signature", + ShortUsage: "cosign download signature ", ShortHelp: "Download signatures from the supplied container image", FlagSet: flagset, Exec: func(ctx context.Context, args []string) error { if len(args) != 1 { return flag.ErrHelp } - return DownloadCmd(ctx, args[0]) + return SignatureCmd(ctx, args[0]) }, } } -func DownloadCmd(ctx context.Context, imageRef string) error { +func SignatureCmd(ctx context.Context, imageRef string) error { ref, err := name.ParseReference(imageRef) if err != nil { return err } - sigRepo, err := SignatureRepositoryForImage(ref) + sigRepo, err := cli.TargetRepositoryForImage(ref) if err != nil { return err } diff --git a/cmd/cosign/cli/sign.go b/cmd/cosign/cli/sign.go index afa6207e452..0e89a7efeab 100644 --- a/cmd/cosign/cli/sign.go +++ b/cmd/cosign/cli/sign.go @@ -308,7 +308,7 @@ func SignCmd(ctx context.Context, so SignOpts, continue } - sigRepo, err := SignatureRepositoryForImage(ref) + sigRepo, err := TargetRepositoryForImage(ref) if err != nil { return err } diff --git a/cmd/cosign/cli/triangulate.go b/cmd/cosign/cli/triangulate.go index 77ff76ca00c..73dd3d3c5df 100644 --- a/cmd/cosign/cli/triangulate.go +++ b/cmd/cosign/cli/triangulate.go @@ -58,7 +58,7 @@ func MungeCmd(_ context.Context, imageRef string) error { return err } - sigRepo, err := SignatureRepositoryForImage(ref) + sigRepo, err := TargetRepositoryForImage(ref) if err != nil { return err } diff --git a/cmd/cosign/cli/util.go b/cmd/cosign/cli/util.go index dd4392d246f..942ea23fb16 100644 --- a/cmd/cosign/cli/util.go +++ b/cmd/cosign/cli/util.go @@ -43,10 +43,10 @@ func TlogServer() string { return rekorServer } -func SignatureRepositoryForImage(signedImg name.Reference) (name.Repository, error) { +func TargetRepositoryForImage(img name.Reference) (name.Repository, error) { wantRepo := os.Getenv(repoEnv) if wantRepo == "" { - return signedImg.Context(), nil + return img.Context(), nil } return name.NewRepository(wantRepo) } diff --git a/cmd/cosign/cli/util_test.go b/cmd/cosign/cli/util_test.go index e74b252c93a..5d90550a7c9 100644 --- a/cmd/cosign/cli/util_test.go +++ b/cmd/cosign/cli/util_test.go @@ -21,7 +21,7 @@ import ( "github.com/google/go-containerregistry/pkg/name" ) -func TestSignatureRepositoryForImage(t *testing.T) { +func TestTargetRepositoryForImage(t *testing.T) { tests := []struct { desc string image name.Reference @@ -71,9 +71,9 @@ func TestSignatureRepositoryForImage(t *testing.T) { os.Setenv(repoEnv, test.envRepo) defer os.Unsetenv(repoEnv) - got, err := SignatureRepositoryForImage(test.image) + got, err := TargetRepositoryForImage(test.image) if err != nil { - t.Fatalf("SignatureRepositoryForImage returned error: %v", err) + t.Fatalf("TargetRepositoryForImage returned error: %v", err) } if got.Name() != test.want.Name() { t.Errorf("expected %s got %s", test.want, got.Name()) diff --git a/cmd/cosign/cli/verify.go b/cmd/cosign/cli/verify.go index 8b58d5c9848..b4f9ec42b87 100644 --- a/cmd/cosign/cli/verify.go +++ b/cmd/cosign/cli/verify.go @@ -129,7 +129,7 @@ func (c *VerifyCommand) Exec(ctx context.Context, args []string) error { if err != nil { return err } - sigRepo, err := SignatureRepositoryForImage(ref) + sigRepo, err := TargetRepositoryForImage(ref) if err != nil { return err } diff --git a/cmd/cosign/main.go b/cmd/cosign/main.go index a104b5e0326..7b28ed07411 100644 --- a/cmd/cosign/main.go +++ b/cmd/cosign/main.go @@ -27,6 +27,7 @@ import ( "github.com/sigstore/cosign/cmd/cosign/cli" "github.com/sigstore/cosign/cmd/cosign/cli/attach" + "github.com/sigstore/cosign/cmd/cosign/cli/download" "github.com/sigstore/cosign/cmd/cosign/cli/pivcli" "github.com/sigstore/cosign/cmd/cosign/cli/upload" ) @@ -48,12 +49,14 @@ func main() { cli.Verify(), cli.Sign(), cli.Generate(), cli.SignBlob(), cli.VerifyBlob(), // Upload sub-tree upload.Upload(), - // Upload sub-tree + // Download sub-tree + download.Download(), + // Attach sub-tree attach.Attach(), // PIV sub-tree pivcli.PivKey(), // PIV sub-tree - cli.Copy(), cli.Clean(), cli.Triangulate(), cli.Download(), + cli.Copy(), cli.Clean(), cli.Triangulate(), cli.Version()}, Exec: func(context.Context, []string) error { return flag.ErrHelp diff --git a/cmd/sget/cli/sget.go b/cmd/sget/cli/sget.go index 6bc7fee3321..400e907d616 100644 --- a/cmd/sget/cli/sget.go +++ b/cmd/sget/cli/sget.go @@ -56,7 +56,7 @@ func SgetCmd(ctx context.Context, imageRef, keyRef string) (io.ReadCloser, error } if co.PubKey != nil || cli.EnableExperimental() { - sigRepo, err := cli.SignatureRepositoryForImage(ref) + sigRepo, err := cli.TargetRepositoryForImage(ref) if err != nil { return nil, err } diff --git a/copasetic/main.go b/copasetic/main.go index cd93abd2a93..d1754d2da52 100644 --- a/copasetic/main.go +++ b/copasetic/main.go @@ -134,7 +134,7 @@ func main() { if err != nil { return nil, err } - sigRepo, err := cli.SignatureRepositoryForImage(ref) + sigRepo, err := cli.TargetRepositoryForImage(ref) if err != nil { return nil, err } @@ -176,7 +176,7 @@ func main() { if err != nil { return nil, err } - sigRepo, err := cli.SignatureRepositoryForImage(ref) + sigRepo, err := cli.TargetRepositoryForImage(ref) if err != nil { return nil, err } diff --git a/test/e2e_test.go b/test/e2e_test.go index dd0d9c8a31b..6d2e5ef9eb1 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -40,6 +40,7 @@ import ( "github.com/sigstore/cosign/cmd/cosign/cli" "github.com/sigstore/cosign/cmd/cosign/cli/attach" + "github.com/sigstore/cosign/cmd/cosign/cli/download" "github.com/sigstore/cosign/cmd/cosign/cli/upload" sget "github.com/sigstore/cosign/cmd/sget/cli" "github.com/sigstore/cosign/pkg/cosign" @@ -84,7 +85,7 @@ func TestSignVerify(t *testing.T) { // Verify should fail at first mustErr(verify(pubKeyPath, imgName, true, nil), t) // So should download - mustErr(cli.DownloadCmd(ctx, imgName), t) + mustErr(download.SignatureCmd(ctx, imgName), t) // Now sign the image so := cli.SignOpts{KeyRef: privKeyPath, Pf: passFunc} @@ -92,7 +93,7 @@ func TestSignVerify(t *testing.T) { // Now verify and download should work! must(verify(pubKeyPath, imgName, true, nil), t) - must(cli.DownloadCmd(ctx, imgName), t) + must(download.SignatureCmd(ctx, imgName), t) // Look for a specific annotation mustErr(verify(pubKeyPath, imgName, true, map[string]interface{}{"foo": "bar"}), t) @@ -127,7 +128,7 @@ func TestSignVerifyClean(t *testing.T) { // Now verify and download should work! must(verify(pubKeyPath, imgName, true, nil), t) - must(cli.DownloadCmd(ctx, imgName), t) + must(download.SignatureCmd(ctx, imgName), t) // Now clean signature from the given image must(cli.CleanCmd(ctx, imgName), t) @@ -186,7 +187,7 @@ func TestDuplicateSign(t *testing.T) { // Verify should fail at first mustErr(verify(pubKeyPath, imgName, true, nil), t) // So should download - mustErr(cli.DownloadCmd(ctx, imgName), t) + mustErr(download.SignatureCmd(ctx, imgName), t) // Now sign the image so := cli.SignOpts{KeyRef: privKeyPath, Pf: passFunc} @@ -194,12 +195,12 @@ func TestDuplicateSign(t *testing.T) { // Now verify and download should work! must(verify(pubKeyPath, imgName, true, nil), t) - must(cli.DownloadCmd(ctx, imgName), t) + must(download.SignatureCmd(ctx, imgName), t) // Signing again should work just fine... must(cli.SignCmd(ctx, so, imgName, true, "", false, false), t) // but a duplicate signature should not be a uploaded - sigRepo, err := cli.SignatureRepositoryForImage(ref) + sigRepo, err := cli.TargetRepositoryForImage(ref) if err != nil { t.Fatalf("failed to get signature repository: %v", err) } @@ -437,7 +438,7 @@ func TestUploadDownload(t *testing.T) { } // Now download it! - sigRepo, err := cli.SignatureRepositoryForImage(ref) + sigRepo, err := cli.TargetRepositoryForImage(ref) if err != nil { t.Fatalf("failed to get signature repository: %v", err) }