Skip to content

Commit

Permalink
Adding blob sign command
Browse files Browse the repository at this point in the history
Signed-off-by: Rishab Semlani <[email protected]>
  • Loading branch information
rrsemlani committed Mar 26, 2024
1 parent a0fff85 commit 440cfd1
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 248 deletions.
29 changes: 29 additions & 0 deletions cmd/notation/blob/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright The Notary Project Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package blob

import "github.com/spf13/cobra"

func Cmd() *cobra.Command {
command := &cobra.Command{
Use: "blob [command]",
Short: "Commands for BLOB artifacts",
}

command.AddCommand(
signCommand(nil),
)

return command
}
119 changes: 15 additions & 104 deletions cmd/notation/blob.go → cmd/notation/blob/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,43 +11,33 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package main
package blob

//Verify this
import (
"context"
"errors"
"fmt"
"github.com/notaryproject/notation-core-go/signature"
"github.com/notaryproject/notation-go"
"github.com/notaryproject/notation-go/plugin/proto"
"github.com/notaryproject/notation-go/registry"
"github.com/notaryproject/notation/internal/cmd"
"github.com/notaryproject/notation/internal/envelope"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
"os"
"strings"
"time"
)

type blobOpts struct {
type blobSignOpts struct {
cmd.LoggingFlagOpts
cmd.SignerFlagOpts
SecureFlagOpts
expiry time.Duration
desc ocispec.Descriptor
sigRepo registry.Repository
pluginConfig []string
userMetadata []string
blobPath string
signaturePath string
outputFormat string
expiry time.Duration
pluginConfig []string
userMetadata []string
blobPath string
signatureDirectory string
force bool
}

func blobSignCommand(opts *blobOpts) *cobra.Command {
func signCommand(opts *blobSignOpts) *cobra.Command {
if opts == nil {
opts = &blobOpts{}
opts = &blobSignOpts{}
}
longMessage := `Sign BLOB artifacts
Expand All @@ -57,7 +47,7 @@ Example - Sign a BLOB artifact using the default signing key, with the default J
notation blob sign <blob_path>
Example - Sign a BLOB artifact by generating the signature in a particular directory:
notation blob sign --signature-directory <directory_path> <blob_path>
notation blob sign --signature-directory <directory_path> <blob_path>
Example - Sign a BLOB artifact and skip user confirmations when overwriting existing signature:
notation blob sign --force <blob_path>
Expand Down Expand Up @@ -87,7 +77,7 @@ Example - Sign a BLOB artifact and specify the signature expiry duration, for ex
Long: longMessage,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errors.New("missing blob_path")
return errors.New("missing blob file path to the artifact: use `notation blob sign --help` to see what parameters are required")
}
opts.blobPath = args[0]
return nil
Expand All @@ -98,18 +88,17 @@ Example - Sign a BLOB artifact and specify the signature expiry duration, for ex
}
opts.LoggingFlagOpts.ApplyFlags(command.Flags())
opts.SignerFlagOpts.ApplyFlagsToCommand(command)
opts.SecureFlagOpts.ApplyFlags(command.Flags())
cmd.SetPflagExpiry(command.Flags(), &opts.expiry)
cmd.SetPflagPluginConfig(command.Flags(), &opts.pluginConfig)
cmd.SetPflagUserMetadata(command.Flags(), &opts.userMetadata, cmd.PflagUserMetadataSignUsage)
//PlaceHolder for MediaType and Signature-directory
return command
}

func runBlobSign(command *cobra.Command, cmdOpts *blobOpts) error {
func runBlobSign(command *cobra.Command, cmdOpts *blobSignOpts) error {
// set log level
ctx := cmdOpts.LoggingFlagOpts.InitializeLogger(command.Context())

// Todo: we will need to replace signer with actual blob signer implementation in notation-go
// initialize
signer, err := cmd.GetSigner(ctx, &cmdOpts.SignerFlagOpts)
if err != nil {
Expand All @@ -123,20 +112,13 @@ func runBlobSign(command *cobra.Command, cmdOpts *blobOpts) error {
// core process
err = notation.BlobSign(ctx, signer, blobOpts) //PlaceHolder
if err != nil {
var errorPushSignatureFailed notation.ErrorPushSignatureFailed
if errors.As(err, &errorPushSignatureFailed) && strings.Contains(err.Error(), referrersTagSchemaDeleteError) {
fmt.Fprintln(os.Stderr, "Warning: Removal of outdated referrers index from remote registry failed. Garbage collection may be required.")
// write out
fmt.Println("Successfully signed")
return nil
}
return err
}
fmt.Println("Successfully signed")
return nil
}

func prepareBlobSigningOpts(ctx context.Context, opts *blobOpts) (notation.SignOptions, error) {
func prepareBlobSigningOpts(ctx context.Context, opts *blobSignOpts) (notation.SignOptions, error) {
mediaType, err := envelope.GetEnvelopeMediaType(opts.SignerFlagOpts.SignatureFormat)
if err != nil {
return notation.SignOptions{}, err
Expand All @@ -159,74 +141,3 @@ func prepareBlobSigningOpts(ctx context.Context, opts *blobOpts) (notation.SignO
}
return blobOpts, nil
}

func blobInspectCommand(opts *blobOpts) *cobra.Command {
if opts == nil {
opts = &blobOpts{}
}
longMessage := `Inspect all signatures associated with the signed artifact.
Example - Inspect signatures on an BLOB artifact:
notation blob inspect <signature_path>
Example - Inspect signatures on an BLOB artifact output as json:
notation blob inspect --output json <signature_path>
`

command := &cobra.Command{
Use: "blob inspect [signaturePath]",
Short: "Inspect all signatures associated with the signed artifact",
Long: longMessage,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errors.New("missing signature_path")
}
opts.signaturePath = args[0]
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
return runBlobInspect(cmd, opts)
},
}

opts.LoggingFlagOpts.ApplyFlags(command.Flags())
opts.SecureFlagOpts.ApplyFlags(command.Flags())
cmd.SetPflagOutput(command.Flags(), &opts.outputFormat, cmd.PflagOutputUsage)
return command
}

func runBlobInspect(command *cobra.Command, opts *blobOpts) error {
// set log level
ctx := opts.LoggingFlagOpts.InitializeLogger(command.Context())

if opts.outputFormat != cmd.OutputJSON && opts.outputFormat != cmd.OutputPlaintext {
return fmt.Errorf("unrecognized output format %s", opts.outputFormat)
}

output := inspectOutput{MediaType: opts.desc.MediaType, Signatures: []signatureOutput{}}

sigBlob, _, _ := opts.sigRepo.FetchSignatureBlob(ctx, opts.desc)
sigEnvelope, _ := signature.ParseEnvelope(opts.desc.MediaType, sigBlob)
envelopeContent, _ := sigEnvelope.Content()
signedArtifactDesc, _ := envelope.DescriptorFromSignaturePayload(&envelopeContent.Payload)
signatureAlgorithm, _ := proto.EncodeSigningAlgorithm(envelopeContent.SignerInfo.SignatureAlgorithm)

sig := signatureOutput{
MediaType: opts.desc.MediaType,
Digest: opts.desc.Digest.String(),
SignatureAlgorithm: string(signatureAlgorithm),
SignedAttributes: getSignedAttributes(opts.outputFormat, envelopeContent),
UserDefinedAttributes: signedArtifactDesc.Annotations,
UnsignedAttributes: getUnsignedAttributes(envelopeContent),
Certificates: getCertificates(opts.outputFormat, envelopeContent),
SignedArtifact: *signedArtifactDesc,
}

// clearing annotations from the SignedArtifact field since they're already
// displayed as UserDefinedAttributes
sig.SignedArtifact.Annotations = nil

output.Signatures = append(output.Signatures, sig)

return nil
}
Loading

0 comments on commit 440cfd1

Please sign in to comment.