github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-config/configtx/internal/policydsl/policyparser_test.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package policydsl_test
     8  
     9  import (
    10  	"github.com/hellobchain/third_party/hyperledger/fabric-config/configtx/internal/policydsl"
    11  	"testing"
    12  
    13  	"github.com/golang/protobuf/proto"
    14  	cb "github.com/hyperledger/fabric-protos-go/common"
    15  	mb "github.com/hyperledger/fabric-protos-go/msp"
    16  
    17  	. "github.com/onsi/gomega"
    18  )
    19  
    20  func TestOutOf1(t *testing.T) {
    21  	gt := NewGomegaWithT(t)
    22  
    23  	p1, err := policydsl.FromString("OutOf(1, 'A.member', 'B.member')")
    24  	gt.Expect(err).NotTo(HaveOccurred())
    25  
    26  	principals := make([]*mb.MSPPrincipal, 0)
    27  
    28  	principals = append(principals, &mb.MSPPrincipal{
    29  		PrincipalClassification: mb.MSPPrincipal_ROLE,
    30  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}),
    31  	})
    32  
    33  	principals = append(principals, &mb.MSPPrincipal{
    34  		PrincipalClassification: mb.MSPPrincipal_ROLE,
    35  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}),
    36  	})
    37  
    38  	p2 := &cb.SignaturePolicyEnvelope{
    39  		Version:    0,
    40  		Rule:       policydsl.NOutOf(1, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1)}),
    41  		Identities: principals,
    42  	}
    43  
    44  	gt.Expect(p1).To(Equal(p2))
    45  }
    46  
    47  func TestOutOf2(t *testing.T) {
    48  	gt := NewGomegaWithT(t)
    49  
    50  	p1, err := policydsl.FromString("OutOf(2, 'A.member', 'B.member')")
    51  	gt.Expect(err).NotTo(HaveOccurred())
    52  
    53  	principals := make([]*mb.MSPPrincipal, 0)
    54  
    55  	principals = append(principals, &mb.MSPPrincipal{
    56  		PrincipalClassification: mb.MSPPrincipal_ROLE,
    57  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}),
    58  	})
    59  
    60  	principals = append(principals, &mb.MSPPrincipal{
    61  		PrincipalClassification: mb.MSPPrincipal_ROLE,
    62  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}),
    63  	})
    64  
    65  	p2 := &cb.SignaturePolicyEnvelope{
    66  		Version:    0,
    67  		Rule:       policydsl.NOutOf(2, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1)}),
    68  		Identities: principals,
    69  	}
    70  
    71  	gt.Expect(p1).To(Equal(p2))
    72  }
    73  
    74  func TestAnd(t *testing.T) {
    75  	gt := NewGomegaWithT(t)
    76  
    77  	p1, err := policydsl.FromString("AND('A.member', 'B.member')")
    78  	gt.Expect(err).NotTo(HaveOccurred())
    79  
    80  	principals := make([]*mb.MSPPrincipal, 0)
    81  
    82  	principals = append(principals, &mb.MSPPrincipal{
    83  		PrincipalClassification: mb.MSPPrincipal_ROLE,
    84  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}),
    85  	})
    86  
    87  	principals = append(principals, &mb.MSPPrincipal{
    88  		PrincipalClassification: mb.MSPPrincipal_ROLE,
    89  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}),
    90  	})
    91  
    92  	p2 := &cb.SignaturePolicyEnvelope{
    93  		Version:    0,
    94  		Rule:       policydsl.And(policydsl.SignedBy(0), policydsl.SignedBy(1)),
    95  		Identities: principals,
    96  	}
    97  
    98  	gt.Expect(p1).To(Equal(p2))
    99  }
   100  
   101  func TestAndClientPeerOrderer(t *testing.T) {
   102  	gt := NewGomegaWithT(t)
   103  
   104  	p1, err := policydsl.FromString("AND('A.client', 'B.peer')")
   105  	gt.Expect(err).NotTo(HaveOccurred())
   106  
   107  	principals := make([]*mb.MSPPrincipal, 0)
   108  
   109  	principals = append(principals, &mb.MSPPrincipal{
   110  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   111  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_CLIENT, MspIdentifier: "A"}),
   112  	})
   113  
   114  	principals = append(principals, &mb.MSPPrincipal{
   115  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   116  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_PEER, MspIdentifier: "B"}),
   117  	})
   118  
   119  	p2 := &cb.SignaturePolicyEnvelope{
   120  		Version:    0,
   121  		Rule:       policydsl.And(policydsl.SignedBy(0), policydsl.SignedBy(1)),
   122  		Identities: principals,
   123  	}
   124  
   125  	gt.Expect(p1).To(Equal(p2))
   126  }
   127  
   128  func TestOr(t *testing.T) {
   129  	gt := NewGomegaWithT(t)
   130  
   131  	p1, err := policydsl.FromString("OR('A.member', 'B.member')")
   132  	gt.Expect(err).NotTo(HaveOccurred())
   133  
   134  	principals := make([]*mb.MSPPrincipal, 0)
   135  
   136  	principals = append(principals, &mb.MSPPrincipal{
   137  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   138  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}),
   139  	})
   140  
   141  	principals = append(principals, &mb.MSPPrincipal{
   142  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   143  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}),
   144  	})
   145  
   146  	p2 := &cb.SignaturePolicyEnvelope{
   147  		Version:    0,
   148  		Rule:       policydsl.Or(policydsl.SignedBy(0), policydsl.SignedBy(1)),
   149  		Identities: principals,
   150  	}
   151  
   152  	gt.Expect(p1).To(Equal(p2))
   153  }
   154  
   155  func TestComplex1(t *testing.T) {
   156  	gt := NewGomegaWithT(t)
   157  
   158  	p1, err := policydsl.FromString("OR('A.member', AND('B.member', 'C.member'))")
   159  	gt.Expect(err).NotTo(HaveOccurred())
   160  
   161  	principals := make([]*mb.MSPPrincipal, 0)
   162  
   163  	principals = append(principals, &mb.MSPPrincipal{
   164  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   165  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}),
   166  	})
   167  
   168  	principals = append(principals, &mb.MSPPrincipal{
   169  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   170  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "C"}),
   171  	})
   172  
   173  	principals = append(principals, &mb.MSPPrincipal{
   174  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   175  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}),
   176  	})
   177  
   178  	p2 := &cb.SignaturePolicyEnvelope{
   179  		Version:    0,
   180  		Rule:       policydsl.Or(policydsl.SignedBy(2), policydsl.And(policydsl.SignedBy(0), policydsl.SignedBy(1))),
   181  		Identities: principals,
   182  	}
   183  
   184  	gt.Expect(p1).To(Equal(p2))
   185  }
   186  
   187  func TestComplex2(t *testing.T) {
   188  	gt := NewGomegaWithT(t)
   189  
   190  	p1, err := policydsl.FromString("OR(AND('A.member', 'B.member'), OR('C.admin', 'D.member'))")
   191  	gt.Expect(err).NotTo(HaveOccurred())
   192  
   193  	principals := make([]*mb.MSPPrincipal, 0)
   194  
   195  	principals = append(principals, &mb.MSPPrincipal{
   196  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   197  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}),
   198  	})
   199  
   200  	principals = append(principals, &mb.MSPPrincipal{
   201  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   202  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}),
   203  	})
   204  
   205  	principals = append(principals, &mb.MSPPrincipal{
   206  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   207  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_ADMIN, MspIdentifier: "C"}),
   208  	})
   209  
   210  	principals = append(principals, &mb.MSPPrincipal{
   211  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   212  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "D"}),
   213  	})
   214  
   215  	p2 := &cb.SignaturePolicyEnvelope{
   216  		Version:    0,
   217  		Rule:       policydsl.Or(policydsl.And(policydsl.SignedBy(0), policydsl.SignedBy(1)), policydsl.Or(policydsl.SignedBy(2), policydsl.SignedBy(3))),
   218  		Identities: principals,
   219  	}
   220  
   221  	gt.Expect(p1).To(Equal(p2))
   222  }
   223  
   224  func TestMSPIDWIthSpecialChars(t *testing.T) {
   225  	gt := NewGomegaWithT(t)
   226  
   227  	p1, err := policydsl.FromString("OR('MSP.member', 'MSP.WITH.DOTS.member', 'MSP-WITH-DASHES.member')")
   228  	gt.Expect(err).NotTo(HaveOccurred())
   229  
   230  	principals := make([]*mb.MSPPrincipal, 0)
   231  
   232  	principals = append(principals, &mb.MSPPrincipal{
   233  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   234  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "MSP"}),
   235  	})
   236  
   237  	principals = append(principals, &mb.MSPPrincipal{
   238  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   239  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "MSP.WITH.DOTS"}),
   240  	})
   241  
   242  	principals = append(principals, &mb.MSPPrincipal{
   243  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   244  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "MSP-WITH-DASHES"}),
   245  	})
   246  
   247  	p2 := &cb.SignaturePolicyEnvelope{
   248  		Version:    0,
   249  		Rule:       policydsl.NOutOf(1, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1), policydsl.SignedBy(2)}),
   250  		Identities: principals,
   251  	}
   252  
   253  	gt.Expect(p1).To(Equal(p2))
   254  }
   255  
   256  func TestBadStringsNoPanic(t *testing.T) {
   257  	gt := NewGomegaWithT(t)
   258  
   259  	_, err := policydsl.FromString("OR('A.member', Bmember)") // error after 1st Evaluate()
   260  	gt.Expect(err).To(MatchError("unrecognized token 'Bmember' in policy string"))
   261  
   262  	_, err = policydsl.FromString("OR('A.member', 'Bmember')") // error after 2nd Evalute()
   263  	gt.Expect(err).To(MatchError("unrecognized token 'Bmember' in policy string"))
   264  
   265  	_, err = policydsl.FromString(`OR('A.member', '\'Bmember\'')`) // error after 3rd Evalute()
   266  	gt.Expect(err).To(MatchError("unrecognized token 'Bmember' in policy string"))
   267  }
   268  
   269  func TestNodeOUs(t *testing.T) {
   270  	gt := NewGomegaWithT(t)
   271  
   272  	p1, err := policydsl.FromString("OR('A.peer', 'B.admin', 'C.orderer', 'D.client')")
   273  	gt.Expect(err).NotTo(HaveOccurred())
   274  
   275  	principals := make([]*mb.MSPPrincipal, 0)
   276  
   277  	principals = append(principals, &mb.MSPPrincipal{
   278  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   279  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_PEER, MspIdentifier: "A"}),
   280  	})
   281  
   282  	principals = append(principals, &mb.MSPPrincipal{
   283  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   284  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_ADMIN, MspIdentifier: "B"}),
   285  	})
   286  
   287  	principals = append(principals, &mb.MSPPrincipal{
   288  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   289  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_ORDERER, MspIdentifier: "C"}),
   290  	})
   291  
   292  	principals = append(principals, &mb.MSPPrincipal{
   293  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   294  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_CLIENT, MspIdentifier: "D"}),
   295  	})
   296  
   297  	p2 := &cb.SignaturePolicyEnvelope{
   298  		Version:    0,
   299  		Rule:       policydsl.NOutOf(1, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1), policydsl.SignedBy(2), policydsl.SignedBy(3)}),
   300  		Identities: principals,
   301  	}
   302  
   303  	gt.Expect(p1).To(Equal(p2))
   304  }
   305  
   306  func TestOutOfNumIsString(t *testing.T) {
   307  	gt := NewGomegaWithT(t)
   308  
   309  	p1, err := policydsl.FromString("OutOf('1', 'A.member', 'B.member')")
   310  	gt.Expect(err).NotTo(HaveOccurred())
   311  
   312  	principals := make([]*mb.MSPPrincipal, 0)
   313  
   314  	principals = append(principals, &mb.MSPPrincipal{
   315  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   316  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}),
   317  	})
   318  
   319  	principals = append(principals, &mb.MSPPrincipal{
   320  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   321  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}),
   322  	})
   323  
   324  	p2 := &cb.SignaturePolicyEnvelope{
   325  		Version:    0,
   326  		Rule:       policydsl.NOutOf(1, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1)}),
   327  		Identities: principals,
   328  	}
   329  
   330  	gt.Expect(p1).To(Equal(p2))
   331  }
   332  
   333  func TestOutOfErrorCase(t *testing.T) {
   334  	tests := []struct {
   335  		testName     string
   336  		policyString string
   337  		expectedErr  string
   338  	}{
   339  		{
   340  			testName:     "1st NewEvaluableExpressionWithFunctions() returns an error",
   341  			policyString: "",
   342  			expectedErr:  "Unexpected end of expression",
   343  		},
   344  		{
   345  			testName:     "outof() if len(args)<2",
   346  			policyString: "OutOf(1)",
   347  			expectedErr:  "expected at least two arguments to NOutOf. Given 1",
   348  		},
   349  		{
   350  			testName:     "outof() }else{. 1st arg is non of float, int, string",
   351  			policyString: "OutOf(true, 'A.member')",
   352  			expectedErr:  "unexpected type bool",
   353  		},
   354  		{
   355  			testName:     "oufof() switch default. 2nd arg is not string.",
   356  			policyString: "OutOf(1, 2)",
   357  			expectedErr:  "unexpected type float64",
   358  		},
   359  		{
   360  			testName:     "firstPass() switch default",
   361  			policyString: "OutOf(1, 'true')",
   362  			expectedErr:  "unexpected type bool",
   363  		},
   364  		{
   365  			testName:     "secondPass() switch args[1].(type) default",
   366  			policyString: `OutOf('\'\\\'A\\\'\'', 'B.member')`,
   367  			expectedErr:  "unrecognized type, expected a number, got string",
   368  		},
   369  		{
   370  			testName:     "secondPass() switch args[1].(type) default",
   371  			policyString: `OutOf(1, '\'1\'')`,
   372  			expectedErr:  "unrecognized type, expected a principal or a policy, got float64",
   373  		},
   374  		{
   375  			testName:     "2nd NewEvaluateExpressionWithFunction() returns an error",
   376  			policyString: `''`,
   377  			expectedErr:  "Unexpected end of expression",
   378  		},
   379  		{
   380  			testName:     "3rd NewEvaluateExpressionWithFunction() returns an error",
   381  			policyString: `'\'\''`,
   382  			expectedErr:  "Unexpected end of expression",
   383  		},
   384  	}
   385  
   386  	for _, tt := range tests {
   387  		t.Run(tt.testName, func(t *testing.T) {
   388  			gt := NewGomegaWithT(t)
   389  
   390  			p, err := policydsl.FromString(tt.policyString)
   391  			gt.Expect(p).To(BeNil())
   392  			gt.Expect(err).To(MatchError(tt.expectedErr))
   393  		})
   394  	}
   395  }
   396  
   397  func TestBadStringBeforeFAB11404_ThisCanDeleteAfterFAB11404HasMerged(t *testing.T) {
   398  	tests := []struct {
   399  		testName     string
   400  		policyString string
   401  		expectedErr  string
   402  	}{
   403  		{
   404  			testName:     "integer in string",
   405  			policyString: "1",
   406  			expectedErr:  `invalid policy string '1'`,
   407  		},
   408  		{
   409  			testName:     "quoted integer in string",
   410  			policyString: "'1'",
   411  			expectedErr:  `invalid policy string ''1''`,
   412  		},
   413  		{
   414  			testName:     "nested quoted integer in string",
   415  			policyString: `'\'1\''`,
   416  			expectedErr:  `invalid policy string ''\'1\'''`,
   417  		},
   418  	}
   419  
   420  	for _, tt := range tests {
   421  		t.Run(tt.testName, func(t *testing.T) {
   422  			gt := NewGomegaWithT(t)
   423  
   424  			p, err := policydsl.FromString(tt.policyString)
   425  			gt.Expect(p).To(BeNil())
   426  			gt.Expect(err).To(MatchError(tt.expectedErr))
   427  		})
   428  	}
   429  }
   430  
   431  func TestSecondPassBoundaryCheck(t *testing.T) {
   432  	gt := NewGomegaWithT(t)
   433  
   434  	// Check lower boundary
   435  	// Prohibit t<0
   436  	p0, err0 := policydsl.FromString("OutOf(-1, 'A.member', 'B.member')")
   437  	gt.Expect(p0).To(BeNil())
   438  	gt.Expect(err0).To(MatchError("invalid t-out-of-n predicate, t -1, n 2"))
   439  
   440  	// Permit t==0 : always satisfied policy
   441  	// There is no clear usecase of t=0, but somebody may already use it, so we don't treat as an error.
   442  	p1, err1 := policydsl.FromString("OutOf(0, 'A.member', 'B.member')")
   443  	gt.Expect(err1).NotTo(HaveOccurred())
   444  	principals := make([]*mb.MSPPrincipal, 0)
   445  	principals = append(principals, &mb.MSPPrincipal{
   446  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   447  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}),
   448  	})
   449  	principals = append(principals, &mb.MSPPrincipal{
   450  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   451  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}),
   452  	})
   453  	expected1 := &cb.SignaturePolicyEnvelope{
   454  		Version:    0,
   455  		Rule:       policydsl.NOutOf(0, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1)}),
   456  		Identities: principals,
   457  	}
   458  	gt.Expect(p1).To(Equal(expected1))
   459  
   460  	// Check upper boundary
   461  	// Permit t==n+1 : never satisfied policy
   462  	// Usecase: To create immutable ledger key
   463  	p2, err2 := policydsl.FromString("OutOf(3, 'A.member', 'B.member')")
   464  	gt.Expect(err2).NotTo(HaveOccurred())
   465  	expected2 := &cb.SignaturePolicyEnvelope{
   466  		Version:    0,
   467  		Rule:       policydsl.NOutOf(3, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1)}),
   468  		Identities: principals,
   469  	}
   470  	gt.Expect(p2).To(Equal(expected2))
   471  
   472  	// Prohibit t>n + 1
   473  	p3, err3 := policydsl.FromString("OutOf(4, 'A.member', 'B.member')")
   474  	gt.Expect(p3).To(BeNil())
   475  	gt.Expect(err3).To(MatchError("invalid t-out-of-n predicate, t 4, n 2"))
   476  }
   477  
   478  // protoMarshalOrPanic serializes a protobuf message and panics if this
   479  // operation fails
   480  func protoMarshalOrPanic(pb proto.Message) []byte {
   481  	data, err := proto.Marshal(pb)
   482  	if err != nil {
   483  		panic(err)
   484  	}
   485  
   486  	return data
   487  }