234 lines
9.2 KiB
Go
234 lines
9.2 KiB
Go
/*
|
|
Copyright IBM Corp. 2017 All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package policy
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/hyperledger/fabric-protos-go/peer"
|
|
"github.com/hyperledger/fabric/common/policies"
|
|
"github.com/hyperledger/fabric/core/policy/mocks"
|
|
"github.com/hyperledger/fabric/protoutil"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestCheckPolicyInvalidArgs(t *testing.T) {
|
|
policyManagerGetter := &mocks.MockChannelPolicyManagerGetter{
|
|
Managers: map[string]policies.Manager{
|
|
"A": &mocks.MockChannelPolicyManager{
|
|
MockPolicy: &mocks.MockPolicy{
|
|
Deserializer: &mocks.MockIdentityDeserializer{
|
|
Identity: []byte("Alice"),
|
|
Msg: []byte("msg1"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
pc := &policyChecker{channelPolicyManagerGetter: policyManagerGetter}
|
|
|
|
err := pc.CheckPolicy("B", "admin", &peer.SignedProposal{})
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Failed to get policy manager for channel [B]")
|
|
}
|
|
|
|
func TestCheckPolicyBySignedDataInvalidArgs(t *testing.T) {
|
|
policyManagerGetter := &mocks.MockChannelPolicyManagerGetter{
|
|
Managers: map[string]policies.Manager{
|
|
"A": &mocks.MockChannelPolicyManager{
|
|
MockPolicy: &mocks.MockPolicy{
|
|
Deserializer: &mocks.MockIdentityDeserializer{
|
|
Identity: []byte("Alice"),
|
|
Msg: []byte("msg1"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
pc := &policyChecker{channelPolicyManagerGetter: policyManagerGetter}
|
|
|
|
err := pc.CheckPolicyBySignedData("", "admin", []*protoutil.SignedData{{}})
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Invalid channel ID name during check policy on signed data. Name must be different from nil.")
|
|
|
|
err = pc.CheckPolicyBySignedData("A", "", []*protoutil.SignedData{{}})
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Invalid policy name during check policy on signed data on channel [A]. Name must be different from nil.")
|
|
|
|
err = pc.CheckPolicyBySignedData("A", "admin", nil)
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Invalid signed data during check policy on channel [A] with policy [admin]")
|
|
|
|
err = pc.CheckPolicyBySignedData("B", "admin", []*protoutil.SignedData{{}})
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Failed to get policy manager for channel [B]")
|
|
|
|
err = pc.CheckPolicyBySignedData("A", "admin", []*protoutil.SignedData{{}})
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Failed evaluating policy on signed data during check policy on channel [A] with policy [admin]")
|
|
}
|
|
|
|
func TestPolicyCheckerInvalidArgs(t *testing.T) {
|
|
policyManagerGetter := &mocks.MockChannelPolicyManagerGetter{
|
|
Managers: map[string]policies.Manager{
|
|
"A": &mocks.MockChannelPolicyManager{
|
|
MockPolicy: &mocks.MockPolicy{Deserializer: &mocks.MockIdentityDeserializer{
|
|
Identity: []byte("Alice"),
|
|
Msg: []byte("msg1"),
|
|
}},
|
|
},
|
|
"B": &mocks.MockChannelPolicyManager{
|
|
MockPolicy: &mocks.MockPolicy{Deserializer: &mocks.MockIdentityDeserializer{
|
|
Identity: []byte("Bob"),
|
|
Msg: []byte("msg2"),
|
|
}},
|
|
},
|
|
"C": &mocks.MockChannelPolicyManager{
|
|
MockPolicy: &mocks.MockPolicy{Deserializer: &mocks.MockIdentityDeserializer{
|
|
Identity: []byte("Alice"),
|
|
Msg: []byte("msg3"),
|
|
}},
|
|
},
|
|
},
|
|
}
|
|
identityDeserializer := &mocks.MockIdentityDeserializer{
|
|
Identity: []byte("Alice"),
|
|
Msg: []byte("msg1"),
|
|
}
|
|
pc := &policyChecker{
|
|
channelPolicyManagerGetter: policyManagerGetter,
|
|
localMSP: identityDeserializer,
|
|
principalGetter: &mocks.MockMSPPrincipalGetter{Principal: []byte("Alice")},
|
|
}
|
|
|
|
// Check that (non-empty channel, empty policy) fails
|
|
err := pc.CheckPolicy("A", "", nil)
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Invalid policy name during check policy on channel [A]. Name must be different from nil.")
|
|
|
|
// Check that (empty channel, empty policy) fails
|
|
err = pc.CheckPolicy("", "", nil)
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Invalid policy name during channelless check policy. Name must be different from nil.")
|
|
|
|
// Check that (non-empty channel, non-empty policy, nil proposal) fails
|
|
err = pc.CheckPolicy("A", "A", nil)
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Invalid signed proposal during check policy on channel [A] with policy [A]")
|
|
|
|
// Check that (empty channel, non-empty policy, nil proposal) fails
|
|
err = pc.CheckPolicy("", "A", nil)
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Invalid signed proposal during channelless check policy with policy [A]")
|
|
}
|
|
|
|
func TestPolicyChecker(t *testing.T) {
|
|
policyManagerGetter := &mocks.MockChannelPolicyManagerGetter{
|
|
Managers: map[string]policies.Manager{
|
|
"A": &mocks.MockChannelPolicyManager{
|
|
MockPolicy: &mocks.MockPolicy{
|
|
Deserializer: &mocks.MockIdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1")},
|
|
},
|
|
},
|
|
"B": &mocks.MockChannelPolicyManager{
|
|
MockPolicy: &mocks.MockPolicy{
|
|
Deserializer: &mocks.MockIdentityDeserializer{
|
|
Identity: []byte("Bob"),
|
|
Msg: []byte("msg2"),
|
|
},
|
|
},
|
|
},
|
|
"C": &mocks.MockChannelPolicyManager{
|
|
MockPolicy: &mocks.MockPolicy{
|
|
Deserializer: &mocks.MockIdentityDeserializer{
|
|
Identity: []byte("Alice"),
|
|
Msg: []byte("msg3"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
identityDeserializer := &mocks.MockIdentityDeserializer{
|
|
Identity: []byte("Alice"),
|
|
Msg: []byte("msg1"),
|
|
}
|
|
pc := &policyChecker{
|
|
channelPolicyManagerGetter: policyManagerGetter,
|
|
localMSP: identityDeserializer,
|
|
principalGetter: &mocks.MockMSPPrincipalGetter{Principal: []byte("Alice")},
|
|
}
|
|
|
|
t.Run("CheckPolicy", func(t *testing.T) {
|
|
// Validate Alice signatures against channel A's readers
|
|
sProp, _ := protoutil.MockSignedEndorserProposalOrPanic("A", &peer.ChaincodeSpec{}, []byte("Alice"), []byte("msg1"))
|
|
policyManagerGetter.Managers["A"].(*mocks.MockChannelPolicyManager).MockPolicy.(*mocks.MockPolicy).Deserializer.(*mocks.MockIdentityDeserializer).Msg = sProp.ProposalBytes
|
|
sProp.Signature = sProp.ProposalBytes
|
|
err := pc.CheckPolicy("A", "readers", sProp)
|
|
require.NoError(t, err)
|
|
|
|
// Proposal from Alice for channel A should fail against channel B, where Alice is not involved
|
|
err = pc.CheckPolicy("B", "readers", sProp)
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Failed evaluating policy on signed data during check policy on channel [B] with policy [readers]: [Invalid Identity]")
|
|
|
|
// Proposal from Alice for channel A should fail against channel C, where Alice is involved but signature is not valid
|
|
err = pc.CheckPolicy("C", "readers", sProp)
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Failed evaluating policy on signed data during check policy on channel [C] with policy [readers]: [Invalid Signature]")
|
|
})
|
|
|
|
t.Run("CheckPolicyNoChannel", func(t *testing.T) {
|
|
sProp, _ := protoutil.MockSignedEndorserProposalOrPanic("A", &peer.ChaincodeSpec{}, []byte("Alice"), []byte("msg1"))
|
|
sProp.Signature = sProp.ProposalBytes
|
|
|
|
// Alice is a member of the local MSP, policy check must succeed
|
|
identityDeserializer.Msg = sProp.ProposalBytes
|
|
err := pc.CheckPolicyNoChannel(Members, sProp)
|
|
require.NoError(t, err)
|
|
|
|
sProp, _ = protoutil.MockSignedEndorserProposalOrPanic("A", &peer.ChaincodeSpec{}, []byte("Bob"), []byte("msg2"))
|
|
// Bob is not a member of the local MSP, policy check must fail
|
|
err = pc.CheckPolicyNoChannel(Members, sProp)
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Failed deserializing proposal creator during channelless check policy with policy [Members]: [Invalid Identity]")
|
|
})
|
|
|
|
t.Run("CheckPolicyNoChannel", func(t *testing.T) {
|
|
signedData := &protoutil.SignedData{
|
|
Identity: []byte("Alice"),
|
|
Data: []byte("msg1"),
|
|
Signature: []byte("msg1"), // for testing only, signature is same as data to pass MockIdentity.Verify
|
|
}
|
|
|
|
// Alice is a member of the local MSP, policy check must succeed
|
|
identityDeserializer.Msg = signedData.Data
|
|
err := pc.CheckPolicyNoChannelBySignedData(Admins, []*protoutil.SignedData{signedData})
|
|
require.NoError(t, err)
|
|
|
|
// CheckPolicyNoChannelBySignedData iterates each signed data and returns an error if any data is invalid
|
|
// Bob is not a member of the local MSP, policy check must fail when deserializing the identity
|
|
signedData2 := &protoutil.SignedData{
|
|
Identity: []byte("Bob"),
|
|
Data: []byte("msg2"),
|
|
Signature: []byte("msg2"),
|
|
}
|
|
err = pc.CheckPolicyNoChannelBySignedData(Admins, []*protoutil.SignedData{signedData, signedData2})
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "failed deserializing signed data identity during channelless check policy with policy [Admins]: [Invalid Identity]")
|
|
|
|
// policy name cannot be empty
|
|
err = pc.CheckPolicyNoChannelBySignedData("", []*protoutil.SignedData{signedData})
|
|
require.EqualError(t, err, "invalid policy name during channelless check policy. Name must be different from nil.")
|
|
|
|
// signed data cannot be nil or empty
|
|
err = pc.CheckPolicyNoChannelBySignedData(Admins, nil)
|
|
require.EqualError(t, err, "no signed data during channelless check policy with policy [Admins]")
|
|
err = pc.CheckPolicyNoChannelBySignedData(Admins, []*protoutil.SignedData{})
|
|
require.EqualError(t, err, "no signed data during channelless check policy with policy [Admins]")
|
|
})
|
|
}
|