Skip to content

Commit

Permalink
fix: resolve comemnts
Browse files Browse the repository at this point in the history
Signed-off-by: Junjie Gao <junjiegao@microsoft.com>
  • Loading branch information
JeyJeyGao committed Jan 21, 2025
1 parent 0640165 commit a1e411f
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 104 deletions.
2 changes: 1 addition & 1 deletion cmd/notation/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func runInspect(command *cobra.Command, opts *inspectOpts) error {
return nil
}

if err := displayHandler.InspectSignature(sigManifestDesc.Digest.String(), sigDesc.MediaType, sigEnvelope); err != nil {
if err := displayHandler.InspectSignature(sigManifestDesc, sigDesc, sigEnvelope); err != nil {
logSkippedSignature(sigManifestDesc, err)
skippedSignatures = true
return nil
Expand Down
7 changes: 5 additions & 2 deletions cmd/notation/internal/display/metadata/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@

package metadata

import "github.com/notaryproject/notation-core-go/signature"
import (
"github.com/notaryproject/notation-core-go/signature"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

// Renderer renders metadata information when an operation is complete.
type Renderer interface {
Expand All @@ -29,5 +32,5 @@ type InspectHandler interface {
OnReferenceResolved(reference, mediaType string)

// InspectSignature inspects a signature to get it ready to be rendered.
InspectSignature(digest string, envelopeMediaType string, sigEnvelope signature.Envelope) error
InspectSignature(manifestDesc, blobDesc ocispec.Descriptor, envelope signature.Envelope) error
}
72 changes: 35 additions & 37 deletions cmd/notation/internal/display/metadata/json/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"strings"
"time"

"github.com/notaryproject/notation-core-go/signature"
coresignature "github.com/notaryproject/notation-core-go/signature"
"github.com/notaryproject/notation-go/plugin/proto"
"github.com/notaryproject/notation/cmd/notation/internal/output"
"github.com/notaryproject/notation/internal/envelope"
Expand All @@ -32,35 +32,35 @@ import (

type inspectOutput struct {
MediaType string `json:"mediaType"`
Signatures []Signature
Signatures []*signature
}

// Signature is the signature envelope for printing in human readable format.
type Signature struct {
// signature is the signature envelope for printing in human readable format.
type signature struct {
MediaType string `json:"mediaType"`
Digest string `json:"digest,omitempty"`
SignatureAlgorithm string `json:"signatureAlgorithm"`
SignedAttributes map[string]any `json:"signedAttributes"`
UserDefinedAttributes map[string]string `json:"userDefinedAttributes"`
UnsignedAttributes map[string]any `json:"unsignedAttributes"`
Certificates []Certificate `json:"certificates"`
Certificates []*certificate `json:"certificates"`
SignedArtifact ocispec.Descriptor `json:"signedArtifact"`
}

// Certificate is the certificate information for printing in human readable
// certificate is the certificate information for printing in human readable
// format.
type Certificate struct {
type certificate struct {
SHA256Fingerprint string `json:"SHA256Fingerprint"`
IssuedTo string `json:"issuedTo"`
IssuedBy string `json:"issuedBy"`
Expiry time.Time `json:"expiry"`
}

// Timestamp is the timestamp information for printing in human readable.
type Timestamp struct {
Timestamp string `json:"timestamp,omitempty"`
Certificates []Certificate `json:"certificates,omitempty"`
Error string `json:"error,omitempty"`
// timestamp is the timestamp information for printing in human readable.
type timestamp struct {
Timestamp string `json:"timestamp,omitempty"`
Certificates []*certificate `json:"certificates,omitempty"`
Error string `json:"error,omitempty"`
}

// InspectHandler is the handler for inspecting metadata information and
Expand All @@ -75,38 +75,36 @@ type InspectHandler struct {
func NewInspectHandler(printer *output.Printer) *InspectHandler {
return &InspectHandler{
printer: printer,
output: inspectOutput{
Signatures: []*signature{},
},
}
}

// OnReferenceResolved sets the artifact reference and media type for the
// handler.
//
// the reference is no-op for this handler.
func (h *InspectHandler) OnReferenceResolved(reference, mediaType string) {
if h.output.MediaType == "" {
h.output.MediaType = mediaType
}
func (h *InspectHandler) OnReferenceResolved(_, mediaType string) {
h.output.MediaType = mediaType
}

// InspectSignature inspects a signature to get it ready to be rendered.
func (h *InspectHandler) InspectSignature(digest string, envelopeMediaType string, sigEnvelope signature.Envelope) error {
sig, err := newSignature(digest, envelopeMediaType, sigEnvelope)
func (h *InspectHandler) InspectSignature(manifestDesc, blobDesc ocispec.Descriptor, envelope coresignature.Envelope) error {
sig, err := newSignature(manifestDesc.Digest.String(), blobDesc.MediaType, envelope)
if err != nil {
return err
}
h.output.Signatures = append(h.output.Signatures, *sig)
h.output.Signatures = append(h.output.Signatures, sig)
return nil
}

func (h *InspectHandler) Render() error {
if h.output.MediaType == "" {
return fmt.Errorf("media type is not set")
}
return output.PrintPrettyJSON(h.printer, h.output)
}

// newSignature parses the signature blob and returns a Signature object.
func newSignature(digest string, envelopeMediaType string, sigEnvelope signature.Envelope) (*Signature, error) {
func newSignature(digest string, envelopeMediaType string, sigEnvelope coresignature.Envelope) (*signature, error) {
envelopeContent, err := sigEnvelope.Content()
if err != nil {
return nil, err
Expand All @@ -121,15 +119,15 @@ func newSignature(digest string, envelopeMediaType string, sigEnvelope signature
if err != nil {
return nil, err
}
sig := &Signature{
sig := &signature{
MediaType: envelopeMediaType,
Digest: digest,
SignatureAlgorithm: string(signatureAlgorithm),
SignedAttributes: getSignedAttributes(envelopeContent),
UserDefinedAttributes: signedArtifactDesc.Annotations,
UnsignedAttributes: getUnsignedAttributes(envelopeContent),
Certificates: getCertificates(envelopeContent.SignerInfo.CertificateChain),
SignedArtifact: *signedArtifactDesc,
SignedArtifact: signedArtifactDesc,
}

// clearing annotations from the SignedArtifact field since they're already
Expand All @@ -139,7 +137,7 @@ func newSignature(digest string, envelopeMediaType string, sigEnvelope signature
return sig, nil
}

func getSignedAttributes(envelopeContent *signature.EnvelopeContent) map[string]any {
func getSignedAttributes(envelopeContent *coresignature.EnvelopeContent) map[string]any {
signedAttributes := map[string]any{
"signingScheme": string(envelopeContent.SignerInfo.SignedAttributes.SigningScheme),
"signingTime": envelopeContent.SignerInfo.SignedAttributes.SigningTime,
Expand All @@ -153,7 +151,7 @@ func getSignedAttributes(envelopeContent *signature.EnvelopeContent) map[string]
return signedAttributes
}

func getUnsignedAttributes(envelopeContent *signature.EnvelopeContent) map[string]any {
func getUnsignedAttributes(envelopeContent *coresignature.EnvelopeContent) map[string]any {
unsignedAttributes := make(map[string]any)
if envelopeContent.SignerInfo.UnsignedAttributes.SigningAgent != "" {
unsignedAttributes["signingAgent"] = envelopeContent.SignerInfo.UnsignedAttributes.SigningAgent
Expand All @@ -164,11 +162,11 @@ func getUnsignedAttributes(envelopeContent *signature.EnvelopeContent) map[strin
return unsignedAttributes
}

func getCertificates(certChain []*x509.Certificate) []Certificate {
var certificates []Certificate
func getCertificates(certChain []*x509.Certificate) []*certificate {
var certificates []*certificate
for _, cert := range certChain {
hash := sha256.Sum256(cert.Raw)
certificates = append(certificates, Certificate{
certificates = append(certificates, &certificate{
SHA256Fingerprint: strings.ToLower(hex.EncodeToString(hash[:])),
IssuedTo: cert.Subject.String(),
IssuedBy: cert.Issuer.String(),
Expand All @@ -178,27 +176,27 @@ func getCertificates(certChain []*x509.Certificate) []Certificate {
return certificates
}

func parseTimestamp(signerInfo signature.SignerInfo) Timestamp {
func parseTimestamp(signerInfo coresignature.SignerInfo) *timestamp {
signedToken, err := tspclient.ParseSignedToken(signerInfo.UnsignedAttributes.TimestampSignature)
if err != nil {
return Timestamp{
return &timestamp{
Error: fmt.Sprintf("failed to parse timestamp countersignature: %s", err),
}
}
info, err := signedToken.Info()
if err != nil {
return Timestamp{
return &timestamp{
Error: fmt.Sprintf("failed to parse timestamp countersignature: %s", err),
}
}
timestamp, err := info.Validate(signerInfo.Signature)
ts, err := info.Validate(signerInfo.Signature)
if err != nil {
return Timestamp{
return &timestamp{
Error: fmt.Sprintf("failed to parse timestamp countersignature: %s", err),
}
}
return Timestamp{
Timestamp: timestamp.Format(time.RFC3339Nano),
return &timestamp{
Timestamp: ts.Format(time.RFC3339Nano),
Certificates: getCertificates(signedToken.Certificates),
}
}
45 changes: 20 additions & 25 deletions cmd/notation/internal/display/metadata/json/inspect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,35 @@ import (
"testing"
"time"

"github.com/notaryproject/notation-core-go/signature"
coresignature "github.com/notaryproject/notation-core-go/signature"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

type errorEnvelope struct{}

func (e errorEnvelope) Sign(req *signature.SignRequest) ([]byte, error) {
func (e errorEnvelope) Sign(req *coresignature.SignRequest) ([]byte, error) {
return nil, errors.New("mock sign error")
}

func (e errorEnvelope) Verify() (*signature.EnvelopeContent, error) {
func (e errorEnvelope) Verify() (*coresignature.EnvelopeContent, error) {
return nil, errors.New("mock verify error")
}

func (e errorEnvelope) Content() (*signature.EnvelopeContent, error) {
func (e errorEnvelope) Content() (*coresignature.EnvelopeContent, error) {
return nil, errors.New("mock content error")
}

func TestGetUnsignedAttributes(t *testing.T) {
envContent := &signature.EnvelopeContent{
SignerInfo: signature.SignerInfo{
UnsignedAttributes: signature.UnsignedAttributes{
envContent := &coresignature.EnvelopeContent{
SignerInfo: coresignature.SignerInfo{
UnsignedAttributes: coresignature.UnsignedAttributes{
TimestampSignature: []byte("invalid"),
},
},
}
expectedErrMsg := "failed to parse timestamp countersignature: cms: syntax error: invalid signed data: failed to convert from BER to DER: asn1: syntax error: decoding BER length octets: short form length octets value should be less or equal to the subsequent octets length"
unsignedAttr := getUnsignedAttributes(envContent)
val, ok := unsignedAttr["timestampSignature"].(Timestamp)
val, ok := unsignedAttr["timestampSignature"].(timestamp)
if !ok {
t.Fatal("expected to have timestampSignature")
}
Expand All @@ -58,11 +59,11 @@ func TestGetUnsignedAttributes(t *testing.T) {

func TestGetSignedAttributes(t *testing.T) {
expiry := time.Now()
envContent := &signature.EnvelopeContent{
SignerInfo: signature.SignerInfo{
SignedAttributes: signature.SignedAttributes{
envContent := &coresignature.EnvelopeContent{
SignerInfo: coresignature.SignerInfo{
SignedAttributes: coresignature.SignedAttributes{
Expiry: expiry,
ExtendedAttributes: []signature.Attribute{
ExtendedAttributes: []coresignature.Attribute{
{
Key: "keyName",
Value: "value",
Expand All @@ -83,8 +84,8 @@ func TestGetSignedAttributes(t *testing.T) {

func TestParseTimestamp(t *testing.T) {
t.Run("invalid timestamp signature", func(t *testing.T) {
signerInfo := signature.SignerInfo{
UnsignedAttributes: signature.UnsignedAttributes{
signerInfo := coresignature.SignerInfo{
UnsignedAttributes: coresignature.UnsignedAttributes{
TimestampSignature: []byte("invalid"),
},
}
Expand All @@ -101,8 +102,8 @@ func TestParseTimestamp(t *testing.T) {
t.Fatal(err)
}

signerInfo := signature.SignerInfo{
UnsignedAttributes: signature.UnsignedAttributes{
signerInfo := coresignature.SignerInfo{
UnsignedAttributes: coresignature.UnsignedAttributes{
TimestampSignature: tsaToken,
},
}
Expand All @@ -119,17 +120,11 @@ func TestInspectSignature_NewSignatureError(t *testing.T) {
h := NewInspectHandler(nil)
// ...existing code to ensure h.output.MediaType is set...
h.OnReferenceResolved("test-ref", "test-media-type")
manifestDesc := ocispec.Descriptor{Digest: "fake-digest"}
blobDesc := ocispec.Descriptor{MediaType: "fake-media-type"}

err := h.InspectSignature("fake-digest", "fake-media-type", errorEnvelope{})
err := h.InspectSignature(manifestDesc, blobDesc, errorEnvelope{})
if err == nil || !strings.Contains(err.Error(), "mock content error") {
t.Fatalf("expected error 'mock content error', got %v", err)
}
}

func TestRenderNoMediaType(t *testing.T) {
h := NewInspectHandler(nil)
err := h.Render()
if err == nil || !strings.Contains(err.Error(), "media type is not set") {
t.Fatalf("expected error 'media type is not set', got %v", err)
}
}
33 changes: 16 additions & 17 deletions cmd/notation/internal/display/metadata/tree/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@ import (
type InspectHandler struct {
printer *output.Printer

root *tree.Node
cncfSigNode *tree.Node
// rootReferenceNode is the root node with the artifact reference as the
// value.
rootReferenceNode *tree.Node
// notationSignaturesNode is the node for all signatures associated with the
// artifact.
notationSignaturesNode *tree.Node
}

// NewInspectHandler creates a new InspectHandler.
Expand All @@ -53,28 +57,23 @@ func NewInspectHandler(printer *output.Printer) *InspectHandler {
// handler.
//
// mediaType is a no-op for this handler.
func (h *InspectHandler) OnReferenceResolved(reference, mediaType string) {
if h.root == nil {
h.root = tree.New(reference)
h.cncfSigNode = h.root.Add(registry.ArtifactTypeNotation)
}
func (h *InspectHandler) OnReferenceResolved(reference, _ string) {
h.rootReferenceNode = tree.New(reference)
h.notationSignaturesNode = h.rootReferenceNode.Add(registry.ArtifactTypeNotation)
}

// InspectSignature inspects a signature to get it ready to be rendered.
func (h *InspectHandler) InspectSignature(digest string, envelopeMediaType string, sigEnvelope signature.Envelope) error {
if h.root == nil || h.cncfSigNode == nil {
return fmt.Errorf("artifact reference is not set")
}

return addSignature(h.cncfSigNode, digest, envelopeMediaType, sigEnvelope)
func (h *InspectHandler) InspectSignature(manifestDesc, blobDesc ocispec.Descriptor, envelope signature.Envelope) error {
return addSignature(h.notationSignaturesNode, manifestDesc.Digest.String(), blobDesc.MediaType, envelope)
}

// Render renders the metadata information when an operation is complete.
func (h *InspectHandler) Render() error {
if h.root == nil {
return fmt.Errorf("artifact reference is not set")
if len(h.notationSignaturesNode.Children) == 0 {
return h.printer.Printf("%s has no associated signature\n", h.rootReferenceNode.Value)
}
return h.root.Print(h.printer)
h.printer.Println("Inspecting all signatures for signed artifact")
return h.rootReferenceNode.Print(h.printer)
}

func addSignature(node *tree.Node, digest string, envelopeMediaType string, sigEnvelope signature.Envelope) error {
Expand Down Expand Up @@ -138,7 +137,7 @@ func addUnsignedAttributes(node *tree.Node, envelopeContent *signature.EnvelopeC
}
}

func addSignedArtifact(node *tree.Node, signedArtifactDesc *ocispec.Descriptor) {
func addSignedArtifact(node *tree.Node, signedArtifactDesc ocispec.Descriptor) {
artifactNode := node.Add("signed artifact")
artifactNode.AddPair("media type", signedArtifactDesc.MediaType)
artifactNode.AddPair("digest", signedArtifactDesc.Digest.String())
Expand Down
Loading

0 comments on commit a1e411f

Please sign in to comment.