Skip to content

Commit

Permalink
[FAB-8526] Embed CredentialManager into IdentityManager
Browse files Browse the repository at this point in the history
IdentityManager now embeds the Credentialmanager interface.
Behind the scene, the CredentialManager implementation is
merged into implementation of the IdentityManager.

This is a part of a bigger refactoring. CredentialManager
interface will be dropped in favour of IdentityManager.

Change-Id: Idf9dd88db78854ec401c93b41a091a5e7f6bcf43
Signed-off-by: Aleksandar Likic <aleksandar.likic@securekey.com>
  • Loading branch information
Aleksandar Likic authored and troyronda committed Feb 26, 2018
1 parent 081c0ff commit c2d4afc
Show file tree
Hide file tree
Showing 12 changed files with 1,099 additions and 314 deletions.
1 change: 1 addition & 0 deletions pkg/context/api/fab/identitymgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

// IdentityManager provides management of identities in a Fabric network
type IdentityManager interface {
contextApi.CredentialManager
CAName() string
Enroll(enrollmentID string, enrollmentSecret string) (core.Key, []byte, error)
Reenroll(user contextApi.User) (core.Key, []byte, error)
Expand Down
94 changes: 94 additions & 0 deletions pkg/fab/identitymgr/caclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package identitymgr

import (
"github.com/pkg/errors"

calib "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric-ca/lib"
config "github.com/hyperledger/fabric-sdk-go/pkg/context/api/core"
"github.com/hyperledger/fabric-sdk-go/pkg/core/config/urlutil"

"github.com/hyperledger/fabric-sdk-go/pkg/context/api/core"
)

// initCAClient initializes a Fabric CA client instance.
// Initialization is lazy, so the client is not required to connect to CA
// in order to transact with Fabric.
func (im *IdentityManager) initCAClient() error {
if im.caClient == nil {
caClient, err := newCAClient(im.orgName, im.config, im.cryptoSuite)
if err != nil {
return errors.Wrapf(err, "failed to initialie Fabric CA client")
}
im.caClient = caClient
caConfig, err := im.config.CAConfig(im.orgName)
if err != nil {
return errors.Wrapf(err, "failed to get CA configurtion for msp: %s", im.orgName)
}
im.registrar = caConfig.Registrar
}
return nil
}

func newCAClient(org string, config config.Config, cryptoSuite core.CryptoSuite) (*calib.Client, error) {

// Create new Fabric-ca client without configs
c := &calib.Client{
Config: &calib.ClientConfig{},
}

conf, err := config.CAConfig(org)
if err != nil {
return nil, err
}

if conf == nil {
return nil, errors.Errorf("Orgnization %s have no corresponding CA in the configs", org)
}

//set server CAName
c.Config.CAName = conf.CAName
//set server URL
c.Config.URL = urlutil.ToAddress(conf.URL)
//certs file list
c.Config.TLS.CertFiles, err = config.CAServerCertPaths(org)
if err != nil {
return nil, err
}

// set key file and cert file
c.Config.TLS.Client.CertFile, err = config.CAClientCertPath(org)
if err != nil {
return nil, err
}

c.Config.TLS.Client.KeyFile, err = config.CAClientKeyPath(org)
if err != nil {
return nil, err
}

// get Client configs
_, err = config.Client()
if err != nil {
return nil, err
}

//TLS flag enabled/disabled
c.Config.TLS.Enabled = urlutil.IsTLSEnabled(conf.URL)
c.Config.MSPDir = config.CAKeyStorePath()

//Factory opts
c.Config.CSP = cryptoSuite

err = c.Init()
if err != nil {
return nil, errors.Wrap(err, "init failed")
}

return c, nil
}
104 changes: 12 additions & 92 deletions pkg/fab/identitymgr/credentialmgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,99 +10,19 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"

"github.com/hyperledger/fabric-sdk-go/pkg/core/config/cryptoutil"

fabricCaUtil "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric-ca/util"
"github.com/hyperledger/fabric-sdk-go/pkg/context/api"
"github.com/hyperledger/fabric-sdk-go/pkg/context/api/core"
"github.com/hyperledger/fabric-sdk-go/pkg/fab/identity"
"github.com/hyperledger/fabric-sdk-go/pkg/fab/identitymgr/persistence"
"github.com/pkg/errors"
)

// CredentialManager is used for retriving user's signing identity (ecert + private key)
type CredentialManager struct {
orgName string
orgMspID string
embeddedUsers map[string]core.TLSKeyPair
mspPrivKeyStore api.KVStore
mspCertStore api.KVStore
config core.Config
cryptoProvider core.CryptoSuite
userStore api.UserStore
}

// NewCredentialManager Constructor for a credential manager.
// **** NOTE The naming convention for the constructors is temporarily
// **** broken, as this package already has a New() function for creating
// **** an IdentityManager. CredentialManager will be merged soon into
// **** IdentityManager.
// @param {string} orgName - organisation id
// @returns {CredentialManager} new credential manager
func NewCredentialManager(orgName string, config core.Config, cryptoProvider core.CryptoSuite) (*CredentialManager, error) {

netConfig, err := config.NetworkConfig()
if err != nil {
return nil, errors.New("network config retrieval failed")
}

// viper keys are case insensitive
orgConfig, ok := netConfig.Organizations[strings.ToLower(orgName)]
if !ok {
return nil, errors.New("org config retrieval failed")
}

if orgConfig.CryptoPath == "" && len(orgConfig.Users) == 0 {
return nil, errors.New("Either a cryptopath or an embedded list of users is required")
}

var mspPrivKeyStore api.KVStore
var mspCertStore api.KVStore

orgCryptoPathTemplate := orgConfig.CryptoPath
if orgCryptoPathTemplate != "" {
if !filepath.IsAbs(orgCryptoPathTemplate) {
orgCryptoPathTemplate = filepath.Join(config.CryptoConfigPath(), orgCryptoPathTemplate)
}
mspPrivKeyStore, err = persistence.NewFileKeyStore(orgCryptoPathTemplate)
if err != nil {
return nil, errors.Wrapf(err, "creating a private key store failed")
}
mspCertStore, err = persistence.NewFileCertStore(orgCryptoPathTemplate)
if err != nil {
return nil, errors.Wrapf(err, "creating a cert store failed")
}
} else {
logger.Warnf("Cryptopath not provided for organization [%s], MSP store(s) not created", orgName)
}

// In the future, shared UserStore from the SDK context will be used
var userStore api.UserStore
clientCofig, err := config.Client()
if err != nil {
return nil, errors.WithMessage(err, "Unable to retrieve client config")
}
if clientCofig.CredentialStore.Path != "" {
userStore, err = identity.NewCertFileUserStore(clientCofig.CredentialStore.Path, cryptoProvider)
}

return &CredentialManager{
orgName: orgName,
orgMspID: orgConfig.MspID,
config: config,
embeddedUsers: orgConfig.Users,
mspPrivKeyStore: mspPrivKeyStore,
mspCertStore: mspCertStore,
cryptoProvider: cryptoProvider,
userStore: userStore,
}, nil
}

// GetSigningIdentity will sign the given object with provided key,
func (mgr *CredentialManager) GetSigningIdentity(userName string) (*api.SigningIdentity, error) {
func (mgr *IdentityManager) GetSigningIdentity(userName string) (*api.SigningIdentity, error) {
if userName == "" {
return nil, errors.New("username is required")
}
Expand Down Expand Up @@ -157,7 +77,7 @@ func (mgr *CredentialManager) GetSigningIdentity(userName string) (*api.SigningI
return signingIdentity, nil
}

func (mgr *CredentialManager) getEmbeddedCertBytes(userName string) ([]byte, error) {
func (mgr *IdentityManager) getEmbeddedCertBytes(userName string) ([]byte, error) {
certPem := mgr.embeddedUsers[strings.ToLower(userName)].Cert.Pem
certPath := mgr.embeddedUsers[strings.ToLower(userName)].Cert.Path

Expand All @@ -180,7 +100,7 @@ func (mgr *CredentialManager) getEmbeddedCertBytes(userName string) ([]byte, err
return pemBytes, nil
}

func (mgr *CredentialManager) getEmbeddedPrivateKey(userName string) (core.Key, error) {
func (mgr *IdentityManager) getEmbeddedPrivateKey(userName string) (core.Key, error) {
keyPem := mgr.embeddedUsers[strings.ToLower(userName)].Key.Pem
keyPath := mgr.embeddedUsers[strings.ToLower(userName)].Key.Path

Expand Down Expand Up @@ -210,10 +130,10 @@ func (mgr *CredentialManager) getEmbeddedPrivateKey(userName string) (core.Key,

if pemBytes != nil {
// Try the crypto provider as a SKI
privateKey, err = mgr.cryptoProvider.GetKey(pemBytes)
privateKey, err = mgr.cryptoSuite.GetKey(pemBytes)
if err != nil || privateKey == nil {
// Try as a pem
privateKey, err = fabricCaUtil.ImportBCCSPKeyFromPEMBytes(pemBytes, mgr.cryptoProvider, true)
privateKey, err = fabricCaUtil.ImportBCCSPKeyFromPEMBytes(pemBytes, mgr.cryptoSuite, true)
if err != nil {
return nil, errors.Wrapf(err, "import private key failed %v", keyPem)
}
Expand All @@ -223,7 +143,7 @@ func (mgr *CredentialManager) getEmbeddedPrivateKey(userName string) (core.Key,
return privateKey, nil
}

func (mgr *CredentialManager) getPrivateKeyPemFromKeyStore(userName string, ski []byte) ([]byte, error) {
func (mgr *IdentityManager) getPrivateKeyPemFromKeyStore(userName string, ski []byte) ([]byte, error) {
if mgr.mspPrivKeyStore == nil {
return nil, nil
}
Expand All @@ -243,7 +163,7 @@ func (mgr *CredentialManager) getPrivateKeyPemFromKeyStore(userName string, ski
return keyBytes, nil
}

func (mgr *CredentialManager) getCertBytesFromCertStore(userName string) ([]byte, error) {
func (mgr *IdentityManager) getCertBytesFromCertStore(userName string) ([]byte, error) {
if mgr.mspCertStore == nil {
return nil, api.ErrUserNotFound
}
Expand All @@ -264,11 +184,11 @@ func (mgr *CredentialManager) getCertBytesFromCertStore(userName string) ([]byte
return certBytes, nil
}

func (mgr *CredentialManager) getPrivateKeyFromCert(userName string, cert []byte) (core.Key, error) {
func (mgr *IdentityManager) getPrivateKeyFromCert(userName string, cert []byte) (core.Key, error) {
if cert == nil {
return nil, errors.New("cert is nil")
}
pubKey, err := cryptoutil.GetPublicKeyFromCert(cert, mgr.cryptoProvider)
pubKey, err := cryptoutil.GetPublicKeyFromCert(cert, mgr.cryptoSuite)
if err != nil {
return nil, errors.WithMessage(err, "fetching public key from cert failed")
}
Expand All @@ -279,16 +199,16 @@ func (mgr *CredentialManager) getPrivateKeyFromCert(userName string, cert []byte
if err != api.ErrNotFound {
return nil, errors.WithMessage(err, "fetching private key from key store failed")
}
return mgr.cryptoProvider.GetKey(pubKey.SKI())
return mgr.cryptoSuite.GetKey(pubKey.SKI())
}

func (mgr *CredentialManager) getPrivateKeyFromKeyStore(userName string, ski []byte) (core.Key, error) {
func (mgr *IdentityManager) getPrivateKeyFromKeyStore(userName string, ski []byte) (core.Key, error) {
pemBytes, err := mgr.getPrivateKeyPemFromKeyStore(userName, ski)
if err != nil {
return nil, err
}
if pemBytes != nil {
return fabricCaUtil.ImportBCCSPKeyFromPEMBytes(pemBytes, mgr.cryptoProvider, true)
return fabricCaUtil.ImportBCCSPKeyFromPEMBytes(pemBytes, mgr.cryptoSuite, true)
}
return nil, api.ErrNotFound
}
12 changes: 2 additions & 10 deletions pkg/fab/identitymgr/credentialmgr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package identitymgr

import (
"math/rand"
"os"
"strconv"
"strings"
"testing"
Expand Down Expand Up @@ -85,7 +84,7 @@ func TestCredentialManager(t *testing.T) {
t.Fatalf("Failed to setup userStore: %s", err)
}

credentialMgr, err := NewCredentialManager(msp, config, cryptoSuite)
credentialMgr, err := New(msp, config, cryptoSuite)
if err != nil {
t.Fatalf("Failed to setup credential manager: %s", err)
}
Expand Down Expand Up @@ -171,7 +170,7 @@ func TestCredentialManagerFromEmbeddedCryptoConfig(t *testing.T) {
t.Fatalf(err.Error())
}

credentialMgr, err := NewCredentialManager(msp, config, cryptosuite.GetDefault())
credentialMgr, err := New(msp, config, cryptosuite.GetDefault())
if err != nil {
t.Fatalf("Failed to setup credential manager: %s", err)
}
Expand Down Expand Up @@ -206,10 +205,3 @@ func TestCredentialManagerFromEmbeddedCryptoConfig(t *testing.T) {
func createRandomName() string {
return "user" + strconv.Itoa(rand.Intn(500000))
}

func cleanupTestPath(t *testing.T, storePath string) {
err := os.RemoveAll(storePath)
if err != nil {
t.Fatalf("Cleaning up directory '%s' failed: %v", storePath, err)
}
}
2 changes: 1 addition & 1 deletion pkg/fab/identitymgr/enrollment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestCredentialManagerWithEnrollment(t *testing.T) {

cs, err := sw.GetSuiteByConfig(config)

credentialMgr, err := NewCredentialManager(orgName, config, cs)
credentialMgr, err := New(orgName, config, cs)
if err != nil {
t.Fatalf("Failed to setup credential manager: %s", err)
}
Expand Down
Loading

0 comments on commit c2d4afc

Please sign in to comment.