Skip to content

Commit 16e170c

Browse files
author
Jason Yellick
committed
[FAB-1576] Enable deliver request policy filtering
https://jira.hyperledger.org/browse/FAB-1576 This changeset completes the enablement of deliver request filtering based on the orderer egress policy. Change-Id: I62b3dbcef2f733d2520e5bf39ef4c11fcb6bfcb5 Signed-off-by: Jason Yellick <[email protected]>
1 parent 3737e31 commit 16e170c

File tree

5 files changed

+87
-17
lines changed

5 files changed

+87
-17
lines changed

orderer/common/deliver/deliver.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ import (
2020
"fmt"
2121

2222
"github.com/hyperledger/fabric/common/policies"
23+
"github.com/hyperledger/fabric/orderer/common/filter"
24+
"github.com/hyperledger/fabric/orderer/common/sharedconfig"
25+
"github.com/hyperledger/fabric/orderer/common/sigfilter"
2326
"github.com/hyperledger/fabric/orderer/rawledger"
2427
cb "github.com/hyperledger/fabric/protos/common"
2528
ab "github.com/hyperledger/fabric/protos/orderer"
@@ -47,6 +50,9 @@ type Support interface {
4750

4851
// Reader returns the chain Reader for the chain
4952
Reader() rawledger.Reader
53+
54+
// SharedConfig returns the shared config manager for this chain
55+
SharedConfig() sharedconfig.Manager
5056
}
5157

5258
type deliverServer struct {
@@ -86,7 +92,11 @@ func (ds *deliverServer) Handle(srv ab.AtomicBroadcast_DeliverServer) error {
8692
return sendStatusReply(srv, cb.Status_NOT_FOUND)
8793
}
8894

89-
// XXX add deliver authorization checking
95+
sf := sigfilter.New(chain.SharedConfig().EgressPolicy, chain.PolicyManager())
96+
result, _ := sf.Apply(envelope)
97+
if result != filter.Forward {
98+
return sendStatusReply(srv, cb.Status_FORBIDDEN)
99+
}
90100

91101
seekInfo := &ab.SeekInfo{}
92102
if err = proto.Unmarshal(payload.Data, seekInfo); err != nil {

orderer/common/deliver/deliver_test.go

+48-11
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ import (
2323

2424
"github.com/hyperledger/fabric/common/policies"
2525
"github.com/hyperledger/fabric/orderer/common/bootstrap/provisional"
26+
"github.com/hyperledger/fabric/orderer/common/sharedconfig"
2627
"github.com/hyperledger/fabric/orderer/localconfig"
28+
mockpolicies "github.com/hyperledger/fabric/orderer/mocks/policies"
29+
mocksharedconfig "github.com/hyperledger/fabric/orderer/mocks/sharedconfig"
2730
"github.com/hyperledger/fabric/orderer/rawledger"
2831
"github.com/hyperledger/fabric/orderer/rawledger/ramledger"
2932
cb "github.com/hyperledger/fabric/protos/common"
@@ -81,11 +84,13 @@ func (mm *mockSupportManager) GetChain(chainID string) (Support, bool) {
8184
}
8285

8386
type mockSupport struct {
84-
ledger rawledger.ReadWriter
87+
ledger rawledger.ReadWriter
88+
sharedConfig *mocksharedconfig.Manager
89+
policyManager *mockpolicies.Manager
8590
}
8691

8792
func (mcs *mockSupport) PolicyManager() policies.Manager {
88-
panic("Unimplemented")
93+
return mcs.policyManager
8994
}
9095

9196
func (mcs *mockSupport) Reader() rawledger.Reader {
@@ -99,13 +104,19 @@ func NewRAMLedger() rawledger.ReadWriter {
99104
return rl
100105
}
101106

107+
func (mcs *mockSupport) SharedConfig() sharedconfig.Manager {
108+
return mcs.sharedConfig
109+
}
110+
102111
func newMockMultichainManager() *mockSupportManager {
103112
rl := NewRAMLedger()
104113
mm := &mockSupportManager{
105114
chains: make(map[string]*mockSupport),
106115
}
107-
mm.chains[string(systemChainID)] = &mockSupport{
108-
ledger: rl,
116+
mm.chains[systemChainID] = &mockSupport{
117+
ledger: rl,
118+
sharedConfig: &mocksharedconfig.Manager{},
119+
policyManager: &mockpolicies.Manager{Policy: &mockpolicies.Policy{}},
109120
}
110121
return mm
111122
}
@@ -134,7 +145,7 @@ func makeSeek(chainID string, seekInfo *ab.SeekInfo) *cb.Envelope {
134145
func TestOldestSeek(t *testing.T) {
135146
mm := newMockMultichainManager()
136147
for i := 1; i < ledgerSize; i++ {
137-
ledger := mm.chains[string(systemChainID)].ledger
148+
ledger := mm.chains[systemChainID].ledger
138149
ledger.Append(rawledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
139150
}
140151

@@ -173,7 +184,7 @@ func TestOldestSeek(t *testing.T) {
173184
func TestNewestSeek(t *testing.T) {
174185
mm := newMockMultichainManager()
175186
for i := 1; i < ledgerSize; i++ {
176-
ledger := mm.chains[string(systemChainID)].ledger
187+
ledger := mm.chains[systemChainID].ledger
177188
ledger.Append(rawledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
178189
}
179190

@@ -205,7 +216,7 @@ func TestNewestSeek(t *testing.T) {
205216
func TestSpecificSeek(t *testing.T) {
206217
mm := newMockMultichainManager()
207218
for i := 1; i < ledgerSize; i++ {
208-
ledger := mm.chains[string(systemChainID)].ledger
219+
ledger := mm.chains[systemChainID].ledger
209220
ledger.Append(rawledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
210221
}
211222

@@ -240,10 +251,36 @@ func TestSpecificSeek(t *testing.T) {
240251
}
241252
}
242253

254+
func TestUnauthorizedSeek(t *testing.T) {
255+
mm := newMockMultichainManager()
256+
for i := 1; i < ledgerSize; i++ {
257+
ledger := mm.chains[systemChainID].ledger
258+
ledger.Append(rawledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
259+
}
260+
mm.chains[systemChainID].policyManager.Policy.Err = fmt.Errorf("Fail to evaluate policy")
261+
262+
m := newMockD()
263+
defer close(m.recvChan)
264+
ds := NewHandlerImpl(mm)
265+
266+
go ds.Handle(m)
267+
268+
m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekSpecified(uint64(0)), Stop: seekSpecified(uint64(0)), Behavior: ab.SeekInfo_BLOCK_UNTIL_READY})
269+
270+
select {
271+
case deliverReply := <-m.sendChan:
272+
if deliverReply.GetStatus() != cb.Status_FORBIDDEN {
273+
t.Fatalf("Received wrong error on the reply channel")
274+
}
275+
case <-time.After(time.Second):
276+
t.Fatalf("Timed out waiting to get all blocks")
277+
}
278+
}
279+
243280
func TestBadSeek(t *testing.T) {
244281
mm := newMockMultichainManager()
245282
for i := 1; i < ledgerSize; i++ {
246-
ledger := mm.chains[string(systemChainID)].ledger
283+
ledger := mm.chains[systemChainID].ledger
247284
ledger.Append(rawledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
248285
}
249286

@@ -268,7 +305,7 @@ func TestBadSeek(t *testing.T) {
268305
func TestFailFastSeek(t *testing.T) {
269306
mm := newMockMultichainManager()
270307
for i := 1; i < ledgerSize; i++ {
271-
ledger := mm.chains[string(systemChainID)].ledger
308+
ledger := mm.chains[systemChainID].ledger
272309
ledger.Append(rawledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
273310
}
274311

@@ -302,7 +339,7 @@ func TestFailFastSeek(t *testing.T) {
302339
func TestBlockingSeek(t *testing.T) {
303340
mm := newMockMultichainManager()
304341
for i := 1; i < ledgerSize; i++ {
305-
ledger := mm.chains[string(systemChainID)].ledger
342+
ledger := mm.chains[systemChainID].ledger
306343
ledger.Append(rawledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
307344
}
308345

@@ -329,7 +366,7 @@ func TestBlockingSeek(t *testing.T) {
329366
case <-time.After(50 * time.Millisecond):
330367
}
331368

332-
ledger := mm.chains[string(systemChainID)].ledger
369+
ledger := mm.chains[systemChainID].ledger
333370
ledger.Append(rawledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", ledgerSize+1))}}))
334371

335372
select {

orderer/common/sigfilter/sigfilter.go

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ type sigFilter struct {
3333

3434
// New creates a new signature filter, at every evaluation, the policySource is called
3535
// just before evaluation to get the policy name to use when evaluating the filter
36+
// In general, both the policy name and the policy itself are mutable, this is why
37+
// not only the policy is retrieved at each invocation, but also the name of which
38+
// policy to retrieve
3639
func New(policySource func() string, policyManager policies.Manager) filter.Rule {
3740
return &sigFilter{
3841
policySource: policySource,

orderer/multichain/chainsupport.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"github.com/hyperledger/fabric/common/util"
2323
"github.com/hyperledger/fabric/orderer/common/blockcutter"
2424
"github.com/hyperledger/fabric/orderer/common/broadcast"
25-
"github.com/hyperledger/fabric/orderer/common/deliver"
2625
"github.com/hyperledger/fabric/orderer/common/filter"
2726
"github.com/hyperledger/fabric/orderer/common/sharedconfig"
2827
"github.com/hyperledger/fabric/orderer/common/sigfilter"
@@ -70,8 +69,16 @@ type ConsenterSupport interface {
7069

7170
// ChainSupport provides a wrapper for the resources backing a chain
7271
type ChainSupport interface {
72+
// This interface is actually the union with the deliver.Support but because of a golang
73+
// limitation https://github.com/golang/go/issues/6977 the methods must be explicitly declared
74+
75+
// PolicyManager returns the current policy manager as specified by the chain configuration
76+
PolicyManager() policies.Manager
77+
78+
// Reader returns the chain Reader for the chain
79+
Reader() rawledger.Reader
80+
7381
broadcast.Support
74-
deliver.Support
7582
ConsenterSupport
7683

7784
// ConfigTxManager returns the corresponding configtx.Manager for this chain

orderer/sbft/backend/backendab.go

+16-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ package backend
1919
import (
2020
"github.com/hyperledger/fabric/common/policies"
2121
"github.com/hyperledger/fabric/orderer/common/deliver"
22+
"github.com/hyperledger/fabric/orderer/common/sharedconfig"
23+
mockpolicies "github.com/hyperledger/fabric/orderer/mocks/policies"
24+
mocksharedconfig "github.com/hyperledger/fabric/orderer/mocks/sharedconfig"
2225
"github.com/hyperledger/fabric/orderer/rawledger"
2326
cb "github.com/hyperledger/fabric/protos/common"
2427
ab "github.com/hyperledger/fabric/protos/orderer"
@@ -39,11 +42,17 @@ func (xxx *xxxSupportManager) GetChain(id string) (deliver.Support, bool) {
3942
}
4043

4144
type xxxSupport struct {
42-
reader rawledger.Reader
45+
reader rawledger.Reader
46+
sharedConfig sharedconfig.Manager
47+
policyManager policies.Manager
4348
}
4449

4550
func (xxx *xxxSupport) PolicyManager() policies.Manager {
46-
panic("Unimplemented")
51+
return xxx.policyManager
52+
}
53+
54+
func (xxx *xxxSupport) SharedConfig() sharedconfig.Manager {
55+
return xxx.sharedConfig
4756
}
4857

4958
func (xxx *xxxSupport) Reader() rawledger.Reader {
@@ -77,7 +86,11 @@ func NewBackendAB(backend *Backend) *BackendAB {
7786

7887
manager := &xxxSupportManager{
7988
chainID: payload.Header.ChainHeader.ChainID,
80-
support: &xxxSupport{reader: backend.ledger},
89+
support: &xxxSupport{
90+
reader: backend.ledger,
91+
sharedConfig: &mocksharedconfig.Manager{},
92+
policyManager: &mockpolicies.Manager{Policy: &mockpolicies.Policy{}},
93+
},
8194
}
8295
// XXX End hackiness
8396

0 commit comments

Comments
 (0)