diff --git a/pkg/client/common/discovery/discoveryfilter_test.go b/pkg/client/common/discovery/discoveryfilter_test.go index 8df98b329e..5ffd94c960 100644 --- a/pkg/client/common/discovery/discoveryfilter_test.go +++ b/pkg/client/common/discovery/discoveryfilter_test.go @@ -12,6 +12,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/client/common/discovery/staticdiscovery" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + fabImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab" "github.com/hyperledger/fabric-sdk-go/pkg/fab/peer" ) @@ -32,7 +33,7 @@ func TestDiscoveryFilter(t *testing.T) { t.Fatalf(err.Error()) } - _, config1, _, err := config.FromBackend(configBackend)() + config1, err := fabImpl.ConfigFromBackend(configBackend) if err != nil { t.Fatalf(err.Error()) } diff --git a/pkg/client/common/discovery/staticdiscovery/staticdiscovery_test.go b/pkg/client/common/discovery/staticdiscovery/staticdiscovery_test.go index 667e02c843..219501d251 100644 --- a/pkg/client/common/discovery/staticdiscovery/staticdiscovery_test.go +++ b/pkg/client/common/discovery/staticdiscovery/staticdiscovery_test.go @@ -11,6 +11,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + fabImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab" "github.com/hyperledger/fabric-sdk-go/pkg/fab/peer" ) @@ -21,7 +22,7 @@ func TestStaticDiscovery(t *testing.T) { t.Fatalf(err.Error()) } - _, config1, _, err := config.FromBackend(configBackend)() + config1, err := fabImpl.ConfigFromBackend(configBackend) if err != nil { t.Fatalf(err.Error()) } @@ -61,7 +62,7 @@ func TestStaticDiscoveryWhenChannelIsEmpty(t *testing.T) { t.Fatalf(err.Error()) } - _, config1, _, err := config.FromBackend(configBackend)() + config1, err := fabImpl.ConfigFromBackend(configBackend) if err != nil { t.Fatalf(err.Error()) } diff --git a/pkg/client/common/selection/staticselection/staticselection_test.go b/pkg/client/common/selection/staticselection/staticselection_test.go index b9d707e03b..65008e3238 100644 --- a/pkg/client/common/selection/staticselection/staticselection_test.go +++ b/pkg/client/common/selection/staticselection/staticselection_test.go @@ -14,6 +14,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + fabImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab" fabmocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks" mspmocks "github.com/hyperledger/fabric-sdk-go/pkg/msp/test/mockmsp" ) @@ -29,9 +30,7 @@ func TestStaticSelection(t *testing.T) { t.Fatalf(err.Error()) } - configProv := config.FromBackend(configBackend) - - _, config, _, err := configProv() + config, err := fabImpl.ConfigFromBackend(configBackend) if err != nil { t.Fatalf(err.Error()) } diff --git a/pkg/client/msp/client_test.go b/pkg/client/msp/client_test.go index 8018330687..f17639b31c 100644 --- a/pkg/client/msp/client_test.go +++ b/pkg/client/msp/client_test.go @@ -22,7 +22,9 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" mspctx "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" + mspImpl "github.com/hyperledger/fabric-sdk-go/pkg/msp" "github.com/hyperledger/fabric-sdk-go/pkg/msp/test/mockmsp" ) @@ -177,11 +179,17 @@ func (f *textFixture) setup() *fabsdk.FabricSDK { panic(fmt.Sprintf("SDK init failed: %v", err)) } - f.cryptoSuiteConfig, _, f.identityConfig, err = sdk.Config()() + configBackend, err := sdk.Config() if err != nil { panic(fmt.Sprintf("Failed to get config: %v", err)) } + f.cryptoSuiteConfig = cryptosuite.ConfigFromBackend(configBackend) + f.identityConfig, err = mspImpl.ConfigFromBackend(configBackend) + if err != nil { + panic(fmt.Sprintf("Failed to get identity config: %v", err)) + } + // Delete all private keys from the crypto suite store // and users from the user store cleanup(f.cryptoSuiteConfig.KeyStorePath()) diff --git a/pkg/client/resmgmt/resmgmt_test.go b/pkg/client/resmgmt/resmgmt_test.go index 3ab598af6d..c564ee8312 100644 --- a/pkg/client/resmgmt/resmgmt_test.go +++ b/pkg/client/resmgmt/resmgmt_test.go @@ -29,6 +29,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" contextImpl "github.com/hyperledger/fabric-sdk-go/pkg/context" configImpl "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + fabImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab" fcmocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks" "github.com/hyperledger/fabric-sdk-go/pkg/fab/peer" "github.com/hyperledger/fabric-sdk-go/pkg/fab/resource/api" @@ -282,7 +283,7 @@ func TestOrdererConfigFail(t *testing.T) { configBackend, err := configImpl.FromFile("./testdata/noorderer_test.yaml")() assert.Nil(t, err) - _, noOrdererConfig, _, err := configImpl.FromBackend(configBackend)() + noOrdererConfig, err := fabImpl.ConfigFromBackend(configBackend) assert.Nil(t, err) ctx.SetEndpointConfig(noOrdererConfig) @@ -319,7 +320,7 @@ func TestJoinChannelNoOrdererConfig(t *testing.T) { if err != nil { t.Fatal(err) } - _, noOrdererConfig, _, err := configImpl.FromBackend(configBackend)() + noOrdererConfig, err := fabImpl.ConfigFromBackend(configBackend) if err != nil { t.Fatal(err) } @@ -334,7 +335,7 @@ func TestJoinChannelNoOrdererConfig(t *testing.T) { if err != nil { t.Fatal(err) } - _, invalidChOrdererConfig, _, err := configImpl.FromBackend(configBackend)() + invalidChOrdererConfig, err := fabImpl.ConfigFromBackend(configBackend) if err != nil { t.Fatal(err) } @@ -352,7 +353,7 @@ func TestJoinChannelNoOrdererConfig(t *testing.T) { if err != nil { t.Fatal(err) } - _, invalidOrdererConfig, _, err := configImpl.FromBackend(configBackend)() + invalidOrdererConfig, err := fabImpl.ConfigFromBackend(configBackend) if err != nil { t.Fatal(err) } @@ -1177,7 +1178,7 @@ func TestCCProposal(t *testing.T) { if err != nil { t.Fatal(err) } - _, cfg, _, err := configImpl.FromBackend(configBackend)() + cfg, err := fabImpl.ConfigFromBackend(configBackend) if err != nil { t.Fatal(err) } @@ -1235,7 +1236,7 @@ func TestCCProposal(t *testing.T) { if err != nil { t.Fatal(err) } - _, cfg, _, err = configImpl.FromBackend(configBackend)() + cfg, err = fabImpl.ConfigFromBackend(configBackend) if err != nil { t.Fatal(err) } @@ -1262,7 +1263,8 @@ func TestCCProposalFailed(t *testing.T) { if err != nil { t.Fatal(err) } - _, cfg, _, err := configImpl.FromBackend(configBackend)() + + cfg, err := fabImpl.ConfigFromBackend(configBackend) if err != nil { t.Fatal(err) } @@ -1373,7 +1375,7 @@ func getNetworkConfig(t *testing.T) fab.EndpointConfig { t.Fatal(err) } - _, config, _, err := configImpl.FromBackend(configBackend)() + config, err := fabImpl.ConfigFromBackend(configBackend) if err != nil { t.Fatal(err) } diff --git a/pkg/common/providers/core/provider.go b/pkg/common/providers/core/provider.go index 063e5591e4..95b52ae6d0 100644 --- a/pkg/common/providers/core/provider.go +++ b/pkg/common/providers/core/provider.go @@ -24,8 +24,6 @@ type CryptoSuiteConfig interface { type Providers interface { CryptoSuite() CryptoSuite SigningManager() SigningManager - //TODO to be removed - CryptoSuiteConfig() CryptoSuiteConfig } //ConfigProvider provides config backend for SDK diff --git a/pkg/common/providers/fab/provider.go b/pkg/common/providers/fab/provider.go index abc023fdb1..0378453266 100644 --- a/pkg/common/providers/fab/provider.go +++ b/pkg/common/providers/fab/provider.go @@ -86,8 +86,6 @@ type EndpointConfig interface { MSPID(org string) (string, error) PeerMSPID(name string) (string, error) OrderersConfig() ([]OrdererConfig, error) - //TODO to be removed, not a config item - RandomOrdererConfig() (*OrdererConfig, error) OrdererConfig(name string) (*OrdererConfig, error) PeersConfig(org string) ([]PeerConfig, error) PeerConfig(org string, name string) (*PeerConfig, error) diff --git a/pkg/common/providers/test/mockcontext/mockcontext.gen.go b/pkg/common/providers/test/mockcontext/mockcontext.gen.go index 527903a965..26c4a84346 100644 --- a/pkg/common/providers/test/mockcontext/mockcontext.gen.go +++ b/pkg/common/providers/test/mockcontext/mockcontext.gen.go @@ -60,18 +60,6 @@ func (mr *MockProvidersMockRecorder) CryptoSuite() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CryptoSuite", reflect.TypeOf((*MockProviders)(nil).CryptoSuite)) } -// CryptoSuiteConfig mocks base method -func (m *MockProviders) CryptoSuiteConfig() core.CryptoSuiteConfig { - ret := m.ctrl.Call(m, "CryptoSuiteConfig") - ret0, _ := ret[0].(core.CryptoSuiteConfig) - return ret0 -} - -// CryptoSuiteConfig indicates an expected call of CryptoSuiteConfig -func (mr *MockProvidersMockRecorder) CryptoSuiteConfig() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CryptoSuiteConfig", reflect.TypeOf((*MockProviders)(nil).CryptoSuiteConfig)) -} - // DiscoveryProvider mocks base method func (m *MockProviders) DiscoveryProvider() fab.DiscoveryProvider { ret := m.ctrl.Call(m, "DiscoveryProvider") @@ -216,18 +204,6 @@ func (mr *MockClientMockRecorder) CryptoSuite() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CryptoSuite", reflect.TypeOf((*MockClient)(nil).CryptoSuite)) } -// CryptoSuiteConfig mocks base method -func (m *MockClient) CryptoSuiteConfig() core.CryptoSuiteConfig { - ret := m.ctrl.Call(m, "CryptoSuiteConfig") - ret0, _ := ret[0].(core.CryptoSuiteConfig) - return ret0 -} - -// CryptoSuiteConfig indicates an expected call of CryptoSuiteConfig -func (mr *MockClientMockRecorder) CryptoSuiteConfig() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CryptoSuiteConfig", reflect.TypeOf((*MockClient)(nil).CryptoSuiteConfig)) -} - // DiscoveryProvider mocks base method func (m *MockClient) DiscoveryProvider() fab.DiscoveryProvider { ret := m.ctrl.Call(m, "DiscoveryProvider") diff --git a/pkg/common/providers/test/mockcore/mockcore.gen.go b/pkg/common/providers/test/mockcore/mockcore.gen.go index 2387e12d42..ac48414851 100644 --- a/pkg/common/providers/test/mockcore/mockcore.gen.go +++ b/pkg/common/providers/test/mockcore/mockcore.gen.go @@ -230,18 +230,6 @@ func (mr *MockProvidersMockRecorder) CryptoSuite() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CryptoSuite", reflect.TypeOf((*MockProviders)(nil).CryptoSuite)) } -// CryptoSuiteConfig mocks base method -func (m *MockProviders) CryptoSuiteConfig() core.CryptoSuiteConfig { - ret := m.ctrl.Call(m, "CryptoSuiteConfig") - ret0, _ := ret[0].(core.CryptoSuiteConfig) - return ret0 -} - -// CryptoSuiteConfig indicates an expected call of CryptoSuiteConfig -func (mr *MockProvidersMockRecorder) CryptoSuiteConfig() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CryptoSuiteConfig", reflect.TypeOf((*MockProviders)(nil).CryptoSuiteConfig)) -} - // SigningManager mocks base method func (m *MockProviders) SigningManager() core.SigningManager { ret := m.ctrl.Call(m, "SigningManager") diff --git a/pkg/common/providers/test/mockfab/mockfab.gen.go b/pkg/common/providers/test/mockfab/mockfab.gen.go index 2c93281218..5b0252f017 100644 --- a/pkg/common/providers/test/mockfab/mockfab.gen.go +++ b/pkg/common/providers/test/mockfab/mockfab.gen.go @@ -218,19 +218,6 @@ func (mr *MockEndpointConfigMockRecorder) PeersConfig(arg0 interface{}) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PeersConfig", reflect.TypeOf((*MockEndpointConfig)(nil).PeersConfig), arg0) } -// RandomOrdererConfig mocks base method -func (m *MockEndpointConfig) RandomOrdererConfig() (*fab.OrdererConfig, error) { - ret := m.ctrl.Call(m, "RandomOrdererConfig") - ret0, _ := ret[0].(*fab.OrdererConfig) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// RandomOrdererConfig indicates an expected call of RandomOrdererConfig -func (mr *MockEndpointConfigMockRecorder) RandomOrdererConfig() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RandomOrdererConfig", reflect.TypeOf((*MockEndpointConfig)(nil).RandomOrdererConfig)) -} - // TLSCACertPool mocks base method func (m *MockEndpointConfig) TLSCACertPool(arg0 ...*x509.Certificate) (*x509.CertPool, error) { varargs := []interface{}{} diff --git a/pkg/context/context.go b/pkg/context/context.go index d63eb28313..b08176f05c 100644 --- a/pkg/context/context.go +++ b/pkg/context/context.go @@ -79,11 +79,6 @@ func (c *Provider) CryptoSuite() core.CryptoSuite { return c.cryptoSuite } -// CryptoSuiteConfig returns cryptosuite config. -func (c *Provider) CryptoSuiteConfig() core.CryptoSuiteConfig { - return c.cryptoSuiteConfig -} - // IdentityManager returns identity manager for organization func (c *Provider) IdentityManager(orgName string) (msp.IdentityManager, bool) { return c.idMgmtProvider.IdentityManager(orgName) diff --git a/pkg/core/config/config.go b/pkg/core/config/config.go index f2381db34e..efd3b16d73 100644 --- a/pkg/core/config/config.go +++ b/pkg/core/config/config.go @@ -16,11 +16,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/logging" "github.com/pkg/errors" - "regexp" - "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" - "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" - "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" ) var logger = logging.NewLogger("fabsdk/core") @@ -33,32 +29,18 @@ type options struct { templatePath string } +const ( + cmdRoot = "FABRIC_SDK" +) + // Option configures the package. type Option func(opts *options) error -//Provider provides all config implementations -//TODO to be removed once FromBackend in replaced with 3 functions for each config Type -type Provider func() (core.CryptoSuiteConfig, fab.EndpointConfig, msp.IdentityConfig, error) - // FromReader loads configuration from in. // configType can be "json" or "yaml". func FromReader(in io.Reader, configType string, opts ...Option) core.ConfigProvider { return func() (core.ConfigBackend, error) { - backend, err := newBackend(opts...) - if err != nil { - return nil, err - } - - if configType == "" { - return nil, errors.New("empty config type") - } - - // read config from bytes array, but must set ConfigType - // for viper to properly unmarshal the bytes array - backend.configViper.SetConfigType(configType) - backend.configViper.MergeConfig(in) - - return backend, nil + return initFromReader(in, configType, opts...) } } @@ -85,24 +67,39 @@ func FromFile(name string, opts ...Option) core.ConfigProvider { return nil, errors.Wrap(err, "loading config file failed") } + setLogLevel(backend) + return backend, nil } } // FromRaw will initialize the configs from a byte array func FromRaw(configBytes []byte, configType string, opts ...Option) core.ConfigProvider { - buf := bytes.NewBuffer(configBytes) - logger.Debugf("config.FromRaw buf Len is %d, Cap is %d: %s", buf.Len(), buf.Cap(), buf) - - return FromReader(buf, configType, opts...) + return func() (core.ConfigBackend, error) { + buf := bytes.NewBuffer(configBytes) + logger.Debugf("config.FromRaw buf Len is %d, Cap is %d: %s", buf.Len(), buf.Cap(), buf) + return initFromReader(buf, configType, opts...) + } } -// FromBackend Creates config provider from config backend -//TODO to be replaced with 3 functions to get 3 kinds of configs -func FromBackend(backend core.ConfigBackend) Provider { - return func() (core.CryptoSuiteConfig, fab.EndpointConfig, msp.IdentityConfig, error) { - return initConfig(backend) +func initFromReader(in io.Reader, configType string, opts ...Option) (core.ConfigBackend, error) { + backend, err := newBackend(opts...) + if err != nil { + return nil, err + } + + if configType == "" { + return nil, errors.New("empty config type") } + + // read config from bytes array, but must set ConfigType + // for viper to properly unmarshal the bytes array + backend.configViper.SetConfigType(configType) + backend.configViper.MergeConfig(in) + + setLogLevel(backend) + + return backend, nil } // WithEnvPrefix defines the prefix for environment variable overrides. @@ -151,44 +148,15 @@ func newViper(cmdRootPrefix string) *viper.Viper { return myViper } -func initConfig(backend core.ConfigBackend) (core.CryptoSuiteConfig, fab.EndpointConfig, msp.IdentityConfig, error) { - - configBackend := &Backend{coreBackend: backend} - setLogLevel(configBackend) - for _, logModule := range logModules { - logger.Debugf("config %s logging level is set to: %s", logModule, logging.ParseString(logging.GetLevel(logModule))) - } - - cryptoConfig := &CryptoSuiteConfig{backend: configBackend} - endpointConfig := &EndpointConfig{backend: configBackend} - - if err := endpointConfig.cacheNetworkConfiguration(); err != nil { - return nil, nil, nil, errors.WithMessage(err, "network configuration load failed") - } - //Compile the entityMatchers - endpointConfig.peerMatchers = make(map[int]*regexp.Regexp) - endpointConfig.ordererMatchers = make(map[int]*regexp.Regexp) - endpointConfig.caMatchers = make(map[int]*regexp.Regexp) - - matchError := endpointConfig.compileMatchers() - if matchError != nil { - return nil, nil, nil, matchError - } - - identityConfig := &IdentityConfig{endpointConfig: endpointConfig} - - return cryptoConfig, endpointConfig, identityConfig, nil -} - // setLogLevel will set the log level of the client -func setLogLevel(backend *Backend) { - loggingLevelString := backend.getString("client.logging.level") +func setLogLevel(backend core.ConfigBackend) { + loggingLevelString, _ := backend.Lookup("client.logging.level") logLevel := logging.INFO - if loggingLevelString != "" { + if loggingLevelString != nil { const logModule = "fabsdk" // TODO: allow more flexability in setting levels for different modules logger.Debugf("%s logging level from the config: %v", logModule, loggingLevelString) var err error - logLevel, err = logging.LogLevel(loggingLevelString) + logLevel, err = logging.LogLevel(loggingLevelString.(string)) if err != nil { panic(err) } diff --git a/pkg/core/config/config_test.go b/pkg/core/config/config_test.go index 34816075a9..0e9070b7dc 100644 --- a/pkg/core/config/config_test.go +++ b/pkg/core/config/config_test.go @@ -8,735 +8,27 @@ package config import ( "bytes" - "crypto/tls" "fmt" "os" - "path" - "path/filepath" - "strings" "testing" - "time" - - "reflect" "github.com/hyperledger/fabric-sdk-go/pkg/common/logging" - "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" - "github.com/hyperledger/fabric-sdk-go/pkg/core/config/endpoint" + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" + "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" "github.com/hyperledger/fabric-sdk-go/pkg/util/pathvar" "github.com/pkg/errors" "github.com/spf13/viper" - "github.com/stretchr/testify/assert" -) - -var endpointConfig *EndpointConfig -var cryptoConfig *CryptoSuiteConfig -var identityConfig *IdentityConfig - -const ( - org0 = "org0" - org1 = "org1" - configTestFilePath = "testdata/config_test.yaml" - configTestTemplateFilePath = "testdata/config_test_template.yaml" - configEmptyTestFilePath = "testdata/empty.yaml" - configPemTestFilePath = "testdata/config_test_pem.yaml" - configEmbeddedUsersTestFilePath = "testdata/config_test_embedded_pems.yaml" - configType = "yaml" - defaultConfigPath = "testdata/template" -) - -func TestCAConfig(t *testing.T) { - //Test config - vConfig := viper.New() - vConfig.SetConfigFile(configTestFilePath) - vConfig.ReadInConfig() - vc := vConfig.ConfigFileUsed() - - if vc == "" { - t.Fatalf("Failed to load config file") - } - - //Test network config version - if vConfig.GetString("version") != "1.0.0" { - t.Fatalf("Incorrect network version") - } - - //Test client organization - if vConfig.GetString("client.organization") != org1 { - t.Fatalf("Incorrect Client organization") - } - - //Test Crypto config path - crossCheckWithViperConfig(endpointConfig.backend.getString("client.cryptoconfig.path"), endpointConfig.CryptoConfigPath(), "Incorrect crypto config path", t) - - //Testing CA Client File Location - certfile, err := identityConfig.CAClientCertPath(org1) - - if certfile == "" || err != nil { - t.Fatalf("CA Cert file location read failed %s", err) - } - - //Testing CA Key File Location - keyFile, err := identityConfig.CAClientKeyPath(org1) - - if keyFile == "" || err != nil { - t.Fatal("CA Key file location read failed") - } - - //Testing CA Server Cert Files - sCertFiles, err := identityConfig.CAServerCertPaths(org1) - - if sCertFiles == nil || len(sCertFiles) == 0 || err != nil { - t.Fatal("Getting CA server cert files failed") - } - - //Testing MSPID - mspID, err := endpointConfig.MSPID(org1) - if mspID != "Org1MSP" || err != nil { - t.Fatal("Get MSP ID failed") - } - - //Testing CAConfig - caConfig, err := identityConfig.CAConfig(org1) - if caConfig == nil || err != nil { - t.Fatal("Get CA Config failed") - } - - // Test User Store Path - if vConfig.GetString("client.credentialStore.path") != identityConfig.CredentialStorePath() { - t.Fatalf("Incorrect User Store path") - } - - // Test CA KeyStore Path - if vConfig.GetString("client.credentialStore.cryptoStore.path") != identityConfig.CAKeyStorePath() { - t.Fatalf("Incorrect CA keystore path") - } - - // Test KeyStore Path - if path.Join(vConfig.GetString("client.credentialStore.cryptoStore.path"), "keystore") != cryptoConfig.KeyStorePath() { - t.Fatalf("Incorrect keystore path ") - } - - // Test BCCSP security is enabled - if vConfig.GetBool("client.BCCSP.security.enabled") != cryptoConfig.IsSecurityEnabled() { - t.Fatalf("Incorrect BCCSP Security enabled flag") - } - - // Test SecurityAlgorithm - if vConfig.GetString("client.BCCSP.security.hashAlgorithm") != cryptoConfig.SecurityAlgorithm() { - t.Fatalf("Incorrect BCCSP Security Hash algorithm") - } - - // Test Security Level - if vConfig.GetInt("client.BCCSP.security.level") != cryptoConfig.SecurityLevel() { - t.Fatalf("Incorrect BCCSP Security Level") - } - - // Test SecurityProvider provider - if vConfig.GetString("client.BCCSP.security.default.provider") != cryptoConfig.SecurityProvider() { - t.Fatalf("Incorrect BCCSP SecurityProvider provider") - } - - // Test Ephemeral flag - if vConfig.GetBool("client.BCCSP.security.ephemeral") != cryptoConfig.Ephemeral() { - t.Fatalf("Incorrect BCCSP Ephemeral flag") - } - - // Test SoftVerify flag - if vConfig.GetBool("client.BCCSP.security.softVerify") != cryptoConfig.SoftVerify() { - t.Fatalf("Incorrect BCCSP Ephemeral flag") - } - - // Test SecurityProviderPin - if vConfig.GetString("client.BCCSP.security.pin") != cryptoConfig.SecurityProviderPin() { - t.Fatalf("Incorrect BCCSP SecurityProviderPin flag") - } - - // Test SecurityProviderPin - if vConfig.GetString("client.BCCSP.security.label") != cryptoConfig.SecurityProviderLabel() { - t.Fatalf("Incorrect BCCSP SecurityProviderPin flag") - } - - // test Client - c, err := identityConfig.Client() - if err != nil { - t.Fatalf("Received error when fetching Client info, error is %s", err) - } - if c == nil { - t.Fatal("Received empty client when fetching Client info") - } - - // testing empty OrgMSP - mspID, err = endpointConfig.MSPID("dummyorg1") - if err == nil { - t.Fatal("Get MSP ID did not fail for dummyorg1") - } -} - -func TestCAConfigFailsByNetworkConfig(t *testing.T) { - - //Tamper 'client.network' value and use a new config to avoid conflicting with other tests - - configBackend, err := FromFile(configTestFilePath)() - if err != nil { - t.Fatalf("Unexpected error reading config: %v", err) - } - - _, endpointCfg, identityCfg, err := FromBackend(configBackend)() - if err != nil { - t.Fatalf("Unexpected error reading config: %v", err) - } - - sampleEndpointConfig := endpointCfg.(*EndpointConfig) - sampleEndpointConfig.networkConfigCached = false - - sampleEndpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("client", "INVALID") - sampleEndpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("peers", "INVALID") - sampleEndpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("organizations", "INVALID") - sampleEndpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("orderers", "INVALID") - sampleEndpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("channels", "INVALID") - - sampleIdentityConfig := identityCfg.(*IdentityConfig) - sampleIdentityConfig.endpointConfig = sampleEndpointConfig - - _, err = sampleEndpointConfig.NetworkConfig() - if err == nil { - t.Fatal("Network config load supposed to fail") - } - - //Test CA client cert file failure scenario - certfile, err := sampleIdentityConfig.CAClientCertPath("peerorg1") - if certfile != "" || err == nil { - t.Fatal("CA Cert file location read supposed to fail") - } - - //Test CA client cert file failure scenario - keyFile, err := sampleIdentityConfig.CAClientKeyPath("peerorg1") - if keyFile != "" || err == nil { - t.Fatal("CA Key file location read supposed to fail") - } - - //Testing CA Server Cert Files failure scenario - sCertFiles, err := sampleIdentityConfig.CAServerCertPaths("peerorg1") - if len(sCertFiles) > 0 || err == nil { - t.Fatal("Getting CA server cert files supposed to fail") - } - - //Testing MSPID failure scenario - mspID, err := sampleEndpointConfig.MSPID("peerorg1") - if mspID != "" || err == nil { - t.Fatal("Get MSP ID supposed to fail") - } - - //Testing CAConfig failure scenario - caConfig, err := sampleIdentityConfig.CAConfig("peerorg1") - if caConfig != nil || err == nil { - t.Fatal("Get CA Config supposed to fail") - } - - //Testing RandomOrdererConfig failure scenario - oConfig, err := sampleEndpointConfig.RandomOrdererConfig() - if oConfig != nil || err == nil { - t.Fatal("Testing get RandomOrdererConfig supposed to fail") - } - - //Testing RandomOrdererConfig failure scenario - oConfig, err = sampleEndpointConfig.OrdererConfig("peerorg1") - if oConfig != nil || err == nil { - t.Fatal("Testing get OrdererConfig supposed to fail") - } - - //Testing PeersConfig failure scenario - pConfigs, err := sampleEndpointConfig.PeersConfig("peerorg1") - if pConfigs != nil || err == nil { - t.Fatal("Testing PeersConfig supposed to fail") - } - - //Testing PeersConfig failure scenario - pConfig, err := sampleEndpointConfig.PeerConfig("peerorg1", "peer1") - if pConfig != nil || err == nil { - t.Fatal("Testing PeerConfig supposed to fail") - } - - //Testing ChannelConfig failure scenario - chConfig, err := sampleEndpointConfig.ChannelConfig("invalid") - if chConfig != nil || err == nil { - t.Fatal("Testing ChannelConfig supposed to fail") - } - - //Testing ChannelPeers failure scenario - cpConfigs, err := sampleEndpointConfig.ChannelPeers("invalid") - if cpConfigs != nil || err == nil { - t.Fatal("Testing ChannelPeeers supposed to fail") - } - - //Testing ChannelOrderers failure scenario - coConfigs, err := sampleEndpointConfig.ChannelOrderers("invalid") - if coConfigs != nil || err == nil { - t.Fatal("Testing ChannelOrderers supposed to fail") - } - - // test empty network objects - sampleEndpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("organizations", nil) - _, err = sampleEndpointConfig.NetworkConfig() - if err == nil { - t.Fatalf("Organizations were empty, it should return an error") - } -} - -func TestTLSCAConfig(t *testing.T) { - //Test TLSCA Cert Pool (Positive test case) - - certFile, _ := identityConfig.CAClientCertPath(org1) - certConfig := endpoint.TLSConfig{Path: certFile} - - cert, err := certConfig.TLSCert() - if err != nil { - t.Fatalf("Failed to get TLS CA Cert, reason: %v", err) - } - - _, err = endpointConfig.TLSCACertPool(cert) - if err != nil { - t.Fatalf("TLS CA cert pool fetch failed, reason: %v", err) - } - - //Try again with same cert - _, err = endpointConfig.TLSCACertPool(cert) - if err != nil { - t.Fatalf("TLS CA cert pool fetch failed, reason: %v", err) - } - - assert.False(t, len(endpointConfig.tlsCerts) > 1, "number of certs in cert list shouldn't accept duplicates") - - //Test TLSCA Cert Pool (Negative test case) - - badCertConfig := endpoint.TLSConfig{Path: "some random invalid path"} - - badCert, err := badCertConfig.TLSCert() - - if err == nil { - t.Fatalf("TLS CA cert pool was supposed to fail") - } - - _, err = endpointConfig.TLSCACertPool(badCert) - - keyFile, _ := identityConfig.CAClientKeyPath(org1) - - keyConfig := endpoint.TLSConfig{Path: keyFile} - - key, err := keyConfig.TLSCert() - - if err == nil { - t.Fatalf("TLS CA cert pool was supposed to fail when provided with wrong cert file") - } - - _, err = endpointConfig.TLSCACertPool(key) -} - -func TestTLSCAConfigFromPems(t *testing.T) { - configBackend, err := FromFile(configEmbeddedUsersTestFilePath)() - if err != nil { - t.Fatal(err) - } - - _, _, c, err := FromBackend(configBackend)() - if err != nil { - t.Fatal(err) - } - - //Test TLSCA Cert Pool (Positive test case) - - certPem, _ := c.CAClientCertPem(org1) - certConfig := endpoint.TLSConfig{Pem: certPem} - - cert, err := certConfig.TLSCert() - - if err != nil { - t.Fatalf("TLS CA cert parse failed, reason: %v", err) - } - - _, err = endpointConfig.TLSCACertPool(cert) - - if err != nil { - t.Fatalf("TLS CA cert pool fetch failed, reason: %v", err) - } - //Test TLSCA Cert Pool (Negative test case) - - badCertConfig := endpoint.TLSConfig{Pem: "some random invalid pem"} - - badCert, err := badCertConfig.TLSCert() - - if err == nil { - t.Fatalf("TLS CA cert parse was supposed to fail") - } - - _, err = endpointConfig.TLSCACertPool(badCert) - - keyPem, _ := identityConfig.CAClientKeyPem(org1) - - keyConfig := endpoint.TLSConfig{Pem: keyPem} - - key, err := keyConfig.TLSCert() - - if err == nil { - t.Fatalf("TLS CA cert pool was supposed to fail when provided with wrong cert file") - } - - _, err = endpointConfig.TLSCACertPool(key) -} - -func TestTimeouts(t *testing.T) { - endpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("client.peer.timeout.connection", "2s") - endpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("client.peer.timeout.response", "6s") - endpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("client.eventService.timeout.connection", "2m") - endpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("client.eventService.timeout.registrationResponse", "2h") - endpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("client.orderer.timeout.connection", "2ms") - endpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("client.global.timeout.query", "7h") - endpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("client.global.timeout.execute", "8h") - endpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("client.global.timeout.resmgmt", "118s") - endpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("client.global.cache.connectionIdle", "1m") - endpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("client.global.cache.eventServiceIdle", "2m") - endpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("client.orderer.timeout.response", "6s") - - t1 := endpointConfig.TimeoutOrDefault(fab.EndorserConnection) - if t1 != time.Second*2 { - t.Fatalf("Timeout not read correctly. Got: %s", t1) - } - t1 = endpointConfig.TimeoutOrDefault(fab.EventHubConnection) - if t1 != time.Minute*2 { - t.Fatalf("Timeout not read correctly. Got: %s", t1) - } - t1 = endpointConfig.TimeoutOrDefault(fab.EventReg) - if t1 != time.Hour*2 { - t.Fatalf("Timeout not read correctly. Got: %s", t1) - } - t1 = endpointConfig.TimeoutOrDefault(fab.Query) - if t1 != time.Hour*7 { - t.Fatalf("Timeout not read correctly. Got: %s", t1) - } - t1 = endpointConfig.TimeoutOrDefault(fab.Execute) - if t1 != time.Hour*8 { - t.Fatalf("Timeout not read correctly. Got: %s", t1) - } - t1 = endpointConfig.TimeoutOrDefault(fab.OrdererConnection) - if t1 != time.Millisecond*2 { - t.Fatalf("Timeout not read correctly. Got: %s", t1) - } - t1 = endpointConfig.TimeoutOrDefault(fab.OrdererResponse) - if t1 != time.Second*6 { - t.Fatalf("Timeout not read correctly. Got: %s", t1) - } - t1 = endpointConfig.TimeoutOrDefault(fab.ConnectionIdle) - if t1 != time.Minute*1 { - t.Fatalf("Timeout not read correctly. Got: %s", t1) - } - t1 = endpointConfig.TimeoutOrDefault(fab.EventServiceIdle) - if t1 != time.Minute*2 { - t.Fatalf("Timeout not read correctly. Got: %s", t1) - } - t1 = endpointConfig.TimeoutOrDefault(fab.PeerResponse) - if t1 != time.Second*6 { - t.Fatalf("Timeout not read correctly. Got: %s", t1) - } - t1 = endpointConfig.TimeoutOrDefault(fab.ResMgmt) - if t1 != time.Second*118 { - t.Fatalf("Timeout not read correctly. Got: %s", t1) - } - - // Test default - endpointConfig.backend.coreBackend.(*defConfigBackend).configViper.Set("client.orderer.timeout.connection", "") - t1 = endpointConfig.TimeoutOrDefault(fab.OrdererConnection) - if t1 != time.Second*5 { - t.Fatalf("Timeout not read correctly. Got: %s", t1) - } - -} - -func TestOrdererConfig(t *testing.T) { - oConfig, err := endpointConfig.RandomOrdererConfig() - - if oConfig == nil || err != nil { - t.Fatal("Testing get RandomOrdererConfig failed") - } - - oConfig, err = endpointConfig.OrdererConfig("invalid") - - if oConfig != nil || err == nil { - t.Fatal("Testing non-existing OrdererConfig failed") - } - - orderers, err := endpointConfig.OrderersConfig() - if err != nil { - t.Fatal(err) - } - - if orderers[0].TLSCACerts.Path != "" { - if !filepath.IsAbs(orderers[0].TLSCACerts.Path) { - t.Fatal("Expected GOPATH relative path to be replaced") - } - } else if len(orderers[0].TLSCACerts.Pem) == 0 { - t.Fatalf("Orderer %v must have at least a TlsCACerts.Path or TlsCACerts.Pem set", orderers[0]) - } -} - -func TestChannelOrderers(t *testing.T) { - orderers, err := endpointConfig.ChannelOrderers("mychannel") - if orderers == nil || err != nil { - t.Fatal("Testing ChannelOrderers failed") - } - - if len(orderers) != 1 { - t.Fatalf("Expecting one channel orderer got %d", len(orderers)) - } - - if orderers[0].TLSCACerts.Path != "" { - if !filepath.IsAbs(orderers[0].TLSCACerts.Path) { - t.Fatal("Expected GOPATH relative path to be replaced") - } - } else if len(orderers[0].TLSCACerts.Pem) == 0 { - t.Fatalf("Orderer %v must have at least a TlsCACerts.Path or TlsCACerts.Pem set", orderers[0]) - } -} - -func testCommonConfigPeerByURL(t *testing.T, expectedConfigURL string, fetchedConfigURL string) { - expectedConfig, err := endpointConfig.peerConfig(expectedConfigURL) - if err != nil { - t.Fatalf(err.Error()) - } - - fetchedConfig, err := endpointConfig.PeerConfigByURL(fetchedConfigURL) - - if fetchedConfig.URL == "" { - t.Fatalf("Url value for the host is empty") - } - - if len(fetchedConfig.GRPCOptions) != len(expectedConfig.GRPCOptions) || fetchedConfig.TLSCACerts.Pem != expectedConfig.TLSCACerts.Pem { - t.Fatalf("Expected Config and fetched config differ") - } - - if fetchedConfig.URL != expectedConfig.URL || fetchedConfig.EventURL != expectedConfig.EventURL || fetchedConfig.GRPCOptions["ssl-target-name-override"] != expectedConfig.GRPCOptions["ssl-target-name-override"] { - t.Fatalf("Expected Config and fetched config differ") - } -} - -func TestPeerConfigByUrl_directMatching(t *testing.T) { - testCommonConfigPeerByURL(t, "peer0.org1.example.com", "peer0.org1.example.com:7051") -} - -func TestPeerConfigByUrl_entityMatchers(t *testing.T) { - testCommonConfigPeerByURL(t, "peer0.org1.example.com", "peer1.org1.example.com:7051") -} - -func testCommonConfigOrderer(t *testing.T, expectedConfigHost string, fetchedConfigHost string) (expectedConfig *fab.OrdererConfig, fetchedConfig *fab.OrdererConfig) { - - expectedConfig, err := endpointConfig.OrdererConfig(expectedConfigHost) - if err != nil { - t.Fatalf(err.Error()) - } - - fetchedConfig, err = endpointConfig.OrdererConfig(fetchedConfigHost) - if err != nil { - t.Fatalf(err.Error()) - } - - if expectedConfig.URL == "" { - t.Fatalf("Url value for the host is empty") - } - if fetchedConfig.URL == "" { - t.Fatalf("Url value for the host is empty") - } - - if len(fetchedConfig.GRPCOptions) != len(expectedConfig.GRPCOptions) || fetchedConfig.TLSCACerts.Pem != expectedConfig.TLSCACerts.Pem { - t.Fatalf("Expected Config and fetched config differ") - } - - return expectedConfig, fetchedConfig -} - -func TestOrdererWithSubstitutedConfig_WithADifferentSubstituteUrl(t *testing.T) { - expectedConfig, fetchedConfig := testCommonConfigOrderer(t, "orderer.example.com", "orderer.example2.com") - - if fetchedConfig.URL == "orderer.example2.com:7050" || fetchedConfig.URL == expectedConfig.URL { - t.Fatalf("Expected Config should have url that is given in urlSubstitutionExp of match pattern") - } - - if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "localhost" { - t.Fatalf("Config should have got localhost as its ssl-target-name-override url as per the matched config") - } -} - -func TestOrdererWithSubstitutedConfig_WithEmptySubstituteUrl(t *testing.T) { - _, fetchedConfig := testCommonConfigOrderer(t, "orderer.example.com", "orderer.example3.com") - - if fetchedConfig.URL != "orderer.example3.com:7050" { - t.Fatalf("Fetched Config should have the same url") - } - - if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "orderer.example3.com" { - t.Fatalf("Fetched config should have the same ssl-target-name-override as its hostname") - } -} - -func TestOrdererWithSubstitutedConfig_WithSubstituteUrlExpression(t *testing.T) { - expectedConfig, fetchedConfig := testCommonConfigOrderer(t, "orderer.example.com", "orderer.example4.com:7050") - - if fetchedConfig.URL != expectedConfig.URL { - t.Fatalf("fetched Config url should be same as expected config url as given in the substituteexp in yaml file") - } - - if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "orderer.example.com" { - t.Fatalf("Fetched config should have the ssl-target-name-override as per sslTargetOverrideUrlSubstitutionExp in yaml file") - } -} - -func TestPeersConfig(t *testing.T) { - pc, err := endpointConfig.PeersConfig(org0) - if err != nil { - t.Fatalf(err.Error()) - } - - for _, value := range pc { - if value.URL == "" { - t.Fatalf("Url value for the host is empty") - } - if value.EventURL == "" { - t.Fatalf("EventUrl value is empty") - } - } - - pc, err = endpointConfig.PeersConfig(org1) - if err != nil { - t.Fatalf(err.Error()) - } - - for _, value := range pc { - if value.URL == "" { - t.Fatalf("Url value for the host is empty") - } - if value.EventURL == "" { - t.Fatalf("EventUrl value is empty") - } - } -} - -func TestPeerConfig(t *testing.T) { - pc, err := endpointConfig.PeerConfig(org1, "peer0.org1.example.com") - if err != nil { - t.Fatalf(err.Error()) - } - - if pc.URL == "" { - t.Fatalf("Url value for the host is empty") - } - - if pc.TLSCACerts.Path != "" { - if !filepath.IsAbs(pc.TLSCACerts.Path) { - t.Fatalf("Expected cert path to be absolute") - } - } else if len(pc.TLSCACerts.Pem) == 0 { - t.Fatalf("Peer %s must have at least a TlsCACerts.Path or TlsCACerts.Pem set", "peer0") - } - if len(pc.GRPCOptions) == 0 || pc.GRPCOptions["ssl-target-name-override"] != "peer0.org1.example.com" { - t.Fatalf("Peer %s must have grpcOptions set in config_test.yaml", "peer0") - } -} - -func testCommonConfigPeer(t *testing.T, expectedConfigHost string, fetchedConfigHost string) (expectedConfig *fab.PeerConfig, fetchedConfig *fab.PeerConfig) { - - expectedConfig, err := endpointConfig.peerConfig(expectedConfigHost) - if err != nil { - t.Fatalf(err.Error()) - } - - fetchedConfig, err = endpointConfig.peerConfig(fetchedConfigHost) - if err != nil { - t.Fatalf(err.Error()) - } - - if expectedConfig.URL == "" { - t.Fatalf("Url value for the host is empty") - } - if fetchedConfig.URL == "" { - t.Fatalf("Url value for the host is empty") - } - - if fetchedConfig.TLSCACerts.Path != expectedConfig.TLSCACerts.Path || len(fetchedConfig.GRPCOptions) != len(expectedConfig.GRPCOptions) { - t.Fatalf("Expected Config and fetched config differ") - } - - return expectedConfig, fetchedConfig -} - -func TestPeerWithSubstitutedConfig_WithADifferentSubstituteUrl(t *testing.T) { - expectedConfig, fetchedConfig := testCommonConfigPeer(t, "peer0.org1.example.com", "peer3.org1.example5.com") - - if fetchedConfig.URL == "peer3.org1.example5.com:7051" || fetchedConfig.URL == expectedConfig.URL { - t.Fatalf("Expected Config should have url that is given in urlSubstitutionExp of match pattern") - } - - if fetchedConfig.EventURL == "peer3.org1.example5.com:7053" || fetchedConfig.EventURL == expectedConfig.EventURL { - t.Fatalf("Expected Config should have event url that is given in eventUrlSubstitutionExp of match pattern") - } - - if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "localhost" { - t.Fatalf("Config should have got localhost as its ssl-target-name-override url as per the matched config") - } -} - -func TestPeerWithSubstitutedConfig_WithEmptySubstituteUrl(t *testing.T) { - _, fetchedConfig := testCommonConfigPeer(t, "peer0.org1.example.com", "peer4.org1.example3.com") - - if fetchedConfig.URL != "peer4.org1.example3.com:7051" { - t.Fatalf("Fetched Config should have the same url") - } - - if fetchedConfig.EventURL != "peer4.org1.example3.com:7053" { - t.Fatalf("Fetched Config should have the same event url") - } - - if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "peer4.org1.example3.com" { - t.Fatalf("Fetched config should have the same ssl-target-name-override as its hostname") - } -} - -func TestPeerWithSubstitutedConfig_WithSubstituteUrlExpression(t *testing.T) { - _, fetchedConfig := testCommonConfigPeer(t, "peer0.org1.example.com", "peer5.example4.com:1234") - - if fetchedConfig.URL != "peer5.org1.example.com:1234" { - t.Fatalf("fetched Config url should change to include org1 as given in the substituteexp in yaml file") - } - - if fetchedConfig.EventURL != "peer5.org1.example.com:7053" { - t.Fatalf("fetched Config event url should change to include org1 as given in the eventsubstituteexp in yaml file") - } - - if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "peer5.org1.example.com" { - t.Fatalf("Fetched config should have the ssl-target-name-override as per sslTargetOverrideUrlSubstitutionExp in yaml file") - } -} - -func TestPeerWithSubstitutedConfig_WithMultipleMatchings(t *testing.T) { - _, fetchedConfig := testCommonConfigPeer(t, "peer0.org2.example.com", "peer2.example2.com:1234") - - //Both 2nd and 5th entityMatchers match, however we are only taking 2nd one as its the first one to match - if fetchedConfig.URL == "peer0.org2.example.com:7051" { - t.Fatalf("fetched Config url should be matched with the first suitable matcher") - } - - if fetchedConfig.EventURL != "localhost:7053" { - t.Fatalf("fetched Config event url should have the config from first suitable matcher") - } + "github.com/stretchr/testify/assert" +) - if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "localhost" { - t.Fatalf("Fetched config should have the ssl-target-name-override as per first suitable matcher in yaml file") - } -} +var configBackend core.ConfigBackend -func TestPeerNotInOrgConfig(t *testing.T) { - _, err := endpointConfig.PeerConfig(org1, "peer1.org0.example.com") - if err == nil { - t.Fatalf("Fetching peer config not for an unassigned org should fail") - } -} +const ( + configTestFilePath = "testdata/config_test.yaml" + configTestTemplateFilePath = "testdata/config_test_template.yaml" + configType = "yaml" + defaultConfigPath = "testdata/template" +) func TestFromRawSuccess(t *testing.T) { // get a config byte for testing @@ -761,13 +53,6 @@ func TestFromReaderSuccess(t *testing.T) { } } -func TestFromFileEmptyFilename(t *testing.T) { - _, err := FromFile("")() - if err == nil { - t.Fatalf("Expected error when passing empty string to FromFile") - } -} - func loadConfigBytesFromFile(t *testing.T, filePath string) ([]byte, error) { // read test config file into bytes array f, err := os.Open(filePath) @@ -791,6 +76,13 @@ func loadConfigBytesFromFile(t *testing.T, filePath string) ([]byte, error) { return cBytes, err } +func TestFromFileEmptyFilename(t *testing.T) { + _, err := FromFile("")() + if err == nil { + t.Fatalf("Expected error when passing empty string to FromFile") + } +} + func TestInitConfigSuccess(t *testing.T) { //Test init config //...Positive case @@ -814,15 +106,14 @@ func TestInitConfigWithCmdRoot(t *testing.T) { t.Fatalf("Failed to initialize config backend with cmd root. Error: %s", err) } - configProvider, _, _, err := FromBackend(configBackend)() - if err != nil { - t.Fatalf("Failed to initialize config with cmd root. Error: %s", err) - } - - config := configProvider.(*CryptoSuiteConfig) + config := cryptosuite.ConfigFromBackend(configBackend) + secAlg, ok := configBackend.Lookup("client.BCCSP.security.hashAlgorithm") + if !ok { + t.Fatal("supposed to get valid value") + } //Test if Viper is initialized after calling init config - if config.backend.getString("client.BCCSP.security.hashAlgorithm") != cryptoConfig.SecurityAlgorithm() { + if secAlg != config.SecurityAlgorithm() { t.Fatal("Config initialized with incorrect viper configuration") } @@ -841,9 +132,8 @@ func TestInitConfigPanic(t *testing.T) { } }() - backend, err := FromFile(configTestFilePath)() + _, err := FromFile(configTestFilePath)() assert.Nil(t, err, "not supposed to get error") - FromBackend(backend)() } func TestInitConfigInvalidLocation(t *testing.T) { @@ -873,28 +163,24 @@ func TestMultipleVipers(t *testing.T) { t.Log(err.Error()) } - configProvider, _, _, err := FromBackend(configBackend)() - if err != nil { - t.Fatal(err) - } - - config := configProvider.(*CryptoSuiteConfig) - // Make sure initial value is unaffected testValue2 := viper.GetString("test.testkey") if testValue2 != "testvalue" { t.Fatalf("Expected testvalue after config initialization") } // Make sure Go SDK config is unaffected - testValue3 := config.backend.getBool("client.BCCSP.security.softVerify") + testValue3, ok := configBackend.Lookup("client.BCCSP.security.softVerify") + if !ok { + t.Fatalf("Expected valid value") + } if testValue3 != true { t.Fatalf("Expected existing config value to remain unchanged") } } func TestEnvironmentVariablesDefaultCmdRoot(t *testing.T) { - testValue := endpointConfig.backend.getString("env.test") - if testValue != "" { + testValue, _ := configBackend.Lookup("env.test") + if testValue != nil { t.Fatalf("Expected environment variable value to be empty but got: %s", testValue) } @@ -905,15 +191,15 @@ func TestEnvironmentVariablesDefaultCmdRoot(t *testing.T) { t.Log(err.Error()) } - testValue = endpointConfig.backend.getString("env.test") - if testValue != "123" { + testValue, ok := configBackend.Lookup("env.test") + if testValue != "123" || !ok { t.Fatalf("Expected environment variable value but got: %s", testValue) } } func TestEnvironmentVariablesSpecificCmdRoot(t *testing.T) { - testValue := endpointConfig.backend.getString("env.test") - if testValue != "" { + testValue, _ := configBackend.Lookup("env.test") + if testValue != nil { t.Fatalf("Expected environment variable value to be empty but got: %s", testValue) } @@ -929,29 +215,12 @@ func TestEnvironmentVariablesSpecificCmdRoot(t *testing.T) { t.Log(err.Error()) } - value, _ := configBackend.Lookup("env.test") - if value != "456" { + value, ok := configBackend.Lookup("env.test") + if value != "456" || !ok { t.Fatalf("Expected environment variable value but got: %s", testValue) } } -func TestNetworkConfig(t *testing.T) { - conf, err := endpointConfig.NetworkConfig() - if err != nil { - t.Fatal(err) - } - if len(conf.Orderers) == 0 { - t.Fatal("Expected orderers to be set") - } - if len(conf.Organizations) == 0 { - t.Fatal("Expected atleast one organisation to be set") - } - // viper map keys are lowercase - if len(conf.Organizations[strings.ToLower(org1)].Peers) == 0 { - t.Fatalf("Expected org %s to be present in network configuration and peers to be set", org1) - } -} - func TestMain(m *testing.M) { setUp(m) r := m.Run() @@ -962,23 +231,16 @@ func TestMain(m *testing.M) { func setUp(m *testing.M) { // do any test setup here... var err error - configBackend, err := FromFile(configTestFilePath)() - if err != nil { - fmt.Println(err.Error()) - } - - cryptoSuiteCfg, endpointCfg, identityCfg, err := FromBackend(configBackend)() + cfgBackend, err := FromFile(configTestFilePath)() if err != nil { fmt.Println(err.Error()) } - endpointConfig = endpointCfg.(*EndpointConfig) - cryptoConfig = cryptoSuiteCfg.(*CryptoSuiteConfig) - identityConfig = identityCfg.(*IdentityConfig) + configBackend = cfgBackend } func teardown() { // do any teadown activities here .. - endpointConfig = nil + configBackend = nil } func crossCheckWithViperConfig(expected string, actual string, message string, t *testing.T) { @@ -988,513 +250,6 @@ func crossCheckWithViperConfig(expected string, actual string, message string, t } } -func TestSystemCertPoolDisabled(t *testing.T) { - - // get a config file with pool disabled - configBackend, err := FromFile(configTestFilePath)() - if err != nil { - t.Fatal(err) - } - - _, configProvider, _, err := FromBackend(configBackend)() - if err != nil { - t.Fatal(err) - } - - certPool, err := configProvider.TLSCACertPool() - if err != nil { - t.Fatal("not supposed to get error") - } - // cert pool should be empty - if len(certPool.Subjects()) > 0 { - t.Fatal("Expecting empty tls cert pool due to disabled system cert pool") - } -} - -func TestSystemCertPoolEnabled(t *testing.T) { - - // get a config file with pool enabled - configBackend, err := FromFile(configPemTestFilePath)() - if err != nil { - t.Fatal(err) - } - - _, configProvider, _, err := FromBackend(configBackend)() - if err != nil { - t.Fatal(err) - } - - certPool, err := configProvider.TLSCACertPool() - if err != nil { - t.Fatal("not supposed to get error") - } - - if len(certPool.Subjects()) == 0 { - t.Fatal("System Cert Pool not loaded even though it is enabled") - } - - // Org2 'mychannel' peer is missing cert + pem (it should not fail when systemCertPool enabled) - _, err = configProvider.ChannelPeers("mychannel") - if err != nil { - t.Fatalf("Should have skipped verifying ca cert + pem: %s", err) - } - -} - -func TestInitConfigFromRawWithPem(t *testing.T) { - // get a config byte for testing - cBytes, err := loadConfigBytesFromFile(t, configPemTestFilePath) - if err != nil { - t.Fatalf("Failed to load sample bytes from File. Error: %s", err) - } - - // test init config from bytes - backend, err := FromRaw(cBytes, configType)() - if err != nil { - t.Fatalf("Failed to initialize config from bytes array. Error: %s", err) - } - - _, epConfig, idConfig, err := FromBackend(backend)() - if err != nil { - t.Fatalf("Failed to initialize config from bytes array. Error: %s", err) - } - - o, err := epConfig.OrderersConfig() - if err != nil { - t.Fatalf("Failed to load orderers from config. Error: %s", err) - } - - if o == nil || len(o) == 0 { - t.Fatalf("orderer cannot be nil or empty") - } - - oPem := `-----BEGIN CERTIFICATE----- -MIICNjCCAdygAwIBAgIRAILSPmMB3BzoLIQGsFxwZr8wCgYIKoZIzj0EAwIwbDEL -MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG -cmFuY2lzY28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRowGAYDVQQDExF0bHNjYS5l -eGFtcGxlLmNvbTAeFw0xNzA3MjgxNDI3MjBaFw0yNzA3MjYxNDI3MjBaMGwxCzAJ -BgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJh -bmNpc2NvMRQwEgYDVQQKEwtleGFtcGxlLmNvbTEaMBgGA1UEAxMRdGxzY2EuZXhh -bXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQfgKb4db53odNzdMXn -P5FZTZTFztOO1yLvCHDofSNfTPq/guw+YYk7ZNmhlhj8JHFG6dTybc9Qb/HOh9hh -gYpXo18wXTAOBgNVHQ8BAf8EBAMCAaYwDwYDVR0lBAgwBgYEVR0lADAPBgNVHRMB -Af8EBTADAQH/MCkGA1UdDgQiBCBxaEP3nVHQx4r7tC+WO//vrPRM1t86SKN0s6XB -8LWbHTAKBggqhkjOPQQDAgNIADBFAiEA96HXwCsuMr7tti8lpcv1oVnXg0FlTxR/ -SQtE5YgdxkUCIHReNWh/pluHTxeGu2jNCH1eh6o2ajSGeeizoapvdJbN ------END CERTIFICATE-----` - loadedOPem := strings.TrimSpace(o[0].TLSCACerts.Pem) // viper's unmarshall adds a \n to the end of a string, hence the TrimeSpace - if loadedOPem != oPem { - t.Fatalf("Orderer Pem doesn't match. Expected \n'%s'\n, but got \n'%s'\n", oPem, loadedOPem) - } - - pc, err := endpointConfig.PeersConfig(org1) - if err != nil { - t.Fatalf(err.Error()) - } - if pc == nil || len(pc) == 0 { - t.Fatalf("peers list of %s cannot be nil or empty", org1) - } - peer0 := "peer0.org1.example.com" - p0, err := epConfig.PeerConfig(org1, peer0) - if err != nil { - t.Fatalf("Failed to load %s of %s from the config. Error: %s", peer0, org1, err) - } - if p0 == nil { - t.Fatalf("%s of %s cannot be nil", peer0, org1) - } - pPem := `-----BEGIN CERTIFICATE----- -MIICSTCCAfCgAwIBAgIRAPQIzfkrCZjcpGwVhMSKd0AwCgYIKoZIzj0EAwIwdjEL -MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG -cmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHzAdBgNVBAMTFnRs -c2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTcwNzI4MTQyNzIwWhcNMjcwNzI2MTQy -NzIwWjB2MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE -BxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEfMB0G -A1UEAxMWdGxzY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49 -AwEHA0IABMOiG8UplWTs898zZ99+PhDHPbKjZIDHVG+zQXopw8SqNdX3NAmZUKUU -sJ8JZ3M49Jq4Ms8EHSEwQf0Ifx3ICHujXzBdMA4GA1UdDwEB/wQEAwIBpjAPBgNV -HSUECDAGBgRVHSUAMA8GA1UdEwEB/wQFMAMBAf8wKQYDVR0OBCIEID9qJz7xhZko -V842OVjxCYYQwCjPIY+5e9ORR+8pxVzcMAoGCCqGSM49BAMCA0cAMEQCIGZ+KTfS -eezqv0ml1VeQEmnAEt5sJ2RJA58+LegUYMd6AiAfEe6BKqdY03qFUgEYmtKG+3Dr -O94CDp7l2k7hMQI0zQ== ------END CERTIFICATE-----` - - loadedPPem := strings.TrimSpace(p0.TLSCACerts.Pem) // viper's unmarshall adds a \n to the end of a string, hence the TrimeSpace - if loadedPPem != pPem { - t.Fatalf("%s Pem doesn't match. Expected \n'%s'\n, but got \n'%s'\n", peer0, pPem, loadedPPem) - } - - // get CA Server cert pems (embedded) for org1 - certs, err := idConfig.CAServerCertPems("org1") - if err != nil { - t.Fatalf("Failed to load CAServerCertPems from config. Error: %s", err) - } - if len(certs) == 0 { - t.Fatalf("Got empty PEM certs for CAServerCertPems") - } - - // get the client cert pem (embedded) for org1 - idConfig.CAClientCertPem("org1") - if err != nil { - t.Fatalf("Failed to load CAClientCertPem from config. Error: %s", err) - } - - // get CA Server certs paths for org1 - certs, err = idConfig.CAServerCertPaths("org1") - if err != nil { - t.Fatalf("Failed to load CAServerCertPaths from config. Error: %s", err) - } - if len(certs) == 0 { - t.Fatalf("Got empty cert file paths for CAServerCertPaths") - } - - // get the client cert path for org1 - idConfig.CAClientCertPath("org1") - if err != nil { - t.Fatalf("Failed to load CAClientCertPath from config. Error: %s", err) - } - - // get the client key pem (embedded) for org1 - idConfig.CAClientKeyPem("org1") - if err != nil { - t.Fatalf("Failed to load CAClientKeyPem from config. Error: %s", err) - } - - // get the client key file path for org1 - idConfig.CAClientKeyPath("org1") - if err != nil { - t.Fatalf("Failed to load CAClientKeyPath from config. Error: %s", err) - } -} - -func TestLoadConfigWithEmbeddedUsersWithPems(t *testing.T) { - // get a config file with embedded users - configBackend, err := FromFile(configEmbeddedUsersTestFilePath)() - if err != nil { - t.Fatal(err) - } - - _, c, _, err := FromBackend(configBackend)() - if err != nil { - t.Fatal(err) - } - - conf, err := c.NetworkConfig() - - if err != nil { - t.Fatal(err) - } - - if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("EmbeddedUser")].Cert.Pem == "" { - t.Fatal("Failed to parse the embedded cert for user EmbeddedUser") - } - - if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("EmbeddedUser")].Key.Pem == "" { - t.Fatal("Failed to parse the embedded key for user EmbeddedUser") - } - - if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("NonExistentEmbeddedUser")].Key.Pem != "" { - t.Fatal("Mistakenly found an embedded key for user NonExistentEmbeddedUser") - } - - if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("NonExistentEmbeddedUser")].Cert.Pem != "" { - t.Fatal("Mistakenly found an embedded cert for user NonExistentEmbeddedUser") - } -} - -func TestLoadConfigWithEmbeddedUsersWithPaths(t *testing.T) { - // get a config file with embedded users - configBackend, err := FromFile(configEmbeddedUsersTestFilePath)() - if err != nil { - t.Fatal(err) - } - - _, c, _, err := FromBackend(configBackend)() - if err != nil { - t.Fatal(err) - } - - conf, err := c.NetworkConfig() - - if err != nil { - t.Fatal(err) - } - - if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("EmbeddedUserWithPaths")].Cert.Path == "" { - t.Fatal("Failed to parse the embedded cert for user EmbeddedUserWithPaths") - } - - if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("EmbeddedUserWithPaths")].Key.Path == "" { - t.Fatal("Failed to parse the embedded key for user EmbeddedUserWithPaths") - } - - if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("NonExistentEmbeddedUser")].Key.Path != "" { - t.Fatal("Mistakenly found an embedded key for user NonExistentEmbeddedUser") - } - - if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("NonExistentEmbeddedUser")].Cert.Path != "" { - t.Fatal("Mistakenly found an embedded cert for user NonExistentEmbeddedUser") - } -} - -func TestInitConfigFromRawWrongType(t *testing.T) { - // get a config byte for testing - cBytes, err := loadConfigBytesFromFile(t, configPemTestFilePath) - if err != nil { - t.Fatalf("Failed to load sample bytes from File. Error: %s", err) - } - - // test init config with empty type - backend, err := FromRaw(cBytes, "")() - if err == nil { - t.Fatalf("Expected error when initializing config with wrong config type but got no error.") - } - - // test init config with wrong type - backend, err = FromRaw(cBytes, "json")() - if err != nil { - t.Fatalf("Failed to initialize config backend from bytes array. Error: %s", err) - } - - _, c, _, err := FromBackend(backend)() - if err != nil { - t.Fatalf("Failed to initialize config from backend. Error: %s", err) - } - - o, err := c.OrderersConfig() - if len(o) > 0 { - t.Fatalf("Expected to get an empty list of orderers for wrong config type") - } - - np, err := c.NetworkPeers() - if len(np) > 0 { - t.Fatalf("Expected to get an empty list of peers for wrong config type") - } -} - -func TestTLSClientCertsFromFiles(t *testing.T) { - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = "../../../test/fixtures/config/mutual_tls/client_sdk_go.pem" - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = "../../../test/fixtures/config/mutual_tls/client_sdk_go-key.pem" - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = "" - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = "" - - certs, err := endpointConfig.TLSClientCerts() - if err != nil { - t.Fatalf("Expected no errors but got error instead: %s", err) - } - - if len(certs) != 1 { - t.Fatalf("Expected only one tls cert struct") - } - - emptyCert := tls.Certificate{} - - if reflect.DeepEqual(certs[0], emptyCert) { - t.Fatalf("Actual cert is empty") - } -} - -func TestTLSClientCertsFromFilesIncorrectPaths(t *testing.T) { - // incorrect paths to files - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = "/test/fixtures/config/mutual_tls/client_sdk_go.pem" - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = "/test/fixtures/config/mutual_tls/client_sdk_go-key.pem" - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = "" - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = "" - - _, err := endpointConfig.TLSClientCerts() - if err == nil { - t.Fatalf("Expected error but got no errors instead") - } - - if !strings.Contains(err.Error(), "no such file or directory") { - t.Fatalf("Expected no such file or directory error") - } -} - -func TestTLSClientCertsFromPem(t *testing.T) { - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = "" - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = "" - - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = `-----BEGIN CERTIFICATE----- -MIIC5TCCAkagAwIBAgIUMYhiY5MS3jEmQ7Fz4X/e1Dx33J0wCgYIKoZIzj0EAwQw -gYwxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3Jv -bnRvMREwDwYDVQQKEwhsaW51eGN0bDEMMAoGA1UECxMDTGFiMTgwNgYDVQQDEy9s -aW51eGN0bCBFQ0MgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAoTGFiKTAe -Fw0xNzEyMDEyMTEzMDBaFw0xODEyMDEyMTEzMDBaMGMxCzAJBgNVBAYTAkNBMRAw -DgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3JvbnRvMREwDwYDVQQKEwhsaW51 -eGN0bDEMMAoGA1UECxMDTGFiMQ8wDQYDVQQDDAZzZGtfZ28wdjAQBgcqhkjOPQIB -BgUrgQQAIgNiAAT6I1CGNrkchIAEmeJGo53XhDsoJwRiohBv2PotEEGuO6rMyaOu -pulj2VOj+YtgWw4ZtU49g4Nv6rq1QlKwRYyMwwRJSAZHIUMhYZjcDi7YEOZ3Fs1h -xKmIxR+TTR2vf9KjgZAwgY0wDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsG -AQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFDwS3xhpAWs81OVWvZt+iUNL -z26DMB8GA1UdIwQYMBaAFLRasbknomawJKuQGiyKs/RzTCujMBgGA1UdEQQRMA+C -DWZhYnJpY19zZGtfZ28wCgYIKoZIzj0EAwQDgYwAMIGIAkIAk1MxMogtMtNO0rM8 -gw2rrxqbW67ulwmMQzp6EJbm/28T2pIoYWWyIwpzrquypI7BOuf8is5b7Jcgn9oz -7sdMTggCQgF7/8ZFl+wikAAPbciIL1I+LyCXKwXosdFL6KMT6/myYjsGNeeDeMbg -3YkZ9DhdH1tN4U/h+YulG/CkKOtUATtQxg== ------END CERTIFICATE-----` - - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = `-----BEGIN EC PRIVATE KEY----- -MIGkAgEBBDByldj7VTpqTQESGgJpR9PFW9b6YTTde2WN6/IiBo2nW+CIDmwQgmAl -c/EOc9wmgu+gBwYFK4EEACKhZANiAAT6I1CGNrkchIAEmeJGo53XhDsoJwRiohBv -2PotEEGuO6rMyaOupulj2VOj+YtgWw4ZtU49g4Nv6rq1QlKwRYyMwwRJSAZHIUMh -YZjcDi7YEOZ3Fs1hxKmIxR+TTR2vf9I= ------END EC PRIVATE KEY-----` - - certs, err := endpointConfig.TLSClientCerts() - if err != nil { - t.Fatalf("Expected no errors but got error instead: %s", err) - } - - if len(certs) != 1 { - t.Fatalf("Expected only one tls cert struct") - } - - emptyCert := tls.Certificate{} - - if reflect.DeepEqual(certs[0], emptyCert) { - t.Fatalf("Actual cert is empty") - } -} - -func TestTLSClientCertFromPemAndKeyFromFile(t *testing.T) { - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = "" - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = "../../../test/fixtures/config/mutual_tls/client_sdk_go-key.pem" - - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = `-----BEGIN CERTIFICATE----- -MIIC5TCCAkagAwIBAgIUMYhiY5MS3jEmQ7Fz4X/e1Dx33J0wCgYIKoZIzj0EAwQw -gYwxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3Jv -bnRvMREwDwYDVQQKEwhsaW51eGN0bDEMMAoGA1UECxMDTGFiMTgwNgYDVQQDEy9s -aW51eGN0bCBFQ0MgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAoTGFiKTAe -Fw0xNzEyMDEyMTEzMDBaFw0xODEyMDEyMTEzMDBaMGMxCzAJBgNVBAYTAkNBMRAw -DgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3JvbnRvMREwDwYDVQQKEwhsaW51 -eGN0bDEMMAoGA1UECxMDTGFiMQ8wDQYDVQQDDAZzZGtfZ28wdjAQBgcqhkjOPQIB -BgUrgQQAIgNiAAT6I1CGNrkchIAEmeJGo53XhDsoJwRiohBv2PotEEGuO6rMyaOu -pulj2VOj+YtgWw4ZtU49g4Nv6rq1QlKwRYyMwwRJSAZHIUMhYZjcDi7YEOZ3Fs1h -xKmIxR+TTR2vf9KjgZAwgY0wDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsG -AQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFDwS3xhpAWs81OVWvZt+iUNL -z26DMB8GA1UdIwQYMBaAFLRasbknomawJKuQGiyKs/RzTCujMBgGA1UdEQQRMA+C -DWZhYnJpY19zZGtfZ28wCgYIKoZIzj0EAwQDgYwAMIGIAkIAk1MxMogtMtNO0rM8 -gw2rrxqbW67ulwmMQzp6EJbm/28T2pIoYWWyIwpzrquypI7BOuf8is5b7Jcgn9oz -7sdMTggCQgF7/8ZFl+wikAAPbciIL1I+LyCXKwXosdFL6KMT6/myYjsGNeeDeMbg -3YkZ9DhdH1tN4U/h+YulG/CkKOtUATtQxg== ------END CERTIFICATE-----` - - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = "" - - certs, err := endpointConfig.TLSClientCerts() - if err != nil { - t.Fatalf("Expected no errors but got error instead: %s", err) - } - - if len(certs) != 1 { - t.Fatalf("Expected only one tls cert struct") - } - - emptyCert := tls.Certificate{} - - if reflect.DeepEqual(certs[0], emptyCert) { - t.Fatalf("Actual cert is empty") - } -} - -func TestTLSClientCertFromFileAndKeyFromPem(t *testing.T) { - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = "../../../test/fixtures/config/mutual_tls/client_sdk_go.pem" - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = "" - - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = "" - - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = `-----BEGIN EC PRIVATE KEY----- -MIGkAgEBBDByldj7VTpqTQESGgJpR9PFW9b6YTTde2WN6/IiBo2nW+CIDmwQgmAl -c/EOc9wmgu+gBwYFK4EEACKhZANiAAT6I1CGNrkchIAEmeJGo53XhDsoJwRiohBv -2PotEEGuO6rMyaOupulj2VOj+YtgWw4ZtU49g4Nv6rq1QlKwRYyMwwRJSAZHIUMh -YZjcDi7YEOZ3Fs1hxKmIxR+TTR2vf9I= ------END EC PRIVATE KEY-----` - - certs, err := endpointConfig.TLSClientCerts() - if err != nil { - t.Fatalf("Expected no errors but got error instead: %s", err) - } - - if len(certs) != 1 { - t.Fatalf("Expected only one tls cert struct") - } - - emptyCert := tls.Certificate{} - - if reflect.DeepEqual(certs[0], emptyCert) { - t.Fatalf("Actual cert is empty") - } -} - -func TestTLSClientCertsPemBeforeFiles(t *testing.T) { - // files have incorrect paths, but pems are loaded first - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = "/test/fixtures/config/mutual_tls/client_sdk_go.pem" - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = "/test/fixtures/config/mutual_tls/client_sdk_go-key.pem" - - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = `-----BEGIN CERTIFICATE----- -MIIC5TCCAkagAwIBAgIUMYhiY5MS3jEmQ7Fz4X/e1Dx33J0wCgYIKoZIzj0EAwQw -gYwxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3Jv -bnRvMREwDwYDVQQKEwhsaW51eGN0bDEMMAoGA1UECxMDTGFiMTgwNgYDVQQDEy9s -aW51eGN0bCBFQ0MgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAoTGFiKTAe -Fw0xNzEyMDEyMTEzMDBaFw0xODEyMDEyMTEzMDBaMGMxCzAJBgNVBAYTAkNBMRAw -DgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3JvbnRvMREwDwYDVQQKEwhsaW51 -eGN0bDEMMAoGA1UECxMDTGFiMQ8wDQYDVQQDDAZzZGtfZ28wdjAQBgcqhkjOPQIB -BgUrgQQAIgNiAAT6I1CGNrkchIAEmeJGo53XhDsoJwRiohBv2PotEEGuO6rMyaOu -pulj2VOj+YtgWw4ZtU49g4Nv6rq1QlKwRYyMwwRJSAZHIUMhYZjcDi7YEOZ3Fs1h -xKmIxR+TTR2vf9KjgZAwgY0wDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsG -AQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFDwS3xhpAWs81OVWvZt+iUNL -z26DMB8GA1UdIwQYMBaAFLRasbknomawJKuQGiyKs/RzTCujMBgGA1UdEQQRMA+C -DWZhYnJpY19zZGtfZ28wCgYIKoZIzj0EAwQDgYwAMIGIAkIAk1MxMogtMtNO0rM8 -gw2rrxqbW67ulwmMQzp6EJbm/28T2pIoYWWyIwpzrquypI7BOuf8is5b7Jcgn9oz -7sdMTggCQgF7/8ZFl+wikAAPbciIL1I+LyCXKwXosdFL6KMT6/myYjsGNeeDeMbg -3YkZ9DhdH1tN4U/h+YulG/CkKOtUATtQxg== ------END CERTIFICATE-----` - - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = `-----BEGIN EC PRIVATE KEY----- -MIGkAgEBBDByldj7VTpqTQESGgJpR9PFW9b6YTTde2WN6/IiBo2nW+CIDmwQgmAl -c/EOc9wmgu+gBwYFK4EEACKhZANiAAT6I1CGNrkchIAEmeJGo53XhDsoJwRiohBv -2PotEEGuO6rMyaOupulj2VOj+YtgWw4ZtU49g4Nv6rq1QlKwRYyMwwRJSAZHIUMh -YZjcDi7YEOZ3Fs1hxKmIxR+TTR2vf9I= ------END EC PRIVATE KEY-----` - - certs, err := endpointConfig.TLSClientCerts() - if err != nil { - t.Fatalf("Expected no errors but got error instead: %s", err) - } - - if len(certs) != 1 { - t.Fatalf("Expected only one tls cert struct") - } - - emptyCert := tls.Certificate{} - - if reflect.DeepEqual(certs[0], emptyCert) { - t.Fatalf("Actual cert is empty") - } -} - -func TestTLSClientCertsNoCerts(t *testing.T) { - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = "" - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = "" - endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = "" - endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = "" - - certs, err := endpointConfig.TLSClientCerts() - if err != nil { - t.Fatalf("Expected no errors but got error instead: %s", err) - } - - if len(certs) != 1 { - t.Fatalf("Expected only empty tls cert struct") - } - - emptyCert := tls.Certificate{} - - if !reflect.DeepEqual(certs[0], emptyCert) { - t.Fatalf("Actual cert is not equal to empty cert") - } -} - func TestNewGoodOpt(t *testing.T) { _, err := FromFile("../../../test/fixtures/config/config_test.yaml", goodOpt())() if err != nil { diff --git a/pkg/core/config/cryptoconfig.go b/pkg/core/config/cryptoconfig.go deleted file mode 100644 index 16c91e301b..0000000000 --- a/pkg/core/config/cryptoconfig.go +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright SecureKey Technologies Inc. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package config - -import ( - "os" - "path" - "strings" - - "github.com/hyperledger/fabric-sdk-go/pkg/util/pathvar" -) - -// CryptoSuiteConfig represents the crypto suite configuration for the client -type CryptoSuiteConfig struct { - backend *Backend -} - -// IsSecurityEnabled config used enable and diable security in cryptosuite -func (c *CryptoSuiteConfig) IsSecurityEnabled() bool { - return c.backend.getBool("client.BCCSP.security.enabled") -} - -// SecurityAlgorithm returns cryptoSuite config hash algorithm -func (c *CryptoSuiteConfig) SecurityAlgorithm() string { - return c.backend.getString("client.BCCSP.security.hashAlgorithm") -} - -// SecurityLevel returns cryptSuite config security level -func (c *CryptoSuiteConfig) SecurityLevel() int { - return c.backend.getInt("client.BCCSP.security.level") -} - -//SecurityProvider provider SW or PKCS11 -func (c *CryptoSuiteConfig) SecurityProvider() string { - return c.backend.getString("client.BCCSP.security.default.provider") -} - -//Ephemeral flag -func (c *CryptoSuiteConfig) Ephemeral() bool { - return c.backend.getBool("client.BCCSP.security.ephemeral") -} - -//SoftVerify flag -func (c *CryptoSuiteConfig) SoftVerify() bool { - return c.backend.getBool("client.BCCSP.security.softVerify") -} - -//SecurityProviderLibPath will be set only if provider is PKCS11 -func (c *CryptoSuiteConfig) SecurityProviderLibPath() string { - configuredLibs := c.backend.getString("client.BCCSP.security.library") - libPaths := strings.Split(configuredLibs, ",") - logger.Debug("Configured BCCSP Lib Paths %v", libPaths) - var lib string - for _, path := range libPaths { - if _, err := os.Stat(strings.TrimSpace(path)); !os.IsNotExist(err) { - lib = strings.TrimSpace(path) - break - } - } - if lib != "" { - logger.Debug("Found softhsm library: %s", lib) - } else { - logger.Debug("Softhsm library was not found") - } - return lib -} - -//SecurityProviderPin will be set only if provider is PKCS11 -func (c *CryptoSuiteConfig) SecurityProviderPin() string { - return c.backend.getString("client.BCCSP.security.pin") -} - -//SecurityProviderLabel will be set only if provider is PKCS11 -func (c *CryptoSuiteConfig) SecurityProviderLabel() string { - return c.backend.getString("client.BCCSP.security.label") -} - -// KeyStorePath returns the keystore path used by BCCSP -func (c *CryptoSuiteConfig) KeyStorePath() string { - keystorePath := pathvar.Subst(c.backend.getString("client.credentialStore.cryptoStore.path")) - return path.Join(keystorePath, "keystore") -} diff --git a/pkg/core/config/configbackend.go b/pkg/core/config/defbackend.go similarity index 64% rename from pkg/core/config/configbackend.go rename to pkg/core/config/defbackend.go index 21350e5004..9a678ea2f0 100644 --- a/pkg/core/config/configbackend.go +++ b/pkg/core/config/defbackend.go @@ -7,12 +7,9 @@ SPDX-License-Identifier: Apache-2.0 package config import ( - "time" - "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" "github.com/hyperledger/fabric-sdk-go/pkg/util/pathvar" "github.com/pkg/errors" - "github.com/spf13/cast" "github.com/spf13/viper" ) @@ -62,45 +59,3 @@ func (c *defConfigBackend) loadTemplateConfig() error { } return nil } - -//Backend backend for all config implementations -type Backend struct { - coreBackend core.ConfigBackend -} - -func (c *Backend) getBool(key string) bool { - value, ok := c.coreBackend.Lookup(key) - if !ok { - return false - } - return cast.ToBool(value) -} - -func (c *Backend) getString(key string) string { - value, ok := c.coreBackend.Lookup(key) - if !ok { - return "" - } - return cast.ToString(value) -} - -func (c *Backend) getInt(key string) int { - value, ok := c.coreBackend.Lookup(key) - if !ok { - return 0 - } - return cast.ToInt(value) -} - -func (c *Backend) getDuration(key string) time.Duration { - value, ok := c.coreBackend.Lookup(key) - if !ok { - return 0 - } - return cast.ToDuration(value) -} - -func (c *Backend) unmarshalKey(key string, rawVal interface{}) bool { - _, ok := c.coreBackend.Lookup(key, core.WithUnmarshalType(rawVal)) - return ok -} diff --git a/pkg/core/config/lookup/lookup.go b/pkg/core/config/lookup/lookup.go new file mode 100644 index 0000000000..fb02ed9f50 --- /dev/null +++ b/pkg/core/config/lookup/lookup.go @@ -0,0 +1,66 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package lookup + +import ( + "time" + + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" + "github.com/spf13/cast" +) + +//New providers lookup wrapper around given backend +func New(coreBackend core.ConfigBackend) *ConfigLookup { + return &ConfigLookup{backend: coreBackend} +} + +//ConfigLookup is wrapper for core.ConfigBackend which performs key lookup and unmarshalling +type ConfigLookup struct { + backend core.ConfigBackend +} + +//GetBool returns bool value for given key +func (c *ConfigLookup) GetBool(key string) bool { + value, ok := c.backend.Lookup(key) + if !ok { + return false + } + return cast.ToBool(value) +} + +//GetString returns string value for given key +func (c *ConfigLookup) GetString(key string) string { + value, ok := c.backend.Lookup(key) + if !ok { + return "" + } + return cast.ToString(value) +} + +//GetInt returns int value for given key +func (c *ConfigLookup) GetInt(key string) int { + value, ok := c.backend.Lookup(key) + if !ok { + return 0 + } + return cast.ToInt(value) +} + +//GetDuration returns time.Duration value for given key +func (c *ConfigLookup) GetDuration(key string) time.Duration { + value, ok := c.backend.Lookup(key) + if !ok { + return 0 + } + return cast.ToDuration(value) +} + +//UnmarshalKey unmarshals value for given key to rawval type +func (c *ConfigLookup) UnmarshalKey(key string, rawVal interface{}) bool { + _, ok := c.backend.Lookup(key, core.WithUnmarshalType(rawVal)) + return ok +} diff --git a/pkg/core/cryptosuite/cryptoconfig.go b/pkg/core/cryptosuite/cryptoconfig.go new file mode 100644 index 0000000000..031030d60e --- /dev/null +++ b/pkg/core/cryptosuite/cryptoconfig.go @@ -0,0 +1,93 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package cryptosuite + +import ( + "os" + "path" + "strings" + + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" + "github.com/hyperledger/fabric-sdk-go/pkg/core/config/lookup" + "github.com/hyperledger/fabric-sdk-go/pkg/util/pathvar" +) + +//ConfigFromBackend returns CryptoSuite config implementation for given backend +func ConfigFromBackend(coreBackend core.ConfigBackend) core.CryptoSuiteConfig { + return &Config{backend: lookup.New(coreBackend)} +} + +// Config represents the crypto suite configuration for the client +type Config struct { + backend *lookup.ConfigLookup +} + +// IsSecurityEnabled config used enable and diable security in cryptosuite +func (c *Config) IsSecurityEnabled() bool { + return c.backend.GetBool("client.BCCSP.security.enabled") +} + +// SecurityAlgorithm returns cryptoSuite config hash algorithm +func (c *Config) SecurityAlgorithm() string { + return c.backend.GetString("client.BCCSP.security.hashAlgorithm") +} + +// SecurityLevel returns cryptSuite config security level +func (c *Config) SecurityLevel() int { + return c.backend.GetInt("client.BCCSP.security.level") +} + +//SecurityProvider provider SW or PKCS11 +func (c *Config) SecurityProvider() string { + return c.backend.GetString("client.BCCSP.security.default.provider") +} + +//Ephemeral flag +func (c *Config) Ephemeral() bool { + return c.backend.GetBool("client.BCCSP.security.ephemeral") +} + +//SoftVerify flag +func (c *Config) SoftVerify() bool { + return c.backend.GetBool("client.BCCSP.security.softVerify") +} + +//SecurityProviderLibPath will be set only if provider is PKCS11 +func (c *Config) SecurityProviderLibPath() string { + configuredLibs := c.backend.GetString("client.BCCSP.security.library") + libPaths := strings.Split(configuredLibs, ",") + logger.Debug("Configured BCCSP Lib Paths %v", libPaths) + var lib string + for _, path := range libPaths { + if _, err := os.Stat(strings.TrimSpace(path)); !os.IsNotExist(err) { + lib = strings.TrimSpace(path) + break + } + } + if lib != "" { + logger.Debug("Found softhsm library: %s", lib) + } else { + logger.Debug("Softhsm library was not found") + } + return lib +} + +//SecurityProviderPin will be set only if provider is PKCS11 +func (c *Config) SecurityProviderPin() string { + return c.backend.GetString("client.BCCSP.security.pin") +} + +//SecurityProviderLabel will be set only if provider is PKCS11 +func (c *Config) SecurityProviderLabel() string { + return c.backend.GetString("client.BCCSP.security.label") +} + +// KeyStorePath returns the keystore path used by BCCSP +func (c *Config) KeyStorePath() string { + keystorePath := pathvar.Subst(c.backend.GetString("client.credentialStore.cryptoStore.path")) + return path.Join(keystorePath, "keystore") +} diff --git a/pkg/core/cryptosuite/cryptoconfig_test.go b/pkg/core/cryptosuite/cryptoconfig_test.go new file mode 100644 index 0000000000..3dc73a3855 --- /dev/null +++ b/pkg/core/cryptosuite/cryptoconfig_test.go @@ -0,0 +1,128 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package cryptosuite + +import ( + "path" + "testing" + + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" + "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/core/mocks" +) + +const configTestFilePath = "../config/testdata/config_test.yaml" + +func TestCAConfig(t *testing.T) { + backend, err := config.FromFile(configTestFilePath)() + if err != nil { + t.Fatal("Failed to get config backend") + } + + customBackend := getCustomBackend(backend) + + config := ConfigFromBackend(customBackend) + cryptoConfig := config.(*Config) + + // Test KeyStore Path + val, ok := customBackend.Lookup("client.credentialStore.cryptoStore.path") + if !ok || val == nil { + t.Fatal("expected valid value") + } + + if path.Join(val.(string), "keystore") != cryptoConfig.KeyStorePath() { + t.Fatalf("Incorrect keystore path ") + } + + // Test BCCSP security is enabled + val, ok = customBackend.Lookup("client.BCCSP.security.enabled") + if !ok || val == nil { + t.Fatal("expected valid value") + } + if val.(bool) != cryptoConfig.IsSecurityEnabled() { + t.Fatalf("Incorrect BCCSP Security enabled flag") + } + + // Test SecurityAlgorithm + val, ok = customBackend.Lookup("client.BCCSP.security.hashAlgorithm") + if !ok || val == nil { + t.Fatal("expected valid value") + } + if val.(string) != cryptoConfig.SecurityAlgorithm() { + t.Fatalf("Incorrect BCCSP Security Hash algorithm") + } + + // Test Security Level + val, ok = customBackend.Lookup("client.BCCSP.security.level") + if !ok || val == nil { + t.Fatal("expected valid value") + } + if val.(int) != cryptoConfig.SecurityLevel() { + t.Fatalf("Incorrect BCCSP Security Level") + } + + // Test SecurityProvider provider + val, ok = customBackend.Lookup("client.BCCSP.security.default.provider") + if !ok || val == nil { + t.Fatal("expected valid value") + } + if val.(string) != cryptoConfig.SecurityProvider() { + t.Fatalf("Incorrect BCCSP SecurityProvider provider") + } + + // Test Ephemeral flag + val, ok = customBackend.Lookup("client.BCCSP.security.ephemeral") + if !ok || val == nil { + t.Fatal("expected valid value") + } + if val.(bool) != cryptoConfig.Ephemeral() { + t.Fatalf("Incorrect BCCSP Ephemeral flag") + } + + // Test SoftVerify flag + val, ok = customBackend.Lookup("client.BCCSP.security.softVerify") + if !ok || val == nil { + t.Fatal("expected valid value") + } + if val.(bool) != cryptoConfig.SoftVerify() { + t.Fatalf("Incorrect BCCSP Ephemeral flag") + } + + // Test SecurityProviderPin + val, ok = customBackend.Lookup("client.BCCSP.security.pin") + if !ok || val == nil { + t.Fatal("expected valid value") + } + if val.(string) != cryptoConfig.SecurityProviderPin() { + t.Fatalf("Incorrect BCCSP SecurityProviderPin flag") + } + + // Test SecurityProviderPin + val, ok = customBackend.Lookup("client.BCCSP.security.label") + if !ok || val == nil { + t.Fatal("expected valid value") + } + if val.(string) != cryptoConfig.SecurityProviderLabel() { + t.Fatalf("Incorrect BCCSP SecurityProviderPin flag") + } + +} + +//getCustomBackend returns custom backend to override config values and to avoid using new config file for test scenarios +func getCustomBackend(configBackend core.ConfigBackend) *mocks.MockConfigBackend { + backendMap := make(map[string]interface{}) + backendMap["client.BCCSP.security.enabled"], _ = configBackend.Lookup("client.BCCSP.security.enabled") + backendMap["client.BCCSP.security.hashAlgorithm"], _ = configBackend.Lookup("client.BCCSP.security.hashAlgorithm") + backendMap["client.BCCSP.security.default.provider"], _ = configBackend.Lookup("client.BCCSP.security.default.provider") + backendMap["client.BCCSP.security.ephemeral"], _ = configBackend.Lookup("client.BCCSP.security.ephemeral") + backendMap["client.BCCSP.security.softVerify"], _ = configBackend.Lookup("client.BCCSP.security.softVerify") + backendMap["client.BCCSP.security.level"] = 2 + backendMap["client.BCCSP.security.pin"] = "1234" + backendMap["client.credentialStore.cryptoStore.path"] = "/tmp" + backendMap["client.BCCSP.security.label"] = "TESTLABEL" + return &mocks.MockConfigBackend{KeyValueMap: backendMap} +} diff --git a/pkg/core/mocks/mockconfigbackend.go b/pkg/core/mocks/mockconfigbackend.go new file mode 100644 index 0000000000..e9c240b6a6 --- /dev/null +++ b/pkg/core/mocks/mockconfigbackend.go @@ -0,0 +1,49 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package mocks + +import ( + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" + "github.com/mitchellh/mapstructure" +) + +//MockConfigBackend mocks config backend for unit tests +type MockConfigBackend struct { + KeyValueMap map[string]interface{} +} + +//Lookup returns or unmarshals value for given key +func (b *MockConfigBackend) Lookup(key string, opts ...core.LookupOption) (interface{}, bool) { + if len(opts) > 0 { + lookupOpts := &core.LookupOpts{} + for _, option := range opts { + option(lookupOpts) + } + + if lookupOpts.UnmarshalType != nil { + v, ok := b.KeyValueMap[key] + if !ok { + return nil, false + } + + decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + DecodeHook: mapstructure.StringToTimeDurationHookFunc(), + Result: lookupOpts.UnmarshalType, + }) + if err != nil { + return nil, false + } + err = decoder.Decode(v) + if err != nil { + return nil, false + } + return lookupOpts.UnmarshalType, true + } + } + v, ok := b.KeyValueMap[key] + return v, ok +} diff --git a/pkg/fab/comm/network_test.go b/pkg/fab/comm/network_test.go index 6d8044d83c..ced9a8b769 100644 --- a/pkg/fab/comm/network_test.go +++ b/pkg/fab/comm/network_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + fabImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab" "github.com/stretchr/testify/assert" ) @@ -21,7 +22,7 @@ func TestNetworkPeerConfigFromURL(t *testing.T) { t.Fatalf("Unexpected error reading config backend: %v", err) } - _, sampleConfig, _, err := config.FromBackend(configBackend)() + sampleConfig, err := fabImpl.ConfigFromBackend(configBackend) if err != nil { t.Fatalf("Unexpected error reading config: %v", err) } diff --git a/pkg/core/config/endpointconfig.go b/pkg/fab/endpointconfig.go similarity index 90% rename from pkg/core/config/endpointconfig.go rename to pkg/fab/endpointconfig.go index df5bea12ee..2cb6f5478d 100644 --- a/pkg/core/config/endpointconfig.go +++ b/pkg/fab/endpointconfig.go @@ -4,18 +4,18 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package config +package fab import ( "crypto/tls" "crypto/x509" - "math/rand" "sort" "strconv" "strings" "time" "github.com/hyperledger/fabric-sdk-go/pkg/common/errors/status" + "github.com/hyperledger/fabric-sdk-go/pkg/common/logging" "github.com/hyperledger/fabric-sdk-go/pkg/core/config/cryptoutil" "github.com/hyperledger/fabric-sdk-go/pkg/core/config/endpoint" "github.com/pkg/errors" @@ -26,14 +26,17 @@ import ( "io/ioutil" + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" + "github.com/hyperledger/fabric-sdk-go/pkg/core/config/lookup" cs "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" "github.com/hyperledger/fabric-sdk-go/pkg/util/pathvar" ) +var logger = logging.NewLogger("fabsdk/fab") + const ( - cmdRoot = "FABRIC_SDK" defaultTimeout = time.Second * 5 defaultConnIdleTimeout = time.Second * 30 defaultCacheSweepInterval = time.Second * 15 @@ -42,9 +45,31 @@ const ( defaultExecuteTimeout = time.Second * 180 ) +//ConfigFromBackend returns endpoint config implementation for given backend +func ConfigFromBackend(coreBackend core.ConfigBackend) (fab.EndpointConfig, error) { + + config := &EndpointConfig{backend: lookup.New(coreBackend)} + + if err := config.cacheNetworkConfiguration(); err != nil { + return nil, errors.WithMessage(err, "network configuration load failed") + } + + //Compile the entityMatchers + config.peerMatchers = make(map[int]*regexp.Regexp) + config.ordererMatchers = make(map[int]*regexp.Regexp) + config.caMatchers = make(map[int]*regexp.Regexp) + + matchError := config.compileMatchers() + if matchError != nil { + return nil, matchError + } + + return config, nil +} + // EndpointConfig represents the endpoint configuration for the client type EndpointConfig struct { - backend *Backend + backend *lookup.ConfigLookup tlsCerts []*x509.Certificate networkConfig *fab.NetworkConfig networkConfigCached bool @@ -126,7 +151,7 @@ func (c *EndpointConfig) OrderersConfig() ([]fab.OrdererConfig, error) { if orderer.TLSCACerts.Path != "" { orderer.TLSCACerts.Path = pathvar.Subst(orderer.TLSCACerts.Path) - } else if len(orderer.TLSCACerts.Pem) == 0 && c.backend.getBool("client.tlsCerts.systemCertPool") == false { + } else if len(orderer.TLSCACerts.Pem) == 0 && c.backend.GetBool("client.tlsCerts.systemCertPool") == false { errors.Errorf("Orderer has no certs configured. Make sure TLSCACerts.Pem or TLSCACerts.Path is set for %s", orderer.URL) } @@ -136,16 +161,6 @@ func (c *EndpointConfig) OrderersConfig() ([]fab.OrdererConfig, error) { return orderers, nil } -// RandomOrdererConfig returns a pseudo-random orderer from the network config -func (c *EndpointConfig) RandomOrdererConfig() (*fab.OrdererConfig, error) { - orderers, err := c.OrderersConfig() - if err != nil { - return nil, err - } - - return randomOrdererConfig(orderers) -} - // OrdererConfig returns the requested orderer func (c *EndpointConfig) OrdererConfig(name string) (*fab.OrdererConfig, error) { config, err := c.NetworkConfig() @@ -431,7 +446,7 @@ func (c *EndpointConfig) TLSCACertPool(certs ...*x509.Certificate) (*x509.CertPo // EventServiceType returns the type of event service client to use func (c *EndpointConfig) EventServiceType() fab.EventServiceType { - etype := c.backend.getString("client.eventService.type") + etype := c.backend.GetString("client.eventService.type") switch etype { case "eventhub": return fab.EventHubEventServiceType @@ -498,54 +513,54 @@ func (c *EndpointConfig) TLSClientCerts() ([]tls.Certificate, error) { // CryptoConfigPath ... func (c *EndpointConfig) CryptoConfigPath() string { - return pathvar.Subst(c.backend.getString("client.cryptoconfig.path")) + return pathvar.Subst(c.backend.GetString("client.cryptoconfig.path")) } func (c *EndpointConfig) getTimeout(tType fab.TimeoutType) time.Duration { var timeout time.Duration switch tType { case fab.EndorserConnection: - timeout = c.backend.getDuration("client.peer.timeout.connection") + timeout = c.backend.GetDuration("client.peer.timeout.connection") case fab.Query: - timeout = c.backend.getDuration("client.global.timeout.query") + timeout = c.backend.GetDuration("client.global.timeout.query") case fab.Execute: - timeout = c.backend.getDuration("client.global.timeout.execute") + timeout = c.backend.GetDuration("client.global.timeout.execute") if timeout == 0 { timeout = defaultExecuteTimeout } case fab.DiscoveryGreylistExpiry: - timeout = c.backend.getDuration("client.peer.timeout.discovery.greylistExpiry") + timeout = c.backend.GetDuration("client.peer.timeout.discovery.greylistExpiry") case fab.PeerResponse: - timeout = c.backend.getDuration("client.peer.timeout.response") + timeout = c.backend.GetDuration("client.peer.timeout.response") case fab.EventHubConnection: - timeout = c.backend.getDuration("client.eventService.timeout.connection") + timeout = c.backend.GetDuration("client.eventService.timeout.connection") case fab.EventReg: - timeout = c.backend.getDuration("client.eventService.timeout.registrationResponse") + timeout = c.backend.GetDuration("client.eventService.timeout.registrationResponse") case fab.OrdererConnection: - timeout = c.backend.getDuration("client.orderer.timeout.connection") + timeout = c.backend.GetDuration("client.orderer.timeout.connection") case fab.OrdererResponse: - timeout = c.backend.getDuration("client.orderer.timeout.response") + timeout = c.backend.GetDuration("client.orderer.timeout.response") case fab.ChannelConfigRefresh: - timeout = c.backend.getDuration("client.global.cache.channelConfig") + timeout = c.backend.GetDuration("client.global.cache.channelConfig") case fab.ChannelMembershipRefresh: - timeout = c.backend.getDuration("client.global.cache.channelMembership") + timeout = c.backend.GetDuration("client.global.cache.channelMembership") case fab.CacheSweepInterval: // EXPERIMENTAL - do we need this to be configurable? - timeout = c.backend.getDuration("client.cache.interval.sweep") + timeout = c.backend.GetDuration("client.cache.interval.sweep") if timeout == 0 { timeout = defaultCacheSweepInterval } case fab.ConnectionIdle: - timeout = c.backend.getDuration("client.global.cache.connectionIdle") + timeout = c.backend.GetDuration("client.global.cache.connectionIdle") if timeout == 0 { timeout = defaultConnIdleTimeout } case fab.EventServiceIdle: - timeout = c.backend.getDuration("client.global.cache.eventServiceIdle") + timeout = c.backend.GetDuration("client.global.cache.eventServiceIdle") if timeout == 0 { timeout = defaultEventServiceIdleTimeout } case fab.ResMgmt: - timeout = c.backend.getDuration("client.global.timeout.resmgmt") + timeout = c.backend.GetDuration("client.global.timeout.resmgmt") if timeout == 0 { timeout = defaultResMgmtTimeout } @@ -556,47 +571,47 @@ func (c *EndpointConfig) getTimeout(tType fab.TimeoutType) time.Duration { func (c *EndpointConfig) cacheNetworkConfiguration() error { networkConfig := fab.NetworkConfig{} - networkConfig.Name = c.backend.getString("name") - networkConfig.Description = c.backend.getString("description") - networkConfig.Version = c.backend.getString("version") + networkConfig.Name = c.backend.GetString("name") + networkConfig.Description = c.backend.GetString("description") + networkConfig.Version = c.backend.GetString("version") - ok := c.backend.unmarshalKey("client", &networkConfig.Client) + ok := c.backend.UnmarshalKey("client", &networkConfig.Client) logger.Debugf("Client is: %+v", networkConfig.Client) if !ok { return errors.New("failed to parse 'client' config item to networkConfig.Client type") } - ok = c.backend.unmarshalKey("channels", &networkConfig.Channels) + ok = c.backend.UnmarshalKey("channels", &networkConfig.Channels) logger.Debugf("channels are: %+v", networkConfig.Channels) if !ok { return errors.New("failed to parse 'channels' config item to networkConfig.Channels type") } - ok = c.backend.unmarshalKey("organizations", &networkConfig.Organizations) + ok = c.backend.UnmarshalKey("organizations", &networkConfig.Organizations) logger.Debugf("organizations are: %+v", networkConfig.Organizations) if !ok { return errors.New("failed to parse 'organizations' config item to networkConfig.Organizations type") } - ok = c.backend.unmarshalKey("orderers", &networkConfig.Orderers) + ok = c.backend.UnmarshalKey("orderers", &networkConfig.Orderers) logger.Debugf("orderers are: %+v", networkConfig.Orderers) if !ok { return errors.New("failed to parse 'orderers' config item to networkConfig.Orderers type") } - ok = c.backend.unmarshalKey("peers", &networkConfig.Peers) + ok = c.backend.UnmarshalKey("peers", &networkConfig.Peers) logger.Debugf("peers are: %+v", networkConfig.Peers) if !ok { return errors.New("failed to parse 'peers' config item to networkConfig.Peers type") } - ok = c.backend.unmarshalKey("certificateAuthorities", &networkConfig.CertificateAuthorities) + ok = c.backend.UnmarshalKey("certificateAuthorities", &networkConfig.CertificateAuthorities) logger.Debugf("certificateAuthorities are: %+v", networkConfig.CertificateAuthorities) if !ok { return errors.New("failed to parse 'certificateAuthorities' config item to networkConfig.CertificateAuthorities type") } - ok = c.backend.unmarshalKey("entityMatchers", &networkConfig.EntityMatchers) + ok = c.backend.UnmarshalKey("entityMatchers", &networkConfig.EntityMatchers) logger.Debugf("Matchers are: %+v", networkConfig.EntityMatchers) if !ok { return errors.New("failed to parse 'entityMatchers' config item to networkConfig.EntityMatchers type") @@ -607,16 +622,6 @@ func (c *EndpointConfig) cacheNetworkConfiguration() error { return nil } -// randomOrdererConfig returns a pseudo-random orderer from the list of orderers -func randomOrdererConfig(orderers []fab.OrdererConfig) (*fab.OrdererConfig, error) { - - rs := rand.NewSource(time.Now().Unix()) - r := rand.New(rs) - randomNumber := r.Intn(len(orderers)) - - return &orderers[randomNumber], nil -} - func (c *EndpointConfig) getPortIfPresent(url string) (int, bool) { s := strings.Split(url, ":") if len(s) > 1 { @@ -923,7 +928,7 @@ func (c *EndpointConfig) verifyPeerConfig(p fab.PeerConfig, peerName string, tls if p.URL == "" { return errors.Errorf("URL does not exist or empty for peer %s", peerName) } - if tlsEnabled && len(p.TLSCACerts.Pem) == 0 && p.TLSCACerts.Path == "" && c.backend.getBool("client.tlsCerts.systemCertPool") == false { + if tlsEnabled && len(p.TLSCACerts.Pem) == 0 && p.TLSCACerts.Path == "" && c.backend.GetBool("client.tlsCerts.systemCertPool") == false { return errors.Errorf("tls.certificate does not exist or empty for peer %s", peerName) } return nil @@ -941,7 +946,7 @@ func (c *EndpointConfig) containsCert(newCert *x509.Certificate) bool { func (c *EndpointConfig) getCertPool() (*x509.CertPool, error) { tlsCertPool := x509.NewCertPool() - if c.backend.getBool("client.tlsCerts.systemCertPool") == true { + if c.backend.GetBool("client.tlsCerts.systemCertPool") == true { var err error if tlsCertPool, err = x509.SystemCertPool(); err != nil { return nil, err @@ -967,6 +972,22 @@ func (c *EndpointConfig) client() (*msp.ClientConfig, error) { return &client, nil } +//Backend returns config lookup of endpoint config +func (c *EndpointConfig) Backend() *lookup.ConfigLookup { + return c.backend +} + +//CAMatchers returns CA matchers of endpoint config +func (c *EndpointConfig) CAMatchers() map[int]*regexp.Regexp { + return c.caMatchers +} + +//ResetNetworkConfig clears network config cache +func (c *EndpointConfig) ResetNetworkConfig() { + c.networkConfig = nil + c.networkConfigCached = false +} + func loadByteKeyOrCertFromFile(c *msp.ClientConfig, isKey bool) ([]byte, error) { var path string a := "key" diff --git a/pkg/fab/endpointconfig_test.go b/pkg/fab/endpointconfig_test.go new file mode 100644 index 0000000000..f34d6c115f --- /dev/null +++ b/pkg/fab/endpointconfig_test.go @@ -0,0 +1,1120 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package fab + +import ( + "crypto/tls" + "testing" + + "os" + + "fmt" + + "time" + + "path/filepath" + + "strings" + + "reflect" + + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" + "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/core/config/endpoint" + "github.com/hyperledger/fabric-sdk-go/pkg/core/mocks" + "github.com/hyperledger/fabric-sdk-go/pkg/util/pathvar" + "github.com/stretchr/testify/assert" +) + +const ( + org0 = "org0" + org1 = "org1" + configTestFilePath = "../core/config/testdata/config_test.yaml" + certPath = "${GOPATH}/src/github.com/hyperledger/fabric-sdk-go/test/fixtures/fabricca/tls/certs/client/client_fabric_client.pem" + keyPath = "${GOPATH}/src/github.com/hyperledger/fabric-sdk-go/test/fixtures/fabricca/tls/certs/client/client_fabric_client-key.pem" + configPemTestFilePath = "../core/config/testdata/config_test_pem.yaml" + configEmbeddedUsersTestFilePath = "../core/config/testdata/config_test_embedded_pems.yaml" + configType = "yaml" +) + +var configBackend core.ConfigBackend + +func TestMain(m *testing.M) { + cfgBackend, err := config.FromFile(configTestFilePath)() + if err != nil { + panic(fmt.Sprintf("Unexpected error reading config: %v", err)) + } + configBackend = cfgBackend + r := m.Run() + os.Exit(r) +} + +func getCustomBackend() *mocks.MockConfigBackend { + backendMap := make(map[string]interface{}) + backendMap["client"], _ = configBackend.Lookup("client") + backendMap["certificateAuthorities"], _ = configBackend.Lookup("certificateAuthorities") + backendMap["entityMatchers"], _ = configBackend.Lookup("entityMatchers") + backendMap["peers"], _ = configBackend.Lookup("peers") + backendMap["organizations"], _ = configBackend.Lookup("organizations") + backendMap["orderers"], _ = configBackend.Lookup("orderers") + backendMap["channels"], _ = configBackend.Lookup("channels") + return &mocks.MockConfigBackend{KeyValueMap: backendMap} +} + +func TestCAConfigFailsByNetworkConfig(t *testing.T) { + + customBackend := getCustomBackend() + customBackend.KeyValueMap["client"], _ = configBackend.Lookup("client") + customBackend.KeyValueMap["certificateAuthorities"], _ = configBackend.Lookup("certificateAuthorities") + customBackend.KeyValueMap["entityMatchers"], _ = configBackend.Lookup("entityMatchers") + customBackend.KeyValueMap["peers"], _ = configBackend.Lookup("peers") + customBackend.KeyValueMap["organizations"], _ = configBackend.Lookup("organizations") + customBackend.KeyValueMap["orderers"], _ = configBackend.Lookup("orderers") + customBackend.KeyValueMap["channels"], _ = configBackend.Lookup("channels") + + endpointCfg, err := ConfigFromBackend(customBackend) + if err != nil { + t.Fatalf("Unexpected error initializing endpoint config: %v", err) + } + + sampleEndpointConfig := endpointCfg.(*EndpointConfig) + sampleEndpointConfig.networkConfigCached = false + + customBackend.KeyValueMap["channels"] = "INVALID" + _, err = sampleEndpointConfig.NetworkConfig() + if err == nil { + t.Fatal("Network config load supposed to fail") + } + + //Testing MSPID failure scenario + mspID, err := sampleEndpointConfig.MSPID("peerorg1") + if mspID != "" || err == nil { + t.Fatal("Get MSP ID supposed to fail") + } + + //Testing OrdererConfig failure scenario + oConfig, err := sampleEndpointConfig.OrdererConfig("peerorg1") + if oConfig != nil || err == nil { + t.Fatal("Testing get OrdererConfig supposed to fail") + } + + //Testing PeersConfig failure scenario + pConfigs, err := sampleEndpointConfig.PeersConfig("peerorg1") + if pConfigs != nil || err == nil { + t.Fatal("Testing PeersConfig supposed to fail") + } + + //Testing PeersConfig failure scenario + pConfig, err := sampleEndpointConfig.PeerConfig("peerorg1", "peer1") + if pConfig != nil || err == nil { + t.Fatal("Testing PeerConfig supposed to fail") + } + + //Testing ChannelConfig failure scenario + chConfig, err := sampleEndpointConfig.ChannelConfig("invalid") + if chConfig != nil || err == nil { + t.Fatal("Testing ChannelConfig supposed to fail") + } + + //Testing ChannelPeers failure scenario + cpConfigs, err := sampleEndpointConfig.ChannelPeers("invalid") + if cpConfigs != nil || err == nil { + t.Fatal("Testing ChannelPeeers supposed to fail") + } + + //Testing ChannelOrderers failure scenario + coConfigs, err := sampleEndpointConfig.ChannelOrderers("invalid") + if coConfigs != nil || err == nil { + t.Fatal("Testing ChannelOrderers supposed to fail") + } + + // test empty network objects + + customBackend.KeyValueMap["channels"], _ = configBackend.Lookup("channels") + delete(customBackend.KeyValueMap, "organizations") + sampleEndpointConfig.networkConfigCached = false + _, err = sampleEndpointConfig.NetworkConfig() + if err == nil { + t.Fatalf("Organizations were empty, it should return an error") + } +} + +func TestTLSCAConfig(t *testing.T) { + //Test TLSCA Cert Pool (Positive test case) + certConfig := endpoint.TLSConfig{Path: pathvar.Subst(certPath)} + + cert, err := certConfig.TLSCert() + if err != nil { + t.Fatalf("Failed to get TLS CA Cert, reason: %v", err) + } + + config, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatalf("Failed to get endpoint config, reason: %v", err) + } + + endpointConfig := config.(*EndpointConfig) + + _, err = endpointConfig.TLSCACertPool(cert) + if err != nil { + t.Fatalf("TLS CA cert pool fetch failed, reason: %v", err) + } + + //Try again with same cert + _, err = endpointConfig.TLSCACertPool(cert) + if err != nil { + t.Fatalf("TLS CA cert pool fetch failed, reason: %v", err) + } + + assert.False(t, len(endpointConfig.tlsCerts) > 1, "number of certs in cert list shouldn't accept duplicates") + + //Test TLSCA Cert Pool (Negative test case) + + badCertConfig := endpoint.TLSConfig{Path: "some random invalid path"} + + badCert, err := badCertConfig.TLSCert() + + if err == nil { + t.Fatalf("TLS CA cert pool was supposed to fail") + } + + _, err = endpointConfig.TLSCACertPool(badCert) + + keyConfig := endpoint.TLSConfig{Path: keyPath} + + key, err := keyConfig.TLSCert() + + if err == nil { + t.Fatalf("TLS CA cert pool was supposed to fail when provided with wrong cert file") + } + + _, err = endpointConfig.TLSCACertPool(key) +} + +func TestTimeouts(t *testing.T) { + + customBackend := getCustomBackend() + customBackend.KeyValueMap["client.peer.timeout.connection"] = "2s" + customBackend.KeyValueMap["client.peer.timeout.response"] = "6s" + customBackend.KeyValueMap["client.eventService.timeout.connection"] = "2m" + customBackend.KeyValueMap["client.eventService.timeout.registrationResponse"] = "2h" + customBackend.KeyValueMap["client.orderer.timeout.connection"] = "2ms" + customBackend.KeyValueMap["client.global.timeout.query"] = "7h" + customBackend.KeyValueMap["client.global.timeout.execute"] = "8h" + customBackend.KeyValueMap["client.global.timeout.resmgmt"] = "118s" + customBackend.KeyValueMap["client.global.cache.connectionIdle"] = "1m" + customBackend.KeyValueMap["client.global.cache.eventServiceIdle"] = "2m" + customBackend.KeyValueMap["client.orderer.timeout.response"] = "6s" + + endpointConfig, err := ConfigFromBackend(customBackend) + if err != nil { + t.Fatal("Failed to get endpoint config from backend") + } + + t1 := endpointConfig.TimeoutOrDefault(fab.EndorserConnection) + if t1 != time.Second*2 { + t.Fatalf("Timeout not read correctly. Got: %s", t1) + } + t1 = endpointConfig.TimeoutOrDefault(fab.EventHubConnection) + if t1 != time.Minute*2 { + t.Fatalf("Timeout not read correctly. Got: %s", t1) + } + t1 = endpointConfig.TimeoutOrDefault(fab.EventReg) + if t1 != time.Hour*2 { + t.Fatalf("Timeout not read correctly. Got: %s", t1) + } + t1 = endpointConfig.TimeoutOrDefault(fab.Query) + if t1 != time.Hour*7 { + t.Fatalf("Timeout not read correctly. Got: %s", t1) + } + t1 = endpointConfig.TimeoutOrDefault(fab.Execute) + if t1 != time.Hour*8 { + t.Fatalf("Timeout not read correctly. Got: %s", t1) + } + t1 = endpointConfig.TimeoutOrDefault(fab.OrdererConnection) + if t1 != time.Millisecond*2 { + t.Fatalf("Timeout not read correctly. Got: %s", t1) + } + t1 = endpointConfig.TimeoutOrDefault(fab.OrdererResponse) + if t1 != time.Second*6 { + t.Fatalf("Timeout not read correctly. Got: %s", t1) + } + t1 = endpointConfig.TimeoutOrDefault(fab.ConnectionIdle) + if t1 != time.Minute*1 { + t.Fatalf("Timeout not read correctly. Got: %s", t1) + } + t1 = endpointConfig.TimeoutOrDefault(fab.EventServiceIdle) + if t1 != time.Minute*2 { + t.Fatalf("Timeout not read correctly. Got: %s", t1) + } + t1 = endpointConfig.TimeoutOrDefault(fab.PeerResponse) + if t1 != time.Second*6 { + t.Fatalf("Timeout not read correctly. Got: %s", t1) + } + t1 = endpointConfig.TimeoutOrDefault(fab.ResMgmt) + if t1 != time.Second*118 { + t.Fatalf("Timeout not read correctly. Got: %s", t1) + } + + // Test default + customBackend.KeyValueMap["client.orderer.timeout.connection"] = "" + t1 = endpointConfig.TimeoutOrDefault(fab.OrdererConnection) + if t1 != time.Second*5 { + t.Fatalf("Timeout not read correctly. Got: %s", t1) + } + +} + +func TestOrdererConfig(t *testing.T) { + endpointConfig, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal("Failed to get endpoint config from backend") + } + + oConfig, err := endpointConfig.OrdererConfig("invalid") + if oConfig != nil || err == nil { + t.Fatal("Testing non-existing OrdererConfig failed") + } + + orderers, err := endpointConfig.OrderersConfig() + if err != nil { + t.Fatal(err) + } + + if orderers[0].TLSCACerts.Path != "" { + if !filepath.IsAbs(orderers[0].TLSCACerts.Path) { + t.Fatal("Expected GOPATH relative path to be replaced") + } + } else if len(orderers[0].TLSCACerts.Pem) == 0 { + t.Fatalf("Orderer %v must have at least a TlsCACerts.Path or TlsCACerts.Pem set", orderers[0]) + } +} + +func TestChannelOrderers(t *testing.T) { + endpointConfig, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal("Failed to get endpoint config from backend") + } + + orderers, err := endpointConfig.ChannelOrderers("mychannel") + if orderers == nil || err != nil { + t.Fatal("Testing ChannelOrderers failed") + } + + if len(orderers) != 1 { + t.Fatalf("Expecting one channel orderer got %d", len(orderers)) + } + + if orderers[0].TLSCACerts.Path != "" { + if !filepath.IsAbs(orderers[0].TLSCACerts.Path) { + t.Fatal("Expected GOPATH relative path to be replaced") + } + } else if len(orderers[0].TLSCACerts.Pem) == 0 { + t.Fatalf("Orderer %v must have at least a TlsCACerts.Path or TlsCACerts.Pem set", orderers[0]) + } +} + +func TestPeerConfigByUrl_directMatching(t *testing.T) { + testCommonConfigPeerByURL(t, "peer0.org1.example.com", "peer0.org1.example.com:7051") +} + +func TestPeerConfigByUrl_entityMatchers(t *testing.T) { + testCommonConfigPeerByURL(t, "peer0.org1.example.com", "peer1.org1.example.com:7051") +} + +func testCommonConfigPeerByURL(t *testing.T, expectedConfigURL string, fetchedConfigURL string) { + config, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal("Failed to get endpoint config from backend") + } + + endpointConfig := config.(*EndpointConfig) + + expectedConfig, err := endpointConfig.peerConfig(expectedConfigURL) + if err != nil { + t.Fatalf(err.Error()) + } + + fetchedConfig, err := endpointConfig.PeerConfigByURL(fetchedConfigURL) + + if fetchedConfig.URL == "" { + t.Fatalf("Url value for the host is empty") + } + + if len(fetchedConfig.GRPCOptions) != len(expectedConfig.GRPCOptions) || fetchedConfig.TLSCACerts.Pem != expectedConfig.TLSCACerts.Pem { + t.Fatalf("Expected Config and fetched config differ") + } + + if fetchedConfig.URL != expectedConfig.URL || fetchedConfig.EventURL != expectedConfig.EventURL || fetchedConfig.GRPCOptions["ssl-target-name-override"] != expectedConfig.GRPCOptions["ssl-target-name-override"] { + t.Fatalf("Expected Config and fetched config differ") + } +} + +func testCommonConfigOrderer(t *testing.T, expectedConfigHost string, fetchedConfigHost string) (expectedConfig *fab.OrdererConfig, fetchedConfig *fab.OrdererConfig) { + + endpointConfig, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal("Failed to get endpoint config from backend") + } + + expectedConfig, err = endpointConfig.OrdererConfig(expectedConfigHost) + if err != nil { + t.Fatalf(err.Error()) + } + + fetchedConfig, err = endpointConfig.OrdererConfig(fetchedConfigHost) + if err != nil { + t.Fatalf(err.Error()) + } + + if expectedConfig.URL == "" { + t.Fatalf("Url value for the host is empty") + } + if fetchedConfig.URL == "" { + t.Fatalf("Url value for the host is empty") + } + + if len(fetchedConfig.GRPCOptions) != len(expectedConfig.GRPCOptions) || fetchedConfig.TLSCACerts.Pem != expectedConfig.TLSCACerts.Pem { + t.Fatalf("Expected Config and fetched config differ") + } + + return expectedConfig, fetchedConfig +} + +func TestOrdererWithSubstitutedConfig_WithADifferentSubstituteUrl(t *testing.T) { + expectedConfig, fetchedConfig := testCommonConfigOrderer(t, "orderer.example.com", "orderer.example2.com") + + if fetchedConfig.URL == "orderer.example2.com:7050" || fetchedConfig.URL == expectedConfig.URL { + t.Fatalf("Expected Config should have url that is given in urlSubstitutionExp of match pattern") + } + + if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "localhost" { + t.Fatalf("Config should have got localhost as its ssl-target-name-override url as per the matched config") + } +} + +func TestOrdererWithSubstitutedConfig_WithEmptySubstituteUrl(t *testing.T) { + _, fetchedConfig := testCommonConfigOrderer(t, "orderer.example.com", "orderer.example3.com") + + if fetchedConfig.URL != "orderer.example3.com:7050" { + t.Fatalf("Fetched Config should have the same url") + } + + if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "orderer.example3.com" { + t.Fatalf("Fetched config should have the same ssl-target-name-override as its hostname") + } +} + +func TestOrdererWithSubstitutedConfig_WithSubstituteUrlExpression(t *testing.T) { + expectedConfig, fetchedConfig := testCommonConfigOrderer(t, "orderer.example.com", "orderer.example4.com:7050") + + if fetchedConfig.URL != expectedConfig.URL { + t.Fatalf("fetched Config url should be same as expected config url as given in the substituteexp in yaml file") + } + + if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "orderer.example.com" { + t.Fatalf("Fetched config should have the ssl-target-name-override as per sslTargetOverrideUrlSubstitutionExp in yaml file") + } +} + +func TestPeersConfig(t *testing.T) { + + endpointConfig, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal("Failed to get endpoint config from backend") + } + + pc, err := endpointConfig.PeersConfig(org0) + if err != nil { + t.Fatalf(err.Error()) + } + + for _, value := range pc { + if value.URL == "" { + t.Fatalf("Url value for the host is empty") + } + if value.EventURL == "" { + t.Fatalf("EventUrl value is empty") + } + } + + pc, err = endpointConfig.PeersConfig(org1) + if err != nil { + t.Fatalf(err.Error()) + } + + for _, value := range pc { + if value.URL == "" { + t.Fatalf("Url value for the host is empty") + } + if value.EventURL == "" { + t.Fatalf("EventUrl value is empty") + } + } +} + +func TestPeerConfig(t *testing.T) { + + endpointConfig, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal("Failed to get endpoint config from backend") + } + + pc, err := endpointConfig.PeerConfig(org1, "peer0.org1.example.com") + if err != nil { + t.Fatalf(err.Error()) + } + + if pc.URL == "" { + t.Fatalf("Url value for the host is empty") + } + + if pc.TLSCACerts.Path != "" { + if !filepath.IsAbs(pc.TLSCACerts.Path) { + t.Fatalf("Expected cert path to be absolute") + } + } else if len(pc.TLSCACerts.Pem) == 0 { + t.Fatalf("Peer %s must have at least a TlsCACerts.Path or TlsCACerts.Pem set", "peer0") + } + if len(pc.GRPCOptions) == 0 || pc.GRPCOptions["ssl-target-name-override"] != "peer0.org1.example.com" { + t.Fatalf("Peer %s must have grpcOptions set in config_test.yaml", "peer0") + } +} + +func testCommonConfigPeer(t *testing.T, expectedConfigHost string, fetchedConfigHost string) (expectedConfig *fab.PeerConfig, fetchedConfig *fab.PeerConfig) { + + config, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal("Failed to get endpoint config from backend") + } + + endpointConfig := config.(*EndpointConfig) + + expectedConfig, err = endpointConfig.peerConfig(expectedConfigHost) + if err != nil { + t.Fatalf(err.Error()) + } + + fetchedConfig, err = endpointConfig.peerConfig(fetchedConfigHost) + if err != nil { + t.Fatalf(err.Error()) + } + + if expectedConfig.URL == "" { + t.Fatalf("Url value for the host is empty") + } + if fetchedConfig.URL == "" { + t.Fatalf("Url value for the host is empty") + } + + if fetchedConfig.TLSCACerts.Path != expectedConfig.TLSCACerts.Path || len(fetchedConfig.GRPCOptions) != len(expectedConfig.GRPCOptions) { + t.Fatalf("Expected Config and fetched config differ") + } + + return expectedConfig, fetchedConfig +} + +func TestPeerWithSubstitutedConfig_WithADifferentSubstituteUrl(t *testing.T) { + expectedConfig, fetchedConfig := testCommonConfigPeer(t, "peer0.org1.example.com", "peer3.org1.example5.com") + + if fetchedConfig.URL == "peer3.org1.example5.com:7051" || fetchedConfig.URL == expectedConfig.URL { + t.Fatalf("Expected Config should have url that is given in urlSubstitutionExp of match pattern") + } + + if fetchedConfig.EventURL == "peer3.org1.example5.com:7053" || fetchedConfig.EventURL == expectedConfig.EventURL { + t.Fatalf("Expected Config should have event url that is given in eventUrlSubstitutionExp of match pattern") + } + + if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "localhost" { + t.Fatalf("Config should have got localhost as its ssl-target-name-override url as per the matched config") + } +} + +func TestPeerWithSubstitutedConfig_WithEmptySubstituteUrl(t *testing.T) { + _, fetchedConfig := testCommonConfigPeer(t, "peer0.org1.example.com", "peer4.org1.example3.com") + + if fetchedConfig.URL != "peer4.org1.example3.com:7051" { + t.Fatalf("Fetched Config should have the same url") + } + + if fetchedConfig.EventURL != "peer4.org1.example3.com:7053" { + t.Fatalf("Fetched Config should have the same event url") + } + + if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "peer4.org1.example3.com" { + t.Fatalf("Fetched config should have the same ssl-target-name-override as its hostname") + } +} + +func TestPeerWithSubstitutedConfig_WithSubstituteUrlExpression(t *testing.T) { + _, fetchedConfig := testCommonConfigPeer(t, "peer0.org1.example.com", "peer5.example4.com:1234") + + if fetchedConfig.URL != "peer5.org1.example.com:1234" { + t.Fatalf("fetched Config url should change to include org1 as given in the substituteexp in yaml file") + } + + if fetchedConfig.EventURL != "peer5.org1.example.com:7053" { + t.Fatalf("fetched Config event url should change to include org1 as given in the eventsubstituteexp in yaml file") + } + + if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "peer5.org1.example.com" { + t.Fatalf("Fetched config should have the ssl-target-name-override as per sslTargetOverrideUrlSubstitutionExp in yaml file") + } +} + +func TestPeerWithSubstitutedConfig_WithMultipleMatchings(t *testing.T) { + _, fetchedConfig := testCommonConfigPeer(t, "peer0.org2.example.com", "peer2.example2.com:1234") + + //Both 2nd and 5th entityMatchers match, however we are only taking 2nd one as its the first one to match + if fetchedConfig.URL == "peer0.org2.example.com:7051" { + t.Fatalf("fetched Config url should be matched with the first suitable matcher") + } + + if fetchedConfig.EventURL != "localhost:7053" { + t.Fatalf("fetched Config event url should have the config from first suitable matcher") + } + + if fetchedConfig.GRPCOptions["ssl-target-name-override"] != "localhost" { + t.Fatalf("Fetched config should have the ssl-target-name-override as per first suitable matcher in yaml file") + } +} + +func TestPeerNotInOrgConfig(t *testing.T) { + endpointConfig, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal("Failed to get endpoint config from backend") + } + + _, err = endpointConfig.PeerConfig(org1, "peer1.org0.example.com") + if err == nil { + t.Fatalf("Fetching peer config not for an unassigned org should fail") + } +} + +func TestNetworkConfig(t *testing.T) { + endpointConfig, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal("Failed to get endpoint config from backend") + } + + conf, err := endpointConfig.NetworkConfig() + if err != nil { + t.Fatal(err) + } + if len(conf.Orderers) == 0 { + t.Fatal("Expected orderers to be set") + } + if len(conf.Organizations) == 0 { + t.Fatal("Expected atleast one organisation to be set") + } + // viper map keys are lowercase + if len(conf.Organizations[strings.ToLower(org1)].Peers) == 0 { + t.Fatalf("Expected org %s to be present in network configuration and peers to be set", org1) + } +} + +func TestSystemCertPoolDisabled(t *testing.T) { + + // get a config file with pool enabled + customBackend := getCustomBackend() + customBackend.KeyValueMap["client.tlsCerts.systemCertPool"] = false + // get a config file with pool disabled + endpointConfig, err := ConfigFromBackend(customBackend) + if err != nil { + t.Fatal("Failed to get endpoint config from backend") + } + + certPool, err := endpointConfig.TLSCACertPool() + if err != nil { + t.Fatal("not supposed to get error") + } + // cert pool should be empty + if len(certPool.Subjects()) > 0 { + t.Fatal("Expecting empty tls cert pool due to disabled system cert pool") + } +} + +func TestInitConfigFromRawWithPem(t *testing.T) { + // get a config byte for testing + cBytes, err := loadConfigBytesFromFile(t, configPemTestFilePath) + if err != nil { + t.Fatalf("Failed to load sample bytes from File. Error: %s", err) + } + + // test init config from bytes + backend, err := config.FromRaw(cBytes, configType)() + if err != nil { + t.Fatalf("Failed to initialize config from bytes array. Error: %s", err) + } + + config, err := ConfigFromBackend(backend) + if err != nil { + t.Fatalf("Failed to initialize config from bytes array. Error: %s", err) + } + + endpointConfig := config.(*EndpointConfig) + + o, err := endpointConfig.OrderersConfig() + if err != nil { + t.Fatalf("Failed to load orderers from config. Error: %s", err) + } + + if o == nil || len(o) == 0 { + t.Fatalf("orderer cannot be nil or empty") + } + + oPem := `-----BEGIN CERTIFICATE----- +MIICNjCCAdygAwIBAgIRAILSPmMB3BzoLIQGsFxwZr8wCgYIKoZIzj0EAwIwbDEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG +cmFuY2lzY28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRowGAYDVQQDExF0bHNjYS5l +eGFtcGxlLmNvbTAeFw0xNzA3MjgxNDI3MjBaFw0yNzA3MjYxNDI3MjBaMGwxCzAJ +BgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJh +bmNpc2NvMRQwEgYDVQQKEwtleGFtcGxlLmNvbTEaMBgGA1UEAxMRdGxzY2EuZXhh +bXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQfgKb4db53odNzdMXn +P5FZTZTFztOO1yLvCHDofSNfTPq/guw+YYk7ZNmhlhj8JHFG6dTybc9Qb/HOh9hh +gYpXo18wXTAOBgNVHQ8BAf8EBAMCAaYwDwYDVR0lBAgwBgYEVR0lADAPBgNVHRMB +Af8EBTADAQH/MCkGA1UdDgQiBCBxaEP3nVHQx4r7tC+WO//vrPRM1t86SKN0s6XB +8LWbHTAKBggqhkjOPQQDAgNIADBFAiEA96HXwCsuMr7tti8lpcv1oVnXg0FlTxR/ +SQtE5YgdxkUCIHReNWh/pluHTxeGu2jNCH1eh6o2ajSGeeizoapvdJbN +-----END CERTIFICATE-----` + loadedOPem := strings.TrimSpace(o[0].TLSCACerts.Pem) // viper's unmarshall adds a \n to the end of a string, hence the TrimeSpace + if loadedOPem != oPem { + t.Fatalf("Orderer Pem doesn't match. Expected \n'%s'\n, but got \n'%s'\n", oPem, loadedOPem) + } + + pc, err := endpointConfig.PeersConfig(org1) + if err != nil { + t.Fatalf(err.Error()) + } + if pc == nil || len(pc) == 0 { + t.Fatalf("peers list of %s cannot be nil or empty", org1) + } + peer0 := "peer0.org1.example.com" + p0, err := endpointConfig.PeerConfig(org1, peer0) + if err != nil { + t.Fatalf("Failed to load %s of %s from the config. Error: %s", peer0, org1, err) + } + if p0 == nil { + t.Fatalf("%s of %s cannot be nil", peer0, org1) + } + pPem := `-----BEGIN CERTIFICATE----- +MIICSTCCAfCgAwIBAgIRAPQIzfkrCZjcpGwVhMSKd0AwCgYIKoZIzj0EAwIwdjEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG +cmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHzAdBgNVBAMTFnRs +c2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTcwNzI4MTQyNzIwWhcNMjcwNzI2MTQy +NzIwWjB2MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE +BxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEfMB0G +A1UEAxMWdGxzY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49 +AwEHA0IABMOiG8UplWTs898zZ99+PhDHPbKjZIDHVG+zQXopw8SqNdX3NAmZUKUU +sJ8JZ3M49Jq4Ms8EHSEwQf0Ifx3ICHujXzBdMA4GA1UdDwEB/wQEAwIBpjAPBgNV +HSUECDAGBgRVHSUAMA8GA1UdEwEB/wQFMAMBAf8wKQYDVR0OBCIEID9qJz7xhZko +V842OVjxCYYQwCjPIY+5e9ORR+8pxVzcMAoGCCqGSM49BAMCA0cAMEQCIGZ+KTfS +eezqv0ml1VeQEmnAEt5sJ2RJA58+LegUYMd6AiAfEe6BKqdY03qFUgEYmtKG+3Dr +O94CDp7l2k7hMQI0zQ== +-----END CERTIFICATE-----` + + loadedPPem := strings.TrimSpace(p0.TLSCACerts.Pem) // viper's unmarshall adds a \n to the end of a string, hence the TrimeSpace + if loadedPPem != pPem { + t.Fatalf("%s Pem doesn't match. Expected \n'%s'\n, but got \n'%s'\n", peer0, pPem, loadedPPem) + } + +} + +func loadConfigBytesFromFile(t *testing.T, filePath string) ([]byte, error) { + // read test config file into bytes array + f, err := os.Open(filePath) + if err != nil { + t.Fatalf("Failed to read config file. Error: %s", err) + } + defer f.Close() + fi, err := f.Stat() + if err != nil { + t.Fatalf("Failed to read config file stat. Error: %s", err) + } + s := fi.Size() + cBytes := make([]byte, s, s) + n, err := f.Read(cBytes) + if err != nil { + t.Fatalf("Failed to read test config for bytes array testing. Error: %s", err) + } + if n == 0 { + t.Fatalf("Failed to read test config for bytes array testing. Mock bytes array is empty") + } + return cBytes, err +} + +func TestLoadConfigWithEmbeddedUsersWithPems(t *testing.T) { + // get a config file with embedded users + configBackend, err := config.FromFile(configEmbeddedUsersTestFilePath)() + if err != nil { + t.Fatal(err) + } + + endpointConfig, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal(err) + } + + conf, err := endpointConfig.NetworkConfig() + + if err != nil { + t.Fatal(err) + } + + if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("EmbeddedUser")].Cert.Pem == "" { + t.Fatal("Failed to parse the embedded cert for user EmbeddedUser") + } + + if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("EmbeddedUser")].Key.Pem == "" { + t.Fatal("Failed to parse the embedded key for user EmbeddedUser") + } + + if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("NonExistentEmbeddedUser")].Key.Pem != "" { + t.Fatal("Mistakenly found an embedded key for user NonExistentEmbeddedUser") + } + + if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("NonExistentEmbeddedUser")].Cert.Pem != "" { + t.Fatal("Mistakenly found an embedded cert for user NonExistentEmbeddedUser") + } +} + +func TestLoadConfigWithEmbeddedUsersWithPaths(t *testing.T) { + // get a config file with embedded users + configBackend, err := config.FromFile(configEmbeddedUsersTestFilePath)() + if err != nil { + t.Fatal(err) + } + + endpointConfig, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal(err) + } + + conf, err := endpointConfig.NetworkConfig() + + if err != nil { + t.Fatal(err) + } + + if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("EmbeddedUserWithPaths")].Cert.Path == "" { + t.Fatal("Failed to parse the embedded cert for user EmbeddedUserWithPaths") + } + + if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("EmbeddedUserWithPaths")].Key.Path == "" { + t.Fatal("Failed to parse the embedded key for user EmbeddedUserWithPaths") + } + + if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("NonExistentEmbeddedUser")].Key.Path != "" { + t.Fatal("Mistakenly found an embedded key for user NonExistentEmbeddedUser") + } + + if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("NonExistentEmbeddedUser")].Cert.Path != "" { + t.Fatal("Mistakenly found an embedded cert for user NonExistentEmbeddedUser") + } +} + +func TestInitConfigFromRawWrongType(t *testing.T) { + // get a config byte for testing + cBytes, err := loadConfigBytesFromFile(t, configPemTestFilePath) + if err != nil { + t.Fatalf("Failed to load sample bytes from File. Error: %s", err) + } + + // test init config with empty type + backend, err := config.FromRaw(cBytes, "")() + if err == nil { + t.Fatalf("Expected error when initializing config with wrong config type but got no error.") + } + + // test init config with wrong type + backend, err = config.FromRaw(cBytes, "json")() + if err != nil { + t.Fatalf("Failed to initialize config backend from bytes array. Error: %s", err) + } + + endpointConfig, err := ConfigFromBackend(backend) + if err != nil { + t.Fatalf("Failed to initialize config from backend. Error: %s", err) + } + + o, err := endpointConfig.OrderersConfig() + if len(o) > 0 { + t.Fatalf("Expected to get an empty list of orderers for wrong config type") + } + + np, err := endpointConfig.NetworkPeers() + if len(np) > 0 { + t.Fatalf("Expected to get an empty list of peers for wrong config type") + } +} + +func TestTLSClientCertsFromFiles(t *testing.T) { + config, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal(err) + } + + endpointConfig := config.(*EndpointConfig) + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = pathvar.Subst(certPath) + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = pathvar.Subst(keyPath) + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = "" + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = "" + + certs, err := endpointConfig.TLSClientCerts() + if err != nil { + t.Fatalf("Expected no errors but got error instead: %s", err) + } + + if len(certs) != 1 { + t.Fatalf("Expected only one tls cert struct") + } + + emptyCert := tls.Certificate{} + + if reflect.DeepEqual(certs[0], emptyCert) { + t.Fatalf("Actual cert is empty") + } +} + +func TestTLSClientCertsFromFilesIncorrectPaths(t *testing.T) { + config, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal(err) + } + + endpointConfig := config.(*EndpointConfig) + // incorrect paths to files + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = "/test/fixtures/config/mutual_tls/client_sdk_go.pem" + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = "/test/fixtures/config/mutual_tls/client_sdk_go-key.pem" + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = "" + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = "" + + _, err = endpointConfig.TLSClientCerts() + if err == nil { + t.Fatalf("Expected error but got no errors instead") + } + + if !strings.Contains(err.Error(), "no such file or directory") { + t.Fatalf("Expected no such file or directory error") + } +} + +func TestTLSClientCertsFromPem(t *testing.T) { + config, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal(err) + } + + endpointConfig := config.(*EndpointConfig) + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = "" + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = "" + + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = `-----BEGIN CERTIFICATE----- +MIIC5TCCAkagAwIBAgIUMYhiY5MS3jEmQ7Fz4X/e1Dx33J0wCgYIKoZIzj0EAwQw +gYwxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3Jv +bnRvMREwDwYDVQQKEwhsaW51eGN0bDEMMAoGA1UECxMDTGFiMTgwNgYDVQQDEy9s +aW51eGN0bCBFQ0MgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAoTGFiKTAe +Fw0xNzEyMDEyMTEzMDBaFw0xODEyMDEyMTEzMDBaMGMxCzAJBgNVBAYTAkNBMRAw +DgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3JvbnRvMREwDwYDVQQKEwhsaW51 +eGN0bDEMMAoGA1UECxMDTGFiMQ8wDQYDVQQDDAZzZGtfZ28wdjAQBgcqhkjOPQIB +BgUrgQQAIgNiAAT6I1CGNrkchIAEmeJGo53XhDsoJwRiohBv2PotEEGuO6rMyaOu +pulj2VOj+YtgWw4ZtU49g4Nv6rq1QlKwRYyMwwRJSAZHIUMhYZjcDi7YEOZ3Fs1h +xKmIxR+TTR2vf9KjgZAwgY0wDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsG +AQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFDwS3xhpAWs81OVWvZt+iUNL +z26DMB8GA1UdIwQYMBaAFLRasbknomawJKuQGiyKs/RzTCujMBgGA1UdEQQRMA+C +DWZhYnJpY19zZGtfZ28wCgYIKoZIzj0EAwQDgYwAMIGIAkIAk1MxMogtMtNO0rM8 +gw2rrxqbW67ulwmMQzp6EJbm/28T2pIoYWWyIwpzrquypI7BOuf8is5b7Jcgn9oz +7sdMTggCQgF7/8ZFl+wikAAPbciIL1I+LyCXKwXosdFL6KMT6/myYjsGNeeDeMbg +3YkZ9DhdH1tN4U/h+YulG/CkKOtUATtQxg== +-----END CERTIFICATE-----` + + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = `-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDByldj7VTpqTQESGgJpR9PFW9b6YTTde2WN6/IiBo2nW+CIDmwQgmAl +c/EOc9wmgu+gBwYFK4EEACKhZANiAAT6I1CGNrkchIAEmeJGo53XhDsoJwRiohBv +2PotEEGuO6rMyaOupulj2VOj+YtgWw4ZtU49g4Nv6rq1QlKwRYyMwwRJSAZHIUMh +YZjcDi7YEOZ3Fs1hxKmIxR+TTR2vf9I= +-----END EC PRIVATE KEY-----` + + certs, err := endpointConfig.TLSClientCerts() + if err != nil { + t.Fatalf("Expected no errors but got error instead: %s", err) + } + + if len(certs) != 1 { + t.Fatalf("Expected only one tls cert struct") + } + + emptyCert := tls.Certificate{} + + if reflect.DeepEqual(certs[0], emptyCert) { + t.Fatalf("Actual cert is empty") + } +} + +func TestTLSClientCertFromPemAndKeyFromFile(t *testing.T) { + config, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal(err) + } + + endpointConfig := config.(*EndpointConfig) + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = "" + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = pathvar.Subst(keyPath) + + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = `-----BEGIN CERTIFICATE----- +MIIC5TCCAkegAwIBAgIUBzAG7MTjO4n9GFkYTkJBnvCInRIwCgYIKoZIzj0EAwQw +gYwxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3Jv +bnRvMREwDwYDVQQKEwhsaW51eGN0bDEMMAoGA1UECxMDTGFiMTgwNgYDVQQDEy9s +aW51eGN0bCBFQ0MgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAoTGFiKTAe +Fw0xNzA3MTkxOTUyMDBaFw0xODA3MTkxOTUyMDBaMGoxCzAJBgNVBAYTAkNBMRAw +DgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3JvbnRvMREwDwYDVQQKEwhsaW51 +eGN0bDEMMAoGA1UECxMDTGFiMRYwFAYDVQQDDA1mYWJyaWNfY2xpZW50MHYwEAYH +KoZIzj0CAQYFK4EEACIDYgAEyW+qHu26Zp7icI2DGkF+w9mENLyx5kVirEEp+u+M +UCeTfKzBwAPw17aSDCiObrpaLdIyecRZKYpCxnfPurKEKfKXebZDKmQdGpxaFKbX +aJvC44EbrOq5x218RqnCDeqAo4GKMIGHMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUE +DDAKBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRBA9pDyeovnjWP +uvftCfEagM/wKjAfBgNVHSMEGDAWgBQUcJ+Hm9wjfMO4jh0E7LBIXBATDzASBgNV +HREECzAJggd0ZXN0aW5nMAoGCCqGSM49BAMEA4GLADCBhwJCATMHAs0T6yZFDByA +XNzhG5LwkITa+GcMJNR9qXlFBG18P+LM/2cdT6Y2+Fz9ZEvGjYMC+c+yg4nyRwu3 +rIYog3WBAkECntF217dk3VCZHXfl+rik6wm+ijzYk+k336UERiSJRu09YHHEh7x6 +NRCHI3uXUJ5/3zDZM3qtV8UYHou4KDS35Q== +-----END CERTIFICATE-----` + + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = "" + + certs, err := endpointConfig.TLSClientCerts() + if err != nil { + t.Fatalf("Expected no errors but got error instead: %s", err) + } + + if len(certs) != 1 { + t.Fatalf("Expected only one tls cert struct") + } + + emptyCert := tls.Certificate{} + + if reflect.DeepEqual(certs[0], emptyCert) { + t.Fatalf("Actual cert is empty") + } +} + +func TestTLSClientCertFromFileAndKeyFromPem(t *testing.T) { + config, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal(err) + } + + endpointConfig := config.(*EndpointConfig) + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = pathvar.Subst(certPath) + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = "" + + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = "" + + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = `-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDAeWRhdAl+olgpLiI9mXHwcgJ1g4NNgPrYFSkkukISeAGfvK348izwG +0Aub948H5IygBwYFK4EEACKhZANiAATJb6oe7bpmnuJwjYMaQX7D2YQ0vLHmRWKs +QSn674xQJ5N8rMHAA/DXtpIMKI5uulot0jJ5xFkpikLGd8+6soQp8pd5tkMqZB0a +nFoUptdom8LjgRus6rnHbXxGqcIN6oA= +-----END EC PRIVATE KEY-----` + + certs, err := endpointConfig.TLSClientCerts() + if err != nil { + t.Fatalf("Expected no errors but got error instead: %s", err) + } + + if len(certs) != 1 { + t.Fatalf("Expected only one tls cert struct") + } + + emptyCert := tls.Certificate{} + + if reflect.DeepEqual(certs[0], emptyCert) { + t.Fatalf("Actual cert is empty") + } +} + +func TestTLSClientCertsPemBeforeFiles(t *testing.T) { + config, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal(err) + } + + endpointConfig := config.(*EndpointConfig) + // files have incorrect paths, but pems are loaded first + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = "/test/fixtures/config/mutual_tls/client_sdk_go.pem" + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = "/test/fixtures/config/mutual_tls/client_sdk_go-key.pem" + + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = `-----BEGIN CERTIFICATE----- +MIIC5TCCAkagAwIBAgIUMYhiY5MS3jEmQ7Fz4X/e1Dx33J0wCgYIKoZIzj0EAwQw +gYwxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3Jv +bnRvMREwDwYDVQQKEwhsaW51eGN0bDEMMAoGA1UECxMDTGFiMTgwNgYDVQQDEy9s +aW51eGN0bCBFQ0MgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAoTGFiKTAe +Fw0xNzEyMDEyMTEzMDBaFw0xODEyMDEyMTEzMDBaMGMxCzAJBgNVBAYTAkNBMRAw +DgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3JvbnRvMREwDwYDVQQKEwhsaW51 +eGN0bDEMMAoGA1UECxMDTGFiMQ8wDQYDVQQDDAZzZGtfZ28wdjAQBgcqhkjOPQIB +BgUrgQQAIgNiAAT6I1CGNrkchIAEmeJGo53XhDsoJwRiohBv2PotEEGuO6rMyaOu +pulj2VOj+YtgWw4ZtU49g4Nv6rq1QlKwRYyMwwRJSAZHIUMhYZjcDi7YEOZ3Fs1h +xKmIxR+TTR2vf9KjgZAwgY0wDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsG +AQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFDwS3xhpAWs81OVWvZt+iUNL +z26DMB8GA1UdIwQYMBaAFLRasbknomawJKuQGiyKs/RzTCujMBgGA1UdEQQRMA+C +DWZhYnJpY19zZGtfZ28wCgYIKoZIzj0EAwQDgYwAMIGIAkIAk1MxMogtMtNO0rM8 +gw2rrxqbW67ulwmMQzp6EJbm/28T2pIoYWWyIwpzrquypI7BOuf8is5b7Jcgn9oz +7sdMTggCQgF7/8ZFl+wikAAPbciIL1I+LyCXKwXosdFL6KMT6/myYjsGNeeDeMbg +3YkZ9DhdH1tN4U/h+YulG/CkKOtUATtQxg== +-----END CERTIFICATE-----` + + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = `-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDByldj7VTpqTQESGgJpR9PFW9b6YTTde2WN6/IiBo2nW+CIDmwQgmAl +c/EOc9wmgu+gBwYFK4EEACKhZANiAAT6I1CGNrkchIAEmeJGo53XhDsoJwRiohBv +2PotEEGuO6rMyaOupulj2VOj+YtgWw4ZtU49g4Nv6rq1QlKwRYyMwwRJSAZHIUMh +YZjcDi7YEOZ3Fs1hxKmIxR+TTR2vf9I= +-----END EC PRIVATE KEY-----` + + certs, err := endpointConfig.TLSClientCerts() + if err != nil { + t.Fatalf("Expected no errors but got error instead: %s", err) + } + + if len(certs) != 1 { + t.Fatalf("Expected only one tls cert struct") + } + + emptyCert := tls.Certificate{} + + if reflect.DeepEqual(certs[0], emptyCert) { + t.Fatalf("Actual cert is empty") + } +} + +func TestTLSClientCertsNoCerts(t *testing.T) { + config, err := ConfigFromBackend(configBackend) + if err != nil { + t.Fatal(err) + } + + endpointConfig := config.(*EndpointConfig) + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Path = "" + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Path = "" + endpointConfig.networkConfig.Client.TLSCerts.Client.Cert.Pem = "" + endpointConfig.networkConfig.Client.TLSCerts.Client.Key.Pem = "" + + certs, err := endpointConfig.TLSClientCerts() + if err != nil { + t.Fatalf("Expected no errors but got error instead: %s", err) + } + + if len(certs) != 1 { + t.Fatalf("Expected only empty tls cert struct") + } + + emptyCert := tls.Certificate{} + + if !reflect.DeepEqual(certs[0], emptyCert) { + t.Fatalf("Actual cert is not equal to empty cert") + } +} diff --git a/pkg/fab/mocks/mockconfig.go b/pkg/fab/mocks/mockconfig.go index 9b5705fa06..02667424a5 100644 --- a/pkg/fab/mocks/mockconfig.go +++ b/pkg/fab/mocks/mockconfig.go @@ -197,14 +197,6 @@ func (c *MockConfig) OrderersConfig() ([]fab.OrdererConfig, error) { return []fab.OrdererConfig{*oConfig}, err } -// RandomOrdererConfig not implemented -func (c *MockConfig) RandomOrdererConfig() (*fab.OrdererConfig, error) { - if c.customRandomOrdererCfg != nil { - return c.customRandomOrdererCfg, nil - } - return nil, nil -} - //SetCustomNetworkPeerCfg sets custom orderer config for unit-tests func (c *MockConfig) SetCustomNetworkPeerCfg(customNetworkPeerCfg []fab.NetworkPeer) { c.customNetworkPeerCfg = customNetworkPeerCfg diff --git a/pkg/fabsdk/fabsdk.go b/pkg/fabsdk/fabsdk.go index 092482fb7b..2df11f8f99 100644 --- a/pkg/fabsdk/fabsdk.go +++ b/pkg/fabsdk/fabsdk.go @@ -19,10 +19,11 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" - "github.com/hyperledger/fabric-sdk-go/pkg/core/config" "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" + fabImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab" sdkApi "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/api" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/provider/chpvdr" + mspImpl "github.com/hyperledger/fabric-sdk-go/pkg/msp" "github.com/pkg/errors" ) @@ -42,6 +43,7 @@ type options struct { CryptoSuiteConfig core.CryptoSuiteConfig endpointConfig fab.EndpointConfig IdentityConfig msp.IdentityConfig + ConfigBackend core.ConfigBackend } // Option configures the SDK. @@ -289,11 +291,12 @@ func (sdk *FabricSDK) Close() { sdk.provider.InfraProvider().Close() } -//Config returns config provider used by SDK -func (sdk *FabricSDK) Config() config.Provider { - return func() (core.CryptoSuiteConfig, fab.EndpointConfig, msp.IdentityConfig, error) { - return sdk.provider.CryptoSuiteConfig(), sdk.provider.EndpointConfig(), sdk.provider.IdentityConfig(), nil +//Config returns config backend used by all SDK config types +func (sdk *FabricSDK) Config() (core.ConfigBackend, error) { + if sdk.opts.ConfigBackend == nil { + return nil, errors.New("unable to find config backend") } + return sdk.opts.ConfigBackend, nil } //Context creates and returns context client which has all the necessary providers @@ -331,23 +334,27 @@ func (sdk *FabricSDK) loadConfig(configProvider core.ConfigProvider) error { if err != nil { return errors.WithMessage(err, "unable to load config backend") } - cryptoSuiteConfig, endpointConfig, identityConfig, err := config.FromBackend(configBackend)() - if err != nil { - return errors.WithMessage(err, "failed to initialize config from config backend") - } //configs passed through opts takes priority if sdk.opts.CryptoSuiteConfig == nil { - sdk.opts.CryptoSuiteConfig = cryptoSuiteConfig + sdk.opts.CryptoSuiteConfig = cryptosuite.ConfigFromBackend(configBackend) } if sdk.opts.endpointConfig == nil { - sdk.opts.endpointConfig = endpointConfig + sdk.opts.endpointConfig, err = fabImpl.ConfigFromBackend(configBackend) + if err != nil { + return errors.WithMessage(err, "failed to initialize endpoint config from config backend") + } } if sdk.opts.IdentityConfig == nil { - sdk.opts.IdentityConfig = identityConfig + sdk.opts.IdentityConfig, err = mspImpl.ConfigFromBackend(configBackend) + if err != nil { + return errors.WithMessage(err, "failed to initialize identity config from config backend") + } } + + sdk.opts.ConfigBackend = configBackend } return nil } diff --git a/pkg/fabsdk/fabsdk_chconfig_test.go b/pkg/fabsdk/fabsdk_chconfig_test.go index 3696254522..cad24b374f 100644 --- a/pkg/fabsdk/fabsdk_chconfig_test.go +++ b/pkg/fabsdk/fabsdk_chconfig_test.go @@ -15,6 +15,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/core/config" "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/provider/fabpvdr" + "github.com/hyperledger/fabric-sdk-go/pkg/msp" ) const ( @@ -79,9 +80,14 @@ func TestNewDefaultTwoValidSDK(t *testing.T) { sdk2.provider.InfraProvider().(*fabpvdr.InfraProvider).SetChannelConfig(mocks.NewMockChannelCfg("orgchannel")) // Default sdk with two channels - _, _, identityConfig, err := sdk1.Config()() + configBackend, err := sdk1.Config() if err != nil { - t.Fatalf("Error getting config from sdk: %s", err) + t.Fatalf("Error getting config backend from sdk: %s", err) + } + + identityConfig, err := msp.ConfigFromBackend(configBackend) + if err != nil { + t.Fatalf("Error getting identity config: %s", err) } client1, err := identityConfig.Client() @@ -93,9 +99,14 @@ func TestNewDefaultTwoValidSDK(t *testing.T) { t.Fatalf("Unexpected org in config: %s", client1.Organization) } - _, _, identityConfig, err = sdk2.Config()() + configBackend, err = sdk2.Config() + if err != nil { + t.Fatalf("Error getting config backend from sdk: %s", err) + } + + identityConfig, err = msp.ConfigFromBackend(configBackend) if err != nil { - t.Fatalf("Error getting config from sdk: %s", err) + t.Fatalf("Error getting identity config : %s", err) } client2, err := identityConfig.Client() diff --git a/pkg/fabsdk/fabsdk_test.go b/pkg/fabsdk/fabsdk_test.go index 4e0e0cb48b..117feacbd1 100644 --- a/pkg/fabsdk/fabsdk_test.go +++ b/pkg/fabsdk/fabsdk_test.go @@ -14,6 +14,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt" configImpl "github.com/hyperledger/fabric-sdk-go/pkg/core/config" mockapisdk "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/test/mocksdkapi" + "github.com/hyperledger/fabric-sdk-go/pkg/msp" "github.com/pkg/errors" ) @@ -239,9 +240,14 @@ func TestWithConfigSuccess(t *testing.T) { } defer sdk.Close() - _, _, identityConfig, err := sdk.Config()() + configBackend, err := sdk.Config() if err != nil { - t.Fatalf("Error getting config from sdk: %s", err) + t.Fatalf("Error getting config backend from sdk: %s", err) + } + + identityConfig, err := msp.ConfigFromBackend(configBackend) + if err != nil { + t.Fatalf("Error getting identity config: %s", err) } client1, err := identityConfig.Client() diff --git a/pkg/fabsdk/factory/defmsp/mspfactory_test.go b/pkg/fabsdk/factory/defmsp/mspfactory_test.go index 5790bf8338..cec13685d2 100644 --- a/pkg/fabsdk/factory/defmsp/mspfactory_test.go +++ b/pkg/fabsdk/factory/defmsp/mspfactory_test.go @@ -14,6 +14,8 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/test/mockmsp" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + cryptosuiteImpl "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" + "github.com/hyperledger/fabric-sdk-go/pkg/fab" "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/factory/defcore" mspimpl "github.com/hyperledger/fabric-sdk-go/pkg/msp" @@ -104,7 +106,17 @@ func TestCreateIdentityManager(t *testing.T) { t.Fatalf(err.Error()) } - cryptoCfg, endpointCfg, identityCfg, err := config.FromBackend(configBackend)() + cryptoCfg := cryptosuiteImpl.ConfigFromBackend(configBackend) + if err != nil { + t.Fatalf(err.Error()) + } + + endpointCfg, err := fab.ConfigFromBackend(configBackend) + if err != nil { + t.Fatalf(err.Error()) + } + + identityCfg, err := mspimpl.ConfigFromBackend(configBackend) if err != nil { t.Fatalf(err.Error()) } diff --git a/pkg/fabsdk/mocks_test.go b/pkg/fabsdk/mocks_test.go index f830327c3a..f0d3b85e3c 100644 --- a/pkg/fabsdk/mocks_test.go +++ b/pkg/fabsdk/mocks_test.go @@ -11,8 +11,9 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/core/logging/api" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" - "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" "github.com/hyperledger/fabric-sdk-go/pkg/core/logging/modlog" + fabImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab" sdkApi "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/api" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/factory/defcore" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/factory/defmsp" @@ -33,11 +34,13 @@ func newMockCorePkg(configBackendProvider core.ConfigProvider) (*mockCorePkg, er return nil, err } - cryptoSuiteConfig, endpointConfig, _, err := config.FromBackend(configBackend)() + endpointConfig, err := fabImpl.ConfigFromBackend(configBackend) if err != nil { return nil, err } + cryptoSuiteConfig := cryptosuite.ConfigFromBackend(configBackend) + pkgSuite := defPkgSuite{} sdkcore, err := pkgSuite.Core() if err != nil { diff --git a/pkg/fabsdk/provider/fabpvdr/fabpvdr_test.go b/pkg/fabsdk/provider/fabpvdr/fabpvdr_test.go index cfdae59ad0..f9930c71f2 100644 --- a/pkg/fabsdk/provider/fabpvdr/fabpvdr_test.go +++ b/pkg/fabsdk/provider/fabpvdr/fabpvdr_test.go @@ -17,8 +17,11 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite/bccsp/sw" coreMocks "github.com/hyperledger/fabric-sdk-go/pkg/core/mocks" + "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" + fabImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab" "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks" peerImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab/peer" + mspImpl "github.com/hyperledger/fabric-sdk-go/pkg/msp" mspmocks "github.com/hyperledger/fabric-sdk-go/pkg/msp/test/mockmsp" "github.com/stretchr/testify/assert" ) @@ -86,7 +89,17 @@ func newInfraProvider(t *testing.T) *InfraProvider { t.Fatalf("config.FromFile failed: %v", err) } - cryptoCfg, endpointCfg, identityCfg, err := config.FromBackend(configBackend)() + cryptoCfg := cryptosuite.ConfigFromBackend(configBackend) + if err != nil { + t.Fatalf(err.Error()) + } + + endpointCfg, err := fabImpl.ConfigFromBackend(configBackend) + if err != nil { + t.Fatalf(err.Error()) + } + + identityCfg, err := mspImpl.ConfigFromBackend(configBackend) if err != nil { t.Fatalf(err.Error()) } diff --git a/pkg/fabsdk/provider/msppvdr/msppvdr_test.go b/pkg/fabsdk/provider/msppvdr/msppvdr_test.go index 60c3067835..57e3fa8e23 100644 --- a/pkg/fabsdk/provider/msppvdr/msppvdr_test.go +++ b/pkg/fabsdk/provider/msppvdr/msppvdr_test.go @@ -10,6 +10,8 @@ import ( "testing" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" + "github.com/hyperledger/fabric-sdk-go/pkg/fab" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/factory/defcore" "github.com/hyperledger/fabric-sdk-go/pkg/msp" "github.com/hyperledger/fabric-sdk-go/pkg/msp/test/mockmsp" @@ -25,7 +27,12 @@ func TestCreateMSPProvider(t *testing.T) { t.Fatalf(err.Error()) } - cryptoSuiteConfig, endpointConfig, _, err := config.FromBackend(configBackend)() + cryptoSuiteConfig := cryptosuite.ConfigFromBackend(configBackend) + if err != nil { + t.Fatalf(err.Error()) + } + + endpointConfig, err := fab.ConfigFromBackend(configBackend) if err != nil { t.Fatalf(err.Error()) } diff --git a/pkg/msp/caclient_test.go b/pkg/msp/caclient_test.go index e6eba5989b..b9d12a4ddf 100644 --- a/pkg/msp/caclient_test.go +++ b/pkg/msp/caclient_test.go @@ -19,6 +19,7 @@ import ( mockmspApi "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/test/mockmsp" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" bccspwrapper "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite/bccsp/wrapper" + "github.com/hyperledger/fabric-sdk-go/pkg/fab" "github.com/hyperledger/fabric-sdk-go/pkg/msp/api" "github.com/hyperledger/fabric-sdk-go/pkg/msp/test/mockmsp" "github.com/pkg/errors" @@ -96,7 +97,12 @@ func TestWrongURL(t *testing.T) { panic(fmt.Sprintf("Failed to read config backend: %v", err)) } - _, wrongURLEndpointConfig, wrongURLIdentityConfig, err := config.FromBackend(configBackend)() + wrongURLIdentityConfig, err := ConfigFromBackend(configBackend) + if err != nil { + panic(fmt.Sprintf("Failed to read config: %v", err)) + } + + wrongURLEndpointConfig, err := fab.ConfigFromBackend(configBackend) if err != nil { panic(fmt.Sprintf("Failed to read config: %v", err)) } @@ -139,7 +145,7 @@ func TestNoConfiguredCAs(t *testing.T) { panic(fmt.Sprintf("Failed to read config: %v", err)) } - _, wrongURLEndpointConfig, _, err := config.FromBackend(configBackend)() + wrongURLEndpointConfig, err := fab.ConfigFromBackend(configBackend) if err != nil { panic(fmt.Sprintf("Failed to read config: %v", err)) } diff --git a/pkg/msp/enrollment_test.go b/pkg/msp/enrollment_test.go index 359aa057d2..81fb3f09a4 100644 --- a/pkg/msp/enrollment_test.go +++ b/pkg/msp/enrollment_test.go @@ -17,7 +17,9 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite/bccsp/sw" + "github.com/hyperledger/fabric-sdk-go/pkg/fab" apimocks "github.com/hyperledger/fabric-sdk-go/pkg/msp/test/mockmspapi" ) @@ -56,11 +58,20 @@ func TestGetSigningIdentityWithEnrollment(t *testing.T) { if err != nil { t.Fatalf(err.Error()) } - cryptoConfig, endpointConfig, identityConfig, err := config.FromBackend(configBackend)() + + cryptoConfig := cryptosuite.ConfigFromBackend(configBackend) + + endpointConfig, err := fab.ConfigFromBackend(configBackend) if err != nil { panic(fmt.Sprintf("Failed to read config: %v", err)) } - clientCofig, err := identityConfig.Client() + + identityConfig, err := ConfigFromBackend(configBackend) + if err != nil { + panic(fmt.Sprintf("Failed to read config: %v", err)) + } + + clientConfig, err := identityConfig.Client() if err != nil { t.Fatalf("Unable to retrieve client config: %v", err) } @@ -97,7 +108,7 @@ func TestGetSigningIdentityWithEnrollment(t *testing.T) { } // Refers to the same location used by the IdentityManager - enrollmentTestUserStore, err = NewCertFileUserStore(clientCofig.CredentialStore.Path) + enrollmentTestUserStore, err = NewCertFileUserStore(clientConfig.CredentialStore.Path) if err != nil { t.Fatalf("Failed to setup userStore: %s", err) } diff --git a/pkg/msp/getsigid_test.go b/pkg/msp/getsigid_test.go index f2bf16c5ad..d7106a4844 100644 --- a/pkg/msp/getsigid_test.go +++ b/pkg/msp/getsigid_test.go @@ -19,6 +19,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/core/config" "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite/bccsp/sw" + "github.com/hyperledger/fabric-sdk-go/pkg/fab" fcmocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks" "github.com/pkg/errors" ) @@ -54,10 +55,19 @@ func TestGetSigningIdentity(t *testing.T) { if err != nil { t.Fatalf(err.Error()) } - cryptoConfig, endpointConfig, identityConfig, err := config.FromBackend(configBackend)() + + cryptoConfig := cryptosuite.ConfigFromBackend(configBackend) + + endpointConfig, err := fab.ConfigFromBackend(configBackend) + if err != nil { + panic(fmt.Sprintf("Failed to read config: %v", err)) + } + + identityConfig, err := ConfigFromBackend(configBackend) if err != nil { panic(fmt.Sprintf("Failed to read config: %v", err)) } + netConfig, err := endpointConfig.NetworkConfig() if err != nil { t.Fatalf("Failed to setup netConfig: %s", err) @@ -158,7 +168,13 @@ func TestGetSigningIdentityInvalidOrg(t *testing.T) { if err != nil { t.Fatalf(err.Error()) } - _, endpointConfig, identityConfig, err := config.FromBackend(configBackend)() + + endpointConfig, err := fab.ConfigFromBackend(configBackend) + if err != nil { + panic(fmt.Sprintf("Failed to read config: %v", err)) + } + + identityConfig, err := ConfigFromBackend(configBackend) if err != nil { panic(fmt.Sprintf("Failed to read config: %v", err)) } @@ -178,7 +194,12 @@ func TestGetSigningIdentityFromEmbeddedCryptoConfig(t *testing.T) { if err != nil { t.Fatalf(err.Error()) } - _, endpointConfig, identityConfig, err := config.FromBackend(configBackend)() + endpointConfig, err := fab.ConfigFromBackend(configBackend) + if err != nil { + panic(fmt.Sprintf("Failed to read config: %v", err)) + } + + identityConfig, err := ConfigFromBackend(configBackend) if err != nil { panic(fmt.Sprintf("Failed to read config: %v", err)) } diff --git a/pkg/core/config/identityconfig.go b/pkg/msp/identityconfig.go similarity index 91% rename from pkg/core/config/identityconfig.go rename to pkg/msp/identityconfig.go index 0aad438693..bec7a44698 100644 --- a/pkg/core/config/identityconfig.go +++ b/pkg/msp/identityconfig.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package config +package msp import ( "fmt" @@ -16,14 +16,25 @@ import ( "sort" "github.com/hyperledger/fabric-sdk-go/pkg/common/errors/status" + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" + fabImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab" "github.com/hyperledger/fabric-sdk-go/pkg/util/pathvar" ) +//ConfigFromBackend returns identity config implementation of give backend +func ConfigFromBackend(coreBackend core.ConfigBackend) (msp.IdentityConfig, error) { + endpointConfig, err := fabImpl.ConfigFromBackend(coreBackend) + if err != nil { + return nil, errors.New("failed load identity configuration") + } + return &IdentityConfig{endpointConfig.(*fabImpl.EndpointConfig)}, nil +} + // IdentityConfig represents the identity configuration for the client type IdentityConfig struct { - endpointConfig *EndpointConfig + endpointConfig *fabImpl.EndpointConfig } // Client returns the Client config @@ -223,12 +234,12 @@ func (c *IdentityConfig) CAClientCertPath(org string) (string, error) { // 'keystore' directory added. This is done because the fabric-ca-client // adds this to the path func (c *IdentityConfig) CAKeyStorePath() string { - return pathvar.Subst(c.endpointConfig.backend.getString("client.credentialStore.cryptoStore.path")) + return pathvar.Subst(c.endpointConfig.Backend().GetString("client.credentialStore.cryptoStore.path")) } // CredentialStorePath returns the user store path func (c *IdentityConfig) CredentialStorePath() string { - return pathvar.Subst(c.endpointConfig.backend.getString("client.credentialStore.path")) + return pathvar.Subst(c.endpointConfig.Backend().GetString("client.credentialStore.path")) } // NetworkConfig returns the network configuration defined in the config file @@ -245,20 +256,21 @@ func (c *IdentityConfig) tryMatchingCAConfig(caName string) (*msp.CAConfig, stri return nil, "", err } //Return if no caMatchers are configured - if len(c.endpointConfig.caMatchers) == 0 { + caMatchers := c.endpointConfig.CAMatchers() + if len(caMatchers) == 0 { return nil, "", errors.New("no CertAuthority entityMatchers are found") } //sort the keys var keys []int - for k := range c.endpointConfig.caMatchers { + for k := range caMatchers { keys = append(keys, k) } sort.Ints(keys) //loop over certAuthorityEntityMatchers to find the matching Cert for _, k := range keys { - v := c.endpointConfig.caMatchers[k] + v := caMatchers[k] if v.MatchString(caName) { // get the matching Config from the index number certAuthorityMatchConfig := networkConfig.EntityMatchers["certificateauthorities"][k] diff --git a/pkg/msp/identityconfig_test.go b/pkg/msp/identityconfig_test.go new file mode 100644 index 0000000000..c718b48a1d --- /dev/null +++ b/pkg/msp/identityconfig_test.go @@ -0,0 +1,382 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package msp + +import ( + "testing" + + "fmt" + + "os" + "strings" + + "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/core/config/endpoint" + "github.com/hyperledger/fabric-sdk-go/pkg/core/mocks" + "github.com/hyperledger/fabric-sdk-go/pkg/util/pathvar" + "github.com/stretchr/testify/assert" +) + +const ( + configTestFilePath = "../core/config/testdata/config_test.yaml" + configEmbeddedUsersTestFilePath = "../core/config/testdata/config_test_embedded_pems.yaml" + configPemTestFilePath = "../core/config/testdata/config_test_pem.yaml" + configType = "yaml" +) + +func TestCAConfigFailsByNetworkConfig(t *testing.T) { + + //Tamper 'client.network' value and use a new config to avoid conflicting with other tests + + configBackend, err := config.FromFile(configTestFilePath)() + if err != nil { + t.Fatalf("Unexpected error reading config: %v", err) + } + + backendMap := make(map[string]interface{}) + backendMap["client"], _ = configBackend.Lookup("client") + backendMap["certificateAuthorities"], _ = configBackend.Lookup("certificateAuthorities") + fmt.Println(configBackend.Lookup("certificateAuthorities")) + backendMap["entityMatchers"], _ = configBackend.Lookup("entityMatchers") + backendMap["peers"], _ = configBackend.Lookup("peers") + backendMap["organizations"], _ = configBackend.Lookup("organizations") + backendMap["orderers"], _ = configBackend.Lookup("orderers") + backendMap["channels"], _ = configBackend.Lookup("channels") + + customBackend := &mocks.MockConfigBackend{KeyValueMap: backendMap} + + identityCfg, err := ConfigFromBackend(customBackend) + if err != nil { + t.Fatalf("Unexpected error initializing endpoint config: %v", err) + } + + sampleIdentityConfig := identityCfg.(*IdentityConfig) + sampleIdentityConfig.endpointConfig.ResetNetworkConfig() + + customBackend.KeyValueMap["channels"] = "INVALID" + _, err = sampleIdentityConfig.networkConfig() + if err == nil { + t.Fatal("Network config load supposed to fail") + } + + customBackend.KeyValueMap["channels"], _ = configBackend.Lookup("channels") + customBackend.KeyValueMap["certificateAuthorities"] = "" + + //Test CA client cert file failure scenario + certfile, err := sampleIdentityConfig.CAClientCertPath("peerorg1") + fmt.Println(err) + if certfile != "" || err == nil { + t.Fatal("CA Cert file location read supposed to fail") + } + + //Test CA client cert file failure scenario + keyFile, err := sampleIdentityConfig.CAClientKeyPath("peerorg1") + if keyFile != "" || err == nil { + t.Fatal("CA Key file location read supposed to fail") + } + + //Testing CA Server Cert Files failure scenario + sCertFiles, err := sampleIdentityConfig.CAServerCertPaths("peerorg1") + if len(sCertFiles) > 0 || err == nil { + t.Fatal("Getting CA server cert files supposed to fail") + } + + //Testing CAConfig failure scenario + caConfig, err := sampleIdentityConfig.CAConfig("peerorg1") + if caConfig != nil || err == nil { + t.Fatal("Get CA Config supposed to fail") + } + +} + +func TestTLSCAConfigFromPems(t *testing.T) { + embeddedBackend, err := config.FromFile(configEmbeddedUsersTestFilePath)() + if err != nil { + t.Fatal(err) + } + + //Test TLSCA Cert Pool (Positive test case) + config, err := ConfigFromBackend(embeddedBackend) + if err != nil { + t.Fatalf("Failed to initialize identity config , reason: %v", err) + } + + identityConfig := config.(*IdentityConfig) + certPem, _ := identityConfig.CAClientCertPem(org1) + certConfig := endpoint.TLSConfig{Pem: certPem} + + cert, err := certConfig.TLSCert() + + if err != nil { + t.Fatalf("TLS CA cert parse failed, reason: %v", err) + } + + _, err = identityConfig.endpointConfig.TLSCACertPool(cert) + + if err != nil { + t.Fatalf("TLS CA cert pool fetch failed, reason: %v", err) + } + //Test TLSCA Cert Pool (Negative test case) + + badCertConfig := endpoint.TLSConfig{Pem: "some random invalid pem"} + + badCert, err := badCertConfig.TLSCert() + + if err == nil { + t.Fatalf("TLS CA cert parse was supposed to fail") + } + + _, err = identityConfig.endpointConfig.TLSCACertPool(badCert) + + keyPem, _ := identityConfig.CAClientKeyPem(org1) + + keyConfig := endpoint.TLSConfig{Pem: keyPem} + + _, err = keyConfig.TLSCert() + if err == nil { + t.Fatalf("TLS CA cert pool was supposed to fail when provided with wrong cert file") + } + +} + +func TestInitConfigFromRawWithPem(t *testing.T) { + // get a config byte for testing + cBytes, err := loadConfigBytesFromFile(t, configPemTestFilePath) + if err != nil { + t.Fatalf("Failed to load sample bytes from File. Error: %s", err) + } + + // test init config from bytes + backend, err := config.FromRaw(cBytes, configType)() + if err != nil { + t.Fatalf("Failed to initialize config from bytes array. Error: %s", err) + } + + config, err := ConfigFromBackend(backend) + if err != nil { + t.Fatalf("Failed to initialize config from bytes array. Error: %s", err) + } + + idConfig := config.(*IdentityConfig) + + o, err := idConfig.endpointConfig.OrderersConfig() + if err != nil { + t.Fatalf("Failed to load orderers from config. Error: %s", err) + } + + if o == nil || len(o) == 0 { + t.Fatalf("orderer cannot be nil or empty") + } + + oPem := `-----BEGIN CERTIFICATE----- +MIICNjCCAdygAwIBAgIRAILSPmMB3BzoLIQGsFxwZr8wCgYIKoZIzj0EAwIwbDEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG +cmFuY2lzY28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRowGAYDVQQDExF0bHNjYS5l +eGFtcGxlLmNvbTAeFw0xNzA3MjgxNDI3MjBaFw0yNzA3MjYxNDI3MjBaMGwxCzAJ +BgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJh +bmNpc2NvMRQwEgYDVQQKEwtleGFtcGxlLmNvbTEaMBgGA1UEAxMRdGxzY2EuZXhh +bXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQfgKb4db53odNzdMXn +P5FZTZTFztOO1yLvCHDofSNfTPq/guw+YYk7ZNmhlhj8JHFG6dTybc9Qb/HOh9hh +gYpXo18wXTAOBgNVHQ8BAf8EBAMCAaYwDwYDVR0lBAgwBgYEVR0lADAPBgNVHRMB +Af8EBTADAQH/MCkGA1UdDgQiBCBxaEP3nVHQx4r7tC+WO//vrPRM1t86SKN0s6XB +8LWbHTAKBggqhkjOPQQDAgNIADBFAiEA96HXwCsuMr7tti8lpcv1oVnXg0FlTxR/ +SQtE5YgdxkUCIHReNWh/pluHTxeGu2jNCH1eh6o2ajSGeeizoapvdJbN +-----END CERTIFICATE-----` + loadedOPem := strings.TrimSpace(o[0].TLSCACerts.Pem) // viper's unmarshall adds a \n to the end of a string, hence the TrimeSpace + if loadedOPem != oPem { + t.Fatalf("Orderer Pem doesn't match. Expected \n'%s'\n, but got \n'%s'\n", oPem, loadedOPem) + } + + pc, err := idConfig.endpointConfig.PeersConfig(org1) + if err != nil { + t.Fatalf(err.Error()) + } + if pc == nil || len(pc) == 0 { + t.Fatalf("peers list of %s cannot be nil or empty", org1) + } + peer0 := "peer0.org1.example.com" + p0, err := idConfig.endpointConfig.PeerConfig(org1, peer0) + if err != nil { + t.Fatalf("Failed to load %s of %s from the config. Error: %s", peer0, org1, err) + } + if p0 == nil { + t.Fatalf("%s of %s cannot be nil", peer0, org1) + } + pPem := `-----BEGIN CERTIFICATE----- +MIICSTCCAfCgAwIBAgIRAPQIzfkrCZjcpGwVhMSKd0AwCgYIKoZIzj0EAwIwdjEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG +cmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHzAdBgNVBAMTFnRs +c2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTcwNzI4MTQyNzIwWhcNMjcwNzI2MTQy +NzIwWjB2MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE +BxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEfMB0G +A1UEAxMWdGxzY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49 +AwEHA0IABMOiG8UplWTs898zZ99+PhDHPbKjZIDHVG+zQXopw8SqNdX3NAmZUKUU +sJ8JZ3M49Jq4Ms8EHSEwQf0Ifx3ICHujXzBdMA4GA1UdDwEB/wQEAwIBpjAPBgNV +HSUECDAGBgRVHSUAMA8GA1UdEwEB/wQFMAMBAf8wKQYDVR0OBCIEID9qJz7xhZko +V842OVjxCYYQwCjPIY+5e9ORR+8pxVzcMAoGCCqGSM49BAMCA0cAMEQCIGZ+KTfS +eezqv0ml1VeQEmnAEt5sJ2RJA58+LegUYMd6AiAfEe6BKqdY03qFUgEYmtKG+3Dr +O94CDp7l2k7hMQI0zQ== +-----END CERTIFICATE-----` + + loadedPPem := strings.TrimSpace(p0.TLSCACerts.Pem) // viper's unmarshall adds a \n to the end of a string, hence the TrimeSpace + if loadedPPem != pPem { + t.Fatalf("%s Pem doesn't match. Expected \n'%s'\n, but got \n'%s'\n", peer0, pPem, loadedPPem) + } + + // get CA Server cert pems (embedded) for org1 + certs, err := idConfig.CAServerCertPems("org1") + if err != nil { + t.Fatalf("Failed to load CAServerCertPems from config. Error: %s", err) + } + if len(certs) == 0 { + t.Fatalf("Got empty PEM certs for CAServerCertPems") + } + + // get the client cert pem (embedded) for org1 + idConfig.CAClientCertPem("org1") + if err != nil { + t.Fatalf("Failed to load CAClientCertPem from config. Error: %s", err) + } + + // get CA Server certs paths for org1 + certs, err = idConfig.CAServerCertPaths("org1") + if err != nil { + t.Fatalf("Failed to load CAServerCertPaths from config. Error: %s", err) + } + if len(certs) == 0 { + t.Fatalf("Got empty cert file paths for CAServerCertPaths") + } + + // get the client cert path for org1 + idConfig.CAClientCertPath("org1") + if err != nil { + t.Fatalf("Failed to load CAClientCertPath from config. Error: %s", err) + } + + // get the client key pem (embedded) for org1 + idConfig.CAClientKeyPem("org1") + if err != nil { + t.Fatalf("Failed to load CAClientKeyPem from config. Error: %s", err) + } + + // get the client key file path for org1 + idConfig.CAClientKeyPath("org1") + if err != nil { + t.Fatalf("Failed to load CAClientKeyPath from config. Error: %s", err) + } +} + +func loadConfigBytesFromFile(t *testing.T, filePath string) ([]byte, error) { + // read test config file into bytes array + f, err := os.Open(filePath) + if err != nil { + t.Fatalf("Failed to read config file. Error: %s", err) + } + defer f.Close() + fi, err := f.Stat() + if err != nil { + t.Fatalf("Failed to read config file stat. Error: %s", err) + } + s := fi.Size() + cBytes := make([]byte, s, s) + n, err := f.Read(cBytes) + if err != nil { + t.Fatalf("Failed to read test config for bytes array testing. Error: %s", err) + } + if n == 0 { + t.Fatalf("Failed to read test config for bytes array testing. Mock bytes array is empty") + } + return cBytes, err +} + +func TestCAConfig(t *testing.T) { + //Test config + backend, err := config.FromFile(configTestFilePath)() + if err != nil { + t.Fatal("Failed to get config backend") + } + + config, err := ConfigFromBackend(backend) + if err != nil { + t.Fatal("Failed to get identity config") + } + identityConfig := config.(*IdentityConfig) + //Test Crypto config path + + val, ok := backend.Lookup("client.cryptoconfig.path") + if !ok || val == nil { + t.Fatal("expected valid value") + } + + assert.True(t, pathvar.Subst(val.(string)) == identityConfig.endpointConfig.CryptoConfigPath(), "Incorrect crypto config path", t) + + //Testing CA Client File Location + certfile, err := identityConfig.CAClientCertPath(org1) + + if certfile == "" || err != nil { + t.Fatalf("CA Cert file location read failed %s", err) + } + + //Testing CA Key File Location + keyFile, err := identityConfig.CAClientKeyPath(org1) + + if keyFile == "" || err != nil { + t.Fatal("CA Key file location read failed") + } + + //Testing CA Server Cert Files + sCertFiles, err := identityConfig.CAServerCertPaths(org1) + + if sCertFiles == nil || len(sCertFiles) == 0 || err != nil { + t.Fatal("Getting CA server cert files failed") + } + + //Testing MSPID + mspID, err := identityConfig.endpointConfig.MSPID(org1) + if mspID != "Org1MSP" || err != nil { + t.Fatal("Get MSP ID failed") + } + + //Testing CAConfig + caConfig, err := identityConfig.CAConfig(org1) + if caConfig == nil || err != nil { + t.Fatal("Get CA Config failed") + } + + // Test User Store Path + val, ok = backend.Lookup("client.credentialStore.path") + if !ok || val == nil { + t.Fatal("expected valid value") + } + if val.(string) != identityConfig.CredentialStorePath() { + t.Fatalf("Incorrect User Store path") + } + + // Test CA KeyStore Path + val, ok = backend.Lookup("client.credentialStore.cryptoStore.path") + if !ok || val == nil { + t.Fatal("expected valid value") + } + if val.(string) != identityConfig.CAKeyStorePath() { + t.Fatalf("Incorrect CA keystore path") + } + + // test Client + c, err := identityConfig.Client() + if err != nil { + t.Fatalf("Received error when fetching Client info, error is %s", err) + } + if c == nil { + t.Fatal("Received empty client when fetching Client info") + } + + // testing empty OrgMSP + mspID, err = identityConfig.endpointConfig.MSPID("dummyorg1") + if err == nil { + t.Fatal("Get MSP ID did not fail for dummyorg1") + } +} diff --git a/pkg/msp/main_test.go b/pkg/msp/main_test.go index 6b9a2f60d4..2845bed38d 100644 --- a/pkg/msp/main_test.go +++ b/pkg/msp/main_test.go @@ -19,7 +19,9 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" "github.com/hyperledger/fabric-sdk-go/pkg/context" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite/bccsp/sw" + fabImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab" kvs "github.com/hyperledger/fabric-sdk-go/pkg/fab/keyvaluestore" mspapi "github.com/hyperledger/fabric-sdk-go/pkg/msp/api" "github.com/hyperledger/fabric-sdk-go/pkg/msp/test/mockmsp" @@ -73,7 +75,14 @@ func (f *textFixture) setup(configPath string) { panic(fmt.Sprintf("Failed to read config backend: %v", err)) } - f.cryptSuiteConfig, f.endpointConfig, f.identityConfig, err = config.FromBackend(configBackend)() + f.cryptSuiteConfig = cryptosuite.ConfigFromBackend(configBackend) + + f.endpointConfig, err = fabImpl.ConfigFromBackend(configBackend) + if err != nil { + panic(fmt.Sprintf("Failed to read config : %v", err)) + } + + f.identityConfig, err = ConfigFromBackend(configBackend) if err != nil { panic(fmt.Sprintf("Failed to read config : %v", err)) } diff --git a/pkg/msp/user_test.go b/pkg/msp/user_test.go index 6883904dbb..65b72f203f 100644 --- a/pkg/msp/user_test.go +++ b/pkg/msp/user_test.go @@ -13,6 +13,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric-ca/util" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" cryptosuiteimpl "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite/bccsp/sw" ) @@ -25,7 +26,11 @@ func TestUserMethods(t *testing.T) { if err != nil { t.Fatalf("Failed to read config: %v", err) } - cryptoConfig, _, identityConfig, err := config.FromBackend(configBackend)() + cryptoConfig := cryptosuite.ConfigFromBackend(configBackend) + if err != nil { + t.Fatalf("Failed to read config: %v", err) + } + identityConfig, err := ConfigFromBackend(configBackend) if err != nil { t.Fatalf("Failed to read config: %v", err) } diff --git a/test/integration/base_test_setup.go b/test/integration/base_test_setup.go index 76cc5c83ad..f99133260f 100644 --- a/test/integration/base_test_setup.go +++ b/test/integration/base_test_setup.go @@ -15,6 +15,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/fab" packager "github.com/hyperledger/fabric-sdk-go/pkg/fab/ccpackager/gopackager" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/common/cauthdsl" @@ -75,7 +76,16 @@ func (setup *BaseSetupImpl) Initialize(sdk *fabsdk.FabricSDK) error { } setup.Identity = adminIdentity - targets, err := getOrgTargets(sdk.Config(), setup.OrgID) + configBackend, err := sdk.Config() + if err != nil { + //For some tests SDK may not have backend set, try with config file if backend is missing + configBackend, err = config.FromFile(setup.ConfigFile)() + if err != nil { + return errors.Wrapf(err, "failed to get config backend from config: %v", err) + } + } + + targets, err := getOrgTargets(configBackend, setup.OrgID) if err != nil { return errors.Wrapf(err, "loading target peers from config failed") } @@ -96,8 +106,9 @@ func (setup *BaseSetupImpl) Initialize(sdk *fabsdk.FabricSDK) error { return nil } -func getOrgTargets(configProvider config.Provider, org string) ([]string, error) { - _, endpointConfig, _, err := configProvider() +func getOrgTargets(configBackend core.ConfigBackend, org string) ([]string, error) { + + endpointConfig, err := fab.ConfigFromBackend(configBackend) if err != nil { return nil, errors.WithMessage(err, "reading config failed") } @@ -138,10 +149,16 @@ func InstallAndInstantiateCC(sdk *fabsdk.FabricSDK, user fabsdk.ContextOption, o return resmgmt.InstantiateCCResponse{}, errors.WithMessage(err, "creating chaincode package failed") } - _, endpointConfig, _, err := sdk.Config()() + configBackend, err := sdk.Config() if err != nil { - return resmgmt.InstantiateCCResponse{}, errors.WithMessage(err, "failed to get config") + return resmgmt.InstantiateCCResponse{}, errors.WithMessage(err, "failed to get config backend") } + + endpointConfig, err := fab.ConfigFromBackend(configBackend) + if err != nil { + return resmgmt.InstantiateCCResponse{}, errors.WithMessage(err, "failed to get endpoint config") + } + mspID, err := endpointConfig.MSPID(orgName) if err != nil { return resmgmt.InstantiateCCResponse{}, errors.WithMessage(err, "looking up MSP ID failed") diff --git a/test/integration/fab/channel_ledger_test.go b/test/integration/fab/channel_ledger_test.go index 54bdfd0ba6..dd95ddd692 100644 --- a/test/integration/fab/channel_ledger_test.go +++ b/test/integration/fab/channel_ledger_test.go @@ -47,7 +47,12 @@ func initializeLedgerTests(t *testing.T) (*fabsdk.FabricSDK, []string) { t.Fatalf("failed to load signing identity: %s", err) } - targets, err := integration.OrgTargetPeers(sdk.Config(), []string{orgName}) + configBackend, err := sdk.Config() + if err != nil { + t.Fatalf("failed to get config backend from SDK: %v", err) + } + + targets, err := integration.OrgTargetPeers(configBackend, []string{orgName}) if err != nil { t.Fatalf("creating peers failed: %v", err) } diff --git a/test/integration/msp/user_data_mgmt_test.go b/test/integration/msp/user_data_mgmt_test.go index c1693f2bb4..2ead11f8f2 100644 --- a/test/integration/msp/user_data_mgmt_test.go +++ b/test/integration/msp/user_data_mgmt_test.go @@ -17,7 +17,9 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context" mspctx "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" configImpl "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite/bccsp/sw" + "github.com/hyperledger/fabric-sdk-go/pkg/fab" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" mspimpl "github.com/hyperledger/fabric-sdk-go/pkg/msp" "github.com/hyperledger/fabric-sdk-go/test/integration" @@ -31,7 +33,14 @@ func TestWithCustomStores(t *testing.T) { t.Fatalf("Unexpected error from config backend: %v", err) } - cryptoConfig, endpointConfig, identityConfig, err := configImpl.FromBackend(configBackend)() + cryptoConfig := cryptosuite.ConfigFromBackend(configBackend) + + endpointConfig, err := fab.ConfigFromBackend(configBackend) + if err != nil { + t.Fatalf("Unexpected error from config: %v", err) + } + + identityConfig, err := mspimpl.ConfigFromBackend(configBackend) if err != nil { t.Fatalf("Unexpected error from config: %v", err) } diff --git a/test/integration/sdk/channel_config_test.go b/test/integration/sdk/channel_config_test.go index 23a35253d2..3d0a059c33 100644 --- a/test/integration/sdk/channel_config_test.go +++ b/test/integration/sdk/channel_config_test.go @@ -15,12 +15,15 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" "github.com/hyperledger/fabric-sdk-go/pkg/context" configImpl "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" + fabImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab" "github.com/hyperledger/fabric-sdk-go/pkg/fab/chconfig" "github.com/hyperledger/fabric-sdk-go/pkg/fab/orderer" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/api" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/factory/defcore" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/provider/fabpvdr" + "github.com/hyperledger/fabric-sdk-go/pkg/msp" "github.com/hyperledger/fabric-sdk-go/test/integration" "github.com/hyperledger/fabric-sdk-go/test/metadata" "github.com/stretchr/testify/assert" @@ -84,7 +87,14 @@ func TestChannelConfigWithOrderer(t *testing.T) { t.Fatalf("Unexpected error from config backend: %v", err) } - cryptoSuiteConfig, endpointConfig, identityConfig, err := configImpl.FromBackend(configBackend)() + cryptoSuiteConfig := cryptosuite.ConfigFromBackend(configBackend) + + endpointConfig, err := fabImpl.ConfigFromBackend(configBackend) + if err != nil { + t.Fatalf("Unexpected error from config: %v", err) + } + + identityConfig, err := msp.ConfigFromBackend(configBackend) if err != nil { t.Fatalf("Unexpected error from config: %v", err) } diff --git a/test/integration/sdk/custom_cryptosuite_test.go b/test/integration/sdk/custom_cryptosuite_test.go index c027d8cc5a..d96bbf9ea3 100644 --- a/test/integration/sdk/custom_cryptosuite_test.go +++ b/test/integration/sdk/custom_cryptosuite_test.go @@ -16,6 +16,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/client/channel" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite/bccsp/wrapper" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/factory/defcore" @@ -63,10 +64,7 @@ func TestEndToEndForCustomCryptoSuite(t *testing.T) { configBackend, err := testSetup.InitConfig()() - cryptoConfig, _, _, err := config.FromBackend(configBackend)() - if err != nil { - panic(fmt.Sprintf("Failed to get default config [%s]", err)) - } + cryptoConfig := cryptosuite.ConfigFromBackend(configBackend) //Get Test BCCSP, // TODO Need to use external BCCSP here diff --git a/test/integration/sdk/ledger_queries_test.go b/test/integration/sdk/ledger_queries_test.go index 0bf77410d7..388f0ba0f9 100644 --- a/test/integration/sdk/ledger_queries_test.go +++ b/test/integration/sdk/ledger_queries_test.go @@ -12,6 +12,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/hyperledger/fabric-sdk-go/pkg/client/ledger" + "github.com/hyperledger/fabric-sdk-go/pkg/fab" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" ) @@ -53,9 +54,14 @@ func TestLedgerClientQueries(t *testing.T) { t.Fatalf("QueryInfo return error: %v", err) } - _, endpointConfig, _, err := sdk.Config()() + configBackend, err := sdk.Config() if err != nil { - t.Fatalf("failed to get config, error: %v", err) + t.Fatalf("failed to get config backend, error: %v", err) + } + + endpointConfig, err := fab.ConfigFromBackend(configBackend) + if err != nil { + t.Fatalf("failed to get endpoint config, error: %v", err) } expectedPeerConfig, err := endpointConfig.PeerConfig(org1Name, "peer0.org1.example.com") diff --git a/test/integration/utils.go b/test/integration/utils.go index 4c6f679ef0..9f8364b3e3 100644 --- a/test/integration/utils.go +++ b/test/integration/utils.go @@ -15,8 +15,11 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt" "github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry" - "github.com/hyperledger/fabric-sdk-go/pkg/core/config" + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" + "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" + "github.com/hyperledger/fabric-sdk-go/pkg/fab" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" + "github.com/hyperledger/fabric-sdk-go/pkg/msp" "github.com/pkg/errors" ) @@ -125,10 +128,10 @@ func JoinChannel(sdk *fabsdk.FabricSDK, name, orgID string) (bool, error) { } // OrgTargetPeers determines peer endpoints for orgs -func OrgTargetPeers(configProvider config.Provider, orgs []string) ([]string, error) { - _, endpointConfig, _, err := configProvider() +func OrgTargetPeers(configBackend core.ConfigBackend, orgs []string) ([]string, error) { + endpointConfig, err := fab.ConfigFromBackend(configBackend) if err != nil { - return nil, errors.WithMessage(err, "reading config failed") + return nil, errors.WithMessage(err, "reading endpoint config failed") } var peers []string for _, org := range orgs { @@ -173,10 +176,17 @@ func CleanupTestPath(t *testing.T, storePath string) { // CleanupUserData removes user data. func CleanupUserData(t *testing.T, sdk *fabsdk.FabricSDK) { - cryptoSuiteConfig, _, identityConfig, err := sdk.Config()() + configBackend, err := sdk.Config() if err != nil { t.Fatal(err) } + + cryptoSuiteConfig := cryptosuite.ConfigFromBackend(configBackend) + identityConfig, err := msp.ConfigFromBackend(configBackend) + if err != nil { + t.Fatal(err) + } + keyStorePath := cryptoSuiteConfig.KeyStorePath() credentialStorePath := identityConfig.CredentialStorePath() CleanupTestPath(t, keyStorePath)