From 2fee96bed89388adcbcc4d6d6ac718e75ec9ee2f Mon Sep 17 00:00:00 2001 From: Will Lahti Date: Wed, 7 Feb 2018 14:29:52 -0500 Subject: [PATCH] [FAB-7952] Improve unclear and generic error message This CR changes the error message reported when a proposal is processed for a channel that either does not exist or the creator is not a member of. The message is still left vague ("access denied") to avoid potential malicious users scanning for channels but echoes back the channel and and org name supplied by the user to provide some troubleshooting help for cases where there was a typo in the channel name or the user had an unexpected MSP configured. The originating error message is logged as-is on the peer to allow peer admins to know the exact root cause of the error. This CR also updates the errors throughout the file to use the github.com/pkg/errors package. Change-Id: Id3589ceb56fa817a3b95026bb3e3e34629346f80 Signed-off-by: Will Lahti --- core/common/validation/fullflow_test.go | 18 +-- core/common/validation/msgvalidation.go | 69 ++++++----- core/common/validation/msgvalidation_test.go | 119 +++++++++++++++++++ msp/mgmt/mgmt.go | 43 +++++-- msp/mgmt/mgmt_test.go | 67 ++++++++++- msp/msp_test.go | 5 + 6 files changed, 273 insertions(+), 48 deletions(-) create mode 100644 core/common/validation/msgvalidation_test.go diff --git a/core/common/validation/fullflow_test.go b/core/common/validation/fullflow_test.go index a6f03b50003..3dd5dbf5547 100644 --- a/core/common/validation/fullflow_test.go +++ b/core/common/validation/fullflow_test.go @@ -35,13 +35,13 @@ import ( "github.com/stretchr/testify/assert" ) -func getProposal() (*peer.Proposal, error) { +func getProposal(channel string) (*peer.Proposal, error) { cis := &peer.ChaincodeInvocationSpec{ ChaincodeSpec: &peer.ChaincodeSpec{ ChaincodeId: getChaincodeID(), Type: peer.ChaincodeSpec_GOLANG}} - proposal, _, err := utils.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, util.GetTestChainID(), cis, signerSerialized) + proposal, _, err := utils.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, channel, cis, signerSerialized) return proposal, err } @@ -120,7 +120,7 @@ func createSignedTxTwoActions(proposal *peer.Proposal, signer msp.SigningIdentit func TestGoodPath(t *testing.T) { // get a toy proposal - prop, err := getProposal() + prop, err := getProposal(util.GetTestChainID()) if err != nil { t.Fatalf("getProposal failed, err %s", err) return @@ -194,7 +194,7 @@ func TestGoodPath(t *testing.T) { func TestTXWithTwoActionsRejected(t *testing.T) { // get a toy proposal - prop, err := getProposal() + prop, err := getProposal(util.GetTestChainID()) if err != nil { t.Fatalf("getProposal failed, err %s", err) return @@ -227,7 +227,7 @@ func TestTXWithTwoActionsRejected(t *testing.T) { func TestBadProp(t *testing.T) { // get a toy proposal - prop, err := getProposal() + prop, err := getProposal(util.GetTestChainID()) if err != nil { t.Fatalf("getProposal failed, err %s", err) return @@ -304,7 +304,7 @@ func corrupt(bytes []byte) { func TestBadTx(t *testing.T) { // get a toy proposal - prop, err := getProposal() + prop, err := getProposal(util.GetTestChainID()) if err != nil { t.Fatalf("getProposal failed, err %s", err) return @@ -361,7 +361,7 @@ func TestBadTx(t *testing.T) { func Test2EndorsersAgree(t *testing.T) { // get a toy proposal - prop, err := getProposal() + prop, err := getProposal(util.GetTestChainID()) if err != nil { t.Fatalf("getProposal failed, err %s", err) return @@ -404,7 +404,7 @@ func Test2EndorsersAgree(t *testing.T) { func Test2EndorsersDisagree(t *testing.T) { // get a toy proposal - prop, err := getProposal() + prop, err := getProposal(util.GetTestChainID()) if err != nil { t.Fatalf("getProposal failed, err %s", err) return @@ -469,6 +469,7 @@ func TestInvocationsBadArgs(t *testing.T) { var signer msp.SigningIdentity var signerSerialized []byte +var signerMSPId string func TestMain(m *testing.M) { // setup crypto algorithms @@ -486,6 +487,7 @@ func TestMain(m *testing.M) { os.Exit(-1) return } + signerMSPId = signer.GetMSPIdentifier() signerSerialized, err = signer.Serialize() if err != nil { diff --git a/core/common/validation/msgvalidation.go b/core/common/validation/msgvalidation.go index 70496f9abe0..145a708728d 100644 --- a/core/common/validation/msgvalidation.go +++ b/core/common/validation/msgvalidation.go @@ -18,15 +18,16 @@ package validation import ( "bytes" - "errors" - "fmt" + "github.com/golang/protobuf/proto" "github.com/hyperledger/fabric/common/channelconfig" "github.com/hyperledger/fabric/common/flogging" mspmgmt "github.com/hyperledger/fabric/msp/mgmt" "github.com/hyperledger/fabric/protos/common" + "github.com/hyperledger/fabric/protos/msp" pb "github.com/hyperledger/fabric/protos/peer" "github.com/hyperledger/fabric/protos/utils" + "github.com/pkg/errors" ) var putilsLogger = flogging.MustGetLogger("protoutils") @@ -34,7 +35,7 @@ var putilsLogger = flogging.MustGetLogger("protoutils") // validateChaincodeProposalMessage checks the validity of a Proposal message of type CHAINCODE func validateChaincodeProposalMessage(prop *pb.Proposal, hdr *common.Header) (*pb.ChaincodeHeaderExtension, error) { if prop == nil || hdr == nil { - return nil, errors.New("Nil arguments") + return nil, errors.New("nil arguments") } putilsLogger.Debugf("validateChaincodeProposalMessage starts for proposal %p, header %p", prop, hdr) @@ -42,7 +43,7 @@ func validateChaincodeProposalMessage(prop *pb.Proposal, hdr *common.Header) (*p // 4) based on the header type (assuming it's CHAINCODE), look at the extensions chaincodeHdrExt, err := utils.GetChaincodeHeaderExtension(hdr) if err != nil { - return nil, errors.New("Invalid header extension for type CHAINCODE") + return nil, errors.New("invalid header extension for type CHAINCODE") } if chaincodeHdrExt.ChaincodeId == nil { @@ -63,7 +64,7 @@ func validateChaincodeProposalMessage(prop *pb.Proposal, hdr *common.Header) (*p // encode more elaborate visibility mechanisms that shall be encoded in // this field (and handled appropriately by the peer) if chaincodeHdrExt.PayloadVisibility != nil { - return nil, errors.New("Invalid payload visibility field") + return nil, errors.New("invalid payload visibility field") } return chaincodeHdrExt, nil @@ -74,7 +75,7 @@ func validateChaincodeProposalMessage(prop *pb.Proposal, hdr *common.Header) (*p // have been unmarshalled and validated func ValidateProposalMessage(signedProp *pb.SignedProposal) (*pb.Proposal, *common.Header, *pb.ChaincodeHeaderExtension, error) { if signedProp == nil { - return nil, nil, nil, errors.New("Nil arguments") + return nil, nil, nil, errors.New("nil arguments") } putilsLogger.Debugf("ValidateProposalMessage starts for signed proposal %p", signedProp) @@ -100,7 +101,17 @@ func ValidateProposalMessage(signedProp *pb.SignedProposal) (*pb.Proposal, *comm // validate the signature err = checkSignatureFromCreator(shdr.Creator, signedProp.Signature, signedProp.ProposalBytes, chdr.ChannelId) if err != nil { - return nil, nil, nil, err + // log the exact message on the peer but return a generic error message to + // avoid malicious users scanning for channels + putilsLogger.Warningf("channel [%s]: %s", chdr.ChannelId, err) + sId := &msp.SerializedIdentity{} + err := proto.Unmarshal(shdr.Creator, sId) + if err != nil { + // log the error here as well but still only return the generic error + err = errors.Wrap(err, "could not deserialize a SerializedIdentity") + putilsLogger.Warningf("channel [%s]: %s", chdr.ChannelId, err) + } + return nil, nil, nil, errors.Errorf("access denied: channel [%s] creator org [%s]", chdr.ChannelId, sId.Mspid) } // Verify that the transaction ID has been computed properly. @@ -135,7 +146,7 @@ func ValidateProposalMessage(signedProp *pb.SignedProposal) (*pb.Proposal, *comm return prop, hdr, chaincodeHdrExt, err default: //NOTE : we proably need a case - return nil, nil, nil, fmt.Errorf("Unsupported proposal type %d", common.HeaderType(chdr.Type)) + return nil, nil, nil, errors.Errorf("unsupported proposal type %d", common.HeaderType(chdr.Type)) } } @@ -143,41 +154,41 @@ func ValidateProposalMessage(signedProp *pb.SignedProposal) (*pb.Proposal, *comm // this function returns nil if the creator // is a valid cert and the signature is valid func checkSignatureFromCreator(creatorBytes []byte, sig []byte, msg []byte, ChainID string) error { - putilsLogger.Debugf("checkSignatureFromCreator starts") + putilsLogger.Debugf("begin") // check for nil argument if creatorBytes == nil || sig == nil || msg == nil { - return errors.New("Nil arguments") + return errors.New("nil arguments") } mspObj := mspmgmt.GetIdentityDeserializer(ChainID) if mspObj == nil { - return fmt.Errorf("could not get msp for chain [%s]", ChainID) + return errors.Errorf("could not get msp for channel [%s]", ChainID) } // get the identity of the creator creator, err := mspObj.DeserializeIdentity(creatorBytes) if err != nil { - return fmt.Errorf("Failed to deserialize creator identity, err %s", err) + return errors.WithMessage(err, "MSP error") } - putilsLogger.Debugf("checkSignatureFromCreator info: creator is %s", creator.GetIdentifier()) + putilsLogger.Debugf("creator is %s", creator.GetIdentifier()) // ensure that creator is a valid certificate err = creator.Validate() if err != nil { - return fmt.Errorf("The creator certificate is not valid, err %s", err) + return errors.WithMessage(err, "creator certificate is not valid") } - putilsLogger.Debugf("checkSignatureFromCreator info: creator is valid") + putilsLogger.Debugf("creator is valid") // validate the signature err = creator.Verify(msg, sig) if err != nil { - return fmt.Errorf("The creator's signature over the proposal is not valid, err %s", err) + return errors.WithMessage(err, "creator's signature over the proposal is not valid") } - putilsLogger.Debugf("checkSignatureFromCreator exists successfully") + putilsLogger.Debugf("exits successfully") return nil } @@ -186,17 +197,17 @@ func checkSignatureFromCreator(creatorBytes []byte, sig []byte, msg []byte, Chai func validateSignatureHeader(sHdr *common.SignatureHeader) error { // check for nil argument if sHdr == nil { - return errors.New("Nil SignatureHeader provided") + return errors.New("nil SignatureHeader provided") } // ensure that there is a nonce if sHdr.Nonce == nil || len(sHdr.Nonce) == 0 { - return errors.New("Invalid nonce specified in the header") + return errors.New("invalid nonce specified in the header") } // ensure that there is a creator if sHdr.Creator == nil || len(sHdr.Creator) == 0 { - return errors.New("Invalid creator specified in the header") + return errors.New("invalid creator specified in the header") } return nil @@ -206,7 +217,7 @@ func validateSignatureHeader(sHdr *common.SignatureHeader) error { func validateChannelHeader(cHdr *common.ChannelHeader) error { // check for nil argument if cHdr == nil { - return errors.New("Nil ChannelHeader provided") + return errors.New("nil ChannelHeader provided") } // validate the header type @@ -214,7 +225,7 @@ func validateChannelHeader(cHdr *common.ChannelHeader) error { common.HeaderType(cHdr.Type) != common.HeaderType_CONFIG_UPDATE && common.HeaderType(cHdr.Type) != common.HeaderType_CONFIG && common.HeaderType(cHdr.Type) != common.HeaderType_PEER_RESOURCE_UPDATE { - return fmt.Errorf("invalid header type %s", common.HeaderType(cHdr.Type)) + return errors.Errorf("invalid header type %s", common.HeaderType(cHdr.Type)) } putilsLogger.Debugf("validateChannelHeader info: header type %d", common.HeaderType(cHdr.Type)) @@ -226,7 +237,7 @@ func validateChannelHeader(cHdr *common.ChannelHeader) error { // TODO: This check will be modified once the Epoch management // will be in place. if cHdr.Epoch != 0 { - return fmt.Errorf("Invalid Epoch in ChannelHeader. It must be 0. It was [%d]", cHdr.Epoch) + return errors.Errorf("invalid Epoch in ChannelHeader. Expected 0, got [%d]", cHdr.Epoch) } // TODO: Validate version in cHdr.Version @@ -237,7 +248,7 @@ func validateChannelHeader(cHdr *common.ChannelHeader) error { // checks for a valid Header func validateCommonHeader(hdr *common.Header) (*common.ChannelHeader, *common.SignatureHeader, error) { if hdr == nil { - return nil, nil, errors.New("Nil header") + return nil, nil, errors.New("nil header") } chdr, err := utils.UnmarshalChannelHeader(hdr.ChannelHeader) @@ -270,7 +281,7 @@ func validateConfigTransaction(data []byte, hdr *common.Header) error { // check for nil argument if data == nil || hdr == nil { - return errors.New("Nil arguments") + return errors.New("nil arguments") } // There is no need to do this validation here, the configtx.Validator handles this @@ -285,7 +296,7 @@ func validateEndorserTransaction(data []byte, hdr *common.Header) error { // check for nil argument if data == nil || hdr == nil { - return errors.New("Nil arguments") + return errors.New("nil arguments") } // if the type is ENDORSER_TRANSACTION we unmarshal a Transaction message @@ -296,7 +307,7 @@ func validateEndorserTransaction(data []byte, hdr *common.Header) error { // check for nil argument if tx == nil { - return errors.New("Nil transaction") + return errors.New("nil transaction") } // TODO: validate tx.Version @@ -305,7 +316,7 @@ func validateEndorserTransaction(data []byte, hdr *common.Header) error { // hlf version 1 only supports a single action per transaction if len(tx.Actions) != 1 { - return fmt.Errorf("Only one action per transaction is supported (tx contains %d)", len(tx.Actions)) + return errors.Errorf("only one action per transaction is supported, tx contains %d", len(tx.Actions)) } putilsLogger.Debugf("validateEndorserTransaction info: there are %d actions", len(tx.Actions)) @@ -313,7 +324,7 @@ func validateEndorserTransaction(data []byte, hdr *common.Header) error { for _, act := range tx.Actions { // check for nil argument if act == nil { - return errors.New("Nil action") + return errors.New("nil action") } // if the type is ENDORSER_TRANSACTION we unmarshal a SignatureHeader diff --git a/core/common/validation/msgvalidation_test.go b/core/common/validation/msgvalidation_test.go new file mode 100644 index 00000000000..0a0871c75a4 --- /dev/null +++ b/core/common/validation/msgvalidation_test.go @@ -0,0 +1,119 @@ +package validation + +import ( + "fmt" + "testing" + + "github.com/hyperledger/fabric/common/util" + "github.com/hyperledger/fabric/msp/mgmt" + "github.com/hyperledger/fabric/protos/common" + "github.com/hyperledger/fabric/protos/peer" + "github.com/hyperledger/fabric/protos/utils" + "github.com/stretchr/testify/assert" +) + +func createTestTransactionEnvelope(channel string, response *peer.Response, simRes []byte) (*common.Envelope, error) { + prop, sProp, err := createTestProposalAndSignedProposal(channel) + if err != nil { + return nil, fmt.Errorf("failed to create test proposal and signed proposal, err %s", err) + } + + // validate it + _, _, _, err = ValidateProposalMessage(sProp) + if err != nil { + return nil, fmt.Errorf("ValidateProposalMessage failed, err %s", err) + } + + // endorse it to get a proposal response + presp, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response, simRes, nil, getChaincodeID(), nil, signer) + if err != nil { + return nil, fmt.Errorf("CreateProposalResponse failed, err %s", err) + } + + // assemble a transaction from that proposal and endorsement + tx, err := utils.CreateSignedTx(prop, signer, presp) + if err != nil { + return nil, fmt.Errorf("CreateSignedTx failed, err %s", err) + } + + return tx, nil +} + +func createTestProposalAndSignedProposal(channel string) (*peer.Proposal, *peer.SignedProposal, error) { + // get a toy proposal + prop, err := getProposal(channel) + if err != nil { + return nil, nil, fmt.Errorf("getProposal failed, err %s", err) + } + + // sign it + sProp, err := utils.GetSignedProposal(prop, signer) + if err != nil { + return nil, nil, fmt.Errorf("GetSignedProposal failed, err %s", err) + } + return prop, sProp, nil +} + +func setupMSPManagerNoMSPs(channel string) error { + err := mgmt.GetManagerForChain(channel).Setup(nil) + if err != nil { + return err + } + + return nil +} + +func TestCheckSignatureFromCreator(t *testing.T) { + response := &peer.Response{Status: 200} + simRes := []byte("simulation_result") + + env, err := createTestTransactionEnvelope(util.GetTestChainID(), response, simRes) + assert.Nil(t, err, "failed to create test transaction: %s", err) + assert.NotNil(t, env) + + // get the payload from the envelope + payload, err := utils.GetPayload(env) + assert.NoError(t, err, "GetPayload returns err %s", err) + + // validate the header + chdr, shdr, err := validateCommonHeader(payload.Header) + assert.NoError(t, err, "validateCommonHeader returns err %s", err) + + // validate the signature in the envelope + err = checkSignatureFromCreator(shdr.Creator, env.Signature, env.Payload, chdr.ChannelId) + assert.NoError(t, err, "checkSignatureFromCreator returns err %s", err) + + // corrupt the creator + err = checkSignatureFromCreator([]byte("junk"), env.Signature, env.Payload, chdr.ChannelId) + assert.Error(t, err) + assert.Contains(t, err.Error(), "MSP error: could not deserialize") + + // check nonexistent channel + err = checkSignatureFromCreator(shdr.Creator, env.Signature, env.Payload, "junkchannel") + assert.Error(t, err) + assert.Contains(t, err.Error(), "MSP error: channel doesn't exist") +} + +func TestValidateProposalMessage(t *testing.T) { + // nonexistent channel + fakeChannel := "fakechannel" + _, sProp, err := createTestProposalAndSignedProposal(fakeChannel) + assert.NoError(t, err) + // validate it - it should fail + _, _, _, err = ValidateProposalMessage(sProp) + assert.Error(t, err) + assert.Contains(t, err.Error(), fmt.Sprintf("access denied: channel [%s] creator org [%s]", fakeChannel, signerMSPId)) + + // invalid signature + _, sProp, err = createTestProposalAndSignedProposal(util.GetTestChainID()) + assert.NoError(t, err) + sigCopy := make([]byte, len(sProp.Signature)) + copy(sigCopy, sProp.Signature) + for i := 0; i < len(sProp.Signature); i++ { + sigCopy[i] = byte(int(sigCopy[i]+1) % 255) + } + // validate it - it should fail + _, _, _, err = ValidateProposalMessage(&peer.SignedProposal{ProposalBytes: sProp.ProposalBytes, Signature: sigCopy}) + assert.Error(t, err) + assert.Contains(t, err.Error(), fmt.Sprintf("access denied: channel [%s] creator org [%s]", util.GetTestChainID(), signerMSPId)) +} diff --git a/msp/mgmt/mgmt.go b/msp/mgmt/mgmt.go index 1de2816974a..cd50144a131 100644 --- a/msp/mgmt/mgmt.go +++ b/msp/mgmt/mgmt.go @@ -77,6 +77,30 @@ var localMsp msp.MSP var mspMap map[string]msp.MSPManager = make(map[string]msp.MSPManager) var mspLogger = flogging.MustGetLogger("msp") +// TODO - this is a temporary solution to allow the peer to track whether the +// MSPManager has been setup for a channel, which indicates whether the channel +// exists or not +type mspMgmtMgr struct { + msp.MSPManager + // track whether this MSPManager has been setup successfully + up bool +} + +func (mgr *mspMgmtMgr) DeserializeIdentity(serializedIdentity []byte) (msp.Identity, error) { + if !mgr.up { + return nil, errors.New("channel doesn't exist") + } + return mgr.MSPManager.DeserializeIdentity(serializedIdentity) +} + +func (mgr *mspMgmtMgr) Setup(msps []msp.MSP) error { + err := mgr.MSPManager.Setup(msps) + if err == nil { + mgr.up = true + } + return err +} + // GetManagerForChain returns the msp manager for the supplied // chain; if no such manager exists, one is created func GetManagerForChain(chainID string) msp.MSPManager { @@ -85,15 +109,16 @@ func GetManagerForChain(chainID string) msp.MSPManager { mspMgr, ok := mspMap[chainID] if !ok { - mspLogger.Debugf("Created new msp manager for chain %s", chainID) - mspMgr = msp.NewMSPManager() - mspMap[chainID] = mspMgr + mspLogger.Debugf("Created new msp manager for channel `%s`", chainID) + mspMgmtMgr := &mspMgmtMgr{msp.NewMSPManager(), false} + mspMap[chainID] = mspMgmtMgr + mspMgr = mspMgmtMgr } else { - // check for internal mspManagerImpl type. if a different type is found, - // it's because a developer has added a new type that implements the - // MSPManager interface and should add a case to the logic above to handle - // it. - if reflect.TypeOf(mspMgr).Elem().Name() != "mspManagerImpl" { + // check for internal mspManagerImpl and mspMgmtMgr types. if a different + // type is found, it's because a developer has added a new type that + // implements the MSPManager interface and should add a case to the logic + // above to handle it. + if !(reflect.TypeOf(mspMgr).Elem().Name() == "mspManagerImpl" || reflect.TypeOf(mspMgr).Elem().Name() == "mspMgmtMgr") { panic("Found unexpected MSPManager type.") } mspLogger.Debugf("Returning existing manager for channel '%s'", chainID) @@ -122,7 +147,7 @@ func XXXSetMSPManager(chainID string, manager msp.MSPManager) { m.Lock() defer m.Unlock() - mspMap[chainID] = manager + mspMap[chainID] = &mspMgmtMgr{manager, true} } // GetLocalMSP returns the local msp (and creates it if it doesn't exist) diff --git a/msp/mgmt/mgmt_test.go b/msp/mgmt/mgmt_test.go index 60a3f059a03..e92840f594e 100644 --- a/msp/mgmt/mgmt_test.go +++ b/msp/mgmt/mgmt_test.go @@ -19,6 +19,8 @@ package mgmt import ( "testing" + "github.com/hyperledger/fabric/common/util" + "github.com/hyperledger/fabric/core/config" "github.com/hyperledger/fabric/msp" "github.com/stretchr/testify/assert" ) @@ -28,14 +30,14 @@ func TestGetManagerForChains(t *testing.T) { mspMgr1 := GetManagerForChain("test") // ensure MSPManager is set if mspMgr1 == nil { - t.FailNow() + t.Fatal("mspMgr1 fail") } // MSPManager for channel now exists mspMgr2 := GetManagerForChain("test") // ensure MSPManager returned matches the first result if mspMgr2 != mspMgr1 { - t.FailNow() + t.Fatal("mspMgr2 != mspMgr1 fail") } } @@ -81,3 +83,64 @@ func TestUpdateLocalMspCache(t *testing.T) { t.Fatalf("firstMsp != secondMsp") } } + +func TestNewMSPMgmtMgr(t *testing.T) { + err := LoadMSPSetupForTesting() + assert.Nil(t, err) + + // test for nonexistent channel + mspMgmtMgr := GetManagerForChain("fake") + + id := GetLocalSigningIdentityOrPanic() + assert.NotNil(t, id) + + serializedID, err := id.Serialize() + if err != nil { + t.Fatalf("Serialize should have succeeded, got err %s", err) + return + } + + idBack, err := mspMgmtMgr.DeserializeIdentity(serializedID) + assert.Error(t, err) + assert.Contains(t, err.Error(), "channel doesn't exist") + assert.Nil(t, idBack, "deserialized identity should have been nil") + + // test for existing channel + mspMgmtMgr = GetManagerForChain(util.GetTestChainID()) + + id = GetLocalSigningIdentityOrPanic() + assert.NotNil(t, id) + + serializedID, err = id.Serialize() + if err != nil { + t.Fatalf("Serialize should have succeeded, got err %s", err) + return + } + + idBack, err = mspMgmtMgr.DeserializeIdentity(serializedID) + assert.NoError(t, err) + assert.NotNil(t, idBack, "deserialized identity should not have been nil") +} + +func LoadMSPSetupForTesting() error { + dir, err := config.GetDevMspDir() + if err != nil { + return err + } + conf, err := msp.GetLocalMspConfig(dir, nil, "DEFAULT") + if err != nil { + return err + } + + err = GetLocalMSP().Setup(conf) + if err != nil { + return err + } + + err = GetManagerForChain(util.GetTestChainID()).Setup([]msp.MSP{GetLocalMSP()}) + if err != nil { + return err + } + + return nil +} diff --git a/msp/msp_test.go b/msp/msp_test.go index 1cfd8eb4621..1d76b0ef9bc 100644 --- a/msp/msp_test.go +++ b/msp/msp_test.go @@ -400,6 +400,11 @@ func TestSerializeIdentitiesWithMSPManager(t *testing.T) { _, err = mspMgr.DeserializeIdentity(serializedID) assert.Error(t, err) + assert.Contains(t, err.Error(), fmt.Sprintf("MSP %s is unknown", sid.Mspid)) + + _, err = mspMgr.DeserializeIdentity([]byte("barf")) + assert.Error(t, err) + assert.Contains(t, err.Error(), "could not deserialize") } func TestIdentitiesGetters(t *testing.T) {