forked from hyperledger/fabric
-
Notifications
You must be signed in to change notification settings - Fork 0
/
support.go
145 lines (126 loc) · 4.97 KB
/
support.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package acl
import (
"github.com/hyperledger/fabric/common/channelconfig"
"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/common/policies"
cb "github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/msp"
"github.com/pkg/errors"
)
var (
logger = flogging.MustGetLogger("discovery.acl")
)
// ChannelConfigGetter enables to retrieve the channel config resources
type ChannelConfigGetter interface {
// GetChannelConfig returns the resources of the channel config
GetChannelConfig(cid string) channelconfig.Resources
}
// ChannelConfigGetterFunc returns the resources of the channel config
type ChannelConfigGetterFunc func(cid string) channelconfig.Resources
// GetChannelConfig returns the resources of the channel config
func (f ChannelConfigGetterFunc) GetChannelConfig(cid string) channelconfig.Resources {
return f(cid)
}
// Verifier verifies a signature and a message
type Verifier interface {
// VerifyByChannel checks that signature is a valid signature of message
// under a peer's verification key, but also in the context of a specific channel.
// If the verification succeeded, Verify returns nil meaning no error occurred.
// If peerIdentity is nil, then the verification fails.
VerifyByChannel(channel string, sd *cb.SignedData) error
}
// Evaluator evaluates signatures.
// It is used to evaluate signatures for the local MSP
type Evaluator interface {
// Evaluate takes a set of SignedData and evaluates whether this set of signatures satisfies the policy
Evaluate(signatureSet []*cb.SignedData) error
}
// DiscoverySupport implements support that is used for service discovery
// that is related to access control
type DiscoverySupport struct {
ChannelConfigGetter
Verifier
Evaluator
}
// NewDiscoverySupport creates a new DiscoverySupport
func NewDiscoverySupport(v Verifier, e Evaluator, chanConf ChannelConfigGetter) *DiscoverySupport {
return &DiscoverySupport{Verifier: v, Evaluator: e, ChannelConfigGetter: chanConf}
}
// Eligible returns whether the given peer is eligible for receiving
// service from the discovery service for a given channel
func (s *DiscoverySupport) EligibleForService(channel string, data cb.SignedData) error {
if channel == "" {
return s.Evaluate([]*cb.SignedData{&data})
}
return s.VerifyByChannel(channel, &data)
}
// ConfigSequence returns the configuration sequence of the given channel
func (s *DiscoverySupport) ConfigSequence(channel string) uint64 {
// No sequence if the channel is empty
if channel == "" {
return 0
}
conf := s.GetChannelConfig(channel)
if conf == nil {
logger.Panic("Failed obtaining channel config for channel", channel)
}
v := conf.ConfigtxValidator()
if v == nil {
logger.Panic("ConfigtxValidator for channel", channel, "is nil")
}
return v.Sequence()
}
func (s *DiscoverySupport) SatisfiesPrincipal(channel string, rawIdentity []byte, principal *msp.MSPPrincipal) error {
conf := s.GetChannelConfig(channel)
if conf == nil {
return errors.Errorf("channel %s doesn't exist", channel)
}
mspMgr := conf.MSPManager()
if mspMgr == nil {
return errors.Errorf("could not find MSP manager for channel %s", channel)
}
identity, err := mspMgr.DeserializeIdentity(rawIdentity)
if err != nil {
return errors.Wrap(err, "failed deserializing identity")
}
return identity.SatisfiesPrincipal(principal)
}
//go:generate mockery -name ChannelPolicyManagerGetter -case underscore -output ../mocks/
// ChannelPolicyManagerGetter is a support interface
// to get access to the policy manager of a given channel
type ChannelPolicyManagerGetter interface {
// Returns the policy manager associated to the passed channel
// and true if it was the manager requested, or false if it is the default manager
Manager(channelID string) (policies.Manager, bool)
}
// NewChannelVerifier returns a new channel verifier from the given policy and policy manager getter
func NewChannelVerifier(policy string, polMgr policies.ChannelPolicyManagerGetter) *ChannelVerifier {
return &ChannelVerifier{
Policy: policy,
ChannelPolicyManagerGetter: polMgr,
}
}
// ChannelVerifier verifies a signature and a message on the context of a channel
type ChannelVerifier struct {
policies.ChannelPolicyManagerGetter
Policy string
}
// VerifyByChannel checks that signature is a valid signature of message
// under a peer's verification key, but also in the context of a specific channel.
// If the verification succeeded, Verify returns nil meaning no error occurred.
// If peerIdentity is nil, then the verification fails.
func (cv *ChannelVerifier) VerifyByChannel(channel string, sd *cb.SignedData) error {
mgr, _ := cv.Manager(channel)
if mgr == nil {
return errors.Errorf("policy manager for channel %s doesn't exist", channel)
}
pol, _ := mgr.GetPolicy(cv.Policy)
if pol == nil {
return errors.New("failed obtaining channel application writers policy")
}
return pol.Evaluate([]*cb.SignedData{sd})
}