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  }