From 1a8109b6d6155d5cb2a72a65b4d49dcab6a13710 Mon Sep 17 00:00:00 2001 From: Shiwei Zhang Date: Wed, 14 Apr 2021 15:22:42 +0800 Subject: [PATCH 1/2] multiple signatures support Signed-off-by: Shiwei Zhang --- cmd/docker-nv2/config/path.go | 59 +++++++++++++++++++++++++++++++++-- cmd/docker-nv2/notary_sign.go | 3 +- cmd/docker-nv2/push.go | 39 +++++++++++++++-------- 3 files changed, 84 insertions(+), 17 deletions(-) diff --git a/cmd/docker-nv2/config/path.go b/cmd/docker-nv2/config/path.go index f94a16ce4..92a67a491 100644 --- a/cmd/docker-nv2/config/path.go +++ b/cmd/docker-nv2/config/path.go @@ -1,7 +1,9 @@ package config import ( + "os" "path/filepath" + "strings" "github.com/docker/cli/cli/config" "github.com/opencontainers/go-digest" @@ -25,11 +27,62 @@ var ( SignatureStoreDirPath = filepath.Join(config.Dir(), SignatureStoreDirName) ) -// SignaturePath returns the path of a signature for a manifest -func SignaturePath(manifestDigest digest.Digest) string { +// SignatureRootPath returns the root path of signatures for a manifest +func SignatureRootPath(manifestDigest digest.Digest) string { return filepath.Join( SignatureStoreDirPath, manifestDigest.Algorithm().String(), - manifestDigest.Encoded()+SignatureExtension, + manifestDigest.Encoded(), + ) +} + +// SignaturePath returns the path of a signature for a manifest +func SignaturePath(manifestDigest, signatureDigest digest.Digest) string { + return filepath.Join( + SignatureRootPath(manifestDigest), + signatureDigest.Algorithm().String(), + signatureDigest.Encoded()+SignatureExtension, ) } + +// SignatureDigests returns the digest of signatures for a manifest +func SignatureDigests(manifestDigest digest.Digest) ([]digest.Digest, error) { + rootPath := SignatureRootPath(manifestDigest) + algorithmEntries, err := os.ReadDir(rootPath) + if err != nil { + if os.IsNotExist(err) { + return nil, nil + } + return nil, err + } + + var digests []digest.Digest + for _, algorithmEntry := range algorithmEntries { + if !algorithmEntry.Type().IsDir() { + continue + } + + algorithm := algorithmEntry.Name() + signatureEntries, err := os.ReadDir(filepath.Join(rootPath, algorithm)) + if err != nil { + return nil, err + } + + for _, signatureEntry := range signatureEntries { + if !signatureEntry.Type().IsRegular() { + continue + } + encoded := signatureEntry.Name() + if !strings.HasSuffix(encoded, SignatureExtension) { + continue + } + encoded = strings.TrimSuffix(encoded, SignatureExtension) + digest := digest.NewDigestFromEncoded(digest.Algorithm(algorithm), encoded) + if err := digest.Validate(); err != nil { + return nil, err + } + digests = append(digests, digest) + } + } + return digests, nil +} diff --git a/cmd/docker-nv2/notary_sign.go b/cmd/docker-nv2/notary_sign.go index 31213ea76..2102eabe9 100644 --- a/cmd/docker-nv2/notary_sign.go +++ b/cmd/docker-nv2/notary_sign.go @@ -7,6 +7,7 @@ import ( "github.com/notaryproject/nv2/cmd/docker-nv2/crypto" "github.com/notaryproject/nv2/cmd/docker-nv2/docker" ios "github.com/notaryproject/nv2/internal/os" + "github.com/opencontainers/go-digest" "github.com/urfave/cli/v2" ) @@ -57,7 +58,7 @@ func notarySign(ctx *cli.Context) error { if err != nil { return err } - sigPath := config.SignaturePath(desc.Digest) + sigPath := config.SignaturePath(desc.Digest, digest.FromBytes(sig)) if err := ios.WriteFile(sigPath, sig); err != nil { return err } diff --git a/cmd/docker-nv2/push.go b/cmd/docker-nv2/push.go index ddbdd84e7..a62b48710 100644 --- a/cmd/docker-nv2/push.go +++ b/cmd/docker-nv2/push.go @@ -37,29 +37,42 @@ func pushImage(ctx *cli.Context) error { } fmt.Println("Pushing signature") - sigPath := config.SignaturePath(desc.Digest) - sig, err := ioutil.ReadFile(sigPath) + sigDigests, err := config.SignatureDigests(desc.Digest) if err != nil { - if os.IsNotExist(err) { - return errors.New("signature not found") - } return err } + if len(sigDigests) == 0 { + return errors.New("no signatures found") + } client, err := docker.GetSignatureRepository(ctx.Context, ctx.Args().First()) if err != nil { return err } - sigDesc, err := client.Put(ctx.Context, sig) - if err != nil { - return err - } + pushSignature := func(sigDigest digest.Digest) error { + sigPath := config.SignaturePath(desc.Digest, sigDigest) + sig, err := ioutil.ReadFile(sigPath) + if err != nil { + return err + } - artifactDesc, err := client.Link(ctx.Context, desc, sigDesc) - if err != nil { - return err + sigDesc, err := client.Put(ctx.Context, sig) + if err != nil { + return err + } + + artifactDesc, err := client.Link(ctx.Context, desc, sigDesc) + if err != nil { + return err + } + fmt.Println("signature manifest digest:", artifactDesc.Digest, "size:", artifactDesc.Size) + return nil + } + for _, sigDigest := range sigDigests { + if err := pushSignature(sigDigest); err != nil { + return err + } } - fmt.Println("signature manifest digest:", artifactDesc.Digest, "size:", artifactDesc.Size) return nil } From 37bdcd7d619371b6966740a24063168999537635 Mon Sep 17 00:00:00 2001 From: Shiwei Zhang Date: Thu, 15 Apr 2021 10:49:17 +0800 Subject: [PATCH 2/2] deprecate the use of ioutil Signed-off-by: Shiwei Zhang --- cmd/docker-nv2/push.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/docker-nv2/push.go b/cmd/docker-nv2/push.go index a62b48710..7d93038c9 100644 --- a/cmd/docker-nv2/push.go +++ b/cmd/docker-nv2/push.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "os/exec" "strconv" @@ -51,7 +50,7 @@ func pushImage(ctx *cli.Context) error { } pushSignature := func(sigDigest digest.Digest) error { sigPath := config.SignaturePath(desc.Digest, sigDigest) - sig, err := ioutil.ReadFile(sigPath) + sig, err := os.ReadFile(sigPath) if err != nil { return err }