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