Skip to content

Commit

Permalink
test: added 2 E2E test cases
Browse files Browse the repository at this point in the history
Signed-off-by: Junjie Gao <[email protected]>
  • Loading branch information
JeyJeyGao committed Jan 6, 2025
1 parent 577e8c6 commit b96330d
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 53 deletions.
6 changes: 3 additions & 3 deletions cmd/notation/blob/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ func runInspect(opts *inspectOpts) error {
return err
}

Check warning on line 68 in cmd/notation/blob/inspect.go

View check run for this annotation

Codecov / codecov/patch

cmd/notation/blob/inspect.go#L67-L68

Added lines #L67 - L68 were not covered by tests

sigBlob, err := os.ReadFile(opts.sigPath)
envelopeBytes, err := os.ReadFile(opts.sigPath)
if err != nil {
return err
}

Check warning on line 73 in cmd/notation/blob/inspect.go

View check run for this annotation

Codecov / codecov/patch

cmd/notation/blob/inspect.go#L72-L73

Added lines #L72 - L73 were not covered by tests

sig, err := envelope.Parse(sigBlob, envelopeMediaType)
sig, err := envelope.Parse(envelopeMediaType, envelopeBytes)
if err != nil {
return err
}

Check warning on line 78 in cmd/notation/blob/inspect.go

View check run for this annotation

Codecov / codecov/patch

cmd/notation/blob/inspect.go#L77-L78

Added lines #L77 - L78 were not covered by tests
Expand All @@ -84,7 +84,7 @@ func runInspect(opts *inspectOpts) error {
case cmd.OutputJSON:
return ioutil.PrintObjectAsJSON(sig)
case cmd.OutputPlaintext:
sig.SignatureNode(opts.sigPath).Print()
sig.ToNode(opts.sigPath).Print()
}
return nil
}
Expand Down
10 changes: 5 additions & 5 deletions cmd/notation/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ type inspectOpts struct {
}

type inspectOutput struct {
MediaType string `json:"mediaType"`
Signatures []*envelope.SignatureInfo `json:"signatures"`
MediaType string `json:"mediaType"`
Signatures []*envelope.Signature `json:"signatures"`
}

func inspectCommand(opts *inspectOpts) *cobra.Command {
Expand Down Expand Up @@ -111,7 +111,7 @@ func runInspect(command *cobra.Command, opts *inspectOpts) error {
if err != nil {
return err
}
output := inspectOutput{MediaType: manifestDesc.MediaType, Signatures: []*envelope.SignatureInfo{}}
output := inspectOutput{MediaType: manifestDesc.MediaType, Signatures: []*envelope.Signature{}}

Check warning on line 114 in cmd/notation/inspect.go

View check run for this annotation

Codecov / codecov/patch

cmd/notation/inspect.go#L114

Added line #L114 was not covered by tests
skippedSignatures := false
err = listSignatures(ctx, sigRepo, manifestDesc, opts.maxSignatures, func(sigManifestDesc ocispec.Descriptor) error {
sigBlob, sigDesc, err := sigRepo.FetchSignatureBlob(ctx, sigManifestDesc)
Expand All @@ -121,7 +121,7 @@ func runInspect(command *cobra.Command, opts *inspectOpts) error {
return nil
}

sig, err := envelope.Parse(sigBlob, sigDesc.MediaType)
sig, err := envelope.Parse(sigDesc.MediaType, sigBlob)

Check warning on line 124 in cmd/notation/inspect.go

View check run for this annotation

Codecov / codecov/patch

cmd/notation/inspect.go#L124

Added line #L124 was not covered by tests
if err != nil {
logSkippedSignature(sigManifestDesc, err)
skippedSignatures = true
Expand Down Expand Up @@ -178,7 +178,7 @@ func printOutput(outputFormat string, ref string, output inspectOutput) error {
cncfSigNode := root.Add(registry.ArtifactTypeNotation)

for _, signature := range output.Signatures {
cncfSigNode.Children = append(cncfSigNode.Children, signature.SignatureNode(signature.Digest))
cncfSigNode.Children = append(cncfSigNode.Children, signature.ToNode(signature.Digest))

Check warning on line 181 in cmd/notation/inspect.go

View check run for this annotation

Codecov / codecov/patch

cmd/notation/inspect.go#L181

Added line #L181 was not covered by tests
}

root.Print()
Expand Down
87 changes: 44 additions & 43 deletions internal/envelope/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,33 +31,41 @@ import (
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

// SignatureInfo is the signature envelope with human readable fields.
type SignatureInfo 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 plugin.SignatureAlgorithm `json:"signatureAlgorithm"`
SignedAttributes map[string]any `json:"signedAttributes"`
UserDefinedAttributes map[string]string `json:"userDefinedAttributes"`
UnsignedAttributes map[string]any `json:"unsignedAttributes"`
Certificates []CertificateInfo `json:"certificates"`
Certificates []Certificate `json:"certificates"`
SignedArtifact ocispec.Descriptor `json:"signedArtifact"`
}

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

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

func Parse(sig []byte, envelopeMediaType string) (*SignatureInfo, error) {
sigEnvelope, err := signature.ParseEnvelope(envelopeMediaType, sig)
// Parse parses the signature blob and returns a Signature object.
//
// envelopeMediaType supports
// - application/jose+json
// - application/cose
func Parse(envelopeMediaType string, envelopeBytes []byte) (*Signature, error) {
sigEnvelope, err := signature.ParseEnvelope(envelopeMediaType, envelopeBytes)
if err != nil {
return nil, err
}

Check warning on line 71 in internal/envelope/signature.go

View check run for this annotation

Codecov / codecov/patch

internal/envelope/signature.go#L70-L71

Added lines #L70 - L71 were not covered by tests
Expand All @@ -76,8 +84,7 @@ func Parse(sig []byte, envelopeMediaType string) (*SignatureInfo, error) {
if err != nil {
return nil, err
}

Check warning on line 86 in internal/envelope/signature.go

View check run for this annotation

Codecov / codecov/patch

internal/envelope/signature.go#L85-L86

Added lines #L85 - L86 were not covered by tests

return &SignatureInfo{
return &Signature{
MediaType: envelopeMediaType,
SignatureAlgorithm: signatureAlgorithm,
SignedAttributes: getSignedAttributes(envelopeContent),
Expand All @@ -93,15 +100,13 @@ func getSignedAttributes(envContent *signature.EnvelopeContent) map[string]any {
"signingScheme": envContent.SignerInfo.SignedAttributes.SigningScheme,
"signingTime": ioutil.Time(envContent.SignerInfo.SignedAttributes.SigningTime),
}
expiry := envContent.SignerInfo.SignedAttributes.Expiry
if !expiry.IsZero() {
if expiry := envContent.SignerInfo.SignedAttributes.Expiry; !expiry.IsZero() {
signedAttributes["expiry"] = ioutil.Time(expiry)
}

Check warning on line 105 in internal/envelope/signature.go

View check run for this annotation

Codecov / codecov/patch

internal/envelope/signature.go#L104-L105

Added lines #L104 - L105 were not covered by tests

for _, attribute := range envContent.SignerInfo.SignedAttributes.ExtendedAttributes {
signedAttributes[fmt.Sprint(attribute.Key)] = fmt.Sprint(attribute.Value)
}

Check warning on line 109 in internal/envelope/signature.go

View check run for this annotation

Codecov / codecov/patch

internal/envelope/signature.go#L108-L109

Added lines #L108 - L109 were not covered by tests

return signedAttributes
}

Expand All @@ -115,57 +120,52 @@ func getUnsignedAttributes(envContent *signature.EnvelopeContent) map[string]any
if envContent.SignerInfo.UnsignedAttributes.SigningAgent != "" {
unsignedAttributes["signingAgent"] = envContent.SignerInfo.UnsignedAttributes.SigningAgent
}

return unsignedAttributes
}

func getCertificates(certChain []*x509.Certificate) []CertificateInfo {
certificates := []CertificateInfo{}
func getCertificates(certChain []*x509.Certificate) []Certificate {
certificates := []Certificate{}

for _, cert := range certChain {
h := sha256.Sum256(cert.Raw)
fingerprint := strings.ToLower(hex.EncodeToString(h[:]))
hash := sha256.Sum256(cert.Raw)

certificate := CertificateInfo{
SHA256Fingerprint: fingerprint,
certificates = append(certificates, Certificate{
SHA256Fingerprint: strings.ToLower(hex.EncodeToString(hash[:])),
IssuedTo: cert.Subject.String(),
IssuedBy: cert.Issuer.String(),
Expiry: ioutil.Time(cert.NotAfter),
}

certificates = append(certificates, certificate)
})
}

return certificates
}

func parseTimestamp(signerInfo signature.SignerInfo) TimestampInfo {
func parseTimestamp(signerInfo signature.SignerInfo) Timestamp {
signedToken, err := tspclient.ParseSignedToken(signerInfo.UnsignedAttributes.TimestampSignature)
if err != nil {
return TimestampInfo{
Error: fmt.Sprintf("failed to parse timestamp countersignature: %s", err.Error()),
return Timestamp{
Error: fmt.Sprintf("failed to parse timestamp countersignature: %s", err),
}
}
info, err := signedToken.Info()
if err != nil {
return TimestampInfo{
Error: fmt.Sprintf("failed to parse timestamp countersignature: %s", err.Error()),
return Timestamp{
Error: fmt.Sprintf("failed to parse timestamp countersignature: %s", err),
}
}

Check warning on line 154 in internal/envelope/signature.go

View check run for this annotation

Codecov / codecov/patch

internal/envelope/signature.go#L151-L154

Added lines #L151 - L154 were not covered by tests
timestamp, err := info.Validate(signerInfo.Signature)
if err != nil {
return TimestampInfo{
Error: fmt.Sprintf("failed to parse timestamp countersignature: %s", err.Error()),
return Timestamp{
Error: fmt.Sprintf("failed to parse timestamp countersignature: %s", err),
}
}

Check warning on line 160 in internal/envelope/signature.go

View check run for this annotation

Codecov / codecov/patch

internal/envelope/signature.go#L157-L160

Added lines #L157 - L160 were not covered by tests
return TimestampInfo{
return Timestamp{
Timestamp: ioutil.Timestamp(*timestamp),
Certificates: getCertificates(signedToken.Certificates),
}
}

// SignatureNode returns a tree node that represents the signature.
func (s *SignatureInfo) SignatureNode(sigName string) *tree.Node {
// ToNode returns a tree node that represents the signature.
func (s *Signature) ToNode(sigName string) *tree.Node {
sigNode := tree.New(sigName)
sigNode.AddPair("signature algorithm", s.SignatureAlgorithm)
sigNode.AddPair("signature envelope type", s.MediaType)
Expand All @@ -181,7 +181,7 @@ func (s *SignatureInfo) SignatureNode(sigName string) *tree.Node {
switch value := v.(type) {
case string:
unsignedAttributesNode.AddPair(k, value)
case TimestampInfo:
case Timestamp:
timestampNode := unsignedAttributesNode.Add("timestamp signature")
if value.Error != "" {
timestampNode.AddPair("error", value.Error)
Expand All @@ -202,16 +202,17 @@ func (s *SignatureInfo) SignatureNode(sigName string) *tree.Node {
}

func addMapToTree[T any](node *tree.Node, m map[string]T) {
if len(m) > 0 {
for k, v := range m {
node.AddPair(k, v)
}
} else {
if len(m) == 0 {
node.Add("(empty)")
return
}

for k, v := range m {
node.AddPair(k, v)
}
}

func addCertificatesToTree(node *tree.Node, name string, certs []CertificateInfo) {
func addCertificatesToTree(node *tree.Node, name string, certs []Certificate) {
certListNode := node.Add(name)
for _, cert := range certs {
certNode := certListNode.AddPair("SHA256 fingerprint", cert.SHA256Fingerprint)
Expand Down
2 changes: 1 addition & 1 deletion internal/envelope/signature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestGetUnsignedAttributes(t *testing.T) {
}
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"].(TimestampInfo)
val, ok := unsignedAttr["timestampSignature"].(Timestamp)
if !ok {
t.Fatal("expected to have timestampSignature")
}
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,4 @@ export NOTATION_E2E_PLUGIN_TAR_GZ_PATH=$CWD/plugin/bin/$PLUGIN_NAME.tar.gz
export NOTATION_E2E_MALICIOUS_PLUGIN_ARCHIVE_PATH=$CWD/testdata/malicious-plugin

# run tests
ginkgo -r -p -v
ginkgo -r -p -v --focus "notation blob inspect"
26 changes: 26 additions & 0 deletions test/e2e/suite/command/blob/blob_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 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 (
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestCommand(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Blob Command Suite")
}
Loading

0 comments on commit b96330d

Please sign in to comment.