Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make AmMemberOf to use only the mspIDs in collection policy (release-2.2) #4248

Merged
merged 1 commit into from
Jun 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 7 additions & 20 deletions core/common/privdata/membershipinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,18 @@ func NewMembershipInfoProvider(mspID string, selfSignedData protoutil.SignedData
}

// AmMemberOf checks whether the current peer is a member of the given collection config.
// If getPolicy returns an error, it will drop the error and return false - same as a RejectAll policy.
// It is used when a chaincode is upgraded to see if the peer's org has become eligible after a collection
// change.
// It is used when a chaincode is upgraded to see if the peer's org has become eligible after a collection change.
func (m *MembershipProvider) AmMemberOf(channelName string, collectionPolicyConfig *peer.CollectionPolicyConfig) (bool, error) {
deserializer := m.IdentityDeserializerFactory(channelName)

// Do a simple check to see if the mspid matches any principal identities in the SignaturePolicy - FAB-17059
if collectionPolicyConfig.GetSignaturePolicy() != nil {
memberOrgs := getMemberOrgs(collectionPolicyConfig.GetSignaturePolicy().GetIdentities(), deserializer)

if _, ok := memberOrgs[m.mspID]; ok {
return true, nil
}
}

// Fall back to default access policy evaluation otherwise
accessPolicy, err := getPolicy(collectionPolicyConfig, deserializer)
if err != nil {
// drop the error and return false - same as reject all policy
logger.Errorf("Reject all due to error getting policy: %s", err)
return false, nil
}
if err := accessPolicy.EvaluateSignedData([]*protoutil.SignedData{&m.selfSignedData}); err != nil {
if collectionPolicyConfig.GetSignaturePolicy() == nil {
logger.Warningf("collection membership policy is nil")
return false, nil
}

return true, nil
memberOrgs := getMemberOrgs(collectionPolicyConfig.GetSignaturePolicy().GetIdentities(), deserializer)

_, ok := memberOrgs[m.mspID]
return ok, nil
}
10 changes: 0 additions & 10 deletions core/common/privdata/membershipinfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,6 @@ func TestMembershipInfoProvider(t *testing.T) {
assert.False(t, res)
assert.Nil(t, err)

// verify membership provider with empty mspID and fall back to default access policy evaluation returns true
membershipProvider = NewMembershipInfoProvider("", peerSelfSignedData, identityDeserializer)
res, err = membershipProvider.AmMemberOf("test1", getAccessPolicy([]string{"peer0", "peer1"}))
assert.True(t, res)
assert.Nil(t, err)

// verify membership provider with empty mspID and fall back to default access policy evaluation returns false
res, err = membershipProvider.AmMemberOf("test1", getAccessPolicy([]string{"peer2", "peer3"}))
assert.False(t, res)
assert.Nil(t, err)
}

func getAccessPolicy(signers []string) *peer.CollectionPolicyConfig {
Expand Down
62 changes: 62 additions & 0 deletions integration/ledger/reset_rollback_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,54 @@ var _ = Describe("rollback, reset, pause and resume peer node commands", func()
Expect(dbPath).To(BeADirectory())
helper.assertPresentInCollectionM("marblesp", "marble2", peer)
})

It("change collection members and rebuild databases", func() {
By("Checking ledger height on each peer")
for _, peer := range helper.peers {
Expect(helper.getLedgerHeight(peer)).Should(Equal(14))
}

org1peer0 := setup.network.Peer("org1", "peer0")
org2peer0 := setup.network.Peer("org2", "peer0")
org3peer0 := setup.network.Peer("org3", "peer0")

By("verifying marble1 to marble5 exist in collectionMarbles & collectionMarblePrivateDetails in the members")
for i := 1; i <= 5; i++ {
helper.assertPresentInCollectionM("marblesp", fmt.Sprintf("marble%d", i), org1peer0)
helper.assertPresentInCollectionM("marblesp", fmt.Sprintf("marble%d", i), org2peer0)
helper.assertPresentInCollectionMPD("marblesp", fmt.Sprintf("marble%d", i), org2peer0)
helper.assertPresentInCollectionMPD("marblesp", fmt.Sprintf("marble%d", i), org3peer0)
}

// Add org1 to collectionMarblesPrivateDetails
By("Updating the chaincode definition to version 2.0")
updatedChaincode := nwo.Chaincode{
Name: "marblesp",
Version: "2.0",
Path: components.Build("github.com/hyperledger/fabric/integration/chaincode/marbles_private/cmd"),
Lang: "binary",
PackageFile: filepath.Join(setup.testDir, "marbles-pvtdata.tar.gz"),
Label: "marbles-private-20",
SignaturePolicy: `OR ('Org1MSP.member','Org2MSP.member', 'Org3MSP.member')`,
CollectionsConfig: filepath.Join("testdata", "collection_configs", "collections_config3.json"),
Sequence: "2",
}

helper.deployChaincode(updatedChaincode)

// statedb rebuild test
By("Stopping peers and deleting the statedb folder on peer Org1.peer0")
org1peer0 = setup.network.Peer("org1", "peer0")
setup.stopPeers()
dbPath := filepath.Join(setup.network.PeerLedgerDir(org1peer0), "stateLeveldb")
Expect(os.RemoveAll(dbPath)).NotTo(HaveOccurred())
Expect(dbPath).NotTo(BeADirectory())
By("Restarting the peer Org1.peer0")
setup.startPeers()
Expect(dbPath).To(BeADirectory())
helper.assertPresentInCollectionM("marblesp", "marble2", org1peer0)
})

})

type setup struct {
Expand Down Expand Up @@ -458,6 +506,20 @@ func (th *testHelper) assertPresentInCollectionM(chaincodeName, marbleName strin
}
}

// assertAbsentInCollectionM asserts that the private data for given marble is present in collection
// 'readMarble' at the given peers
func (th *testHelper) assertAbsentInCollectionM(chaincodeName, marbleName string, peerList ...*nwo.Peer) {
command := commands.ChaincodeQuery{
ChannelID: th.channelID,
Name: chaincodeName,
Ctor: fmt.Sprintf(`{"Args":["readMarble","%s"]}`, marbleName),
}
expectedMsg := fmt.Sprintf(`{"docType":"marble","name":"%s"`, marbleName)
for _, peer := range peerList {
th.queryChaincode(peer, command, expectedMsg, false)
}
}

// assertPresentInCollectionMPD asserts that the private data for given marble is present
// in collection 'readMarblePrivateDetails' at the given peers
func (th *testHelper) assertPresentInCollectionMPD(chaincodeName, marbleName string, peerList ...*nwo.Peer) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{
"name": "collectionMarbles",
"policy": "OR('Org1MSP.member', 'Org2MSP.member')",
"requiredPeerCount": 1,
"maxPeerCount": 2,
"blockToLive":1000000,
"memberOnlyRead": false
},
{
"name": "collectionMarblePrivateDetails",
"policy": "OR('Org1MSP.member', 'Org2MSP.member', 'Org3MSP.member')",
"requiredPeerCount": 1,
"maxPeerCount": 2,
"blockToLive":1000000,
"memberOnlyRead": false
}
]