Skip to content

Commit

Permalink
[FAB-2969] Access control at CSCC
Browse files Browse the repository at this point in the history
This change-set does the following:
1. Add access control to cscc by verifying that the caller
has appropriate rights.
Tests have been modified to cover this access control

This change-set comes in the context of:
1. https://jira.hyperledger.org/browse/FAB-2969

Change-Id: If8698026a81b5402b5336c83ec553a8c39f2d8e0
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
  • Loading branch information
adecaro committed Apr 20, 2017
1 parent fed2efa commit e63c915
Show file tree
Hide file tree
Showing 8 changed files with 306 additions and 162 deletions.
263 changes: 132 additions & 131 deletions core/chaincode/exectransaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,20 @@ limitations under the License.
package chaincode

import (
"encoding/json"
"fmt"
"math/rand"
"net"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
"testing"
"time"

"encoding/json"
"strings"

"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/core/common/ccprovider"
Expand Down Expand Up @@ -497,27 +498,6 @@ func _(chainID string, _ string) error {
return nil
}

// Test deploy of a transaction
func TestExecuteDeployTransaction(t *testing.T) {
//chaincoe is deployed as part of many tests. No need for a separate one for this
t.Skip()
chainID := util.GetTestChainID()

executeDeployTransaction(t, chainID, "example01", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01")
}

// Test deploy of a transaction with a GOPATH with multiple elements
func TestGopathExecuteDeployTransaction(t *testing.T) {
//this is no longer critical as chaincode is assembled in the client side (SDK)
t.Skip()
chainID := util.GetTestChainID()

// add a trailing slash to GOPATH
// and a couple of elements - it doesn't matter what they are
os.Setenv("GOPATH", os.Getenv("GOPATH")+string(os.PathSeparator)+string(os.PathListSeparator)+"/tmp/foo"+string(os.PathListSeparator)+"/tmp/bar")
executeDeployTransaction(t, chainID, "example01", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01")
}

// Disable this temporarily.
// TODO: Need to enable this after update chaincode interface of chaincode repo.
// Test deploy of a transaction with a chaincode over HTTP.
Expand Down Expand Up @@ -634,6 +614,118 @@ const (
chaincodeExample06JavaPath = "../../examples/chaincode/java/chaincode_example06"
)

func runChaincodeInvokeChaincode(t *testing.T, chainID string, _ string) (err error) {
var ctxt = context.Background()

// Deploy first chaincode
url1 := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"

cID1 := &pb.ChaincodeID{Name: "example02", Path: url1, Version: "0"}
f := "init"
args := util.ToChaincodeArgs(f, "a", "100", "b", "200")

spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}}

cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil)

var nextBlockNumber uint64

_, err = deploy(ctxt, cccid1, spec1, nextBlockNumber)
nextBlockNumber++
ccID1 := spec1.ChaincodeId.Name
if err != nil {
t.Fail()
t.Logf("Error initializing chaincode %s(%s)", ccID1, err)
theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1})
return
}

t.Logf("deployed chaincode_example02 got cID1:% s,\n ccID1:% s", cID1, ccID1)

time.Sleep(time.Second)

// Deploy second chaincode
url2 := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example04"

cID2 := &pb.ChaincodeID{Name: "example04", Path: url2, Version: "0"}
f = "init"
args = util.ToChaincodeArgs(f, "e", "0")

spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}}

cccid2 := ccprovider.NewCCContext(chainID, "example04", "0", "", false, nil, nil)

_, err = deploy(ctxt, cccid2, spec2, nextBlockNumber)
nextBlockNumber++
ccID2 := spec2.ChaincodeId.Name
if err != nil {
t.Fail()
t.Logf("Error initializing chaincode %s(%s)", ccID2, err)
theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1})
theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2})
return
}

time.Sleep(time.Second)

// Invoke second chaincode passing the first chaincode's name as first param,
// which will inturn invoke the first chaincode
f = "invoke"
cid := spec1.ChaincodeId.Name
args = util.ToChaincodeArgs(f, cid, "e", "1")

spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}}
// Invoke chaincode
var uuid string
_, uuid, _, err = invoke(ctxt, chainID, spec2, nextBlockNumber)

if err != nil {
t.Fail()
t.Logf("Error invoking <%s>: %s", ccID2, err)
theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1})
theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2})
return
}

cccid1.TxID = uuid

// Check the state in the ledger
err = checkFinalState(cccid1)
if err != nil {
t.Fail()
t.Logf("Incorrect final state after transaction for <%s>: %s", ccID1, err)
theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1})
theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2})
return
}

theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1})
theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2})

return
}

// Test deploy of a transaction
func TestExecuteDeployTransaction(t *testing.T) {
//chaincoe is deployed as part of many tests. No need for a separate one for this
t.Skip()
chainID := util.GetTestChainID()

executeDeployTransaction(t, chainID, "example01", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01")
}

// Test deploy of a transaction with a GOPATH with multiple elements
func TestGopathExecuteDeployTransaction(t *testing.T) {
//this is no longer critical as chaincode is assembled in the client side (SDK)
t.Skip()
chainID := util.GetTestChainID()

// add a trailing slash to GOPATH
// and a couple of elements - it doesn't matter what they are
os.Setenv("GOPATH", os.Getenv("GOPATH")+string(os.PathSeparator)+string(os.PathListSeparator)+"/tmp/foo"+string(os.PathListSeparator)+"/tmp/bar")
executeDeployTransaction(t, chainID, "example01", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01")
}

func TestExecuteInvokeTransaction(t *testing.T) {

testCases := []struct {
Expand Down Expand Up @@ -746,97 +838,6 @@ func TestChaincodeInvokeChaincode(t *testing.T) {
closeListenerAndSleep(lis)
}

func runChaincodeInvokeChaincode(t *testing.T, chainID string, _ string) (err error) {
var ctxt = context.Background()

// Deploy first chaincode
url1 := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"

cID1 := &pb.ChaincodeID{Name: "example02", Path: url1, Version: "0"}
f := "init"
args := util.ToChaincodeArgs(f, "a", "100", "b", "200")

spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}}

cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil)

var nextBlockNumber uint64

_, err = deploy(ctxt, cccid1, spec1, nextBlockNumber)
nextBlockNumber++
ccID1 := spec1.ChaincodeId.Name
if err != nil {
t.Fail()
t.Logf("Error initializing chaincode %s(%s)", ccID1, err)
theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1})
return
}

t.Logf("deployed chaincode_example02 got cID1:% s,\n ccID1:% s", cID1, ccID1)

time.Sleep(time.Second)

// Deploy second chaincode
url2 := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example04"

cID2 := &pb.ChaincodeID{Name: "example04", Path: url2, Version: "0"}
f = "init"
args = util.ToChaincodeArgs(f, "e", "0")

spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}}

cccid2 := ccprovider.NewCCContext(chainID, "example04", "0", "", false, nil, nil)

_, err = deploy(ctxt, cccid2, spec2, nextBlockNumber)
nextBlockNumber++
ccID2 := spec2.ChaincodeId.Name
if err != nil {
t.Fail()
t.Logf("Error initializing chaincode %s(%s)", ccID2, err)
theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1})
theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2})
return
}

time.Sleep(time.Second)

// Invoke second chaincode passing the first chaincode's name as first param,
// which will inturn invoke the first chaincode
f = "invoke"
cid := spec1.ChaincodeId.Name
args = util.ToChaincodeArgs(f, cid, "e", "1")

spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}}
// Invoke chaincode
var uuid string
_, uuid, _, err = invoke(ctxt, chainID, spec2, nextBlockNumber)

if err != nil {
t.Fail()
t.Logf("Error invoking <%s>: %s", ccID2, err)
theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1})
theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2})
return
}

cccid1.TxID = uuid

// Check the state in the ledger
err = checkFinalState(cccid1)
if err != nil {
t.Fail()
t.Logf("Incorrect final state after transaction for <%s>: %s", ccID1, err)
theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1})
theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2})
return
}

theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1})
theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2})

return
}

// Test the execution of a chaincode that invokes another chaincode with wrong parameters. Should receive error from
// from the called chaincode
func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) {
Expand Down Expand Up @@ -1647,6 +1648,23 @@ func TestChaincodeInitializeInitError(t *testing.T) {
}
}

func TestMain(m *testing.M) {
var err error

// setup the MSP manager so that we can sign/verify
mspMgrConfigDir := "../../msp/sampleconfig/"
msptesttools.LoadMSPSetupForTesting(mspMgrConfigDir)
signer, err = mspmgmt.GetLocalMSP().GetDefaultSigningIdentity()
if err != nil {
os.Exit(-1)
fmt.Print("Could not initialize msp/signer")
return
}

SetupTestConfig()
os.Exit(m.Run())
}

func deployChaincode(ctx context.Context, chaincodeCtx *ccprovider.CCContext, chaincodeType pb.ChaincodeSpec_Type, path string, args [][]byte, nextBlockNumber uint64) ([]byte, error) {

chaincodeSpec := &pb.ChaincodeSpec{
Expand All @@ -1670,23 +1688,6 @@ func deployChaincode(ctx context.Context, chaincodeCtx *ccprovider.CCContext, ch

var signer msp.SigningIdentity

func TestMain(m *testing.M) {
var err error

// setup the MSP manager so that we can sign/verify
mspMgrConfigDir := "../../msp/sampleconfig/"
msptesttools.LoadMSPSetupForTesting(mspMgrConfigDir)
signer, err = mspmgmt.GetLocalMSP().GetDefaultSigningIdentity()
if err != nil {
os.Exit(-1)
fmt.Print("Could not initialize msp/signer")
return
}

SetupTestConfig()
os.Exit(m.Run())
}

var rng *rand.Rand = rand.New(rand.NewSource(time.Now().UnixNano()))

func generateChaincodeName(chaincodeType pb.ChaincodeSpec_Type) string {
Expand Down
24 changes: 18 additions & 6 deletions core/peer/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,21 +256,33 @@ func MockCreateChain(cid string) error {
return err
}

i := mockconfigtx.Initializer{
chains.Lock()
defer chains.Unlock()

// Here we need to mock also the policy manager
// in order for the ACL to be checked
initializer := mockconfigtx.Initializer{
Resources: mockconfigtx.Resources{
PolicyManagerVal: &mockpolicies.Manager{
Policy: &mockpolicies.Policy{},
},
},
PolicyProposerVal: &mockconfigtx.PolicyProposer{
Transactional: mockconfigtx.Transactional{},
},
ValueProposerVal: &mockconfigtx.ValueProposer{
Transactional: mockconfigtx.Transactional{},
},
}

manager := &mockconfigtx.Manager{
Initializer: initializer,
}

chains.Lock()
defer chains.Unlock()
chains.list[cid] = &chain{
cs: &chainSupport{
ledger: ledger,
Manager: &mockconfigtx.Manager{Initializer: i},
},
Manager: manager,
ledger: ledger},
}

return nil
Expand Down
3 changes: 2 additions & 1 deletion core/policy/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ type MockIdentityDeserializer struct {
}

func (d *MockIdentityDeserializer) DeserializeIdentity(serializedIdentity []byte) (msp.Identity, error) {
fmt.Printf("id : [%s], [%s]\n", string(serializedIdentity), string(d.Identity))
fmt.Printf("[DeserializeIdentity] id : [%s], [%s]\n", string(serializedIdentity), string(d.Identity))
if bytes.Equal(d.Identity, serializedIdentity) {
fmt.Printf("GOT : [%s], [%s]\n", string(serializedIdentity), string(d.Identity))
return &MockIdentity{identity: d.Identity, msg: d.Msg}, nil
Expand All @@ -93,6 +93,7 @@ type MockIdentity struct {
}

func (id *MockIdentity) SatisfiesPrincipal(p *mspproto.MSPPrincipal) error {
fmt.Printf("[SatisfiesPrincipal] id : [%s], [%s]\n", string(id.identity), string(p.Principal))
if !bytes.Equal(id.identity, p.Principal) {
return fmt.Errorf("Different identities [% x]!=[% x]", id.identity, p.Principal)
}
Expand Down
5 changes: 3 additions & 2 deletions core/policy/policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"testing"

"github.com/hyperledger/fabric/common/policies"
"github.com/hyperledger/fabric/msp/mgmt"
"github.com/hyperledger/fabric/protos/peer"
"github.com/hyperledger/fabric/protos/utils"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -73,11 +74,11 @@ func TestPolicyChecker(t *testing.T) {

// Alice is a member of the local MSP, policy check must succeed
identityDeserializer.Msg = sProp.ProposalBytes
err = pc.CheckPolicyNoChannel("member", sProp)
err = pc.CheckPolicyNoChannel(mgmt.Members, sProp)
assert.NoError(t, err)

sProp, _ = utils.MockSignedEndorserProposalOrPanic("A", &peer.ChaincodeSpec{}, []byte("Bob"), []byte("msg2"))
// Bob is not a member of the local MSP, policy check must fail
err = pc.CheckPolicyNoChannel("member", sProp)
err = pc.CheckPolicyNoChannel(mgmt.Members, sProp)
assert.Error(t, err)
}
Loading

0 comments on commit e63c915

Please sign in to comment.