diff --git a/identity/config/identity.go b/identity/config/identity.go new file mode 100644 index 00000000..e2586714 --- /dev/null +++ b/identity/config/identity.go @@ -0,0 +1,101 @@ +package config + +import ( + "errors" + + "github.com/s7techlab/hlf-sdk-go/api" + "github.com/s7techlab/hlf-sdk-go/identity" +) + +var ( + ErrMSPIDEmpty = errors.New(`MSP ID is empty`) + ErrMSPPathEmpty = errors.New(`MSP path is empty`) + + ErrMSPSignCertPathEmpty = errors.New(`MSP signcert path is empty`) + ErrMSPSignKeyPathEmpty = errors.New(`MSP signkey path is empty`) + + ErrMSPSignCertEmpty = errors.New(`MSP signcert is empty`) + ErrMSPSignKeyEmpty = errors.New(`MSP signkey is empty`) + + ErrSignerNotFound = errors.New(`signer not found`) +) + +type ( + MSP struct { + ID string `yaml:"id"` + Path string `yaml:"path"` + + // SignCertPath and SignKeyPath take precedence over Path. If they are present, Path will be ignored + SignCertPath string `yaml:"signcert_path"` + SignKeyPath string `yaml:"signkey_path"` + + // if SignCert and SignKey are present, Path, SignCertPath and SignKeyPath will be ignored + SignCert []byte `yaml:"signcert"` + SignKey []byte `yaml:"signkey"` + } +) + +func (m MSP) MustSigner() api.Identity { + signer, err := m.Signer() + if err != nil { + panic(err) + } + + return signer +} + +func (m MSP) Signer() (api.Identity, error) { + mspConfig, err := m.MSP(identity.WithSkipConfig()) + if err != nil { + return nil, err + } + + signer := mspConfig.Signer() + if signer == nil { + return nil, ErrSignerNotFound + } + + return signer, nil +} + +func (m MSP) MSP(opts ...identity.MSPOpt) (identity.MSP, error) { + if m.ID == `` { + return nil, ErrMSPIDEmpty + } + + // cert and key contents take precedence over Path and cert and key paths + if len(m.SignCert) != 0 || len(m.SignKey) != 0 { + if len(m.SignCert) == 0 { + return nil, ErrMSPSignCertEmpty + } + + if len(m.SignKey) == 0 { + return nil, ErrMSPSignKeyEmpty + } + + opts = append(opts, identity.WithSignCert(m.SignCert), identity.WithSignKey(m.SignKey)) + + return identity.MSPFromPath(m.ID, "", opts...) + } + + // cert and key paths take precedence over Path + if m.SignCertPath != `` || m.SignKeyPath != `` { + if m.SignCertPath == `` { + return nil, ErrMSPSignCertPathEmpty + } + + if m.SignKeyPath == `` { + return nil, ErrMSPSignKeyPathEmpty + } + + opts = append(opts, identity.WithSignCertPath(m.SignCertPath), identity.WithSignKeyPath(m.SignKeyPath)) + + return identity.MSPFromPath(m.ID, "", opts...) + } + + if m.Path == `` { + return nil, ErrMSPPathEmpty + } + + return identity.MSPFromPath(m.ID, m.Path, opts...) +} diff --git a/identity/loader.go b/identity/loader.go index 28034e71..7409be9d 100644 --- a/identity/loader.go +++ b/identity/loader.go @@ -86,7 +86,7 @@ func Certificate(certRaw []byte) (*x509.Certificate, error) { return cert, nil } -// Key parses raw key btes +// Key parses raw key bytes func Key(keyRaw []byte) (interface{}, error) { keyPEM, _ := pem.Decode(keyRaw) if keyPEM == nil { diff --git a/identity/msp.go b/identity/msp.go index bf20fadc..ceefd7ca 100644 --- a/identity/msp.go +++ b/identity/msp.go @@ -44,6 +44,13 @@ type ( MSPOpts struct { mspPath string + // signCert and signKey take precedence over signCertPath and signKeyPath + signCert []byte + signKey []byte + + signCertPath string + signKeyPath string + signCertsPath string keystorePath string adminCertsPath string @@ -51,6 +58,7 @@ type ( userPaths []string + skipConfig bool validateCertChain bool logger *zap.Logger } @@ -59,7 +67,6 @@ type ( ) func applyDefaultMSPPaths(mspOpts *MSPOpts) { - if mspOpts.adminCertsPath == `` { mspOpts.adminCertsPath = AdminCertsPath(mspOpts.mspPath) } @@ -97,12 +104,51 @@ func MSPFromConfig(fabricMspConfig *mspproto.FabricMSPConfig) (*MSPConfig, error return mspConfig, nil } +func WithSkipConfig() MSPOpt { + return func(mspOpts *MSPOpts) { + mspOpts.skipConfig = true + } +} + func WithAdminMSPPath(adminMSPPath string) MSPOpt { return func(mspOpts *MSPOpts) { mspOpts.adminMSPPath = adminMSPPath } } +func WithSignCertPath(signCertPath string) MSPOpt { + return func(mspOpts *MSPOpts) { + mspOpts.signCertPath = signCertPath + } +} + +func WithSignKeyPath(signKeyPath string) MSPOpt { + return func(mspOpts *MSPOpts) { + mspOpts.signKeyPath = signKeyPath + } +} + +func WithSignCert(signCert []byte) MSPOpt { + return func(mspOpts *MSPOpts) { + mspOpts.signCert = signCert + } +} + +func WithSignKey(signKey []byte) MSPOpt { + return func(mspOpts *MSPOpts) { + mspOpts.signKey = signKey + } +} + +func MustMSPFromPath(mspID, mspPath string, opts ...MSPOpt) *MSPConfig { + mspConfig, err := MSPFromPath(mspID, mspPath, opts...) + if err != nil { + panic(err) + } + + return mspConfig +} + // MSPFromPath loads msp config from filesystem func MSPFromPath(mspID, mspPath string, opts ...MSPOpt) (*MSPConfig, error) { var err error @@ -124,6 +170,18 @@ func MSPFromPath(mspID, mspPath string, opts ...MSPOpt) (*MSPConfig, error) { mspConfig := &MSPConfig{} + if len(mspOpts.signCert) != 0 && len(mspOpts.signKey) != 0 { + mspConfig.signer, err = FromBytes(mspID, mspOpts.signCert, mspOpts.signKey) + if err != nil { + return nil, err + } + } else if mspOpts.signCertPath != "" && mspOpts.signKeyPath != "" { + mspConfig.signer, err = FromCertKeyPath(mspID, mspOpts.signCertPath, mspOpts.signKeyPath) + if err != nil { + return nil, err + } + } + // admin in separate msp path if mspOpts.adminMSPPath != `` { logger.Debug(`load admin identities from separate msp path`, @@ -148,7 +206,8 @@ func MSPFromPath(mspID, mspPath string, opts ...MSPOpt) (*MSPConfig, error) { if len(mspOpts.userPaths) > 0 { for _, userPath := range mspOpts.userPaths { - users, err := ListFromPath(mspID, userPath, mspOpts.keystorePath) + var users []api.Identity + users, err = ListFromPath(mspID, userPath, mspOpts.keystorePath) // usePaths set explicit, so if dir is not exists - error occurred if err != nil { return nil, fmt.Errorf(`read users identity from=%s: %w`, userPath, err) @@ -160,15 +219,17 @@ func MSPFromPath(mspID, mspPath string, opts ...MSPOpt) (*MSPConfig, error) { logger.Debug(`user identities loaded`, zap.Int(`num`, len(mspConfig.users))) } - if mspOpts.signCertsPath != `` { + if mspOpts.signCertsPath != `` && mspConfig.signer == nil { mspConfig.signer, err = FirstFromPath(mspID, mspOpts.signCertsPath, mspOpts.keystorePath) if err != nil { return nil, fmt.Errorf(`read signer identity from=%s: %w`, mspOpts.signCertsPath, err) } } - if mspConfig.mspConfig, err = FabricMSPConfigFromPath(mspID, mspOpts.mspPath); err != nil { - return nil, err + if !mspOpts.skipConfig { + if mspConfig.mspConfig, err = FabricMSPConfigFromPath(mspID, mspOpts.mspPath); err != nil { + return nil, err + } } if mspOpts.validateCertChain { diff --git a/identity/msp_test.go b/identity/msp_test.go index 683c09d1..b085fba3 100644 --- a/identity/msp_test.go +++ b/identity/msp_test.go @@ -79,7 +79,7 @@ var _ = Describe(`Cert`, func() { }) }) - Context(`Peer from FabricMSPCofig`, func() { + Context(`Peer from FabricMSPConfig`, func() { It(`allow to create msp from FabricMSPConfig`, func() { msp, err := identity.MSPFromConfig(Org1MSPPeer.FabricMSPConfig())