Skip to content

Commit

Permalink
DARC: implement access control when updating
Browse files Browse the repository at this point in the history
  • Loading branch information
Gilthoniel committed May 1, 2020
1 parent ed350c1 commit 200e1a0
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 43 deletions.
5 changes: 0 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
Expand All @@ -20,8 +18,6 @@ github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
Expand Down Expand Up @@ -79,7 +75,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
Expand Down
30 changes: 27 additions & 3 deletions ledger/arc/darc/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type darcAction struct {
access Access
}

// TODO: client factory

// NewCreate returns a new action to create a DARC.
func NewCreate(access Access) basic.ClientAction {
return darcAction{access: access}
Expand Down Expand Up @@ -67,7 +69,8 @@ func (act darcAction) Fingerprint(w io.Writer, enc encoding.ProtoMarshaler) erro

// serverAction is the server-side action for DARCs.
type serverAction struct {
encoder encoding.ProtoMarshaler
encoder encoding.ProtoMarshaler
darcFactory arc.AccessControlFactory
darcAction
}

Expand All @@ -79,13 +82,33 @@ func (act serverAction) Consume(ctx basic.Context, page inventory.WritablePage)
return xerrors.Errorf("couldn't pack access: %v", err)
}

err = act.access.Match(UpdateAccessRule, ctx.GetIdentity())
if err != nil {
// This prevents to update the arc so that no one is allowed to update
// it in the future.
return xerrors.New("transaction identity should be allowed to update")
}

key := act.key
if key == nil {
// No key defined means a creation request then we use the transaction
// ID as a unique key for the DARC.
key = ctx.GetID()
} else {
// TODO: access control
value, err := page.Read(key)
if err != nil {
return xerrors.Errorf("couldn't read value: %v", err)
}

access, err := act.darcFactory.FromProto(value)
if err != nil {
return xerrors.Errorf("couldn't decode access: %v", err)
}

err = access.Match(UpdateAccessRule, ctx.GetIdentity())
if err != nil {
return xerrors.Errorf("no access: %v", err)
}
}

err = page.Write(key, accesspb)
Expand Down Expand Up @@ -126,11 +149,12 @@ func (f actionFactory) FromProto(in proto.Message) (basic.ServerAction, error) {
}

servAccess := serverAction{
encoder: f.encoder,
darcFactory: f.darcFactory,
darcAction: darcAction{
key: pb.GetKey(),
access: access.(Access),
},
encoder: f.encoder,
}

return servAccess, nil
Expand Down
42 changes: 39 additions & 3 deletions ledger/arc/darc/action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,17 @@ func TestAction_Fingerprint(t *testing.T) {
}

func TestServerAction_Consume(t *testing.T) {
access, err := NewAccess().Evolve(UpdateAccessRule, fakeIdentity{buffer: []byte("doggy")})
require.NoError(t, err)

action := serverAction{
encoder: encoding.NewProtoEncoder(),
darcAction: darcAction{key: []byte{0x01}},
encoder: encoding.NewProtoEncoder(),
darcFactory: NewFactory(),
darcAction: darcAction{key: []byte{0x01}, access: access},
}

call := &fake.Call{}
err := action.Consume(fakeContext{}, fakePage{call: call})
err = action.Consume(fakeContext{}, fakePage{call: call})
require.NoError(t, err)
require.Equal(t, 1, call.Len())
// Key is provided so it's an update.
Expand All @@ -80,6 +84,20 @@ func TestServerAction_Consume(t *testing.T) {
action.encoder = encoding.NewProtoEncoder()
err = action.Consume(fakeContext{}, fakePage{err: xerrors.New("oops")})
require.EqualError(t, err, "couldn't write access: oops")

action.darcAction.key = []byte{0x01}
err = action.Consume(fakeContext{}, fakePage{err: xerrors.New("oops")})
require.EqualError(t, err, "couldn't read value: oops")

action.darcFactory = badArcFactory{}
err = action.Consume(fakeContext{}, fakePage{})
require.EqualError(t, err, "couldn't decode access: oops")

action.darcFactory = NewFactory()
action.access.rules[UpdateAccessRule].matches["cat"] = struct{}{}
err = action.Consume(fakeContext{identity: []byte("cat")}, fakePage{})
require.EqualError(t, err,
"no access: couldn't match 'darc:update': couldn't match identity 'cat'")
}

func TestActionFactory_FromProto(t *testing.T) {
Expand All @@ -101,20 +119,38 @@ func TestActionFactory_FromProto(t *testing.T) {
// -----------------------------------------------------------------------------
// Utility functions

var testAccess = &AccessProto{
Rules: map[string]*Expression{
UpdateAccessRule: {Matches: []string{"doggy"}},
},
}

type fakeContext struct {
basic.Context
identity []byte
}

func (ctx fakeContext) GetID() []byte {
return []byte{0x34}
}

func (ctx fakeContext) GetIdentity() arc.Identity {
if ctx.identity != nil {
return fakeIdentity{buffer: ctx.identity}
}
return fakeIdentity{buffer: []byte("doggy")}
}

type fakePage struct {
inventory.WritablePage
call *fake.Call
err error
}

func (page fakePage) Read(key []byte) (proto.Message, error) {
return testAccess, page.err
}

func (page fakePage) Write(key []byte, value proto.Message) error {
page.call.Add(key, value)

Expand Down
5 changes: 2 additions & 3 deletions ledger/arc/darc/expr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package darc

import (
"bytes"
fmt "fmt"
"testing"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -48,7 +47,7 @@ func TestExpression_Match(t *testing.T) {
require.NoError(t, err)

err = expr.Match([]arc.Identity{fakeIdentity{buffer: []byte{0xcc}}})
require.EqualError(t, err, "couldn't match identity '0xcc'")
require.EqualError(t, err, "couldn't match identity '\xcc'")

err = expr.Match([]arc.Identity{fakeIdentity{err: xerrors.New("oops")}})
require.EqualError(t, err, "couldn't marshal identity: oops")
Expand Down Expand Up @@ -98,5 +97,5 @@ func (i fakeIdentity) MarshalText() ([]byte, error) {
}

func (i fakeIdentity) String() string {
return fmt.Sprintf("%#x", i.buffer)
return string(i.buffer)
}
7 changes: 6 additions & 1 deletion ledger/arc/darc/mod.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ func (ac Access) Match(rule string, targets ...arc.Identity) error {
return xerrors.Errorf("rule '%s' not found", rule)
}

return expr.Match(targets)
err := expr.Match(targets)
if err != nil {
return xerrors.Errorf("couldn't match '%s': %v", rule, err)
}

return nil
}

// Fingerprint implements encoding.Fingerprinter. It serializes the access to
Expand Down
4 changes: 4 additions & 0 deletions ledger/arc/darc/mod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ func TestAccess_Match(t *testing.T) {

err = access.Match("unknown", idents...)
require.EqualError(t, err, "rule 'unknown' not found")

err = access.Match("fake", fakeIdentity{buffer: []byte{0xcc}})
require.EqualError(t, err,
"couldn't match 'fake': couldn't match identity '\xcc'")
}

func TestAccess_Fingerprint(t *testing.T) {
Expand Down
18 changes: 0 additions & 18 deletions ledger/byzcoin/mod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

proto "github.com/golang/protobuf/proto"
"github.com/stretchr/testify/require"
"go.dedis.ch/fabric/blockchain"
"go.dedis.ch/fabric/crypto"
"go.dedis.ch/fabric/crypto/bls"
"go.dedis.ch/fabric/encoding"
Expand Down Expand Up @@ -166,20 +165,3 @@ func makeDarc(t *testing.T, signer crypto.Signer) darc.Access {

return access
}

type fakeBlock struct {
blockchain.Block
}

func (b fakeBlock) GetIndex() uint64 {
return 0
}

type fakeBlockchain struct {
blockchain.Blockchain
err error
}

func (bc fakeBlockchain) GetBlock() (blockchain.Block, error) {
return fakeBlock{}, bc.err
}
11 changes: 1 addition & 10 deletions ledger/byzcoin/txproc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
any "github.com/golang/protobuf/ptypes/any"
"github.com/stretchr/testify/require"
"go.dedis.ch/fabric/ledger/inventory"
"go.dedis.ch/fabric/ledger/transactions"
"golang.org/x/xerrors"
)

Expand Down Expand Up @@ -59,6 +58,7 @@ func TestTxProcessor_Process(t *testing.T) {
proc.inventory = fakeInventory{page: &fakePage{}}
page, err = proc.process(payload)
require.NoError(t, err)
require.NotNil(t, page)
}

func TestTxProcessor_Commit(t *testing.T) {
Expand Down Expand Up @@ -146,12 +146,3 @@ func (inv fakeInventory) Stage(f func(inventory.WritablePage) error) (inventory.
func (inv fakeInventory) Commit([]byte) error {
return inv.err
}

type fakeTxFactory struct {
transactions.TransactionFactory
err error
}

func (f fakeTxFactory) FromProto(proto.Message) (transactions.ServerTransaction, error) {
return nil, f.err
}

0 comments on commit 200e1a0

Please sign in to comment.