Skip to content

Commit

Permalink
feat: Added notation certificate command for trust store (#405)
Browse files Browse the repository at this point in the history
This PR is the implementation of `notation certificate` command
regarding the use of trust store.
Based on community meeting, this command only effects on User level.

Signed-off-by: Patrick Zheng <patrickzheng@microsoft.com>
  • Loading branch information
Two-Hearts committed Oct 31, 2022
1 parent 8d1d4dc commit f0e77eb
Show file tree
Hide file tree
Showing 28 changed files with 968 additions and 346 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Notation is a CLI project to add signatures as standard items in the registry ec
export IMAGE=localhost:5000/net-monitor:v1
docker build -t $IMAGE https://github.com/wabbit-networks/net-monitor.git#main
docker push $IMAGE
notation cert generate-test --default --trust "wabbit-networks-dev"
notation cert generate-test --default "wabbit-networks-dev"
notation sign --plain-http $IMAGE
notation list --plain-http $IMAGE
notation verify --plain-http $IMAGE
Expand Down
202 changes: 0 additions & 202 deletions cmd/notation/cert.go

This file was deleted.

82 changes: 82 additions & 0 deletions cmd/notation/cert/add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package cert

import (
"errors"
"fmt"

"github.com/notaryproject/notation/cmd/notation/internal/truststore"
"github.com/spf13/cobra"
)

type certAddOpts struct {
storeType string
namedStore string
path []string
}

func certAddCommand(opts *certAddOpts) *cobra.Command {
if opts == nil {
opts = &certAddOpts{}
}
command := &cobra.Command{
Use: "add --type <type> --store <name> [flags] <cert_path>...",
Short: "Add certificates to the trust store.",
Args: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errors.New("missing certificate path")
}
opts.path = args
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
return addCerts(opts)
},
}
command.Flags().StringVarP(&opts.storeType, "type", "t", "", "specify trust store type, options: ca, signingAuthority")
command.Flags().StringVarP(&opts.namedStore, "store", "s", "", "specify named store")
return command
}

func addCerts(opts *certAddOpts) error {
storeType := opts.storeType
if storeType == "" {
return errors.New("store type cannot be empty")
}
if !truststore.IsValidStoreType(storeType) {
return fmt.Errorf("unsupported store type: %s", storeType)
}
namedStore := opts.namedStore
if !truststore.IsValidFileName(namedStore) {
return errors.New("named store name needs to follow [a-zA-Z0-9_.-]+ format")
}
var success []string
var failure []string
var errorSlice []error
for _, p := range opts.path {
err := truststore.AddCert(p, storeType, namedStore, false)
if err != nil {
failure = append(failure, p)
errorSlice = append(errorSlice, err)
} else {
success = append(success, p)
}
}

//write out
if len(success) != 0 {
fmt.Printf("Successfully added following certificates to named store %s of type %s:\n", namedStore, storeType)
for _, p := range success {
fmt.Println(p)
}
}
if len(failure) != 0 {
errStr := fmt.Sprintf("Failed to add following certificates to named store %s of type %s:\n", namedStore, storeType)

for ind := range failure {
errStr = errStr + fmt.Sprintf("%s, with error %q\n", failure[ind], errorSlice[ind])
}
return errors.New(errStr)
}

return nil
}
38 changes: 38 additions & 0 deletions cmd/notation/cert/add_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cert

import (
"reflect"
"testing"
)

func TestCertAddCommand(t *testing.T) {
opts := &certAddOpts{}
cmd := certAddCommand(opts)
expected := &certAddOpts{
storeType: "ca",
namedStore: "test",
path: []string{"path"},
}
if err := cmd.ParseFlags([]string{
"path",
"-t", "ca",
"-s", "test"}); err != nil {
t.Fatalf("Parse Flag failed: %v", err)
}
if err := cmd.Args(cmd, cmd.Flags().Args()); err != nil {
t.Fatalf("Parse Args failed: %v", err)
}
if !reflect.DeepEqual(*expected, *opts) {
t.Fatalf("Expect cert add opts: %v, got: %v", expected, opts)
}
}

func TestCertAddCommand_MissingArgs(t *testing.T) {
cmd := certAddCommand(nil)
if err := cmd.ParseFlags([]string{}); err != nil {
t.Fatalf("Parse Flag failed: %v", err)
}
if err := cmd.Args(cmd, cmd.Flags().Args()); err == nil {
t.Fatal("Parse Args expected error, but ok")
}
}
22 changes: 22 additions & 0 deletions cmd/notation/cert/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cert

import "github.com/spf13/cobra"

func Cmd() *cobra.Command {
command := &cobra.Command{
Use: "certificate",
Aliases: []string{"cert"},
Short: "Manage certificates in trust store",
Long: "Manage certificates in trust store for signature verification.",
}

command.AddCommand(
certAddCommand(nil),
certListCommand(nil),
certShowCommand(nil),
certDeleteCommand(nil),
certGenerateTestCommand(nil),
)

return command
}
Loading

0 comments on commit f0e77eb

Please sign in to comment.