diff --git a/core/scc/cscc/configure.go b/core/scc/cscc/configure.go index a1a920cfe56..6c20ec18603 100644 --- a/core/scc/cscc/configure.go +++ b/core/scc/cscc/configure.go @@ -28,7 +28,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/hyperledger/fabric/common/channelconfig" "github.com/hyperledger/fabric/common/flogging" - "github.com/hyperledger/fabric/common/policies" + "github.com/hyperledger/fabric/core/aclmgmt" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/peer" "github.com/hyperledger/fabric/core/policy" @@ -126,6 +126,7 @@ func (e *PeerConfiger) Invoke(stub shim.ChaincodeStubInterface) pb.Response { } // 2. check local MSP Admins policy + // TODO: move to ACLProvider once it will support chainless ACLs if err = e.policyChecker.CheckPolicyNoChannel(mgmt.Admins, sp); err != nil { return shim.Error(fmt.Sprintf("\"JoinChain\" request failed authorization check "+ "for channel [%s]: [%s]", cid, err)) @@ -133,13 +134,15 @@ func (e *PeerConfiger) Invoke(stub shim.ChaincodeStubInterface) pb.Response { return joinChain(cid, block) case GetConfigBlock: - // 2. check the channel reader policy - if err = e.policyChecker.CheckPolicy(string(args[1]), policies.ChannelApplicationReaders, sp); err != nil { + // 2. check policy + if err = aclmgmt.GetACLProvider().CheckACL(aclmgmt.CSCC_GetConfigBlock, string(args[1]), sp); err != nil { return shim.Error(fmt.Sprintf("\"GetConfigBlock\" request failed authorization check for channel [%s]: [%s]", args[1], err)) } + return getConfigBlock(args[1]) case GetChannels: // 2. check local MSP Members policy + // TODO: move to ACLProvider once it will support chainless ACLs if err = e.policyChecker.CheckPolicyNoChannel(mgmt.Members, sp); err != nil { return shim.Error(fmt.Sprintf("\"GetChannels\" request failed authorization check: [%s]", err)) } diff --git a/core/scc/cscc/configure_test.go b/core/scc/cscc/configure_test.go index add33b86096..402a8f9121e 100644 --- a/core/scc/cscc/configure_test.go +++ b/core/scc/cscc/configure_test.go @@ -1,4 +1,5 @@ /* + Copyright IBM Corp. 2016 All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +19,6 @@ package cscc import ( "fmt" "os" - "strings" "testing" "time" @@ -28,6 +28,8 @@ import ( "github.com/hyperledger/fabric/common/localmsp" "github.com/hyperledger/fabric/common/mocks/scc" "github.com/hyperledger/fabric/common/policies" + "github.com/hyperledger/fabric/core/aclmgmt" + aclmocks "github.com/hyperledger/fabric/core/aclmgmt/mocks" "github.com/hyperledger/fabric/core/chaincode" "github.com/hyperledger/fabric/core/chaincode/accesscontrol" "github.com/hyperledger/fabric/core/chaincode/shim" @@ -47,6 +49,7 @@ import ( cb "github.com/hyperledger/fabric/protos/common" pb "github.com/hyperledger/fabric/protos/peer" "github.com/hyperledger/fabric/protos/utils" + "github.com/pkg/errors" "github.com/spf13/viper" "github.com/stretchr/testify/assert" ) @@ -78,9 +81,16 @@ func (*mockDeliveryClientFactory) Service(g service.GossipService, endpoints []s return &mockDeliveryClient{}, nil } +var mockAclProvider *aclmocks.MockACLProvider + func TestMain(m *testing.M) { msptesttools.LoadMSPSetupForTesting() + mockAclProvider = &aclmocks.MockACLProvider{} + mockAclProvider.Reset() + + aclmgmt.RegisterACLProvider(mockAclProvider) + os.Exit(m.Run()) } @@ -110,15 +120,18 @@ func TestConfigerInvokeInvalidParameters(t *testing.T) { assert.Equal(t, res.Status, int32(shim.ERROR), "CSCC invoke expected to fail no signed proposal provided") assert.Contains(t, res.Message, "failed authorization check") - args = [][]byte{[]byte("GetConfigBlock"), []byte("testChainID")} - res = stub.MockInvokeWithSignedProposal("4", args, nil) - assert.Equal(t, res.Status, int32(shim.ERROR), "CSCC invoke expected to fail no signed proposal provided") - assert.Contains(t, res.Message, "failed authorization check") - args = [][]byte{[]byte("fooFunction"), []byte("testChainID")} res = stub.MockInvoke("5", args) assert.Equal(t, res.Status, int32(shim.ERROR), "CSCC invoke expected wrong function name provided") assert.Equal(t, res.Message, "Requested function fooFunction not found.") + + mockAclProvider.Reset() + mockAclProvider.On("CheckACL", aclmgmt.CSCC_GetConfigBlock, "testChainID", (*pb.SignedProposal)(nil)).Return(errors.New("Nil SignedProposal")) + args = [][]byte{[]byte("GetConfigBlock"), []byte("testChainID")} + res = stub.MockInvokeWithSignedProposal("4", args, nil) + assert.Equal(t, res.Status, int32(shim.ERROR), "CSCC invoke expected to fail no signed proposal provided") + assert.Contains(t, res.Message, "Nil SignedProposal") + mockAclProvider.AssertExpectations(t) } func TestConfigerInvokeJoinChainMissingParams(t *testing.T) { @@ -142,6 +155,7 @@ func TestConfigerInvokeJoinChainMissingParams(t *testing.T) { } func TestConfigerInvokeJoinChainWrongParams(t *testing.T) { + viper.Set("peer.fileSystemPath", "/tmp/hyperledgertest/") os.Mkdir("/tmp/hyperledgertest", 0755) defer os.RemoveAll("/tmp/hyperledgertest/") @@ -244,7 +258,7 @@ func TestConfigerInvokeJoinChainCorrectParams(t *testing.T) { if res.Status == shim.OK { t.Fatalf("cscc invoke JoinChain must fail : %v", res.Message) } - assert.True(t, strings.HasPrefix(res.Message, "\"JoinChain\" request failed authorization check for channel")) + assert.Contains(t, res.Message, "\"JoinChain\" request failed authorization check for channel") sProp.Signature = sProp.ProposalBytes // Query the configuration block @@ -253,8 +267,21 @@ func TestConfigerInvokeJoinChainCorrectParams(t *testing.T) { if err != nil { t.Fatalf("cscc invoke JoinChain failed with: %v", err) } + + // Test an ACL failure on GetConfigBlock + mockAclProvider.Reset() + mockAclProvider.On("CheckACL", aclmgmt.CSCC_GetConfigBlock, "mytestchainid", sProp).Return(errors.New("Failed authorization")) args = [][]byte{[]byte("GetConfigBlock"), []byte(chainID)} - policyManagerGetter.Managers["mytestchainid"].(*policymocks.MockChannelPolicyManager).MockPolicy.(*policymocks.MockPolicy).Deserializer.(*policymocks.MockIdentityDeserializer).Msg = sProp.ProposalBytes + res = stub.MockInvokeWithSignedProposal("2", args, sProp) + if res.Status == shim.OK { + t.Fatalf("cscc invoke GetConfigBlock shoulda have failed: %v", res.Message) + } + assert.Contains(t, res.Message, "Failed authorization") + mockAclProvider.AssertExpectations(t) + + // Test with ACL okay + mockAclProvider.Reset() + mockAclProvider.On("CheckACL", aclmgmt.CSCC_GetConfigBlock, "mytestchainid", sProp).Return(nil) if res := stub.MockInvokeWithSignedProposal("2", args, sProp); res.Status != shim.OK { t.Fatalf("cscc invoke GetConfigBlock failed with: %v", res.Message) } @@ -279,6 +306,7 @@ func TestConfigerInvokeJoinChainCorrectParams(t *testing.T) { } func TestPeerConfiger_SubmittingOrdererGenesis(t *testing.T) { + viper.Set("peer.fileSystemPath", "/tmp/hyperledgertest/") os.Mkdir("/tmp/hyperledgertest", 0755) defer os.RemoveAll("/tmp/hyperledgertest/")