go_study/fabric-main/common/policydsl/policyparser_test.go

409 lines
14 KiB
Go

/*
Copyright IBM Corp. 2017 All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package policydsl
import (
"reflect"
"testing"
"github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric-protos-go/msp"
"github.com/hyperledger/fabric/protoutil"
"github.com/stretchr/testify/require"
)
func TestOutOf1(t *testing.T) {
p1, err := FromString("OutOf(1, 'A.member', 'B.member')")
require.NoError(t, err)
principals := make([]*msp.MSPPrincipal, 0)
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"}),
})
p2 := &common.SignaturePolicyEnvelope{
Version: 0,
Rule: NOutOf(1, []*common.SignaturePolicy{SignedBy(0), SignedBy(1)}),
Identities: principals,
}
require.Equal(t, p1, p2)
}
func TestOutOf2(t *testing.T) {
p1, err := FromString("OutOf(2, 'A.member', 'B.member')")
require.NoError(t, err)
principals := make([]*msp.MSPPrincipal, 0)
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"}),
})
p2 := &common.SignaturePolicyEnvelope{
Version: 0,
Rule: NOutOf(2, []*common.SignaturePolicy{SignedBy(0), SignedBy(1)}),
Identities: principals,
}
require.Equal(t, p1, p2)
}
func TestAnd(t *testing.T) {
p1, err := FromString("AND('A.member', 'B.member')")
require.NoError(t, err)
principals := make([]*msp.MSPPrincipal, 0)
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"}),
})
p2 := &common.SignaturePolicyEnvelope{
Version: 0,
Rule: And(SignedBy(0), SignedBy(1)),
Identities: principals,
}
require.Equal(t, p1, p2)
}
func TestAndClientPeerOrderer(t *testing.T) {
p1, err := FromString("AND('A.client', 'B.peer')")
require.NoError(t, err)
principals := make([]*msp.MSPPrincipal, 0)
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_CLIENT, MspIdentifier: "A"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_PEER, MspIdentifier: "B"}),
})
p2 := &common.SignaturePolicyEnvelope{
Version: 0,
Rule: And(SignedBy(0), SignedBy(1)),
Identities: principals,
}
require.True(t, reflect.DeepEqual(p1, p2))
}
func TestOr(t *testing.T) {
p1, err := FromString("OR('A.member', 'B.member')")
require.NoError(t, err)
principals := make([]*msp.MSPPrincipal, 0)
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"}),
})
p2 := &common.SignaturePolicyEnvelope{
Version: 0,
Rule: Or(SignedBy(0), SignedBy(1)),
Identities: principals,
}
require.Equal(t, p1, p2)
}
func TestComplex1(t *testing.T) {
p1, err := FromString("OR('A.member', AND('B.member', 'C.member'))")
require.NoError(t, err)
principals := make([]*msp.MSPPrincipal, 0)
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "C"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"}),
})
p2 := &common.SignaturePolicyEnvelope{
Version: 0,
Rule: Or(SignedBy(2), And(SignedBy(0), SignedBy(1))),
Identities: principals,
}
require.Equal(t, p1, p2)
}
func TestComplex2(t *testing.T) {
p1, err := FromString("OR(AND('A.member', 'B.member'), OR('C.admin', 'D.member'))")
require.NoError(t, err)
principals := make([]*msp.MSPPrincipal, 0)
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_ADMIN, MspIdentifier: "C"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "D"}),
})
p2 := &common.SignaturePolicyEnvelope{
Version: 0,
Rule: Or(And(SignedBy(0), SignedBy(1)), Or(SignedBy(2), SignedBy(3))),
Identities: principals,
}
require.Equal(t, p1, p2)
}
func TestMSPIDWIthSpecialChars(t *testing.T) {
p1, err := FromString("OR('MSP.member', 'MSP.WITH.DOTS.member', 'MSP-WITH-DASHES.member')")
require.NoError(t, err)
principals := make([]*msp.MSPPrincipal, 0)
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "MSP"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "MSP.WITH.DOTS"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "MSP-WITH-DASHES"}),
})
p2 := &common.SignaturePolicyEnvelope{
Version: 0,
Rule: NOutOf(1, []*common.SignaturePolicy{SignedBy(0), SignedBy(1), SignedBy(2)}),
Identities: principals,
}
require.Equal(t, p1, p2)
}
func TestBadStringsNoPanic(t *testing.T) {
_, err := FromString("OR('A.member', Bmember)") // error after 1st Evaluate()
require.EqualError(t, err, "unrecognized token 'Bmember' in policy string")
_, err = FromString("OR('A.member', 'Bmember')") // error after 2nd Evalute()
require.EqualError(t, err, "unrecognized token 'Bmember' in policy string")
_, err = FromString(`OR('A.member', '\'Bmember\'')`) // error after 3rd Evalute()
require.EqualError(t, err, "unrecognized token 'Bmember' in policy string")
}
func TestNodeOUs(t *testing.T) {
p1, err := FromString("OR('A.peer', 'B.admin', 'C.orderer', 'D.client')")
require.NoError(t, err)
principals := make([]*msp.MSPPrincipal, 0)
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_PEER, MspIdentifier: "A"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_ADMIN, MspIdentifier: "B"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_ORDERER, MspIdentifier: "C"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_CLIENT, MspIdentifier: "D"}),
})
p2 := &common.SignaturePolicyEnvelope{
Version: 0,
Rule: NOutOf(1, []*common.SignaturePolicy{SignedBy(0), SignedBy(1), SignedBy(2), SignedBy(3)}),
Identities: principals,
}
require.Equal(t, p1, p2)
}
func TestOutOfNumIsString(t *testing.T) {
p1, err := FromString("OutOf('1', 'A.member', 'B.member')")
require.NoError(t, err)
principals := make([]*msp.MSPPrincipal, 0)
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"}),
})
p2 := &common.SignaturePolicyEnvelope{
Version: 0,
Rule: NOutOf(1, []*common.SignaturePolicy{SignedBy(0), SignedBy(1)}),
Identities: principals,
}
require.Equal(t, p1, p2)
}
func TestOutOfErrorCase(t *testing.T) {
p1, err1 := FromString("") // 1st NewEvaluableExpressionWithFunctions() returns an error
require.Nil(t, p1)
require.EqualError(t, err1, "Unexpected end of expression")
p2, err2 := FromString("OutOf(1)") // outof() if len(args)<2
require.Nil(t, p2)
require.EqualError(t, err2, "expected at least two arguments to NOutOf. Given 1")
p3, err3 := FromString("OutOf(true, 'A.member')") // outof() }else{. 1st arg is non of float, int, string
require.Nil(t, p3)
require.EqualError(t, err3, "unexpected type bool")
p4, err4 := FromString("OutOf(1, 2)") // oufof() switch default. 2nd arg is not string.
require.Nil(t, p4)
require.EqualError(t, err4, "unexpected type float64")
p5, err5 := FromString("OutOf(1, 'true')") // firstPass() switch default
require.Nil(t, p5)
require.EqualError(t, err5, "unexpected type bool")
p6, err6 := FromString(`OutOf('\'\\\'A\\\'\'', 'B.member')`) // secondPass() switch args[1].(type) default
require.Nil(t, p6)
require.EqualError(t, err6, "unrecognized type, expected a number, got string")
p7, err7 := FromString(`OutOf(1, '\'1\'')`) // secondPass() switch args[1].(type) default
require.Nil(t, p7)
require.EqualError(t, err7, "unrecognized type, expected a principal or a policy, got float64")
p8, err8 := FromString(`''`) // 2nd NewEvaluateExpressionWithFunction() returns an error
require.Nil(t, p8)
require.EqualError(t, err8, "Unexpected end of expression")
p9, err9 := FromString(`'\'\''`) // 3rd NewEvaluateExpressionWithFunction() returns an error
require.Nil(t, p9)
require.EqualError(t, err9, "Unexpected end of expression")
}
func TestBadStringBeforeFAB11404_ThisCanDeleteAfterFAB11404HasMerged(t *testing.T) {
s1 := "1" // ineger in string
p1, err1 := FromString(s1)
require.Nil(t, p1)
require.EqualError(t, err1, `invalid policy string '1'`)
s2 := "'1'" // quoted ineger in string
p2, err2 := FromString(s2)
require.Nil(t, p2)
require.EqualError(t, err2, `invalid policy string ''1''`)
s3 := `'\'1\''` // nested quoted ineger in string
p3, err3 := FromString(s3)
require.Nil(t, p3)
require.EqualError(t, err3, `invalid policy string ''\'1\'''`)
}
func TestSecondPassBoundaryCheck(t *testing.T) {
// Check lower boundary
// Prohibit t<0
p0, err0 := FromString("OutOf(-1, 'A.member', 'B.member')")
require.Nil(t, p0)
require.EqualError(t, err0, "invalid t-out-of-n predicate, t -1, n 2")
// Permit t==0 : always satisfied policy
// There is no clear usecase of t=0, but somebody may already use it, so we don't treat as an error.
p1, err1 := FromString("OutOf(0, 'A.member', 'B.member')")
require.NoError(t, err1)
principals := make([]*msp.MSPPrincipal, 0)
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "A"}),
})
principals = append(principals, &msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_ROLE,
Principal: protoutil.MarshalOrPanic(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "B"}),
})
expected1 := &common.SignaturePolicyEnvelope{
Version: 0,
Rule: NOutOf(0, []*common.SignaturePolicy{SignedBy(0), SignedBy(1)}),
Identities: principals,
}
require.Equal(t, expected1, p1)
// Check upper boundary
// Permit t==n+1 : never satisfied policy
// Usecase: To create immutable ledger key
p2, err2 := FromString("OutOf(3, 'A.member', 'B.member')")
require.NoError(t, err2)
expected2 := &common.SignaturePolicyEnvelope{
Version: 0,
Rule: NOutOf(3, []*common.SignaturePolicy{SignedBy(0), SignedBy(1)}),
Identities: principals,
}
require.Equal(t, expected2, p2)
// Prohibit t>n + 1
p3, err3 := FromString("OutOf(4, 'A.member', 'B.member')")
require.Nil(t, p3)
require.EqualError(t, err3, "invalid t-out-of-n predicate, t 4, n 2")
}