github.com/yimialmonte/fabric@v2.1.1+incompatible/discovery/endorsement/collection_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package endorsement 8 9 import ( 10 "bytes" 11 "fmt" 12 "testing" 13 14 "github.com/hyperledger/fabric-protos-go/common" 15 "github.com/hyperledger/fabric-protos-go/discovery" 16 "github.com/hyperledger/fabric-protos-go/msp" 17 "github.com/hyperledger/fabric-protos-go/peer" 18 "github.com/hyperledger/fabric/common/policies" 19 "github.com/hyperledger/fabric/gossip/api" 20 gcommon "github.com/hyperledger/fabric/gossip/common" 21 disc "github.com/hyperledger/fabric/gossip/discovery" 22 "github.com/hyperledger/fabric/protoutil" 23 "github.com/stretchr/testify/assert" 24 ) 25 26 func TestPrincipalsFromCollectionConfig(t *testing.T) { 27 t.Run("Empty config", func(t *testing.T) { 28 res, err := principalsFromCollectionConfig(nil) 29 assert.NoError(t, err) 30 assert.Empty(t, res) 31 }) 32 33 t.Run("Not empty config", func(t *testing.T) { 34 org1AndOrg2 := []*msp.MSPPrincipal{orgPrincipal("Org1MSP"), orgPrincipal("Org2MSP")} 35 org3AndOrg4 := []*msp.MSPPrincipal{orgPrincipal("Org3MSP"), orgPrincipal("Org4MSP")} 36 col2principals := map[string][]*msp.MSPPrincipal{ 37 "foo": org1AndOrg2, 38 "bar": org3AndOrg4, 39 } 40 config := buildCollectionConfig(col2principals) 41 res, err := principalsFromCollectionConfig(config) 42 assert.NoError(t, err) 43 assertEqualPrincipalSets(t, policies.PrincipalSet(org1AndOrg2), res["foo"]) 44 assertEqualPrincipalSets(t, policies.PrincipalSet(org3AndOrg4), res["bar"]) 45 assert.Empty(t, res["baz"]) 46 }) 47 } 48 49 func TestNewCollectionFilterInvalidInput(t *testing.T) { 50 t.Run("Invalid collection type", func(t *testing.T) { 51 collections := &peer.CollectionConfigPackage{} 52 collections.Config = []*peer.CollectionConfig{ 53 { 54 Payload: nil, 55 }, 56 } 57 filter, err := principalsFromCollectionConfig(collections) 58 assert.Nil(t, filter) 59 assert.Contains(t, err.Error(), "expected a static collection") 60 }) 61 62 t.Run("Invalid membership policy", func(t *testing.T) { 63 collections := &peer.CollectionConfigPackage{} 64 collections.Config = []*peer.CollectionConfig{ 65 { 66 Payload: &peer.CollectionConfig_StaticCollectionConfig{ 67 StaticCollectionConfig: &peer.StaticCollectionConfig{ 68 Name: "foo", 69 }, 70 }, 71 }, 72 } 73 filter, err := principalsFromCollectionConfig(collections) 74 assert.Nil(t, filter) 75 assert.Contains(t, err.Error(), "MemberOrgsPolicy of foo is nil") 76 }) 77 78 t.Run("Missing policy", func(t *testing.T) { 79 collections := &peer.CollectionConfigPackage{} 80 collections.Config = []*peer.CollectionConfig{ 81 { 82 Payload: &peer.CollectionConfig_StaticCollectionConfig{ 83 StaticCollectionConfig: &peer.StaticCollectionConfig{ 84 Name: "foo", 85 MemberOrgsPolicy: &peer.CollectionPolicyConfig{}, 86 }, 87 }, 88 }, 89 } 90 filter, err := principalsFromCollectionConfig(collections) 91 assert.Nil(t, filter) 92 assert.Contains(t, err.Error(), "policy of foo is nil") 93 }) 94 } 95 96 func TestToIdentityFilter(t *testing.T) { 97 col2principals := make(principalSetsByCollectionName) 98 col2principals["foo"] = []*msp.MSPPrincipal{orgPrincipal("Org1MSP"), orgPrincipal("Org2MSP")} 99 100 t.Run("collection doesn't exist in mapping", func(t *testing.T) { 101 filter, err := col2principals.toIdentityFilter("mychannel", &principalEvaluatorMock{}, &discovery.ChaincodeCall{ 102 Name: "mycc", 103 CollectionNames: []string{"bar"}, 104 }) 105 assert.Nil(t, filter) 106 assert.Equal(t, "collection bar doesn't exist in collection config for chaincode mycc", err.Error()) 107 }) 108 109 t.Run("collection exists in mapping", func(t *testing.T) { 110 filter, err := col2principals.toIdentityFilter("mychannel", &principalEvaluatorMock{}, &discovery.ChaincodeCall{ 111 Name: "mycc", 112 CollectionNames: []string{"foo"}, 113 }) 114 assert.NoError(t, err) 115 identity := protoutil.MarshalOrPanic(&msp.SerializedIdentity{ 116 Mspid: "Org2MSP", 117 }) 118 assert.True(t, filter(identity)) 119 identity = protoutil.MarshalOrPanic(&msp.SerializedIdentity{ 120 Mspid: "Org3MSP", 121 }) 122 assert.False(t, filter(identity)) 123 }) 124 } 125 126 func TestCombine(t *testing.T) { 127 filter1 := identityFilter(func(identity api.PeerIdentityType) bool { 128 return bytes.Equal([]byte("p1"), identity) || bytes.Equal([]byte("p2"), identity) 129 }) 130 131 filter2 := identityFilter(func(identity api.PeerIdentityType) bool { 132 return bytes.Equal([]byte("p2"), identity) || bytes.Equal([]byte("p3"), identity) 133 }) 134 135 filter := identityFilters{filter1, filter2}.combine() 136 assert.False(t, filter(api.PeerIdentityType("p1"))) 137 assert.True(t, filter(api.PeerIdentityType("p2"))) 138 assert.False(t, filter(api.PeerIdentityType("p3"))) 139 assert.False(t, filter(api.PeerIdentityType("p4"))) 140 } 141 142 func TestToMemberFilter(t *testing.T) { 143 unauthorizedIdentity := api.PeerIdentityType("unauthorizedIdentity") 144 authorizedIdentity := api.PeerIdentityType("authorizedIdentity") 145 notPresentIdentity := api.PeerIdentityType("api.PeerIdentityInfo") 146 147 filter := identityFilter(func(identity api.PeerIdentityType) bool { 148 return bytes.Equal(authorizedIdentity, identity) 149 }) 150 identityInfoByID := map[string]api.PeerIdentityInfo{ 151 "authorizedIdentity": {PKIId: gcommon.PKIidType(authorizedIdentity), Identity: authorizedIdentity}, 152 "unauthorizedIdentity": {PKIId: gcommon.PKIidType(unauthorizedIdentity), Identity: unauthorizedIdentity}, 153 } 154 memberFilter := filter.toMemberFilter(identityInfoByID) 155 156 t.Run("Member is authorized", func(t *testing.T) { 157 authorized := memberFilter(disc.NetworkMember{ 158 PKIid: gcommon.PKIidType(authorizedIdentity), 159 }) 160 assert.True(t, authorized) 161 }) 162 163 t.Run("Member is unauthorized", func(t *testing.T) { 164 authorized := memberFilter(disc.NetworkMember{ 165 PKIid: gcommon.PKIidType(unauthorizedIdentity), 166 }) 167 assert.False(t, authorized) 168 }) 169 170 t.Run("Member is not found in mapping", func(t *testing.T) { 171 authorized := memberFilter(disc.NetworkMember{ 172 PKIid: gcommon.PKIidType(notPresentIdentity), 173 }) 174 assert.False(t, authorized) 175 }) 176 177 } 178 179 func TestIsIdentityAuthorizedByPrincipalSet(t *testing.T) { 180 principals := []*msp.MSPPrincipal{orgPrincipal("Org1MSP"), orgPrincipal("Org2MSP")} 181 t.Run("Authorized", func(t *testing.T) { 182 identity := protoutil.MarshalOrPanic(&msp.SerializedIdentity{ 183 Mspid: "Org1MSP", 184 }) 185 authorized := isIdentityAuthorizedByPrincipalSet("mychannel", &principalEvaluatorMock{}, principals, identity) 186 assert.True(t, authorized) 187 }) 188 189 t.Run("Unauthorized", func(t *testing.T) { 190 identity := protoutil.MarshalOrPanic(&msp.SerializedIdentity{ 191 Mspid: "Org3MSP", 192 }) 193 authorized := isIdentityAuthorizedByPrincipalSet("mychannel", &principalEvaluatorMock{}, principals, identity) 194 assert.False(t, authorized) 195 }) 196 } 197 198 func TestFilterForPrincipalSets(t *testing.T) { 199 org1AndOrg2 := []*msp.MSPPrincipal{orgPrincipal("Org1MSP"), orgPrincipal("Org2MSP")} 200 org2AndOrg3 := []*msp.MSPPrincipal{orgPrincipal("Org2MSP"), orgPrincipal("Org3MSP")} 201 org3AndOrg4 := []*msp.MSPPrincipal{orgPrincipal("Org3MSP"), orgPrincipal("Org4MSP")} 202 203 identity := protoutil.MarshalOrPanic(&msp.SerializedIdentity{ 204 Mspid: "Org2MSP", 205 }) 206 207 t.Run("Identity is authorized by all principals", func(t *testing.T) { 208 filter := filterForPrincipalSets("mychannel", &principalEvaluatorMock{}, policies.PrincipalSets{org1AndOrg2, org2AndOrg3}) 209 assert.True(t, filter(identity)) 210 }) 211 212 t.Run("Identity is not authorized by all principals", func(t *testing.T) { 213 filter := filterForPrincipalSets("mychannel", &principalEvaluatorMock{}, policies.PrincipalSets{org1AndOrg2, org3AndOrg4}) 214 assert.False(t, filter(identity)) 215 }) 216 } 217 218 func buildCollectionConfig(col2principals map[string][]*msp.MSPPrincipal) *peer.CollectionConfigPackage { 219 collections := &peer.CollectionConfigPackage{} 220 for col, principals := range col2principals { 221 collections.Config = append(collections.Config, &peer.CollectionConfig{ 222 Payload: &peer.CollectionConfig_StaticCollectionConfig{ 223 StaticCollectionConfig: &peer.StaticCollectionConfig{ 224 Name: col, 225 MemberOrgsPolicy: &peer.CollectionPolicyConfig{ 226 Payload: &peer.CollectionPolicyConfig_SignaturePolicy{ 227 SignaturePolicy: &common.SignaturePolicyEnvelope{ 228 Identities: principals, 229 }, 230 }, 231 }, 232 }, 233 }, 234 }) 235 } 236 237 return collections 238 } 239 240 func orgPrincipal(mspID string) *msp.MSPPrincipal { 241 return &msp.MSPPrincipal{ 242 PrincipalClassification: msp.MSPPrincipal_ROLE, 243 Principal: protoutil.MarshalOrPanic(&msp.MSPRole{ 244 MspIdentifier: mspID, 245 Role: msp.MSPRole_PEER, 246 }), 247 } 248 } 249 250 func assertEqualPrincipalSets(t *testing.T, ps1, ps2 policies.PrincipalSet) { 251 ps1s := fmt.Sprintf("%v", ps1) 252 ps2s := fmt.Sprintf("%v", ps2) 253 assert.Equal(t, ps1s, ps2s) 254 }