forked from hyperledger/fabric
-
Notifications
You must be signed in to change notification settings - Fork 0
/
application.go
163 lines (131 loc) · 5.85 KB
/
application.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package policy
import (
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/common/cauthdsl"
"github.com/hyperledger/fabric/common/policies"
"github.com/hyperledger/fabric/msp"
"github.com/hyperledger/fabric/protoutil"
"github.com/pkg/errors"
)
//go:generate mockery -dir . -name Policy -case underscore -output mocks/
// Policy is the local interface that used to generate mocks for foreign interface.
type Policy interface {
policies.Policy
}
//go:generate mockery -dir . -name ChannelPolicyManagerGetter -case underscore -output mocks/
// ChannelPolicyManagerGetter is the local interface that used to generate mocks for foreign interface.
type ChannelPolicyManagerGetter interface {
policies.ChannelPolicyManagerGetter
}
//go:generate mockery -dir . -name PolicyManager -case underscore -output mocks/
// PolicyManager is the local interface that used to generate mocks for foreign interface.
type PolicyManager interface {
policies.Manager
}
//go:generate mockery -dir . -name IdentityDeserializer -case underscore -output mocks/
// IdentityDeserializer is the local interface that used to generate mocks for foreign interface.
type IdentityDeserializer interface {
msp.IdentityDeserializer
}
//go:generate mockery -dir . -name Identity -case underscore -output mocks/
// Identity is the local interface that used to generate mocks for foreign interface.
type Identity interface {
msp.Identity
}
//go:generate mockery -dir . -name ChannelPolicyReferenceProvider -case underscore -output mocks/
//go:generate mockery -dir . -name SignaturePolicyProvider -case underscore -output mocks/
// SignaturePolicyProvider provides the backing implementation of a policy.
type SignaturePolicyProvider interface {
// NewPolicy creates a new policy based on the policy bytes.
NewPolicy(signaturePolicy *common.SignaturePolicyEnvelope) (policies.Policy, error)
}
// ChannelPolicyReferenceProvider is used to determine if a set of signature is valid and complies with a policy.
type ChannelPolicyReferenceProvider interface {
// NewPolicy creates a new policy based on the policy bytes.
NewPolicy(channelConfigPolicyReference string) (policies.Policy, error)
}
type ApplicationPolicyEvaluator struct {
signaturePolicyProvider SignaturePolicyProvider
channelPolicyReferenceProvider ChannelPolicyReferenceProvider
}
// Manager defines functions to interface with the policy manager of a channel
type Manager interface {
// GetPolicy returns a policy and true if it was the policy requested, or false if it is the default policy
GetPolicy(id string) (policies.Policy, bool)
}
type ChannelPolicyReferenceProviderImpl struct {
Manager
}
func (c *ChannelPolicyReferenceProviderImpl) NewPolicy(channelConfigPolicyReference string) (policies.Policy, error) {
p, ok := c.GetPolicy(channelConfigPolicyReference)
if !ok {
return nil, errors.Errorf("failed to retrieve policy for reference %s", channelConfigPolicyReference)
}
return p, nil
}
// dynamicPolicyManager implements a policy manager that
// always acts on the latest config for this channel
type dynamicPolicyManager struct {
channelPolicyManagerGetter policies.ChannelPolicyManagerGetter
channelID string
}
func (d *dynamicPolicyManager) GetPolicy(id string) (policies.Policy, bool) {
mgr := d.channelPolicyManagerGetter.Manager(d.channelID)
if mgr == nil {
// this will never happen - if we are here we
// managed to retrieve the policy manager for
// this channel once, and so by the way the
// channel config is managed, we cannot fail.
panic("programming error")
}
return mgr.GetPolicy(id)
}
// New returns an evaluator for application policies
func New(deserializer msp.IdentityDeserializer, channel string, channelPolicyManagerGetter policies.ChannelPolicyManagerGetter) (*ApplicationPolicyEvaluator, error) {
mgr := channelPolicyManagerGetter.Manager(channel)
if mgr == nil {
return nil, errors.Errorf("failed to retrieve policy manager for channel %s", channel)
}
return &ApplicationPolicyEvaluator{
signaturePolicyProvider: &cauthdsl.EnvelopeBasedPolicyProvider{Deserializer: deserializer},
channelPolicyReferenceProvider: &ChannelPolicyReferenceProviderImpl{Manager: &dynamicPolicyManager{
channelID: channel,
channelPolicyManagerGetter: channelPolicyManagerGetter,
}},
}, nil
}
func (a *ApplicationPolicyEvaluator) evaluateSignaturePolicy(signaturePolicy *common.SignaturePolicyEnvelope, signatureSet []*protoutil.SignedData) error {
p, err := a.signaturePolicyProvider.NewPolicy(signaturePolicy)
if err != nil {
return errors.WithMessage(err, "could not create evaluator for signature policy")
}
return p.EvaluateSignedData(signatureSet)
}
func (a *ApplicationPolicyEvaluator) evaluateChannelConfigPolicyReference(channelConfigPolicyReference string, signatureSet []*protoutil.SignedData) error {
p, err := a.channelPolicyReferenceProvider.NewPolicy(channelConfigPolicyReference)
if err != nil {
return errors.WithMessage(err, "could not create evaluator for channel reference policy")
}
return p.EvaluateSignedData(signatureSet)
}
func (a *ApplicationPolicyEvaluator) Evaluate(policyBytes []byte, signatureSet []*protoutil.SignedData) error {
p := &peer.ApplicationPolicy{}
err := proto.Unmarshal(policyBytes, p)
if err != nil {
return errors.Wrap(err, "failed to unmarshal ApplicationPolicy bytes")
}
switch policy := p.Type.(type) {
case *peer.ApplicationPolicy_SignaturePolicy:
return a.evaluateSignaturePolicy(policy.SignaturePolicy, signatureSet)
case *peer.ApplicationPolicy_ChannelConfigPolicyReference:
return a.evaluateChannelConfigPolicyReference(policy.ChannelConfigPolicyReference, signatureSet)
default:
return errors.Errorf("unsupported policy type %T", policy)
}
}