157 lines
4.9 KiB
Go
157 lines
4.9 KiB
Go
/*
|
|
Copyright IBM Corp. 2016 All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package aclmgmt
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
"github.com/hyperledger/fabric-protos-go/common"
|
|
"github.com/hyperledger/fabric-protos-go/peer"
|
|
"github.com/hyperledger/fabric/core/aclmgmt/mocks"
|
|
"github.com/hyperledger/fabric/core/policy"
|
|
"github.com/hyperledger/fabric/internal/pkg/identity"
|
|
msptesttools "github.com/hyperledger/fabric/msp/mgmt/testtools"
|
|
"github.com/hyperledger/fabric/protoutil"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func newPolicyProvider(pEvaluator policyEvaluator) aclmgmtPolicyProvider {
|
|
return &aclmgmtPolicyProviderImpl{pEvaluator}
|
|
}
|
|
|
|
// ------- mocks ---------
|
|
|
|
// mockPolicyEvaluatorImpl implements policyEvaluator
|
|
type mockPolicyEvaluatorImpl struct {
|
|
pmap map[string]string
|
|
peval map[string]error
|
|
}
|
|
|
|
func (pe *mockPolicyEvaluatorImpl) PolicyRefForAPI(resName string) string {
|
|
return pe.pmap[resName]
|
|
}
|
|
|
|
func (pe *mockPolicyEvaluatorImpl) Evaluate(polName string, sd []*protoutil.SignedData) error {
|
|
err, ok := pe.peval[polName]
|
|
if !ok {
|
|
return PolicyNotFound(polName)
|
|
}
|
|
|
|
// this could be non nil or some error
|
|
return err
|
|
}
|
|
|
|
//go:generate counterfeiter -o mocks/signer_serializer.go --fake-name SignerSerializer . signerSerializer
|
|
|
|
type signerSerializer interface {
|
|
identity.SignerSerializer
|
|
}
|
|
|
|
//go:generate counterfeiter -o mocks/defaultaclprovider.go --fake-name DefaultACLProvider . defaultACLProvider
|
|
|
|
func TestPolicyBase(t *testing.T) {
|
|
evaluator := &mockPolicyEvaluatorImpl{pmap: map[string]string{"res": "pol"}, peval: map[string]error{"pol": nil}}
|
|
provider := newPolicyProvider(evaluator)
|
|
|
|
t.Run("SignedProposal", func(t *testing.T) {
|
|
proposal, _ := protoutil.MockSignedEndorserProposalOrPanic("A", &peer.ChaincodeSpec{}, []byte("Alice"), []byte("msg1"))
|
|
err := provider.CheckACL("pol", proposal)
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("Envelope", func(t *testing.T) {
|
|
signer := &mocks.SignerSerializer{}
|
|
envelope, err := protoutil.CreateSignedEnvelope(common.HeaderType_CONFIG, "myc", signer, &common.ConfigEnvelope{}, 0, 0)
|
|
require.NoError(t, err)
|
|
err = provider.CheckACL("pol", envelope)
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("SignedData", func(t *testing.T) {
|
|
data := &protoutil.SignedData{
|
|
Data: []byte("DATA"),
|
|
Identity: []byte("IDENTITY"),
|
|
Signature: []byte("SIGNATURE"),
|
|
}
|
|
err := provider.CheckACL("pol", data)
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
|
|
func TestPolicyBad(t *testing.T) {
|
|
peval := &mockPolicyEvaluatorImpl{pmap: map[string]string{"res": "pol"}, peval: map[string]error{"pol": nil}}
|
|
pprov := newPolicyProvider(peval)
|
|
|
|
// bad policy
|
|
err := pprov.CheckACL("pol", []byte("not a signed proposal"))
|
|
require.Error(t, err, InvalidIdInfo("pol").Error())
|
|
|
|
sProp, _ := protoutil.MockSignedEndorserProposalOrPanic("A", &peer.ChaincodeSpec{}, []byte("Alice"), []byte("msg1"))
|
|
err = pprov.CheckACL("badpolicy", sProp)
|
|
require.Error(t, err)
|
|
|
|
sProp, _ = protoutil.MockSignedEndorserProposalOrPanic("A", &peer.ChaincodeSpec{}, []byte("Alice"), []byte("msg1"))
|
|
sProp.ProposalBytes = []byte("bad proposal bytes")
|
|
err = pprov.CheckACL("res", sProp)
|
|
require.Error(t, err)
|
|
|
|
sProp, _ = protoutil.MockSignedEndorserProposalOrPanic("A", &peer.ChaincodeSpec{}, []byte("Alice"), []byte("msg1"))
|
|
prop := &peer.Proposal{}
|
|
if proto.Unmarshal(sProp.ProposalBytes, prop) != nil {
|
|
t.FailNow()
|
|
}
|
|
prop.Header = []byte("bad hdr")
|
|
sProp.ProposalBytes = protoutil.MarshalOrPanic(prop)
|
|
err = pprov.CheckACL("res", sProp)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
// test to ensure ptypes are processed by default provider
|
|
func TestForceDefaultsForPType(t *testing.T) {
|
|
defAclProvider := &mocks.DefaultACLProvider{}
|
|
defAclProvider.CheckACLReturns(nil)
|
|
defAclProvider.IsPtypePolicyReturns(true)
|
|
rp := &resourceProvider{defaultProvider: defAclProvider}
|
|
err := rp.CheckACL("aptype", "somechannel", struct{}{})
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestCheckACLNoChannel(t *testing.T) {
|
|
// use mocked objects to test good path
|
|
mockDefAclProvider := &mocks.DefaultACLProvider{}
|
|
mockDefAclProvider.CheckACLNoChannelReturns(nil)
|
|
mockDefAclProvider.IsPtypePolicyReturns(true)
|
|
rp := &resourceProvider{defaultProvider: mockDefAclProvider}
|
|
err := rp.CheckACLNoChannel("aptype", struct{}{})
|
|
require.NoError(t, err)
|
|
|
|
// error paths
|
|
defAclProvider := &defaultACLProviderImpl{
|
|
pResourcePolicyMap: map[string]string{"aptype": policy.Admins},
|
|
}
|
|
rp = &resourceProvider{defaultProvider: defAclProvider}
|
|
err = rp.CheckACLNoChannel("nontype", struct{}{})
|
|
require.Error(t, err, "cannot override peer type policy for channeless ACL check")
|
|
|
|
rp = &resourceProvider{defaultProvider: defAclProvider}
|
|
err = rp.CheckACLNoChannel("aptype", struct{}{})
|
|
require.EqualError(t, err, "Unknown id on channelless checkACL aptype")
|
|
}
|
|
|
|
func init() {
|
|
// setup the MSP manager so that we can sign/verify
|
|
err := msptesttools.LoadMSPSetupForTesting()
|
|
if err != nil {
|
|
fmt.Printf("Could not load msp config, err %s", err)
|
|
os.Exit(-1)
|
|
return
|
|
}
|
|
}
|