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

Refactor signing options a bit between blob/image. #455

Merged
merged 1 commit into from
Jul 19, 2021
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
46 changes: 18 additions & 28 deletions cmd/cosign/cli/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,15 @@ EXAMPLES
return flag.ErrHelp
}

so := SignOpts{
KeyRef: *key,
Annotations: annotations.annotations,
Pf: GetPass,
Sk: *sk,
Slot: *slot,
IDToken: *idToken,
ko := KeyOpts{
KeyRef: *key,
PassFunc: GetPass,
Sk: *sk,
Slot: *slot,
IDToken: *idToken,
}
for _, img := range args {
if err := SignCmd(ctx, so, img, *cert, *upload, *payloadPath, *force, *recursive); err != nil {
if err := SignCmd(ctx, ko, annotations.annotations, img, *cert, *upload, *payloadPath, *force, *recursive); err != nil {
return errors.Wrapf(err, "signing %s", img)
}
}
Expand All @@ -149,15 +148,6 @@ EXAMPLES
}
}

type SignOpts struct {
Annotations map[string]interface{}
KeyRef string
Sk bool
Slot string
Pf cosign.PassFunc
IDToken string
}

func getTransitiveImages(rootIndex *remote.Descriptor, repo name.Repository, opts ...remote.Option) ([]name.Digest, error) {
var imgs []name.Digest

Expand Down Expand Up @@ -193,16 +183,16 @@ func getTransitiveImages(rootIndex *remote.Descriptor, repo name.Repository, opt
return imgs, nil
}

func SignCmd(ctx context.Context, so SignOpts,
func SignCmd(ctx context.Context, ko KeyOpts, annotations map[string]interface{},
imageRef string, certPath string, upload bool, payloadPath string, force bool, recursive bool) error {

// A key file or token is required unless we're in experimental mode!
if EnableExperimental() {
if nOf(so.KeyRef, so.Sk) > 1 {
if nOf(ko.KeyRef, ko.Sk) > 1 {
return &KeyParseError{}
}
} else {
if !oneOf(so.KeyRef, so.Sk) {
if !oneOf(ko.KeyRef, ko.Sk) {
return &KeyParseError{}
}
}
Expand Down Expand Up @@ -238,8 +228,8 @@ func SignCmd(ctx context.Context, so SignOpts,
var dupeDetector signature.Verifier
var cert, chain string
switch {
case so.Sk:
sk, err := pivkey.GetKeyWithSlot(so.Slot)
case ko.Sk:
sk, err := pivkey.GetKeyWithSlot(ko.Slot)
defer sk.Close()
if err != nil {
return err
Expand All @@ -262,8 +252,8 @@ func SignCmd(ctx context.Context, so SignOpts,
}
cert = string(cosign.CertToPem(certFromPIV))

case so.KeyRef != "":
k, err := signerVerifierFromKeyRef(ctx, so.KeyRef, so.Pf)
case ko.KeyRef != "":
k, err := signerVerifierFromKeyRef(ctx, ko.KeyRef, ko.PassFunc)
if err != nil {
return errors.Wrap(err, "reading key")
}
Expand Down Expand Up @@ -310,7 +300,7 @@ func SignCmd(ctx context.Context, so SignOpts,

default: // Keyless!
fmt.Fprintln(os.Stderr, "Generating ephemeral keys...")
k, err := fulcio.NewSigner(ctx, so.IDToken)
k, err := fulcio.NewSigner(ctx, ko.IDToken)
if err != nil {
return errors.Wrap(err, "getting key from Fulcio")
}
Expand Down Expand Up @@ -366,7 +356,7 @@ func SignCmd(ctx context.Context, so SignOpts,
if len(payload) == 0 {
payload, err = (&sigPayload.Cosign{
Image: img,
Annotations: so.Annotations,
Annotations: annotations,
}).MarshalJSON()
if err != nil {
return errors.Wrap(err, "payload")
Expand Down Expand Up @@ -416,7 +406,7 @@ func SignCmd(ctx context.Context, so SignOpts,
fmt.Println("tlog entry created with index: ", *entry.LogIndex)

uo.Bundle = bundle(entry)
uo.AdditionalAnnotations = annotations(entry)
uo.AdditionalAnnotations = parseAnnotations(entry)
}

fmt.Fprintln(os.Stderr, "Pushing signature to:", sigRef.String())
Expand All @@ -443,7 +433,7 @@ func bundle(entry *models.LogEntryAnon) *cremote.Bundle {
}
}

func annotations(entry *models.LogEntryAnon) map[string]string {
func parseAnnotations(entry *models.LogEntryAnon) map[string]string {
annts := map[string]string{}
if bund := bundle(entry); bund != nil {
contents, _ := json.Marshal(bund)
Expand Down
24 changes: 14 additions & 10 deletions cmd/cosign/cli/sign_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,14 @@ EXAMPLES
return flag.ErrHelp
}
ko := KeyOpts{
KeyRef: *key,
Sk: *sk,
Slot: *slot,
KeyRef: *key,
Sk: *sk,
Slot: *slot,
PassFunc: GetPass,
IDToken: *idToken,
}
for _, blob := range args {
if _, err := SignBlobCmd(ctx, ko, blob, *b64, GetPass, *idToken, *output); err != nil {
if _, err := SignBlobCmd(ctx, ko, blob, *b64, *output); err != nil {
return errors.Wrapf(err, "signing %s", blob)
}
}
Expand All @@ -99,12 +101,14 @@ EXAMPLES
}

type KeyOpts struct {
Sk bool
Slot string
KeyRef string
Sk bool
Slot string
KeyRef string
IDToken string
PassFunc cosign.PassFunc
}

func SignBlobCmd(ctx context.Context, ko KeyOpts, payloadPath string, b64 bool, pf cosign.PassFunc, idToken, output string) ([]byte, error) {
func SignBlobCmd(ctx context.Context, ko KeyOpts, payloadPath string, b64 bool, output string) ([]byte, error) {
var payload []byte
var err error
if payloadPath == "-" {
Expand All @@ -121,7 +125,7 @@ func SignBlobCmd(ctx context.Context, ko KeyOpts, payloadPath string, b64 bool,
var signer signature.Signer
switch {
case ko.KeyRef != "":
k, err := signerFromKeyRef(ctx, ko.KeyRef, pf)
k, err := signerFromKeyRef(ctx, ko.KeyRef, ko.PassFunc)
if err != nil {
return nil, errors.Wrap(err, "loading key")
}
Expand All @@ -140,7 +144,7 @@ func SignBlobCmd(ctx context.Context, ko KeyOpts, payloadPath string, b64 bool,
default:
// Keyless!
fmt.Fprintln(os.Stderr, "Generating ephemeral keys...")
k, err := fulcio.NewSigner(ctx, idToken)
k, err := fulcio.NewSigner(ctx, ko.IDToken)
if err != nil {
return nil, errors.Wrap(err, "getting key from Fulcio")
}
Expand Down
10 changes: 5 additions & 5 deletions cmd/cosign/cli/sign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ import (
func TestSignCmdLocalKeyAndSk(t *testing.T) {
ctx := context.Background()

for _, so := range []SignOpts{
for _, ko := range []KeyOpts{
// local and sk keys
{
KeyRef: "testLocalPath",
Pf: GetPass,
Sk: true,
KeyRef: "testLocalPath",
PassFunc: GetPass,
Sk: true,
},
} {
err := SignCmd(ctx, so, "", "", false, "", false, false)
err := SignCmd(ctx, ko, nil, "", "", false, "", false, false)
if (errors.Is(err, &KeyParseError{}) == false) {
t.Fatal("expected KeyParseError")
}
Expand Down
50 changes: 27 additions & 23 deletions test/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ func TestSignVerify(t *testing.T) {
mustErr(download.SignatureCmd(ctx, imgName), t)

// Now sign the image
so := cli.SignOpts{KeyRef: privKeyPath, Pf: passFunc}
must(cli.SignCmd(ctx, so, imgName, "", true, "", false, false), t)
ko := cli.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc}
must(cli.SignCmd(ctx, ko, nil, imgName, "", true, "", false, false), t)

// Now verify and download should work!
must(verify(pubKeyPath, imgName, true, nil), t)
Expand All @@ -99,8 +99,8 @@ func TestSignVerify(t *testing.T) {
mustErr(verify(pubKeyPath, imgName, true, map[string]interface{}{"foo": "bar"}), t)

// Sign the image with an annotation
so.Annotations = map[string]interface{}{"foo": "bar"}
must(cli.SignCmd(ctx, so, imgName, "", true, "", false, false), t)
annotations := map[string]interface{}{"foo": "bar"}
must(cli.SignCmd(ctx, ko, annotations, imgName, "", true, "", false, false), t)

// It should match this time.
must(verify(pubKeyPath, imgName, true, map[string]interface{}{"foo": "bar"}), t)
Expand All @@ -123,8 +123,8 @@ func TestSignVerifyClean(t *testing.T) {
ctx := context.Background()

// Now sign the image
so := cli.SignOpts{KeyRef: privKeyPath, Pf: passFunc}
must(cli.SignCmd(ctx, so, imgName, "", true, "", false, false), t)
ko := cli.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc}
must(cli.SignCmd(ctx, ko, nil, imgName, "", true, "", false, false), t)

// Now verify and download should work!
must(verify(pubKeyPath, imgName, true, nil), t)
Expand Down Expand Up @@ -156,13 +156,13 @@ func TestBundle(t *testing.T) {

ctx := context.Background()

so := cli.SignOpts{
KeyRef: privKeyPath,
Pf: passFunc,
ko := cli.KeyOpts{
KeyRef: privKeyPath,
PassFunc: passFunc,
}

// Sign the image
must(cli.SignCmd(ctx, so, imgName, "", true, "", false, false), t)
must(cli.SignCmd(ctx, ko, nil, imgName, "", true, "", false, false), t)
// Make sure verify works
must(verify(pubKeyPath, imgName, true, nil), t)

Expand Down Expand Up @@ -190,15 +190,15 @@ func TestDuplicateSign(t *testing.T) {
mustErr(download.SignatureCmd(ctx, imgName), t)

// Now sign the image
so := cli.SignOpts{KeyRef: privKeyPath, Pf: passFunc}
must(cli.SignCmd(ctx, so, imgName, "", true, "", false, false), t)
ko := cli.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc}
must(cli.SignCmd(ctx, ko, nil, imgName, "", true, "", false, false), t)

// Now verify and download should work!
must(verify(pubKeyPath, imgName, true, nil), t)
must(download.SignatureCmd(ctx, imgName), t)

// Signing again should work just fine...
must(cli.SignCmd(ctx, so, imgName, "", true, "", false, false), t)
must(cli.SignCmd(ctx, ko, nil, imgName, "", true, "", false, false), t)
// but a duplicate signature should not be a uploaded
sigRepo, err := cli.TargetRepositoryForImage(ref)
if err != nil {
Expand Down Expand Up @@ -291,15 +291,15 @@ func TestMultipleSignatures(t *testing.T) {
mustErr(verify(pub2, imgName, true, nil), t)

// Now sign the image with one key
so := cli.SignOpts{KeyRef: priv1, Pf: passFunc}
must(cli.SignCmd(ctx, so, imgName, "", true, "", false, false), t)
ko := cli.KeyOpts{KeyRef: priv1, PassFunc: passFunc}
must(cli.SignCmd(ctx, ko, nil, imgName, "", true, "", false, false), t)
// Now verify should work with that one, but not the other
must(verify(pub1, imgName, true, nil), t)
mustErr(verify(pub2, imgName, true, nil), t)

// Now sign with the other key too
so.KeyRef = priv2
must(cli.SignCmd(ctx, so, imgName, "", true, "", false, false), t)
ko.KeyRef = priv2
must(cli.SignCmd(ctx, ko, nil, imgName, "", true, "", false, false), t)

// Now verify should work with both
must(verify(pub1, imgName, true, nil), t)
Expand Down Expand Up @@ -337,7 +337,11 @@ func TestSignBlob(t *testing.T) {
mustErr(cli.VerifyBlobCmd(ctx, ko2, "", "badsig", blob), t)

// Now sign the blob with one key
sig, err := cli.SignBlobCmd(ctx, cli.KeyOpts{KeyRef: privKeyPath1}, bp, true, passFunc, "", "")
ko := cli.KeyOpts{
KeyRef: privKeyPath1,
PassFunc: passFunc,
}
sig, err := cli.SignBlobCmd(ctx, ko, bp, true, "")
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -591,11 +595,11 @@ func TestTlog(t *testing.T) {
mustErr(verify(pubKeyPath, imgName, true, nil), t)

// Now sign the image without the tlog
so := cli.SignOpts{
KeyRef: privKeyPath,
Pf: passFunc,
ko := cli.KeyOpts{
KeyRef: privKeyPath,
PassFunc: passFunc,
}
must(cli.SignCmd(ctx, so, imgName, "", true, "", false, false), t)
must(cli.SignCmd(ctx, ko, nil, imgName, "", true, "", false, false), t)

// Now verify should work!
must(verify(pubKeyPath, imgName, true, nil), t)
Expand All @@ -607,7 +611,7 @@ func TestTlog(t *testing.T) {
mustErr(verify(pubKeyPath, imgName, true, nil), t)

// Sign again with the tlog env var on
must(cli.SignCmd(ctx, so, imgName, "", true, "", false, false), t)
must(cli.SignCmd(ctx, ko, nil, imgName, "", true, "", false, false), t)
// And now verify works!
must(verify(pubKeyPath, imgName, true, nil), t)
}
Expand Down