Skip to content

Commit

Permalink
feat: basic function of backward compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
junczhu committed Jan 18, 2024
1 parent 69b4a2b commit 8cfe2f9
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 40 deletions.
52 changes: 19 additions & 33 deletions pkg/verifier/notation/notation.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"encoding/json"
"fmt"
paths "path/filepath"
"reflect"
"strings"

ratifyconfig "github.com/deislabs/ratify/config"
Expand Down Expand Up @@ -64,19 +65,6 @@ type NotationPluginVerifierConfig struct { //nolint:revive // ignore linter to h
TrustPolicyDoc trustpolicy.Document `json:"trustPolicyDoc"`
}

// NotationPluginVerifierConfig describes the configuration of notation verifier
type NotationPluginVerifierLegacyConfig struct { //nolint:revive // ignore linter to have unique type name
Name string `json:"name"`
ArtifactTypes string `json:"artifactTypes"`

// VerificationCerts is array of directories containing certificates.
VerificationCerts []string `json:"verificationCerts"`
// VerificationCerts is map defining which keyvault certificates belong to which trust store type and trust store name.
VerificationCertStores map[string][]string `json:"verificationCertStores"`
// TrustPolicyDoc represents a trustpolicy.json document. Reference: https://pkg.go.dev/github.com/notaryproject/[email protected]/verifier/trustpolicy#Document
TrustPolicyDoc trustpolicy.Document `json:"trustPolicyDoc"`
}

type notationPluginVerifier struct {
name string
verifierType string
Expand Down Expand Up @@ -204,16 +192,22 @@ func (v *notationPluginVerifier) verifySignature(ctx context.Context, subjectRef
func parseVerifierConfig(verifierConfig config.VerifierConfig, namespace string) (*NotationPluginVerifierConfig, error) {
verifierName := verifierConfig[types.Name].(string)
conf := &NotationPluginVerifierConfig{}
confLegacy := &NotationPluginVerifierLegacyConfig{}
verifierConfigBytes, err := json.Marshal(verifierConfig)
if err != nil {
return nil, re.ErrorCodeConfigInvalid.NewError(re.Verifier, verifierName, re.EmptyLink, err, nil, re.HideStackTrace)
}
if err := json.Unmarshal(verifierConfigBytes, &confLegacy); err != nil {
conf = convertToNewConfig(confLegacy)
} else if err := json.Unmarshal(verifierConfigBytes, &conf); err != nil {
if err := json.Unmarshal(verifierConfigBytes, &conf); err != nil {
return nil, re.ErrorCodeConfigInvalid.NewError(re.Verifier, verifierName, re.EmptyLink, err, fmt.Sprintf("failed to unmarshal to notationPluginVerifierConfig from: %+v.", verifierConfig), re.HideStackTrace)
}
// would optimize when have both ca and certs
if _, ok := conf.VerificationCertStores["certs"]; ok {
conf.VerificationCertStores["ca"] =
map[string][]interface{}{
"certs": conf.VerificationCertStores["certs"].([]interface{}),
}
delete(conf.VerificationCertStores, "certs")
}
logger.GetLogger(context.Background(), logOpt).Debugf("VerificationCertStores is empty %+v", conf.VerificationCertStores)
// append namespace to uniquely identify the certstore
if len(conf.VerificationCertStores) > 0 {
logger.GetLogger(context.Background(), logOpt).Debugf("VerificationCertStores is not empty, will append namespace %v to certificate store if resource does not already contain a namespace", namespace)
Expand All @@ -228,18 +222,6 @@ func parseVerifierConfig(verifierConfig config.VerifierConfig, namespace string)
return conf, nil
}

func convertToNewConfig(conf *NotationPluginVerifierLegacyConfig) *NotationPluginVerifierConfig {
newConf := &NotationPluginVerifierConfig{
Name: conf.Name,
ArtifactTypes: conf.ArtifactTypes,
VerificationCerts: conf.VerificationCerts,
VerificationCertStores: make(map[string]interface{}),
TrustPolicyDoc: conf.TrustPolicyDoc,
}
newConf.VerificationCertStores["ca"] = conf.VerificationCertStores
return newConf
}

// signatures should not have nested references
func (v *notationPluginVerifier) GetNestedReferences() []string {
return []string{}
Expand All @@ -252,12 +234,16 @@ func prependNamespaceToCertStore(verificationCertStore map[string]interface{}, n
}
for _, trustStoreType := range truststore.Types {
if mapValue, ok := verificationCertStore[string(trustStoreType)].(map[string][]string); ok {
certStores := mapValue[string(trustStoreType)]
for i, certstore := range certStores {
if !isNamespacedNamed(certstore) {
certStores[i] = namespace + constants.NamespaceSeperator + certstore
for _, certStores := range mapValue {
for i, certstore := range certStores {
if !isNamespacedNamed(certstore) {
certStores[i] = namespace + constants.NamespaceSeperator + certstore
}
}
}
} else {
logger.GetLogger(context.Background(), logOpt).Debugf("truststore type %v is not a map[string][]string, skipping", trustStoreType)
logger.GetLogger(context.Background(), logOpt).Debugf("verificationCertStore type is %v", reflect.TypeOf(verificationCertStore[string(trustStoreType)]))
}
}
return verificationCertStore, nil
Expand Down
32 changes: 28 additions & 4 deletions pkg/verifier/notation/notation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"context"
"crypto/x509"
"crypto/x509/pkix"
"encoding/json"
"fmt"
paths "path/filepath"
"reflect"
Expand Down Expand Up @@ -205,13 +206,17 @@ func TestCanVerify(t *testing.T) {

func TestParseVerifierConfig(t *testing.T) {
verificationCertStoresSample := make(map[string]interface{})
verificationCertStoresSample["ca"] = map[string][]string{
verificationCertStoresSample["ca"] = map[string][]interface{}{
"cert-ca": {"defaultns/akv1", "testns/akv2"},
"cert-ca2": {"testns/akv3", "testns/akv4"},
}
verificationCertStoresSample["signingAuthority"] = map[string][]string{
"cert-sa": {"defaultns/akv5", "testns/akv6"},
"cert-sa2": {"testns/akv7", "testns/akv8"},
verificationCertStoresSample2 := make(map[string]interface{})
verificationCertStoresSample2["certs"] = []string{
"defaultns/akv1", "testns/akv2",
}
verificationCertStoresSample2Expected := make(map[string]interface{})
verificationCertStoresSample2Expected["ca"] = map[string][]string{
"certs": {"defaultns/akv1", "testns/akv2"},
}
tests := []struct {
name string
Expand Down Expand Up @@ -265,12 +270,31 @@ func TestParseVerifierConfig(t *testing.T) {
VerificationCertStores: verificationCertStoresSample,
},
},
{
name: "successfully parsed with specified cert stores",
configMap: map[string]interface{}{
"name": test,
"verificationCerts": []string{testPath},
"verificationCertStores": verificationCertStoresSample2,
},
expectErr: false,
expect: &NotationPluginVerifierConfig{
Name: test,
VerificationCerts: []string{testPath, defaultCertDir},
VerificationCertStores: verificationCertStoresSample2Expected,
},
},
}

//TODO add new test for parseVerifierConfig
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
notationPluginConfig, err := parseVerifierConfig(tt.configMap, "testns")
verifierConfigBytes, _ := json.Marshal(tt.expect)
json.Unmarshal(verifierConfigBytes, &tt.expect)

verifierConfigBytes, _ = json.Marshal(notationPluginConfig)
json.Unmarshal(verifierConfigBytes, &notationPluginConfig)

if (err != nil) != tt.expectErr {
t.Errorf("error = %v, expectErr = %v", err, tt.expectErr)
Expand Down
9 changes: 6 additions & 3 deletions pkg/verifier/notation/truststore.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ import (
"context"
"crypto/x509"
"errors"
"fmt"

"github.com/deislabs/ratify/internal/logger"
"github.com/deislabs/ratify/pkg/controllers"
"github.com/deislabs/ratify/pkg/utils"
"github.com/notaryproject/notation-go/verifier/truststore"
"github.com/sirupsen/logrus"
)

var logOpt = logger.Option{
Expand Down Expand Up @@ -54,7 +54,7 @@ func (s trustStore) GetCertificates(ctx context.Context, _ truststore.Type, name

func (s trustStore) getCertificatesInternal(ctx context.Context, storeType truststore.Type, namedStore string, certificatesMap map[string][]*x509.Certificate) ([]*x509.Certificate, error) {
certs := make([]*x509.Certificate, 0)

logger.GetLogger(ctx, logOpt).Debugf("truststore getting certStore %v", s.certStoresByType)
// certs configured for this namedStore overrides cert path
if mapValue, ok := s.certStoresByType[string(storeType)].(map[string][]string); ok {
if certGroup := mapValue[namedStore]; len(certGroup) > 0 {
Expand All @@ -67,7 +67,8 @@ func (s trustStore) getCertificatesInternal(ctx context.Context, storeType trust
certs = append(certs, result...)
}
if len(certs) == 0 {
return certs, fmt.Errorf("unable to fetch certificates for namedStore: %+v", namedStore)
logger.GetLogger(ctx, logOpt).Warnf("unable to fetch certificates for namedStore: %+v", namedStore)
// return certs, fmt.Errorf("unable to fetch certificates for namedStore: %+v", namedStore)
}
} else {
for _, path := range s.certPaths {
Expand Down Expand Up @@ -96,7 +97,9 @@ func (s trustStore) filterValidCerts(certs []*x509.Certificate) ([]*x509.Certifi
filteredCerts = append(filteredCerts, cert)
}
if len(filteredCerts) == 0 {
logrus.Debugf("start filteredCerts")
return nil, errors.New("valid certificates must be provided, only CA certificates or self-signed signing certificates are supported")
}
logrus.Debugf("end filteredCerts")
return filteredCerts, nil
}

0 comments on commit 8cfe2f9

Please sign in to comment.