Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update: Package notation refactoring #191

Merged
merged 32 commits into from
Nov 11, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
219e11b
update
Two-Hearts Nov 8, 2022
1862c7e
notation refactoring
Two-Hearts Nov 8, 2022
f8f1b59
update
Two-Hearts Nov 8, 2022
e56be2b
refactored notation
Two-Hearts Nov 8, 2022
1f5a10c
updates
Two-Hearts Nov 8, 2022
7775782
update
Two-Hearts Nov 8, 2022
223b4e6
Merge branch 'notaryproject:main' into notation
Two-Hearts Nov 9, 2022
293d7a7
update
Two-Hearts Nov 9, 2022
7a40295
resolve conflicts
Two-Hearts Nov 9, 2022
f01fa86
update
Two-Hearts Nov 9, 2022
9b8ed37
update
Two-Hearts Nov 9, 2022
53fa4a4
update
Two-Hearts Nov 9, 2022
e1a4497
update
Two-Hearts Nov 9, 2022
5fc3cc0
updated per code review
Two-Hearts Nov 9, 2022
6cd2b89
updated per code review
Two-Hearts Nov 9, 2022
e496e5c
update
Two-Hearts Nov 9, 2022
5a77b81
updated per code review
Two-Hearts Nov 9, 2022
aeea620
updated per code review
Two-Hearts Nov 9, 2022
8409a45
resolve conflicts
Two-Hearts Nov 10, 2022
f192a8c
update
Two-Hearts Nov 10, 2022
81eeafc
update
Two-Hearts Nov 10, 2022
af27f20
updated per code review
Two-Hearts Nov 10, 2022
c9e4409
update
Two-Hearts Nov 10, 2022
537851b
updated per code review
Two-Hearts Nov 10, 2022
8b7066e
updated per code review
Two-Hearts Nov 10, 2022
4032f5e
Merge branch 'notaryproject:main' into notation
Two-Hearts Nov 10, 2022
55aee1a
updated per code review
Two-Hearts Nov 10, 2022
01df7de
updated per code review
Two-Hearts Nov 11, 2022
631731b
updated per code review
Two-Hearts Nov 11, 2022
73e2c5f
update
Two-Hearts Nov 11, 2022
70a1cf9
updated per code review
Two-Hearts Nov 11, 2022
23a6feb
updated per code review
Two-Hearts Nov 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,17 @@ require (
github.com/go-ldap/ldap/v3 v3.4.4
github.com/notaryproject/notation-core-go v0.2.0-beta.1
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.2
github.com/opencontainers/image-spec v1.1.0-rc2
github.com/oras-project/artifacts-spec v1.0.0-rc.2
github.com/veraison/go-cose v1.0.0-rc.1.0.20220824135457-9d2fab636b83
oras.land/oras-go/v2 v2.0.0-rc.3
oras.land/oras-go/v2 v2.0.0-rc.4
)

require (
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
github.com/opencontainers/distribution-spec/specs-go v0.0.0-20220620172159-4ab4752c3b86 // indirect
github.com/x448/float16 v0.8.4 // indirect
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
Expand Down
12 changes: 5 additions & 7 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e h1:NeAW1fUYUEWhft7pkxDf6WoUvEZJ/uOKsvtpjLnn8MU=
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
Expand All @@ -12,12 +12,10 @@ github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQA
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/notaryproject/notation-core-go v0.2.0-beta.1 h1:8tFxNycWCcPLti9ZYST5kjkX2wMXtX9YPvMjiBAQ1tA=
github.com/notaryproject/notation-core-go v0.2.0-beta.1/go.mod h1:s8DZptmN1rZS0tBLTPt/w+d4o6eAcGWTYYJlXaJhQ4U=
github.com/opencontainers/distribution-spec/specs-go v0.0.0-20220620172159-4ab4752c3b86 h1:Oumw+lPnO8qNLTY2mrqPJZMoGExLi/0h/DdikoLTXVU=
github.com/opencontainers/distribution-spec/specs-go v0.0.0-20220620172159-4ab4752c3b86/go.mod h1:aA4vdXRS8E1TG7pLZOz85InHi3BiPdErh8IpJN6E0x4=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=
github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
github.com/oras-project/artifacts-spec v1.0.0-rc.2 h1:9SMCNSxkJEHqWGDiMCuy6TXHgvjgwXGdXZZGXLKQvVE=
github.com/oras-project/artifacts-spec v1.0.0-rc.2/go.mod h1:Xch2aLzSwtkhbFFN6LUzTfLtukYvMMdXJ4oZ8O7BOdc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand All @@ -43,5 +41,5 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
oras.land/oras-go/v2 v2.0.0-rc.3 h1:O4GeIwJ9Ge7rbCkqa/M7DLrL55ww+ZEc+Rhc63OYitU=
oras.land/oras-go/v2 v2.0.0-rc.3/go.mod h1:PrY+cCglzK/DrQoJUtxbYVbL94ZHecVS3eJR01RglpE=
oras.land/oras-go/v2 v2.0.0-rc.4 h1:hg/R2znUQ1+qd43gRmL16VeX1GIZ8hQlLalBjYhhKSk=
oras.land/oras-go/v2 v2.0.0-rc.4/go.mod h1:YGHvWBGuqRlZgUyXUIoKsR3lcuCOb3DAtG0SEsEw1iY=
97 changes: 97 additions & 0 deletions internal/common/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package common

import (
"fmt"
"regexp"
"strings"

ldapv3 "github.com/go-ldap/ldap/v3"
)

const (
Wildcard = "*"
X509Subject = "x509.subject"
)

// isPresent is a utility function to check if a string exists in an array
func IsPresent(val string, values []string) bool {
for _, v := range values {
if v == val {
return true
}
}
return false
}

// Internal type to hold raw and parsed Distinguished Names
type ParsedDN struct {
RawString string
ParsedMap map[string]string
}

// ParseDistinguishedName parses a DN name and validates Notary V2 rules
func ParseDistinguishedName(name string) (map[string]string, error) {
mandatoryFields := []string{"C", "ST", "O"}
attrKeyValue := make(map[string]string)
dn, err := ldapv3.ParseDN(name)

if err != nil {
return nil, fmt.Errorf("distinguished name (DN) %q is not valid, it must contain 'C', 'ST', and 'O' RDN attributes at a minimum, and follow RFC 4514 standard", name)
}

for _, rdn := range dn.RDNs {

// multi-valued RDNs are not supported (TODO: add spec reference here)
if len(rdn.Attributes) > 1 {
return nil, fmt.Errorf("distinguished name (DN) %q has multi-valued RDN attributes, remove multi-valued RDN attributes as they are not supported", name)
}
for _, attribute := range rdn.Attributes {
if attrKeyValue[attribute.Type] == "" {
attrKeyValue[attribute.Type] = attribute.Value
} else {
return nil, fmt.Errorf("distinguished name (DN) %q has duplicate RDN attribute for %q, DN can only have unique RDN attributes", name, attribute.Type)
}
}
}

// Verify mandatory fields are present
for _, field := range mandatoryFields {
if attrKeyValue[field] == "" {
return nil, fmt.Errorf("distinguished name (DN) %q has no mandatory RDN attribute for %q, it must contain 'C', 'ST', and 'O' RDN attributes at a minimum", name, field)
}
}
// No errors
return attrKeyValue, nil
}

// IsSubsetDN returns true if dn1 is a subset of dn2 i.e. every key/value pair of dn1 has a matching key/value pair in dn2, otherwise returns false
func IsSubsetDN(dn1 map[string]string, dn2 map[string]string) bool {
for key := range dn1 {
if dn1[key] != dn2[key] {
return false
}
}
return true
}

// ValidateRegistryScopeFormat validates if a scope is following the format defined in distribution spec
func ValidateRegistryScopeFormat(scope string) error {
// Domain and Repository regexes are adapted from distribution implementation
// https://github.com/distribution/distribution/blob/main/reference/regexp.go#L31
domainRegexp := regexp.MustCompile(`^(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?$`)
repositoryRegexp := regexp.MustCompile(`^[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?(?:(?:/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?$`)
errorMessage := "registry scope %q is not valid, make sure it is the fully qualified registry URL without the scheme/protocol. e.g domain.com/my/repository"
firstSlash := strings.Index(scope, "/")
if firstSlash < 0 {
return fmt.Errorf(errorMessage, scope)
}
domain := scope[:firstSlash]
repository := scope[firstSlash+1:]

if domain == "" || repository == "" || !domainRegexp.MatchString(domain) || !repositoryRegexp.MatchString(repository) {
return fmt.Errorf(errorMessage, scope)
}

// No errors
return nil
}
52 changes: 29 additions & 23 deletions internal/mock/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import (
_ "embed"

"github.com/notaryproject/notation-core-go/signature"
"github.com/notaryproject/notation-go"
"github.com/notaryproject/notation-go/plugin"
"github.com/notaryproject/notation-go/plugin/manager"
"github.com/notaryproject/notation-go/registry"
"github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

//go:embed testdata/ca_valid_sig_env.json
Expand Down Expand Up @@ -40,13 +39,19 @@ var (
SampleArtifactUri = "registry.acme-rockets.io/software/net-monitor@sha256:60043cf45eaebc4c0867fea485a039b598f52fd09fd5b07b0b2d2f88fad9d74e"
SampleDigest = digest.Digest("sha256:60043cf45eaebc4c0867fea485a039b598f52fd09fd5b07b0b2d2f88fad9d74e")
Annotations = map[string]string{"key": "value"}
ImageDescriptor = notation.Descriptor{
ImageDescriptor = ocispec.Descriptor{
MediaType: "application/vnd.docker.distribution.manifest.v2+json",
Digest: SampleDigest,
Size: 528,
Annotations: nil,
}
JwsSigEnvDescriptor = notation.Descriptor{
SigManfiestDescriptor = ocispec.Descriptor{
MediaType: "application/vnd.cncf.oras.artifact.manifest.v1+json",
Digest: SampleDigest,
Size: 300,
Annotations: Annotations,
}
JwsSigEnvDescriptor = ocispec.Descriptor{
MediaType: "application/jose+json",
Digest: SampleDigest,
Size: 100,
Expand All @@ -60,39 +65,40 @@ var (
)

type Repository struct {
ResolveResponse notation.Descriptor
ResolveError error
ListSignatureManifestsResponse []registry.SignatureManifest
ListSignatureManifestsError error
GetResponse []byte
GetError error
ResolveResponse ocispec.Descriptor
ResolveError error
ListSignaturesResponse []ocispec.Descriptor
ListSignaturesError error
FetchSignatureBlobResponse []byte
FetchSignatureBlobError error
}

func NewRepository() Repository {
return Repository{
ResolveResponse: ImageDescriptor,
ListSignatureManifestsResponse: []registry.SignatureManifest{{
Blob: JwsSigEnvDescriptor,
Annotations: Annotations,
}},
GetResponse: MockCaValidSigEnv,
ResolveResponse: ImageDescriptor,
ListSignaturesResponse: []ocispec.Descriptor{SigManfiestDescriptor},
FetchSignatureBlobResponse: MockCaValidSigEnv,
}
}

func (t Repository) Resolve(ctx context.Context, reference string) (notation.Descriptor, error) {
func (t Repository) Resolve(ctx context.Context, reference string) (ocispec.Descriptor, error) {
return t.ResolveResponse, t.ResolveError
}

func (t Repository) ListSignatureManifests(ctx context.Context, manifestDigest digest.Digest) ([]registry.SignatureManifest, error) {
return t.ListSignatureManifestsResponse, t.ListSignatureManifestsError
func (t Repository) ListSignatures(ctx context.Context, desc ocispec.Descriptor, fn func(signatureManifests []ocispec.Descriptor) error) error {
err := fn(t.ListSignaturesResponse)
if err != nil {
return err
}
patrickzheng200 marked this conversation as resolved.
Show resolved Hide resolved
return t.ListSignaturesError
}

func (t Repository) GetBlob(ctx context.Context, digest digest.Digest) ([]byte, error) {
return t.GetResponse, t.GetError
func (t Repository) FetchSignatureBlob(ctx context.Context, desc ocispec.Descriptor) ([]byte, ocispec.Descriptor, error) {
return t.FetchSignatureBlobResponse, JwsSigEnvDescriptor, t.FetchSignatureBlobError
}

func (t Repository) PutSignatureManifest(ctx context.Context, signature []byte, signatureMediaType string, manifest notation.Descriptor, annotaions map[string]string) (notation.Descriptor, registry.SignatureManifest, error) {
return notation.Descriptor{}, registry.SignatureManifest{}, nil
func (t Repository) PushSignature(ctx context.Context, blob []byte, mediaType string, subject ocispec.Descriptor, annotations map[string]string) (blobDesc, manifestDesc ocispec.Descriptor, err error) {
return ocispec.Descriptor{}, ocispec.Descriptor{}, nil
}

type PluginManager struct {
Expand Down
25 changes: 25 additions & 0 deletions internal/mock_origin/mockfs/fs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package mockfs

import (
"io/fs"
"path/filepath"

"github.com/notaryproject/notation-go/dir"
)

type sysFSMock struct {
fs.FS
root string
}

func (s sysFSMock) SysPath(items ...string) (string, error) {
pathItems := []string{s.root}
pathItems = append(pathItems, items...)
return filepath.Join(pathItems...), nil
}

func NewSysFSMock(fsys fs.FS, root string) dir.SysFS {
return sysFSMock{
FS: fsys,
root: root}
}
Loading