Skip to content

Commit 4b812a5

Browse files
author
zaihaoyin
committed
refactor:support cose signature format
Signed-off-by: zaihaoyin <[email protected]>
1 parent a9fb055 commit 4b812a5

30 files changed

+2276
-812
lines changed

config/config.go

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ type Config struct {
2323
InsecureRegistries []string `json:"insecureRegistries"`
2424
CredentialsStore string `json:"credsStore,omitempty"`
2525
CredentialHelpers map[string]string `json:"credHelpers,omitempty"`
26+
// EnvelopeType defines the envelope type for signing
27+
EnvelopeType string `json:"envelopeType,omitempty"`
2628
}
2729

2830
// VerificationCertificates is a collection of public certs used for verification.

config/config_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ var sampleConfig = &Config{
2929
InsecureRegistries: []string{
3030
"registry.wabbit-networks.io",
3131
},
32+
EnvelopeType: "jws",
3233
}
3334

3435
func TestLoadFile(t *testing.T) {

config/testdata/config.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@
1313
},
1414
"insecureRegistries": [
1515
"registry.wabbit-networks.io"
16-
]
16+
],
17+
"envelopeType": "jws"
1718
}

go.mod

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,21 @@ go 1.17
44

55
require (
66
github.com/go-ldap/ldap/v3 v3.4.4
7-
github.com/golang-jwt/jwt/v4 v4.4.2
8-
github.com/notaryproject/notation-core-go v0.1.0-alpha.3
7+
github.com/notaryproject/notation-core-go v0.0.0-20220901064119-7bf2b3e37c06
98
github.com/opencontainers/go-digest v1.0.0
109
github.com/opencontainers/image-spec v1.0.2
1110
github.com/oras-project/artifacts-spec v1.0.0-rc.2
11+
github.com/veraison/go-cose v1.0.0-rc.1.0.20220824135457-9d2fab636b83
1212
oras.land/oras-go/v2 v2.0.0-rc.2
1313
)
1414

1515
require (
1616
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
17+
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
1718
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
19+
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
1820
github.com/opencontainers/distribution-spec/specs-go v0.0.0-20220620172159-4ab4752c3b86 // indirect
21+
github.com/x448/float16 v0.8.4 // indirect
1922
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
2023
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
2124
)

go.sum

+9-2
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e h1:NeAW1fUYUEWhft
22
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
33
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
44
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5+
github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
6+
github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
57
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
68
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
79
github.com/go-ldap/ldap/v3 v3.4.4 h1:qPjipEpt+qDa6SI/h1fzuGWoRUY+qqQ9sOZq67/PYUs=
810
github.com/go-ldap/ldap/v3 v3.4.4/go.mod h1:fe1MsuN5eJJ1FeLT/LEBVdWfNWKh459R7aXgXtJC+aI=
11+
github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
912
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
1013
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
11-
github.com/notaryproject/notation-core-go v0.1.0-alpha.3 h1:gzB+h5TGzuocWiJxuYZgE/FwUIbJyKAHfk2hWSBbCGg=
12-
github.com/notaryproject/notation-core-go v0.1.0-alpha.3/go.mod h1:Wfyh5SrQ718JegKPhTs7y74rXg86tWd5NfOx2uHK1nI=
14+
github.com/notaryproject/notation-core-go v0.0.0-20220901064119-7bf2b3e37c06 h1:tvnxwHtQEACckbLYYoyCPkAawNJk1BAsGFLrDhou2U0=
15+
github.com/notaryproject/notation-core-go v0.0.0-20220901064119-7bf2b3e37c06/go.mod h1:vRFI64uedpKUChiadJ/2q8jJNdKtxHa7Er1JbSnm8AY=
1316
github.com/opencontainers/distribution-spec/specs-go v0.0.0-20220620172159-4ab4752c3b86 h1:Oumw+lPnO8qNLTY2mrqPJZMoGExLi/0h/DdikoLTXVU=
1417
github.com/opencontainers/distribution-spec/specs-go v0.0.0-20220620172159-4ab4752c3b86/go.mod h1:aA4vdXRS8E1TG7pLZOz85InHi3BiPdErh8IpJN6E0x4=
1518
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
@@ -23,6 +26,10 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
2326
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
2427
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
2528
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
29+
github.com/veraison/go-cose v1.0.0-rc.1.0.20220824135457-9d2fab636b83 h1:g8vDfnNOPcGzg6mnlBGc0J5t5lAJkaepXqbc9qFRnFs=
30+
github.com/veraison/go-cose v1.0.0-rc.1.0.20220824135457-9d2fab636b83/go.mod h1:7ziE85vSq4ScFTg6wyoMXjucIGOf4JkFEZi/an96Ct4=
31+
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
32+
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
2633
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
2734
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
2835
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=

internal/mock/mocks.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package mock
22

33
import (
4+
"context"
45
_ "embed"
5-
nsigner "github.com/notaryproject/notation-core-go/signer"
6-
)
76

8-
import (
9-
"context"
7+
"github.com/notaryproject/notation-core-go/signature"
108
"github.com/notaryproject/notation-go"
119
"github.com/notaryproject/notation-go/plugin"
1210
"github.com/notaryproject/notation-go/plugin/manager"
@@ -54,7 +52,7 @@ var (
5452
Size: 100,
5553
Annotations: Annotations,
5654
}
57-
PluginExtendedCriticalAttribute = nsigner.Attribute{
55+
PluginExtendedCriticalAttribute = signature.Attribute{
5856
Key: "SomeKey",
5957
Critical: true,
6058
Value: "SomeValue",
@@ -93,7 +91,7 @@ func (t Repository) GetBlob(ctx context.Context, digest digest.Digest) ([]byte,
9391
return t.GetResponse, t.GetError
9492
}
9593

96-
func (t Repository) PutSignatureManifest(ctx context.Context, signature []byte, manifest notation.Descriptor, annotaions map[string]string) (notation.Descriptor, registry.SignatureManifest, error) {
94+
func (t Repository) PutSignatureManifest(ctx context.Context, signature []byte, signatureMediaType string, manifest notation.Descriptor, annotaions map[string]string) (notation.Descriptor, registry.SignatureManifest, error) {
9795
return notation.Descriptor{}, registry.SignatureManifest{}, nil
9896
}
9997

notation.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99
"github.com/opencontainers/go-digest"
1010
)
1111

12-
// Media type for Notary payload for OCI artifacts, which contains an artifact descriptor.
13-
const MediaTypePayload = "application/vnd.cncf.notary.payload.v1+json"
12+
// SigningAgent is the unprotected header field used by signature
13+
const SigningAgent = "Notation/1.0.0"
1414

1515
// Descriptor describes the artifact that needs to be signed.
1616
type Descriptor struct {
@@ -65,7 +65,9 @@ type Signer interface {
6565
}
6666

6767
// VerifyOptions contains parameters for Verifier.Verify.
68-
type VerifyOptions struct{}
68+
type VerifyOptions struct {
69+
SignatureMediaType string
70+
}
6971

7072
// Validate does basic validation on VerifyOptions.
7173
func (opts VerifyOptions) Validate() error {

plugin/plugin.go

+19-19
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package plugin
33
import (
44
"context"
55
"time"
6-
7-
"github.com/notaryproject/notation-core-go/signer"
86
)
97

108
// Prefix is the prefix required on all plugin binary names.
@@ -127,17 +125,21 @@ type DescribeKeyResponse struct {
127125

128126
// One of following supported key types:
129127
// https://github.com/notaryproject/notaryproject/blob/main/signature-specification.md#algorithm-selection
130-
KeySpec signer.KeySpec `json:"keySpec"`
128+
KeySpec string `json:"keySpec"`
129+
130+
// Ordered list of certificates starting with leaf certificate
131+
// and ending with root certificate.
131132
}
132133

133134
// GenerateSignatureRequest contains the parameters passed in a generate-signature request.
135+
// do we still need keyspec and hash?
134136
type GenerateSignatureRequest struct {
135-
ContractVersion string `json:"contractVersion"`
136-
KeyID string `json:"keyId"`
137-
KeySpec signer.KeySpec `json:"keySpec"`
138-
Hash signer.HashAlgorithm `json:"hashAlgorithm"`
139-
Payload []byte `json:"payload"`
140-
PluginConfig map[string]string `json:"pluginConfig,omitempty"`
137+
ContractVersion string `json:"contractVersion"`
138+
KeyID string `json:"keyId"`
139+
Payload []byte `json:"payload"`
140+
KeySpec string `json:"keySpec"`
141+
Hash string `json:"hashAlgorithm"`
142+
PluginConfig map[string]string `json:"pluginConfig,omitempty"`
141143
}
142144

143145
func (GenerateSignatureRequest) Command() Command {
@@ -146,9 +148,9 @@ func (GenerateSignatureRequest) Command() Command {
146148

147149
// GenerateSignatureResponse is the response of a generate-signature request.
148150
type GenerateSignatureResponse struct {
149-
KeyID string `json:"keyId"`
150-
Signature []byte `json:"signature"`
151-
SigningAlgorithm signer.SignatureAlgorithm `json:"signingAlgorithm"`
151+
KeyID string `json:"keyId"`
152+
Signature []byte `json:"signature"`
153+
SigningAlgorithm string `json:"signingAlgorithm"`
152154

153155
// Ordered list of certificates starting with leaf certificate
154156
// and ending with root certificate.
@@ -194,13 +196,11 @@ type Signature struct {
194196
// CriticalAttributes contains all Notary V2 defined critical
195197
// attributes and their values in the signature envelope
196198
type CriticalAttributes struct {
197-
ContentType string `json:"contentType"`
198-
SigningScheme string `json:"signingScheme"`
199-
Expiry *time.Time `json:"expiry,omitempty"`
200-
AuthenticSigningTime *time.Time `json:"authenticSigningTime,omitempty"`
201-
VerificationPlugin string `json:"verificationPlugin,omitempty"`
202-
VerificationPluginMinVersion string `json:"verificationPluginMinVersion,omitempty"`
203-
ExtendedAttributes map[string]interface{} `json:"extendedAttributes,omitempty"`
199+
ContentType string `json:"contentType"`
200+
SigningScheme string `json:"signingScheme"`
201+
Expiry *time.Time `json:"expiry,omitempty"`
202+
AuthenticSigningTime *time.Time `json:"authenticSigningTime,omitempty"`
203+
ExtendedAttributes map[string]interface{} `json:"extendedAttributes,omitempty"`
204204
}
205205

206206
// TrustPolicy represents trusted identities that sign the artifacts

registry/interface.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type SignatureRepository interface {
1616
GetBlob(ctx context.Context, digest digest.Digest) ([]byte, error)
1717

1818
// PutSignatureManifest creates and uploads an signature artifact linking the manifest and the signature
19-
PutSignatureManifest(ctx context.Context, signature []byte, manifest notation.Descriptor, annotations map[string]string) (notation.Descriptor, SignatureManifest, error)
19+
PutSignatureManifest(ctx context.Context, signature []byte, signatureMediaType string, manifest notation.Descriptor, annotations map[string]string) (notation.Descriptor, SignatureManifest, error)
2020
}
2121

2222
// Repository provides functions for verification and signing workflows

registry/mediatype.go

-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,3 @@ package registry
22

33
// ArtifactTypeNotation specifies the artifact type for a notation object.
44
const ArtifactTypeNotation = "application/vnd.cncf.notary.v2.signature"
5-
6-
// MediaTypeNotationSignature specifies the media type for the notation signature.
7-
const MediaTypeNotationSignature = "application/jose+json"

registry/repository.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ func (c *RepositoryClient) GetBlob(ctx context.Context, digest digest.Digest) ([
9292
}
9393

9494
// PutSignatureManifest creates and uploads an signature artifact linking the manifest and the signature
95-
func (c *RepositoryClient) PutSignatureManifest(ctx context.Context, signature []byte, subjectManifest notation.Descriptor, annotations map[string]string) (notation.Descriptor, SignatureManifest, error) {
96-
signatureDesc, err := c.uploadSignature(ctx, signature)
95+
func (c *RepositoryClient) PutSignatureManifest(ctx context.Context, signature []byte, signatureMediaType string, subjectManifest notation.Descriptor, annotations map[string]string) (notation.Descriptor, SignatureManifest, error) {
96+
signatureDesc, err := c.uploadSignature(ctx, signature, signatureMediaType)
9797
if err != nil {
9898
return notation.Descriptor{}, SignatureManifest{}, err
9999
}
@@ -137,9 +137,9 @@ func (c *RepositoryClient) getArtifactManifest(ctx context.Context, manifestDige
137137
}
138138

139139
// uploadSignature uploads the signature to the registry
140-
func (c *RepositoryClient) uploadSignature(ctx context.Context, signature []byte) (artifactspec.Descriptor, error) {
140+
func (c *RepositoryClient) uploadSignature(ctx context.Context, signature []byte, signatureMediaType string) (artifactspec.Descriptor, error) {
141141
desc := ocispec.Descriptor{
142-
MediaType: MediaTypeNotationSignature,
142+
MediaType: signatureMediaType,
143143
Digest: digest.FromBytes(signature),
144144
Size: int64(len(signature)),
145145
}

registry/repository_test.go

+54-10
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const (
2828
validDigest7 = "13b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
2929
validDigest8 = "57f2c47061dae97063dc46598168a80a9f89302c1f24fe2a422a1ec0aba3017a"
3030
validDigest9 = "023c624b58dbbcd3c0dd82b4c53f04194d1247c6eebdaab7c610cf7d66709b3b"
31+
validDigest10 = "1761e09cad8aa44e48ffb41c78371a6c139bd0df555c90b5d99739b9551c7828"
3132
invalidDigest = "invaliddigest"
3233
algo = "sha256"
3334
validDigestWithAlgo = algo + ":" + validDigest
@@ -39,6 +40,7 @@ const (
3940
validDigestWithAlgo7 = algo + ":" + validDigest7
4041
validDigestWithAlgo8 = algo + ":" + validDigest8
4142
validDigestWithAlgo9 = algo + ":" + validDigest9
43+
validDigestWithAlgo10 = algo + ":" + validDigest10
4244
validHost = "localhost"
4345
validRegistry = validHost + ":5000"
4446
invalidHost = "badhost"
@@ -52,6 +54,7 @@ const (
5254
validReference6 = validRegistry + "/" + validRepo + "@" + validDigest6
5355
invalidReference = "invalid reference"
5456
joseTag = "application/jose+json"
57+
coseTag = "application/cose"
5558
validTimestamp = "2022-07-29T02:23:10Z"
5659
size = 104
5760
size2 = 135
@@ -103,14 +106,15 @@ const (
103106
)
104107

105108
type args struct {
106-
ctx context.Context
107-
reference string
108-
remoteClient remote.Client
109-
plainHttp bool
110-
digest digest.Digest
111-
annotations map[string]string
112-
subjectManifest notation.Descriptor
113-
signature []byte
109+
ctx context.Context
110+
reference string
111+
remoteClient remote.Client
112+
plainHttp bool
113+
digest digest.Digest
114+
annotations map[string]string
115+
subjectManifest notation.Descriptor
116+
signature []byte
117+
signatureMediaType string
114118
}
115119

116120
type mockRemoteClient struct {
@@ -255,6 +259,17 @@ func (c mockRemoteClient) Do(req *http.Request) (*http.Response, error) {
255259
"Content-Type": {mediaType},
256260
},
257261
}, nil
262+
case "/v2/test/manifests/" + validDigestWithAlgo10:
263+
if req.Method == "GET" {
264+
return &http.Response{}, fmt.Errorf(msg)
265+
}
266+
return &http.Response{
267+
StatusCode: http.StatusCreated,
268+
Body: io.NopCloser(bytes.NewReader([]byte(msg))),
269+
Header: map[string][]string{
270+
"Docker-Content-Digest": {validDigestWithAlgo10},
271+
},
272+
}, nil
258273
case "/v2/test/blobs/uploads/":
259274
switch req.Host {
260275
case validRegistry:
@@ -507,7 +522,7 @@ func TestPutSignatureManifest(t *testing.T) {
507522
},
508523
},
509524
{
510-
name: "succeed to put signature manifest",
525+
name: "succeed to put signature manifest with jws media type",
511526
expectErr: false,
512527
expectDes: notation.Descriptor{
513528
MediaType: artifactspec.MediaTypeArtifactManifest,
@@ -531,6 +546,35 @@ func TestPutSignatureManifest(t *testing.T) {
531546
annotations: map[string]string{
532547
artifactspec.AnnotationArtifactCreated: validTimestamp,
533548
},
549+
signatureMediaType: joseTag,
550+
},
551+
},
552+
{
553+
name: "succeed to put signature manifest with cose media type",
554+
expectErr: false,
555+
expectDes: notation.Descriptor{
556+
MediaType: artifactspec.MediaTypeArtifactManifest,
557+
Digest: digest.Digest(validDigestWithAlgo10),
558+
Size: 364,
559+
},
560+
expectManifest: SignatureManifest{
561+
Annotations: map[string]string{
562+
artifactspec.AnnotationArtifactCreated: validTimestamp,
563+
},
564+
Blob: notation.Descriptor{
565+
MediaType: coseTag,
566+
Digest: validDigestWithAlgo5,
567+
},
568+
},
569+
args: args{
570+
reference: validReference,
571+
signature: make([]byte, 0),
572+
ctx: context.Background(),
573+
remoteClient: mockRemoteClient{},
574+
annotations: map[string]string{
575+
artifactspec.AnnotationArtifactCreated: validTimestamp,
576+
},
577+
signatureMediaType: coseTag,
534578
},
535579
},
536580
}
@@ -540,7 +584,7 @@ func TestPutSignatureManifest(t *testing.T) {
540584
ref, _ := registry.ParseReference(args.reference)
541585
client := NewRepositoryClient(args.remoteClient, ref, args.plainHttp)
542586

543-
des, manifest, err := client.PutSignatureManifest(args.ctx, args.signature, args.subjectManifest, args.annotations)
587+
des, manifest, err := client.PutSignatureManifest(args.ctx, args.signature, args.signatureMediaType, args.subjectManifest, args.annotations)
544588
if (err != nil) != tt.expectErr {
545589
t.Errorf("error = %v, expectErr = %v", err, tt.expectErr)
546590
}

0 commit comments

Comments
 (0)