Skip to content

Commit

Permalink
[FAB-8566] Load CA Registrar from configuration
Browse files Browse the repository at this point in the history
This change allows embedding the CA registrar key and cert
in SDK configuration. The registrar user name is taken from
the CA configuration.

Change-Id: I97cabb10c5f8856db2db9ac41b8014013cca4719
Signed-off-by: Aleksandar Likic <aleksandar.likic@securekey.com>
  • Loading branch information
Aleksandar Likic committed Feb 28, 2018
1 parent 7ef01a3 commit e81d3ed
Show file tree
Hide file tree
Showing 8 changed files with 787 additions and 94 deletions.
7 changes: 7 additions & 0 deletions pkg/context/api/fab/identitymgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,17 @@ SPDX-License-Identifier: Apache-2.0
package fab

import (
"errors"

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

var (
// ErrCARegistrarNotFound indicates the CA registrar was not found
ErrCARegistrarNotFound = errors.New("CA registrar not found")
)

// IdentityManager provides management of identities in a Fabric network
type IdentityManager interface {
GetSigningIdentity(name string) (*contextApi.SigningIdentity, error)
Expand Down
48 changes: 44 additions & 4 deletions pkg/fab/identitymgr/caclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (
"github.com/pkg/errors"

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

"github.com/hyperledger/fabric-sdk-go/pkg/context/api/core"
Expand All @@ -20,19 +22,57 @@ import (
// 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 {

// Read CA configuration
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

// Initialize CA client
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)
}

return nil
}

func (im *IdentityManager) getRegistrarSI(enrollID string, enrollSecret string) (*calib.Identity, error) {

if enrollID == "" {
return nil, fab.ErrCARegistrarNotFound
}

si, err := im.GetSigningIdentity(enrollID)
if err != nil {
if err != contextApi.ErrUserNotFound {
return nil, err
}
if enrollSecret == "" {
return nil, fab.ErrCARegistrarNotFound
}

// Attempt to enroll the registrar
_, _, err = im.Enroll(enrollID, enrollSecret)
if err != nil {
return errors.Wrapf(err, "failed to get CA configurtion for msp: %s", im.orgName)
return nil, err
}
si, err = im.GetSigningIdentity(enrollID)
if err != nil {
return nil, err
}
im.registrar = caConfig.Registrar
}
return nil
registrar, err := im.caClient.NewIdentity(si.PrivateKey, si.EnrollmentCert)
if err != nil {
return nil, errors.Wrap(err, "failed to create CA signing identity")
}
return registrar, nil
}

func newCAClient(org string, config config.Config, cryptoSuite core.CryptoSuite) (*calib.Client, error) {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ import (
"github.com/pkg/errors"
)

var testPrivKey = `-----BEGIN PRIVATE KEY-----
var (
testPrivKey = `-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgp4qKKB0WCEfx7XiB
5Ul+GpjM1P5rqc6RhjD5OkTgl5OhRANCAATyFT0voXX7cA4PPtNstWleaTpwjvbS
J3+tMGTG67f+TdCfDxWYMpQYxLlE8VkbEzKWDwCYvDZRMKCQfv2ErNvb
-----END PRIVATE KEY-----`

var testCert = `-----BEGIN CERTIFICATE-----
testCert = `-----BEGIN CERTIFICATE-----
MIICGTCCAcCgAwIBAgIRALR/1GXtEud5GQL2CZykkOkwCgYIKoZIzj0EAwIwczEL
MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG
cmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh
Expand All @@ -44,7 +45,8 @@ AiaiI2BjxnL3/TetJ8iFJYZyWvK//an13WV/AiARBJd/pI5A7KZgQxJhXmmR8bie
XdsmTcdRvJ3TS/6HCA==
-----END CERTIFICATE-----`

var msp = "Org1"
msp = "Org1"
)

func TestGetSigningIdentity(t *testing.T) {

Expand Down
95 changes: 33 additions & 62 deletions pkg/fab/identitymgr/identitymgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type IdentityManager struct {

// CA Client state
caClient *calib.Client
registrar config.EnrollCredentials
registrar core.EnrollCredentials
}

// New creates a new instance of IdentityManager
Expand Down Expand Up @@ -124,6 +124,7 @@ func (im *IdentityManager) CAName() string {
// enrollmentSecret The secret associated with the enrollment ID
// Returns X509 certificate
func (im *IdentityManager) Enroll(enrollmentID string, enrollmentSecret string) (core.Key, []byte, error) {

if err := im.initCAClient(); err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -156,6 +157,7 @@ func (im *IdentityManager) Enroll(enrollmentID string, enrollmentSecret string)
// Reenroll an enrolled user in order to receive a signed X509 certificate
// Returns X509 certificate
func (im *IdentityManager) Reenroll(user contextApi.User) (core.Key, []byte, error) {

if err := im.initCAClient(); err != nil {
return nil, nil, err
}
Expand All @@ -169,18 +171,24 @@ func (im *IdentityManager) Reenroll(user contextApi.User) (core.Key, []byte, err
req := &caapi.ReenrollmentRequest{
CAName: im.caClient.Config.CAName,
}
// Create signing identity
identity, err := im.createSigningIdentity(user)
caidentity, err := im.caClient.NewIdentity(user.PrivateKey(), user.EnrollmentCertificate())
if err != nil {
logger.Debugf("Invalid re-enroll request, %s is not a valid user %s\n", user.Name(), err)
return nil, nil, errors.Wrap(err, "createSigningIdentity failed")
return nil, nil, errors.Wrap(err, "failed to create CA signing identity")
}

reenrollmentResponse, err := identity.Reenroll(req)
caresp, err := caidentity.Reenroll(req)
if err != nil {
return nil, nil, errors.Wrap(err, "reenroll failed")
}
newUser := identity.NewUser(im.orgMspID, user.Name())
newUser.SetEnrollmentCertificate(caresp.Identity.GetECert().Cert())
newUser.SetPrivateKey(caresp.Identity.GetECert().Key())
err = im.userStore.Store(newUser)
if err != nil {
return nil, nil, errors.Wrap(err, "reenroll failed")
}
return reenrollmentResponse.Identity.GetECert().Key(), reenrollmentResponse.Identity.GetECert().Cert(), nil

return caresp.Identity.GetECert().Key(), caresp.Identity.GetECert().Cert(), nil
}

// Register a User with the Fabric CA
Expand All @@ -190,22 +198,16 @@ func (im *IdentityManager) Register(request *fab.RegistrationRequest) (string, e
if err := im.initCAClient(); err != nil {
return "", err
}
if im.registrar.EnrollID == "" {
return "", fab.ErrCARegistrarNotFound
}
// Validate registration request
if request == nil {
return "", errors.New("registration request is required")
}
if request.Name == "" {
return "", errors.New("request.Name is required")
}
registrar, err := im.getRegistrar()
if err != nil {
return "", errors.Wrapf(err, "failed to get registrar")
}
// Create request signing identity
identity, err := im.createSigningIdentity(registrar)
if err != nil {
return "", errors.Wrap(err, "failed to create request for signing identity")
}
// Contruct request for Fabric CA client
var attributes []caapi.Attribute
for i := range request.Attributes {
Expand All @@ -220,9 +222,13 @@ func (im *IdentityManager) Register(request *fab.RegistrationRequest) (string, e
Affiliation: request.Affiliation,
Secret: request.Secret,
Attributes: attributes}
// Make registration request

response, err := identity.Register(&req)
registrar, err := im.getRegistrarSI(im.registrar.EnrollID, im.registrar.EnrollSecret)
if err != nil {
return "", err
}

response, err := registrar.Register(&req)
if err != nil {
return "", errors.Wrap(err, "failed to register user")
}
Expand All @@ -237,19 +243,13 @@ func (im *IdentityManager) Revoke(request *fab.RevocationRequest) (*fab.Revocati
if err := im.initCAClient(); err != nil {
return nil, err
}
if im.registrar.EnrollID == "" {
return nil, fab.ErrCARegistrarNotFound
}
// Validate revocation request
if request == nil {
return nil, errors.New("revocation request is required")
}
registrar, err := im.getRegistrar()
if err != nil {
return nil, errors.Wrapf(err, "failed to ret registrar")
}
// Create request signing identity
identity, err := im.createSigningIdentity(registrar)
if err != nil {
return nil, errors.Wrap(err, "failed to create request for signing identity")
}
// Create revocation request
var req = caapi.RevocationRequest{
CAName: request.CAName,
Expand All @@ -259,7 +259,12 @@ func (im *IdentityManager) Revoke(request *fab.RevocationRequest) (*fab.Revocati
Reason: request.Reason,
}

resp, err := identity.Revoke(&req)
registrar, err := im.getRegistrarSI(im.registrar.EnrollID, im.registrar.EnrollSecret)
if err != nil {
return nil, err
}

resp, err := registrar.Revoke(&req)
if err != nil {
return nil, errors.Wrap(err, "failed to revoke")
}
Expand All @@ -279,37 +284,3 @@ func (im *IdentityManager) Revoke(request *fab.RevocationRequest) (*fab.Revocati
CRL: resp.CRL,
}, nil
}

func (im *IdentityManager) getRegistrar() (contextApi.User, error) {
user, err := im.userStore.Load(contextApi.UserKey{MspID: im.orgMspID, Name: im.registrar.EnrollID})
if err != nil {
if err != contextApi.ErrUserNotFound {
return nil, err
}
if im.registrar.EnrollSecret == "" {
return nil, errors.New("registrar not found and cannot be enrolled because enrollment secret is not present")
}
_, _, err = im.Enroll(im.registrar.EnrollID, im.registrar.EnrollSecret)
if err != nil {
return nil, err
}
user, err = im.userStore.Load(contextApi.UserKey{MspID: im.orgMspID, Name: im.registrar.EnrollID})
}
return user, err
}

// createSigningIdentity creates an identity to sign Fabric CA requests with
func (im *IdentityManager) createSigningIdentity(user contextApi.User) (*calib.Identity, error) {
// Validate user
if user == nil {
return nil, errors.New("user required")
}
// Validate enrolment information
cert := user.EnrollmentCertificate()
key := user.PrivateKey()
if key == nil || cert == nil {
return nil, errors.New(
"Unable to read user enrolment information to create signing identity")
}
return im.caClient.NewIdentity(key, cert)
}
Loading

0 comments on commit e81d3ed

Please sign in to comment.