github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/common/cauthdsl/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 cauthdsl
     8  
     9  import (
    10  	"reflect"
    11  	"testing"
    12  
    13  	"github.com/hyperledger/fabric-protos-go/common"
    14  	"github.com/hyperledger/fabric-protos-go/msp"
    15  	"github.com/hyperledger/fabric/protoutil"
    16  	"github.com/stretchr/testify/assert"
    17  )
    18  
    19  func TestOutOf1(t *testing.T) {
    20  	p1, err := FromString("OutOf(1, 'A.member', 'B.member')")
    21  	assert.NoError(t, err)
    22  
    23  	principals := make([]*msp.MSPPrincipal, 0)
    24  
    25  	principals = append(principals, &msp.MSPPrincipal{
    26  		PrincipalClassification: msp.MSPPrincipal_ROLE,
    27  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"})})
    28  
    29  	principals = append(principals, &msp.MSPPrincipal{
    30  		PrincipalClassification: msp.MSPPrincipal_ROLE,
    31  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"})})
    32  
    33  	p2 := &common.SignaturePolicyEnvelope{
    34  		Version:    0,
    35  		Rule:       NOutOf(1, []*common.SignaturePolicy{SignedBy(0), SignedBy(1)}),
    36  		Identities: principals,
    37  	}
    38  
    39  	assert.Equal(t, p1, p2)
    40  }
    41  
    42  func TestOutOf2(t *testing.T) {
    43  	p1, err := FromString("OutOf(2, 'A.member', 'B.member')")
    44  	assert.NoError(t, err)
    45  
    46  	principals := make([]*msp.MSPPrincipal, 0)
    47  
    48  	principals = append(principals, &msp.MSPPrincipal{
    49  		PrincipalClassification: msp.MSPPrincipal_ROLE,
    50  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"})})
    51  
    52  	principals = append(principals, &msp.MSPPrincipal{
    53  		PrincipalClassification: msp.MSPPrincipal_ROLE,
    54  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"})})
    55  
    56  	p2 := &common.SignaturePolicyEnvelope{
    57  		Version:    0,
    58  		Rule:       NOutOf(2, []*common.SignaturePolicy{SignedBy(0), SignedBy(1)}),
    59  		Identities: principals,
    60  	}
    61  
    62  	assert.Equal(t, p1, p2)
    63  }
    64  
    65  func TestAnd(t *testing.T) {
    66  	p1, err := FromString("AND('A.member', 'B.member')")
    67  	assert.NoError(t, err)
    68  
    69  	principals := make([]*msp.MSPPrincipal, 0)
    70  
    71  	principals = append(principals, &msp.MSPPrincipal{
    72  		PrincipalClassification: msp.MSPPrincipal_ROLE,
    73  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"})})
    74  
    75  	principals = append(principals, &msp.MSPPrincipal{
    76  		PrincipalClassification: msp.MSPPrincipal_ROLE,
    77  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"})})
    78  
    79  	p2 := &common.SignaturePolicyEnvelope{
    80  		Version:    0,
    81  		Rule:       And(SignedBy(0), SignedBy(1)),
    82  		Identities: principals,
    83  	}
    84  
    85  	assert.Equal(t, p1, p2)
    86  }
    87  
    88  func TestAndClientPeerOrderer(t *testing.T) {
    89  	p1, err := FromString("AND('A.client', 'B.peer')")
    90  	assert.NoError(t, err)
    91  
    92  	principals := make([]*msp.MSPPrincipal, 0)
    93  
    94  	principals = append(principals, &msp.MSPPrincipal{
    95  		PrincipalClassification: msp.MSPPrincipal_ROLE,
    96  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_CLIENT, MspIdentifier: "A"})})
    97  
    98  	principals = append(principals, &msp.MSPPrincipal{
    99  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   100  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_PEER, MspIdentifier: "B"})})
   101  
   102  	p2 := &common.SignaturePolicyEnvelope{
   103  		Version:    0,
   104  		Rule:       And(SignedBy(0), SignedBy(1)),
   105  		Identities: principals,
   106  	}
   107  
   108  	assert.True(t, reflect.DeepEqual(p1, p2))
   109  
   110  }
   111  
   112  func TestOr(t *testing.T) {
   113  	p1, err := FromString("OR('A.member', 'B.member')")
   114  	assert.NoError(t, err)
   115  
   116  	principals := make([]*msp.MSPPrincipal, 0)
   117  
   118  	principals = append(principals, &msp.MSPPrincipal{
   119  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   120  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"})})
   121  
   122  	principals = append(principals, &msp.MSPPrincipal{
   123  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   124  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"})})
   125  
   126  	p2 := &common.SignaturePolicyEnvelope{
   127  		Version:    0,
   128  		Rule:       Or(SignedBy(0), SignedBy(1)),
   129  		Identities: principals,
   130  	}
   131  
   132  	assert.Equal(t, p1, p2)
   133  }
   134  
   135  func TestComplex1(t *testing.T) {
   136  	p1, err := FromString("OR('A.member', AND('B.member', 'C.member'))")
   137  	assert.NoError(t, err)
   138  
   139  	principals := make([]*msp.MSPPrincipal, 0)
   140  
   141  	principals = append(principals, &msp.MSPPrincipal{
   142  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   143  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"})})
   144  
   145  	principals = append(principals, &msp.MSPPrincipal{
   146  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   147  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "C"})})
   148  
   149  	principals = append(principals, &msp.MSPPrincipal{
   150  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   151  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"})})
   152  
   153  	p2 := &common.SignaturePolicyEnvelope{
   154  		Version:    0,
   155  		Rule:       Or(SignedBy(2), And(SignedBy(0), SignedBy(1))),
   156  		Identities: principals,
   157  	}
   158  
   159  	assert.Equal(t, p1, p2)
   160  }
   161  
   162  func TestComplex2(t *testing.T) {
   163  	p1, err := FromString("OR(AND('A.member', 'B.member'), OR('C.admin', 'D.member'))")
   164  	assert.NoError(t, err)
   165  
   166  	principals := make([]*msp.MSPPrincipal, 0)
   167  
   168  	principals = append(principals, &msp.MSPPrincipal{
   169  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   170  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"})})
   171  
   172  	principals = append(principals, &msp.MSPPrincipal{
   173  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   174  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"})})
   175  
   176  	principals = append(principals, &msp.MSPPrincipal{
   177  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   178  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_ADMIN, MspIdentifier: "C"})})
   179  
   180  	principals = append(principals, &msp.MSPPrincipal{
   181  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   182  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "D"})})
   183  
   184  	p2 := &common.SignaturePolicyEnvelope{
   185  		Version:    0,
   186  		Rule:       Or(And(SignedBy(0), SignedBy(1)), Or(SignedBy(2), SignedBy(3))),
   187  		Identities: principals,
   188  	}
   189  
   190  	assert.Equal(t, p1, p2)
   191  }
   192  
   193  func TestMSPIDWIthSpecialChars(t *testing.T) {
   194  	p1, err := FromString("OR('MSP.member', 'MSP.WITH.DOTS.member', 'MSP-WITH-DASHES.member')")
   195  	assert.NoError(t, err)
   196  
   197  	principals := make([]*msp.MSPPrincipal, 0)
   198  
   199  	principals = append(principals, &msp.MSPPrincipal{
   200  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   201  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "MSP"})})
   202  
   203  	principals = append(principals, &msp.MSPPrincipal{
   204  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   205  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "MSP.WITH.DOTS"})})
   206  
   207  	principals = append(principals, &msp.MSPPrincipal{
   208  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   209  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "MSP-WITH-DASHES"})})
   210  
   211  	p2 := &common.SignaturePolicyEnvelope{
   212  		Version:    0,
   213  		Rule:       NOutOf(1, []*common.SignaturePolicy{SignedBy(0), SignedBy(1), SignedBy(2)}),
   214  		Identities: principals,
   215  	}
   216  
   217  	assert.Equal(t, p1, p2)
   218  }
   219  
   220  func TestBadStringsNoPanic(t *testing.T) {
   221  	_, err := FromString("OR('A.member', Bmember)") // error after 1st Evaluate()
   222  	assert.EqualError(t, err, "unrecognized token 'Bmember' in policy string")
   223  
   224  	_, err = FromString("OR('A.member', 'Bmember')") // error after 2nd Evalute()
   225  	assert.EqualError(t, err, "unrecognized token 'Bmember' in policy string")
   226  
   227  	_, err = FromString(`OR('A.member', '\'Bmember\'')`) // error after 3rd Evalute()
   228  	assert.EqualError(t, err, "unrecognized token 'Bmember' in policy string")
   229  }
   230  
   231  func TestNodeOUs(t *testing.T) {
   232  	p1, err := FromString("OR('A.peer', 'B.admin', 'C.orderer', 'D.client')")
   233  	assert.NoError(t, err)
   234  
   235  	principals := make([]*msp.MSPPrincipal, 0)
   236  
   237  	principals = append(principals, &msp.MSPPrincipal{
   238  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   239  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_PEER, MspIdentifier: "A"})})
   240  
   241  	principals = append(principals, &msp.MSPPrincipal{
   242  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   243  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_ADMIN, MspIdentifier: "B"})})
   244  
   245  	principals = append(principals, &msp.MSPPrincipal{
   246  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   247  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_ORDERER, MspIdentifier: "C"})})
   248  
   249  	principals = append(principals, &msp.MSPPrincipal{
   250  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   251  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_CLIENT, MspIdentifier: "D"})})
   252  
   253  	p2 := &common.SignaturePolicyEnvelope{
   254  		Version:    0,
   255  		Rule:       NOutOf(1, []*common.SignaturePolicy{SignedBy(0), SignedBy(1), SignedBy(2), SignedBy(3)}),
   256  		Identities: principals,
   257  	}
   258  
   259  	assert.Equal(t, p1, p2)
   260  }
   261  
   262  func TestOutOfNumIsString(t *testing.T) {
   263  	p1, err := FromString("OutOf('1', 'A.member', 'B.member')")
   264  	assert.NoError(t, err)
   265  
   266  	principals := make([]*msp.MSPPrincipal, 0)
   267  
   268  	principals = append(principals, &msp.MSPPrincipal{
   269  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   270  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"})})
   271  
   272  	principals = append(principals, &msp.MSPPrincipal{
   273  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   274  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"})})
   275  
   276  	p2 := &common.SignaturePolicyEnvelope{
   277  		Version:    0,
   278  		Rule:       NOutOf(1, []*common.SignaturePolicy{SignedBy(0), SignedBy(1)}),
   279  		Identities: principals,
   280  	}
   281  
   282  	assert.Equal(t, p1, p2)
   283  }
   284  
   285  func TestOutOfErrorCase(t *testing.T) {
   286  	p1, err1 := FromString("") // 1st NewEvaluableExpressionWithFunctions() returns an error
   287  	assert.Nil(t, p1)
   288  	assert.EqualError(t, err1, "Unexpected end of expression")
   289  
   290  	p2, err2 := FromString("OutOf(1)") // outof() if len(args)<2
   291  	assert.Nil(t, p2)
   292  	assert.EqualError(t, err2, "Expected at least two arguments to NOutOf. Given 1")
   293  
   294  	p3, err3 := FromString("OutOf(true, 'A.member')") // outof() }else{. 1st arg is non of float, int, string
   295  	assert.Nil(t, p3)
   296  	assert.EqualError(t, err3, "Unexpected type bool")
   297  
   298  	p4, err4 := FromString("OutOf(1, 2)") // oufof() switch default. 2nd arg is not string.
   299  	assert.Nil(t, p4)
   300  	assert.EqualError(t, err4, "Unexpected type float64")
   301  
   302  	p5, err5 := FromString("OutOf(1, 'true')") // firstPass() switch default
   303  	assert.Nil(t, p5)
   304  	assert.EqualError(t, err5, "Unexpected type bool")
   305  
   306  	p6, err6 := FromString(`OutOf('\'\\\'A\\\'\'', 'B.member')`) // secondPass() switch args[1].(type) default
   307  	assert.Nil(t, p6)
   308  	assert.EqualError(t, err6, "Unrecognized type, expected a number, got string")
   309  
   310  	p7, err7 := FromString(`OutOf(1, '\'1\'')`) // secondPass() switch args[1].(type) default
   311  	assert.Nil(t, p7)
   312  	assert.EqualError(t, err7, "Unrecognized type, expected a principal or a policy, got float64")
   313  
   314  	p8, err8 := FromString(`''`) // 2nd NewEvaluateExpressionWithFunction() returns an error
   315  	assert.Nil(t, p8)
   316  	assert.EqualError(t, err8, "Unexpected end of expression")
   317  
   318  	p9, err9 := FromString(`'\'\''`) // 3rd NewEvaluateExpressionWithFunction() returns an error
   319  	assert.Nil(t, p9)
   320  	assert.EqualError(t, err9, "Unexpected end of expression")
   321  }
   322  
   323  func TestBadStringBeforeFAB11404_ThisCanDeleteAfterFAB11404HasMerged(t *testing.T) {
   324  	s1 := "1" // ineger in string
   325  	p1, err1 := FromString(s1)
   326  	assert.Nil(t, p1)
   327  	assert.EqualError(t, err1, `invalid policy string '1'`)
   328  
   329  	s2 := "'1'" // quoted ineger in string
   330  	p2, err2 := FromString(s2)
   331  	assert.Nil(t, p2)
   332  	assert.EqualError(t, err2, `invalid policy string ''1''`)
   333  
   334  	s3 := `'\'1\''` // nested quoted ineger in string
   335  	p3, err3 := FromString(s3)
   336  	assert.Nil(t, p3)
   337  	assert.EqualError(t, err3, `invalid policy string ''\'1\'''`)
   338  }
   339  
   340  func TestSecondPassBoundaryCheck(t *testing.T) {
   341  	// Check lower boundary
   342  	// Prohibit t<0
   343  	p0, err0 := FromString("OutOf(-1, 'A.member', 'B.member')")
   344  	assert.Nil(t, p0)
   345  	assert.EqualError(t, err0, "Invalid t-out-of-n predicate, t -1, n 2")
   346  
   347  	// Permit t==0 : always satisfied policy
   348  	// There is no clear usecase of t=0, but somebody may already use it, so we don't treat as an error.
   349  	p1, err1 := FromString("OutOf(0, 'A.member', 'B.member')")
   350  	assert.NoError(t, err1)
   351  	principals := make([]*msp.MSPPrincipal, 0)
   352  	principals = append(principals, &msp.MSPPrincipal{
   353  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   354  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"})})
   355  	principals = append(principals, &msp.MSPPrincipal{
   356  		PrincipalClassification: msp.MSPPrincipal_ROLE,
   357  		Principal:               protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"})})
   358  	expected1 := &common.SignaturePolicyEnvelope{
   359  		Version:    0,
   360  		Rule:       NOutOf(0, []*common.SignaturePolicy{SignedBy(0), SignedBy(1)}),
   361  		Identities: principals,
   362  	}
   363  	assert.Equal(t, expected1, p1)
   364  
   365  	// Check upper boundary
   366  	// Permit t==n+1 : never satisfied policy
   367  	// Usecase: To create immutable ledger key
   368  	p2, err2 := FromString("OutOf(3, 'A.member', 'B.member')")
   369  	assert.NoError(t, err2)
   370  	expected2 := &common.SignaturePolicyEnvelope{
   371  		Version:    0,
   372  		Rule:       NOutOf(3, []*common.SignaturePolicy{SignedBy(0), SignedBy(1)}),
   373  		Identities: principals,
   374  	}
   375  	assert.Equal(t, expected2, p2)
   376  
   377  	// Prohibit t>n + 1
   378  	p3, err3 := FromString("OutOf(4, 'A.member', 'B.member')")
   379  	assert.Nil(t, p3)
   380  	assert.EqualError(t, err3, "Invalid t-out-of-n predicate, t 4, n 2")
   381  }