Skip to content

Commit

Permalink
Merge branch 'dev' into alibabacloud-rrsa
Browse files Browse the repository at this point in the history
  • Loading branch information
DahuK authored Nov 8, 2024
2 parents dcaf03e + 4510dd8 commit a36efd0
Show file tree
Hide file tree
Showing 7 changed files with 338 additions and 13 deletions.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ require (
github.com/golang/protobuf v1.5.4
github.com/google/go-containerregistry v0.20.2
github.com/gorilla/mux v1.8.1
github.com/notaryproject/notation-core-go v1.1.0
github.com/notaryproject/notation-go v1.2.1
github.com/notaryproject/notation-core-go v1.2.0-rc.1
github.com/notaryproject/notation-go v1.3.0-rc.1
github.com/notaryproject/notation-plugin-framework-go v1.0.0
github.com/open-policy-agent/cert-controller v0.8.0
github.com/open-policy-agent/frameworks/constraint v0.0.0-20230411224310-3f237e2710fa
Expand Down Expand Up @@ -241,7 +241,7 @@ require (
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.28.0
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect
golang.org/x/mod v0.20.0 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sys v0.26.0 // indirect
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -546,10 +546,10 @@ github.com/mozillazg/docker-credential-acr-helper v0.3.0/go.mod h1:cZlu3tof523uj
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/notaryproject/notation-core-go v1.1.0 h1:xCybcONOKcCyPNihJUSa+jRNsyQFNkrk0eJVVs1kWeg=
github.com/notaryproject/notation-core-go v1.1.0/go.mod h1:+6AOh41JPrnVLbW/19SJqdhVHwKgIINBO/np0e7nXJA=
github.com/notaryproject/notation-go v1.2.1 h1:fbCMBcvg1xttrisd5CyM60QDectGYYF701Us0M3cKN8=
github.com/notaryproject/notation-go v1.2.1/go.mod h1:re9V+TfuNRaUq5e3NuNcCJN53++sL2KbnJrjGyOUpgE=
github.com/notaryproject/notation-core-go v1.2.0-rc.1 h1:VMFlG+9a1JoNAQ3M96g8iqCq0cDRtE7XBaiTD8Ouvqw=
github.com/notaryproject/notation-core-go v1.2.0-rc.1/go.mod h1:b/70rA4OgOHlg0A7pb8zTWKJadFO6781zS3a37KHEJQ=
github.com/notaryproject/notation-go v1.3.0-rc.1 h1:pm9tdUy2tWYqlwyRDZyKXgLwAscDATPUYv0ul2RK/Iw=
github.com/notaryproject/notation-go v1.3.0-rc.1/go.mod h1:W4o45yolX4Q+3PKlcpGleLLXEKWHa3BshEqw/JX5c6I=
github.com/notaryproject/notation-plugin-framework-go v1.0.0 h1:6Qzr7DGXoCgXEQN+1gTZWuJAZvxh3p8Lryjn5FaLzi4=
github.com/notaryproject/notation-plugin-framework-go v1.0.0/go.mod h1:RqWSrTOtEASCrGOEffq0n8pSg2KOgKYiWqFWczRSics=
github.com/notaryproject/tspclient-go v0.2.0 h1:g/KpQGmyk/h7j60irIRG1mfWnibNOzJ8WhLqAzuiQAQ=
Expand Down Expand Up @@ -825,8 +825,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down
37 changes: 33 additions & 4 deletions pkg/verifier/notation/notation.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import (
"github.com/ratify-project/ratify/pkg/verifier/factory"
"github.com/ratify-project/ratify/pkg/verifier/types"

"github.com/notaryproject/notation-core-go/revocation"
"github.com/notaryproject/notation-core-go/revocation/purpose"
_ "github.com/notaryproject/notation-core-go/signature/cose" // register COSE signature
_ "github.com/notaryproject/notation-core-go/signature/jws" // register JWS signature
"github.com/notaryproject/notation-go"
Expand Down Expand Up @@ -103,8 +105,7 @@ func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.V
if err != nil {
return nil, re.ErrorCodePluginInitFailure.WithDetail("Failed to create the Notation Verifier").WithError(err)
}

verifyService, err := getVerifierService(conf, pluginDirectory)
verifyService, err := getVerifierService(conf, pluginDirectory, NewRevocationFactoryImpl())
if err != nil {
return nil, re.ErrorCodePluginInitFailure.WithDetail("Failed to create the Notation Verifier").WithError(err)
}
Expand Down Expand Up @@ -176,12 +177,40 @@ func (v *notationPluginVerifier) Verify(ctx context.Context,
return verifier.NewVerifierResult("", v.name, v.verifierType, "Notation signature verification success", true, nil, extensions), nil
}

func getVerifierService(conf *NotationPluginVerifierConfig, pluginDirectory string) (notation.Verifier, error) {
func getVerifierService(conf *NotationPluginVerifierConfig, pluginDirectory string, revocationFactory RevocationFactory) (notation.Verifier, error) {
store, err := newTrustStore(conf.VerificationCerts, conf.VerificationCertStores)
if err != nil {
return nil, err
}
verifier, err := notationVerifier.New(&conf.TrustPolicyDoc, store, NewRatifyPluginManager(pluginDirectory))

// revocation check using corecrl from notation-core-go and crl from notation-go
// This is the implementation for revocation check from notation cli to support crl and cache configurations
// removed timeout
// Related PR: notaryproject/notation#1043
// Related File: https://github.com/notaryproject/notation/commits/main/cmd/notation/verify.go5
crlFetcher, err := revocationFactory.NewFetcher()
if err != nil {
return nil, err
}
revocationCodeSigningValidator, err := revocationFactory.NewValidator(revocation.Options{
CRLFetcher: crlFetcher,
CertChainPurpose: purpose.CodeSigning,
})
if err != nil {
return nil, err
}
revocationTimestampingValidator, err := revocationFactory.NewValidator(revocation.Options{
CRLFetcher: crlFetcher,
CertChainPurpose: purpose.Timestamping,
})
if err != nil {
return nil, err
}

verifier, err := notationVerifier.NewWithOptions(&conf.TrustPolicyDoc, store, NewRatifyPluginManager(pluginDirectory), notationVerifier.VerifierOptions{
RevocationCodeSigningValidator: revocationCodeSigningValidator,
RevocationTimestampingValidator: revocationTimestampingValidator,
})
if err != nil {
return nil, re.ErrorCodePluginInitFailure.WithDetail("Failed to create the Notation Verifier").WithError(err)
}
Expand Down
103 changes: 103 additions & 0 deletions pkg/verifier/notation/notation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"fmt"
"net/http"
paths "path/filepath"
"reflect"
"testing"

"github.com/notaryproject/notation-core-go/revocation"
corecrl "github.com/notaryproject/notation-core-go/revocation/crl"
"github.com/notaryproject/notation-core-go/revocation/purpose"
sig "github.com/notaryproject/notation-core-go/signature"
"github.com/notaryproject/notation-go"
"github.com/opencontainers/go-digest"
Expand Down Expand Up @@ -558,3 +562,102 @@ func TestNormalizeLegacyCertStore(t *testing.T) {
})
}
}
func TestGetVerifierService(t *testing.T) {
tests := []struct {
name string
conf *NotationPluginVerifierConfig
pluginDir string
RevocationFactory RevocationFactory
expectErr bool
errContent error
}{
{
name: "failed to create CRL fetcher",
conf: &NotationPluginVerifierConfig{
VerificationCerts: []string{defaultCertDir},
},
pluginDir: "",
RevocationFactory: mockRevocationFactory{httpClient: &http.Client{}, failFetcher: true},
expectErr: true,
errContent: nil,
},
{
name: "failed to create file cache",
conf: &NotationPluginVerifierConfig{
VerificationCerts: []string{defaultCertDir},
},
pluginDir: "",
RevocationFactory: mockRevocationFactory{httpClient: &http.Client{}, failFileCache: true},
expectErr: true,
errContent: nil,
},
{
name: "failed to create code signing validator",
conf: &NotationPluginVerifierConfig{
VerificationCerts: []string{defaultCertDir},
},
pluginDir: "",
RevocationFactory: mockRevocationFactory{httpClient: &http.Client{}, failCodeSigningValidator: true},
expectErr: true,
errContent: fmt.Errorf("failed to create code signing validator"),
},
{
name: "failed to create timestamping validator",
conf: &NotationPluginVerifierConfig{
VerificationCerts: []string{defaultCertDir},
},
pluginDir: "",
RevocationFactory: mockRevocationFactory{httpClient: &http.Client{}, failTimestampingValidator: true},
expectErr: true,
errContent: fmt.Errorf("failed to create timestamping validator"),
},
{
name: "failed to create verifier",
conf: &NotationPluginVerifierConfig{
VerificationCerts: []string{defaultCertDir},
},
pluginDir: "",
RevocationFactory: mockRevocationFactory{httpClient: &http.Client{}, failVerifier: true},
expectErr: true,
errContent: nil,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := getVerifierService(tt.conf, tt.pluginDir, tt.RevocationFactory)
if (err != nil) != tt.expectErr {
t.Errorf("error = %v, expectErr = %v", err, tt.expectErr)
}
if tt.errContent != nil && err.Error() != tt.errContent.Error() {
t.Errorf("error = %v, expectErr = %v, content = %v", err, tt.expectErr, tt.errContent)
}
})
}
}

type mockRevocationFactory struct {
failFetcher bool
failFileCache bool
failCodeSigningValidator bool
failTimestampingValidator bool
failVerifier bool
httpClient *http.Client
}

func (m mockRevocationFactory) NewFetcher() (corecrl.Fetcher, error) {
if m.failFetcher {
return nil, fmt.Errorf("failed to create fetcher")
}
return corecrl.NewHTTPFetcher(m.httpClient)
}

func (m mockRevocationFactory) NewValidator(opts revocation.Options) (revocation.Validator, error) {
if m.failCodeSigningValidator && opts.CertChainPurpose == purpose.CodeSigning {
return nil, fmt.Errorf("failed to create code signing validator")
}
if m.failTimestampingValidator && opts.CertChainPurpose == purpose.Timestamping {
return nil, fmt.Errorf("failed to create timestamping validator")
}
return revocation.NewWithOptions(opts)
}
63 changes: 63 additions & 0 deletions pkg/verifier/notation/notationrevocationfactory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright The Ratify 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 notation

import (
"net/http"

"github.com/notaryproject/notation-core-go/revocation"
corecrl "github.com/notaryproject/notation-core-go/revocation/crl"
"github.com/notaryproject/notation-go/dir"
"github.com/notaryproject/notation-go/verifier/crl"
)

type RevocationFactoryImpl struct {
cacheRoot string
httpClient *http.Client
}

// NewRevocationFactoryImpl returns a new NewRevocationFactoryImpl instance
func NewRevocationFactoryImpl() RevocationFactory {
return &RevocationFactoryImpl{
cacheRoot: dir.PathCRLCache,
httpClient: &http.Client{},
}
}

// NewFetcher returns a new fetcher instance
func (f *RevocationFactoryImpl) NewFetcher() (corecrl.Fetcher, error) {
crlFetcher, err := corecrl.NewHTTPFetcher(f.httpClient)
if err != nil {
return nil, err
}
crlFetcher.Cache, err = newFileCache(f.cacheRoot)
if err != nil {
return nil, err
}
return crlFetcher, nil
}

// NewValidator returns a new validator instance
func (f *RevocationFactoryImpl) NewValidator(opts revocation.Options) (revocation.Validator, error) {
return revocation.NewWithOptions(opts)
}

// newFileCache returns a new file cache instance
func newFileCache(root string) (*crl.FileCache, error) {
cacheRoot, err := dir.CacheFS().SysPath(root)
if err != nil {
return nil, err
}
return crl.NewFileCache(cacheRoot)
}
103 changes: 103 additions & 0 deletions pkg/verifier/notation/notationrevocationfactory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright The Ratify 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 notation

import (
"net/http"
"runtime"
"testing"

"github.com/notaryproject/notation-core-go/revocation"
"github.com/stretchr/testify/assert"
)

func TestNewRevocationFactoryImpl(t *testing.T) {
factory := NewRevocationFactoryImpl()
assert.NotNil(t, factory)
}

func TestNewFetcher(t *testing.T) {
tests := []struct {
name string
cacheRoot string
httpClient *http.Client
wantErr bool
}{
{
name: "valid fetcher",
cacheRoot: "/valid/path",
httpClient: &http.Client{},
wantErr: false,
},
{
name: "invalid fetcher with nil httpClient",
cacheRoot: "/valid/path",
httpClient: nil,
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
factory := &RevocationFactoryImpl{
cacheRoot: tt.cacheRoot,
httpClient: tt.httpClient,
}

fetcher, err := factory.NewFetcher()
if tt.wantErr {
assert.Error(t, err)
assert.Nil(t, fetcher)
}
})
}
}

func TestNewValidator(t *testing.T) {
factory := &RevocationFactoryImpl{}
opts := revocation.Options{}

validator, err := factory.NewValidator(opts)
assert.NoError(t, err)
assert.NotNil(t, validator)
}
func TestNewFileCache(t *testing.T) {
tests := []struct {
name string
cacheRoot string
wantErr bool
}{
{
name: "valid cache root",
cacheRoot: "/valid/path",
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("skipping test on Windows")
}
cache, err := newFileCache(tt.cacheRoot)
if tt.wantErr {
assert.Error(t, err)
assert.Nil(t, cache)
} else {
assert.NoError(t, err)
assert.NotNil(t, cache)
}
})
}
}
Loading

0 comments on commit a36efd0

Please sign in to comment.