Skip to content

Commit

Permalink
update: updated CLI outputs of sign/verification (#450)
Browse files Browse the repository at this point in the history
Signed-off-by: Patrick Zheng <patrickzheng@microsoft.com>
  • Loading branch information
Two-Hearts authored Dec 5, 2022
1 parent 55e8b5b commit 767f8ae
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 71 deletions.
8 changes: 4 additions & 4 deletions cmd/notation/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"errors"
"fmt"

notationRegistry "github.com/notaryproject/notation-go/registry"
notationregistry "github.com/notaryproject/notation-go/registry"
"github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -50,7 +50,7 @@ func runList(command *cobra.Command, opts *listOpts) error {
}

// core process
manifestDesc, err := getManifestDescriptorFromReference(command.Context(), &opts.SecureFlagOpts, reference)
manifestDesc, _, err := getManifestDescriptor(command.Context(), &opts.SecureFlagOpts, reference)
if err != nil {
return err
}
Expand All @@ -61,7 +61,7 @@ func runList(command *cobra.Command, opts *listOpts) error {

// printSignatureManifestDigests returns the signature manifest digests of
// the subject manifest.
func printSignatureManifestDigests(ctx context.Context, manifestDigest digest.Digest, sigRepo notationRegistry.Repository, reference string) error {
func printSignatureManifestDigests(ctx context.Context, manifestDigest digest.Digest, sigRepo notationregistry.Repository, reference string) error {
// prepare title
ref, err := registry.ParseReference(reference)
if err != nil {
Expand All @@ -72,7 +72,7 @@ func printSignatureManifestDigests(ctx context.Context, manifestDigest digest.Di
printTitle := func() {
if !titlePrinted {
fmt.Println(ref)
fmt.Printf("└── %s\n", notationRegistry.ArtifactTypeNotation)
fmt.Printf("└── %s\n", notationregistry.ArtifactTypeNotation)
titlePrinted = true
}
}
Expand Down
27 changes: 16 additions & 11 deletions cmd/notation/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,27 @@ import (
"oras.land/oras-go/v2/registry"
)

func getManifestDescriptorFromContext(ctx context.Context, opts *SecureFlagOpts, ref string) (ocispec.Descriptor, error) {
if ref == "" {
return ocispec.Descriptor{}, errors.New("missing reference")
// getManifestDescriptor returns target artifact manifest descriptor and
// registry.Reference given user input reference.
func getManifestDescriptor(ctx context.Context, opts *SecureFlagOpts, reference string) (ocispec.Descriptor, registry.Reference, error) {
if reference == "" {
return ocispec.Descriptor{}, registry.Reference{}, errors.New("missing reference")
}

return getManifestDescriptorFromReference(ctx, opts, ref)
}

func getManifestDescriptorFromReference(ctx context.Context, opts *SecureFlagOpts, reference string) (ocispec.Descriptor, error) {
ref, err := registry.ParseReference(reference)
if err != nil {
return ocispec.Descriptor{}, err
return ocispec.Descriptor{}, registry.Reference{}, err
}
if ref.Reference == "" {
return ocispec.Descriptor{}, registry.Reference{}, errors.New("reference is missing digest or tag")
}
repo, err := getRepositoryClient(opts, ref)
if err != nil {
return ocispec.Descriptor{}, err
return ocispec.Descriptor{}, registry.Reference{}, err
}

manifestDesc, err := repo.Resolve(ctx, ref.Reference)
if err != nil {
return ocispec.Descriptor{}, registry.Reference{}, err
}
return repo.Resolve(ctx, ref.ReferenceOrDefault())
return manifestDesc, ref, nil
}
23 changes: 14 additions & 9 deletions cmd/notation/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/notaryproject/notation/internal/envelope"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
"oras.land/oras-go/v2/registry"
)

type signOpts struct {
Expand Down Expand Up @@ -74,7 +75,7 @@ func runSign(command *cobra.Command, cmdOpts *signOpts) error {
}

// core process
desc, opts, err := prepareSigningContent(command.Context(), cmdOpts)
opts, ref, err := prepareSigningContent(command.Context(), cmdOpts)
if err != nil {
return err
}
Expand All @@ -88,30 +89,34 @@ func runSign(command *cobra.Command, cmdOpts *signOpts) error {
}

// write out
fmt.Println(desc.Digest)
fmt.Println("Successfully signed", ref)
return nil
}

func prepareSigningContent(ctx context.Context, opts *signOpts) (ocispec.Descriptor, notation.SignOptions, error) {
manifestDesc, err := getManifestDescriptorFromContext(ctx, &opts.SecureFlagOpts, opts.reference)
func prepareSigningContent(ctx context.Context, opts *signOpts) (notation.SignOptions, registry.Reference, error) {
ref, err := resolveReference(ctx, &opts.SecureFlagOpts, opts.reference, func(ref registry.Reference, manifestDesc ocispec.Descriptor) {
fmt.Printf("Warning: Always sign the artifact using digest(`@sha256:...`) rather than a tag(`:%s`) because tags are mutable and a tag reference can point to a different artifact than the one signed.\n", ref.Reference)
fmt.Printf("Resolved artifact tag `%s` to digest `%s` before signing.\n", ref.Reference, manifestDesc.Digest.String())
})
if err != nil {
return ocispec.Descriptor{}, notation.SignOptions{}, err
return notation.SignOptions{}, registry.Reference{}, err
}

mediaType, err := envelope.GetEnvelopeMediaType(opts.SignerFlagOpts.SignatureFormat)
if err != nil {
return ocispec.Descriptor{}, notation.SignOptions{}, err
return notation.SignOptions{}, registry.Reference{}, err
}
pluginConfig, err := cmd.ParseFlagPluginConfig(opts.pluginConfig)
if err != nil {
return ocispec.Descriptor{}, notation.SignOptions{}, err
return notation.SignOptions{}, registry.Reference{}, err
}

signOpts := notation.SignOptions{
ArtifactReference: opts.reference,
ArtifactReference: ref.String(),
SignatureMediaType: mediaType,
ExpiryDuration: opts.expiry,
PluginConfig: pluginConfig,
}

return manifestDesc, signOpts, nil
return signOpts, ref, nil
}
66 changes: 37 additions & 29 deletions cmd/notation/verify.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package main

import (
"context"
"errors"
"fmt"
"math"
"os"
"strings"

"github.com/notaryproject/notation-go"
notationregistry "github.com/notaryproject/notation-go/registry"
"github.com/notaryproject/notation-go/verifier"
"github.com/notaryproject/notation/internal/cmd"
"github.com/notaryproject/notation/internal/ioutil"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"

"github.com/spf13/cobra"
"oras.land/oras-go/v2/registry"
Expand Down Expand Up @@ -57,13 +57,16 @@ Example - Verify a signature on an OCI artifact identified by a tag (Notation w
}

func runVerify(command *cobra.Command, opts *verifyOpts) error {
// resolve the given reference and set the digest.
ref, err := resolveReference(command, opts)
// resolve the given reference and set the digest
ref, err := resolveReference(command.Context(), &opts.SecureFlagOpts, opts.reference, func(ref registry.Reference, manifestDesc ocispec.Descriptor) {
fmt.Printf("Resolved artifact tag `%s` to digest `%s` before verification.\n", ref.Reference, manifestDesc.Digest.String())
fmt.Println("Warning: The resolved digest may not point to the same signed artifact, since tags are mutable.")
})
if err != nil {
return err
}

// initialize verifier.
// initialize verifier
verifier, err := verifier.NewFromConfig()
if err != nil {
return err
Expand All @@ -76,7 +79,7 @@ func runVerify(command *cobra.Command, opts *verifyOpts) error {
}
repo := notationregistry.NewRepository(&remoteRepo)

// set up verification plugin config.
// set up verification plugin config
configs, err := cmd.ParseFlagPluginConfig(opts.pluginConfig)
if err != nil {
return err
Expand All @@ -90,39 +93,44 @@ func runVerify(command *cobra.Command, opts *verifyOpts) error {
MaxSignatureAttempts: math.MaxInt64,
}

// core verify process.
// core verify process
_, outcomes, err := notation.Verify(command.Context(), verifier, repo, verifyOpts)

// write out.
return ioutil.PrintVerificationResults(os.Stdout, outcomes, err, ref.Reference)
// write out
// on failure
if err != nil || len(outcomes) == 0 {
return fmt.Errorf("signature verification failed for all the signatures associated with %s", ref.String())
}

// on success
outcome := outcomes[0]
// print out warning for any failed result with logged verification action
for _, result := range outcome.VerificationResults {
if result.Error != nil {
// at this point, the verification action has to be logged and
// it's failed
fmt.Printf("Warning: %v was set to \"logged\" and failed with error: %v\n", result.Type, result.Error)
}
}
fmt.Println("Successfully verified signature for", ref.String())
return nil
}

func resolveReference(command *cobra.Command, opts *verifyOpts) (registry.Reference, error) {
ref, err := registry.ParseReference(opts.reference)
func resolveReference(ctx context.Context, opts *SecureFlagOpts, reference string, fn func(registry.Reference, ocispec.Descriptor)) (registry.Reference, error) {
manifestDesc, ref, err := getManifestDescriptor(ctx, opts, reference)
if err != nil {
return registry.Reference{}, err
}

if isDigestReference(opts.reference) {
// reference is a digest reference
if err := ref.ValidateReferenceAsDigest(); err == nil {
return ref, nil
}

// Resolve tag reference to digest reference.
manifestDesc, err := getManifestDescriptorFromReference(command.Context(), &opts.SecureFlagOpts, opts.reference)
if err != nil {
return registry.Reference{}, err
}

// reference is a tag reference
fn(ref, manifestDesc)
// resolve tag to digest reference
ref.Reference = manifestDesc.Digest.String()
return ref, nil
}

func isDigestReference(reference string) bool {
parts := strings.SplitN(reference, "/", 2)
if len(parts) == 1 {
return false
}

index := strings.Index(parts[1], "@")
return index != -1
return ref, nil
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f
github.com/docker/docker-credential-helpers v0.7.0
github.com/notaryproject/notation-core-go v0.2.0-beta.1.0.20221123104522-9b5de089a023
github.com/notaryproject/notation-go v0.12.0-beta.1.0.20221202040523-bc022cc61d50
github.com/notaryproject/notation-go v0.12.0-beta.1.0.20221205052202-e9545a718368
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0-rc2
github.com/spf13/cobra v1.6.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/notaryproject/notation-core-go v0.2.0-beta.1.0.20221123104522-9b5de089a023 h1:Z/2hxPJOjWfmgOPTNkGBDp/LVIEtizd9uJNQvjFE0Dc=
github.com/notaryproject/notation-core-go v0.2.0-beta.1.0.20221123104522-9b5de089a023/go.mod h1:n8Gbvl9sKa00KptkKEL5XKUyMTIALe74QipKauE2rj4=
github.com/notaryproject/notation-go v0.12.0-beta.1.0.20221202040523-bc022cc61d50 h1:1i9PCRE6fLzYDxAE2HjDvXD1+U+5z25bWWwJOV2mk78=
github.com/notaryproject/notation-go v0.12.0-beta.1.0.20221202040523-bc022cc61d50/go.mod h1:2Xy40C9rJip3h9XPC6ei2HEEdUoZJ5KDC6mlX/FD0oQ=
github.com/notaryproject/notation-go v0.12.0-beta.1.0.20221205052202-e9545a718368 h1:OIrolpRY9PpFeWPtMPEOKNdYf+2TI13XY6gmmkJc+JY=
github.com/notaryproject/notation-go v0.12.0-beta.1.0.20221205052202-e9545a718368/go.mod h1:2Xy40C9rJip3h9XPC6ei2HEEdUoZJ5KDC6mlX/FD0oQ=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=
Expand Down
15 changes: 0 additions & 15 deletions internal/ioutil/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"io"
"text/tabwriter"

"github.com/notaryproject/notation-go"
"github.com/notaryproject/notation-go/config"
)

Expand Down Expand Up @@ -33,17 +32,3 @@ func PrintKeyMap(w io.Writer, target string, v []config.KeySuite) error {
}
return tw.Flush()
}

func PrintVerificationResults(w io.Writer, v []*notation.VerificationOutcome, resultErr error, digest string) error {
tw := newTabWriter(w)

if resultErr == nil {
fmt.Fprintf(tw, "Successfully verified for %s\n", digest)
// TODO[https://github.com/notaryproject/notation/issues/304]: print out failed validations as warnings.
return nil
}
fmt.Printf("Signature verification failed for all the signatures associated with digest: %s\n", digest)
tw.Flush()

return resultErr
}

0 comments on commit 767f8ae

Please sign in to comment.