Skip to content

Commit

Permalink
Revert "feat: add support for json output for notation verify (nota…
Browse files Browse the repository at this point in the history
…ryproject#527)"

This reverts commit 33c2281.

Signed-off-by: Pritesh Bandi <pritesb@amazon.com>
  • Loading branch information
Pritesh Bandi committed Feb 15, 2023
1 parent c47a452 commit 93e91fc
Show file tree
Hide file tree
Showing 6 changed files with 17 additions and 139 deletions.
52 changes: 13 additions & 39 deletions cmd/notation/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@ type verifyOpts struct {
reference string
pluginConfig []string
userMetadata []string
outputFormat string
}

type verifyOutput struct {
Reference string `json:"reference"`
UserMetadata map[string]string `json:"userMetadata,omitempty"`
Result string `json:"result"`
}

func verifyCommand(opts *verifyOpts) *cobra.Command {
Expand All @@ -59,19 +52,14 @@ Example - Verify a signature on an OCI artifact identified by a tag (Notation w
opts.reference = args[0]
return nil
},
RunE: func(cmnd *cobra.Command, args []string) error {
if opts.outputFormat != cmd.OutputJson && opts.outputFormat != cmd.OutputPlaintext {
return fmt.Errorf("unrecognized output format: %v", opts.outputFormat)
}

return runVerify(cmnd, opts)
RunE: func(cmd *cobra.Command, args []string) error {
return runVerify(cmd, opts)
},
}
opts.LoggingFlagOpts.ApplyFlags(command.Flags())
opts.SecureFlagOpts.ApplyFlags(command.Flags())
command.Flags().StringArrayVar(&opts.pluginConfig, "plugin-config", nil, "{key}={value} pairs that are passed as it is to a plugin, if the verification is associated with a verification plugin, refer plugin documentation to set appropriate values")
cmd.SetPflagUserMetadata(command.Flags(), &opts.userMetadata, cmd.PflagUserMetadataVerifyUsage)
cmd.SetPflagOutput(command.Flags(), &opts.outputFormat, cmd.PflagOutputUsage)
return command
}

Expand Down Expand Up @@ -144,8 +132,13 @@ func runVerify(command *cobra.Command, opts *verifyOpts) error {
fmt.Fprintf(os.Stderr, "Warning: %v was set to %q and failed with error: %v\n", result.Type, result.Action, result.Error)
}
}

return printResult(opts.outputFormat, ref.String(), outcome)
if reflect.DeepEqual(outcome.VerificationLevel, trustpolicy.LevelSkip) {
fmt.Println("Trust policy is configured to skip signature verification for", ref.String())
} else {
fmt.Println("Successfully verified signature for", ref.String())
printMetadataIfPresent(outcome)
}
return nil
}

func resolveReference(ctx context.Context, opts *SecureFlagOpts, reference string, sigRepo notationregistry.Repository, fn func(registry.Reference, ocispec.Descriptor)) (registry.Reference, error) {
Expand All @@ -167,33 +160,14 @@ func resolveReference(ctx context.Context, opts *SecureFlagOpts, reference strin
return ref, nil
}

func printResult(outputFormat, reference string, outcome *notation.VerificationOutcome) error {
if reflect.DeepEqual(outcome.VerificationLevel, trustpolicy.LevelSkip) {
switch outputFormat {
case cmd.OutputJson:
output := verifyOutput{Reference: reference, Result: "SkippedByTrustPolicy", UserMetadata: map[string]string{}}
return ioutil.PrintObjectAsJSON(output)
default:
fmt.Println("Trust policy is configured to skip signature verification for", reference)
return nil
}
}

func printMetadataIfPresent(outcome *notation.VerificationOutcome) {
// the signature envelope is parsed as part of verification.
// since user metadata is only printed on successful verification,
// this error can be ignored
metadata, _ := outcome.UserMetadata()

switch outputFormat {
case cmd.OutputJson:
output := verifyOutput{Reference: reference, Result: "Success", UserMetadata: metadata}
return ioutil.PrintObjectAsJSON(output)
default:
fmt.Println("Successfully verified signature for", reference)
if len(metadata) > 0 {
fmt.Println("\nThe artifact was signed with the following user metadata.")
ioutil.PrintMetadataMap(os.Stdout, metadata)
}
return nil
if len(metadata) > 0 {
fmt.Println("\nThe artifact was signed with the following user metadata.")
ioutil.PrintMetadataMap(os.Stdout, metadata)
}
}
7 changes: 1 addition & 6 deletions cmd/notation/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package main
import (
"reflect"
"testing"

"github.com/notaryproject/notation/internal/cmd"
)

func TestVerifyCommand_BasicArgs(t *testing.T) {
Expand All @@ -17,7 +15,6 @@ func TestVerifyCommand_BasicArgs(t *testing.T) {
Password: "password",
},
pluginConfig: []string{"key1=val1"},
outputFormat: cmd.OutputPlaintext,
}
if err := command.ParseFlags([]string{
expected.reference,
Expand All @@ -43,14 +40,12 @@ func TestVerifyCommand_MoreArgs(t *testing.T) {
PlainHTTP: true,
},
pluginConfig: []string{"key1=val1", "key2=val2"},
outputFormat: cmd.OutputJson,
}
if err := command.ParseFlags([]string{
expected.reference,
"--plain-http",
"--plugin-config", "key1=val1",
"--plugin-config", "key2=val2",
"--output", "json"}); err != nil {
"--plugin-config", "key2=val2"}); err != nil {
t.Fatalf("Parse Flag failed: %v", err)
}
if err := command.Args(command, command.Flags().Args()); err != nil {
Expand Down
15 changes: 1 addition & 14 deletions internal/cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ import (
"github.com/spf13/pflag"
)

const (
OutputPlaintext = "text"
OutputJson = "json"
)

var (
PflagKey = &pflag.Flag{
Name: "key",
Expand Down Expand Up @@ -80,20 +75,12 @@ var (
Name: "user-metadata",
Shorthand: "m",
}

PflagUserMetadataSignUsage = "{key}={value} pairs that are added to the signature payload"
PflagUserMetadataVerifyUsage = "user defined {key}={value} pairs that must be present in the signature for successful verification if provided"
SetPflagUserMetadata = func(fs *pflag.FlagSet, p *[]string, usage string) {
fs.StringArrayVarP(p, PflagUserMetadata.Name, PflagUserMetadata.Shorthand, nil, usage)
}

PflagOutput = &pflag.Flag{
Name: "output",
Shorthand: "o",
}
PflagOutputUsage = fmt.Sprintf("output format, options: '%s', '%s'", OutputJson, OutputPlaintext)
SetPflagOutput = func(fs *pflag.FlagSet, p *string, usage string) {
fs.StringVarP(p, PflagOutput.Name, PflagOutput.Shorthand, OutputPlaintext, usage)
}
)

// KeyValueSlice is a flag with type int
Expand Down
16 changes: 1 addition & 15 deletions internal/ioutil/print.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package ioutil

import (
"encoding/json"
"fmt"
"io"
"text/tabwriter"
Expand Down Expand Up @@ -34,7 +33,6 @@ func PrintKeyMap(w io.Writer, target *string, v []config.KeySuite) error {
return tw.Flush()
}

// PrintMetadataMap prints a map to a given Writer as a table
func PrintMetadataMap(w io.Writer, metadata map[string]string) error {
tw := newTabWriter(w)
fmt.Fprintln(tw, "\nKEY\tVALUE\t")
Expand All @@ -44,16 +42,4 @@ func PrintMetadataMap(w io.Writer, metadata map[string]string) error {
}

return tw.Flush()
}

// PrintObjectAsJSON takes an interface and prints it as an indented JSON string
func PrintObjectAsJSON(i interface{}) error {
jsonBytes, err := json.MarshalIndent(i, "", " ")
if err != nil {
return err
}

fmt.Println(string(jsonBytes))

return nil
}
}
25 changes: 1 addition & 24 deletions specs/commandline/verify.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,11 @@ Usage:
Flags:
-d, --debug debug mode
-h, --help help for verify
-o, --output string output format, options: 'json', 'text' (default "text")
-p, --password string password for registry operations (default to $NOTATION_PASSWORD if not specified)
--plain-http registry access via plain HTTP
--plugin-config stringArray {key}={value} pairs that are passed as it is to a plugin, if the verification is associated with a verification plugin, refer plugin documentation to set appropriate values
-m, --user-metadata stringArray user defined {key}={value} pairs that must be present in the signature for successful verification if provided
-u, --username string username for registry operations (default to $NOTATION_USERNAME if not specified)
-m, --user-metadata stringArray user defined {key}={value} pairs that must be present in the signature for successful verification if provided
-v, --verbose verbose mode
```

Expand Down Expand Up @@ -169,25 +168,3 @@ An example of output messages for a successful verification:
Warning: Always verify the artifact using digest(@sha256:...) rather than a tag(:v1) because resolved digest may not point to the same signed artifact, as tags are mutable.
Successfully verified signature for localhost:5000/net-monitor@sha256:b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
```

### Verify signatures on an OCI artifact with json output

Use the `--output` flag to format successful verification output in json.

```shell
notation verify --output json localhost:5000/net-monitor@sha256:b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
```

An example of output messages for a successful verification:

```text
{
"reference": "localhost:5000/net-monitor@sha256:b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
"userMetadata": {
"io.wabbit-networks.buildId": "123"
},
"result": "Success"
}
```

On unsuccessful verification, nothing is written to `stdout`, and the failure is logged to `stderr`.
41 changes: 0 additions & 41 deletions test/e2e/suite/command/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,45 +49,4 @@ var _ = Describe("notation verify", func() {
MatchKeyWords(VerifySuccessfully)
})
})

It("with added user metadata", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.Exec("sign", artifact.ReferenceWithDigest(), "--user-metadata", "io.wabbit-networks.buildId=123").
MatchKeyWords(SignSuccessfully)

notation.Exec("verify", artifact.ReferenceWithTag()).
MatchKeyWords(
VerifySuccessfully,
"KEY",
"VALUE",
"io.wabbit-networks.buildId",
"123",
)

notation.Exec("verify", artifact.ReferenceWithDigest(), "--user-metadata", "io.wabbit-networks.buildId=123").
MatchKeyWords(
VerifySuccessfully,
"KEY",
"VALUE",
"io.wabbit-networks.buildId",
"123",
)

notation.ExpectFailure().Exec("verify", artifact.ReferenceWithDigest(), "--user-metadata", "io.wabbit-networks.buildId=321").
MatchErrKeyWords("unable to find specified metadata in the signature")
})
})

It("with json output", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.Exec("sign", artifact.ReferenceWithDigest(), "--user-metadata", "io.wabbit-networks.buildId=123").
MatchKeyWords(SignSuccessfully)

notation.Exec("verify", artifact.ReferenceWithDigest(), "--output", "json").
MatchContent(fmt.Sprintf("{\n \"reference\": \"%s\",\n \"userMetadata\": {\n \"io.wabbit-networks.buildId\": \"123\"\n },\n \"result\": \"Success\"\n}\n", artifact.ReferenceWithDigest()))

notation.ExpectFailure().Exec("verify", artifact.ReferenceWithDigest(), "--user-metadata", "io.wabbit-networks.buildId=321").
MatchErrKeyWords("unable to find specified metadata in the signature")
})
})
})

0 comments on commit 93e91fc

Please sign in to comment.