Skip to content

Commit

Permalink
[FAB-7452] Allow embedding cryptoconfig in the Config
Browse files Browse the repository at this point in the history
This change extends the functionality of configs with embedded users
to allow for embedding a path to a file instead.

Added a test case for embedded users with TLS config that contains
both a path and a pem.

Change-Id: I8bee00c5a37b07a5b5815dc3f45af669d6ee2ac2
Signed-off-by: Emil Nikolov <emil.e.nikolov@gmail.com>
  • Loading branch information
e-nikolov committed Dec 23, 2017
1 parent 6caa1e6 commit 035e4f9
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 138 deletions.
13 changes: 7 additions & 6 deletions api/apiconfig/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,13 @@ type NetworkPeer struct {
type OrganizationConfig struct {
MspID string
CryptoPath string
Users map[string]UserConfig
Users map[string]TLSKeyPair
Peers []string
CertificateAuthorities []string
AdminPrivateKey TLSConfig
SignedCert TLSConfig
}

type UserConfig struct {
Key string
Cert string
}

// OrdererConfig defines an orderer configuration
type OrdererConfig struct {
URL string
Expand Down Expand Up @@ -156,3 +151,9 @@ type MutualTLSConfig struct {
Certfile string
}
}

// TLSKeyPair contains the private key and certificate for TLS encryption
type TLSKeyPair struct {
Key TLSConfig
Cert TLSConfig
}
40 changes: 35 additions & 5 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,7 @@ O94CDp7l2k7hMQI0zQ==
}
}

func TestLoadConfigWithEmbeddedUsers(t *testing.T) {
func TestLoadConfigWithEmbeddedUsersWithPems(t *testing.T) {
// get a config file with embedded users
c, err := InitConfig(configEmbeddedUsersTestFilePath)
if err != nil {
Expand All @@ -851,19 +851,49 @@ func TestLoadConfigWithEmbeddedUsers(t *testing.T) {
t.Fatal(err)
}

if conf.Organizations[strings.ToLower(org1)].Users[strings.ToLower("EmbeddedUser")].Cert == "" {
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 == "" {
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 != "" {
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 != "" {
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
c, err := InitConfig(configEmbeddedUsersTestFilePath)
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")
}
}
Expand Down
94 changes: 73 additions & 21 deletions pkg/fabric-client/credentialmgr/credentialmgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var logger = logging.NewLogger("fabric_sdk_go")
// CredentialManager is used for retriving user's signing identity (ecert + private key)
type CredentialManager struct {
orgName string
embeddedUsers map[string]apiconfig.UserConfig
embeddedUsers map[string]apiconfig.TLSKeyPair
keyDir string
certDir string
config apiconfig.Config
Expand Down Expand Up @@ -62,7 +62,6 @@ func NewCredentialManager(orgName string, config apiconfig.Config, cryptoProvide

// GetSigningIdentity will sign the given object with provided key,
func (mgr *CredentialManager) GetSigningIdentity(userName string) (*apifabclient.SigningIdentity, error) {

if userName == "" {
return nil, errors.New("username is required")
}
Expand All @@ -72,48 +71,101 @@ func (mgr *CredentialManager) GetSigningIdentity(userName string) (*apifabclient
return nil, errors.WithMessage(err, "MSP ID config read failed")
}

privateKey, err := mgr.getPrivateKey(userName)

if err != nil {
return nil, err
}

enrollmentCert, err := mgr.getEnrollmentCert(userName)

if err != nil {
return nil, err
}

signingIdentity := &apifabclient.SigningIdentity{MspID: mspID, PrivateKey: privateKey, EnrollmentCert: enrollmentCert}

return signingIdentity, nil
}

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

var privateKey apicryptosuite.Key
var enrollmentCert []byte
var err error

embeddedCertBytes := []byte(mgr.embeddedUsers[strings.ToLower(userName)].Cert)
embeddedKeyBytes := []byte(mgr.embeddedUsers[strings.ToLower(userName)].Key)
if keyPem != "" {
// First try importing from the Embedded Pem
privateKey, err = fabricCaUtil.ImportBCCSPKeyFromPEMBytes([]byte(keyPem), mgr.cryptoProvider, true)

// First check the embedded users and then the paths
if len(embeddedCertBytes) != 0 && len(embeddedKeyBytes) != 0 {
privateKey, err = fabricCaUtil.ImportBCCSPKeyFromPEMBytes(embeddedKeyBytes, mgr.cryptoProvider, true)
if err != nil {
return nil, errors.Wrapf(err, "import private key failed %v", embeddedKeyBytes)
return nil, errors.Wrapf(err, "import private key failed %v", keyPem)
}
} else if keyPath != "" {
// Then try importing from the Embedded Path
privateKey, err = fabricCaUtil.ImportBCCSPKeyFromPEM(keyPath, mgr.cryptoProvider, true)

if err != nil {
return nil, errors.Wrap(err, "import private key failed")
}
} else if mgr.keyDir != "" {
// Then try importing from the Crypto Path

enrollmentCert = embeddedCertBytes
} else {
privateKeyDir := strings.Replace(mgr.keyDir, "{userName}", userName, -1)
enrollmentCertDir := strings.Replace(mgr.certDir, "{userName}", userName, -1)

privateKeyPath, err := getFirstPathFromDir(privateKeyDir)
if err != nil {
return nil, errors.WithMessage(err, "find private key path failed")
}

enrollmentCertPath, err := getFirstPathFromDir(enrollmentCertDir)
if err != nil {
return nil, errors.WithMessage(err, "find enrollment cert path failed")
return nil, errors.WithMessage(err, "find private key path failed")
}

privateKey, err = fabricCaUtil.ImportBCCSPKeyFromPEM(privateKeyPath, mgr.cryptoProvider, true)

if err != nil {
return nil, errors.Wrap(err, "import private key failed")
}
enrollmentCert, err = ioutil.ReadFile(enrollmentCertPath)
} else {
return nil, errors.Errorf("failed to find a private key for user %s", userName)
}

return privateKey, nil
}

func (mgr *CredentialManager) getEnrollmentCert(userName string) ([]byte, error) {
var err error

certPem := mgr.embeddedUsers[strings.ToLower(userName)].Cert.Pem
certPath := mgr.embeddedUsers[strings.ToLower(userName)].Cert.Path

var enrollmentCertBytes []byte

if certPem != "" {
enrollmentCertBytes = []byte(certPem)
} else if certPath != "" {
enrollmentCertBytes, err = ioutil.ReadFile(certPath)

if err != nil {
return nil, errors.Wrap(err, "reading enrollment cert path failed")
}
}
} else if mgr.certDir != "" {
enrollmentCertDir := strings.Replace(mgr.certDir, "{userName}", userName, -1)
enrollmentCertPath, err := getFirstPathFromDir(enrollmentCertDir)

signingIdentity := &apifabclient.SigningIdentity{MspID: mspID, PrivateKey: privateKey, EnrollmentCert: enrollmentCert}
if err != nil {
return nil, errors.WithMessage(err, "find enrollment cert path failed")
}

return signingIdentity, nil
enrollmentCertBytes, err = ioutil.ReadFile(enrollmentCertPath)

if err != nil {
return nil, errors.WithMessage(err, "reading enrollment cert path failed")
}
} else {
return nil, errors.Errorf("failed to find enrollment cert for user %s", userName)
}

return enrollmentCertBytes, nil
}

// Gets the first path from the dir directory
Expand Down
15 changes: 15 additions & 0 deletions pkg/fabric-client/credentialmgr/credentialmgr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,19 @@ func TestCredentialManagerFromEmbeddedCryptoConfig(t *testing.T) {
if err != nil {
t.Fatalf("Failed to retrieve signing identity: %+v", err)
}

_, err = credentialMgr.GetSigningIdentity("EmbeddedUserWithPaths")
if err != nil {
t.Fatalf("Failed to retrieve signing identity: %+v", err)
}

_, err = credentialMgr.GetSigningIdentity("EmbeddedUserMixed")
if err != nil {
t.Fatalf("Failed to retrieve signing identity: %+v", err)
}

_, err = credentialMgr.GetSigningIdentity("EmbeddedUserMixed2")
if err != nil {
t.Fatalf("Failed to retrieve signing identity: %+v", err)
}
}
Loading

0 comments on commit 035e4f9

Please sign in to comment.