/
application.go
131 lines (109 loc) · 4.94 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
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package policy
import (
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/common/cauthdsl"
"github.com/hyperledger/fabric/common/policies"
"github.com/hyperledger/fabric/msp"
"github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/peer"
"github.com/hyperledger/fabric/protoutil"
"github.com/pkg/errors"
)
// Provider 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)
}
// ChannelPolicyReference 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)
}
//go:generate mockery -dir ../../common/policies/ -name Policy -case underscore -output mocks/
//go:generate mockery -dir ../../common/policies/ -name ChannelPolicyManagerGetter -case underscore -output mocks/
//go:generate mockery -dir ../../common/policies/ -name Manager -case underscore -output mocks/
//go:generate mockery -dir . -name ChannelPolicyReferenceProvider -case underscore -output mocks/
//go:generate mockery -dir . -name SignaturePolicyProvider -case underscore -output mocks/
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, ok := d.channelPolicyManagerGetter.Manager(d.channelID)
if !ok {
// 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) {
_, ok := channelPolicyManagerGetter.Manager(channel)
if !ok {
return nil, errors.Errorf("failed to retrieve policy manager for channel %s", channel)
}
return &ApplicationPolicyEvaluator{
signaturePolicyProvider: &cauthdsl.ProviderFromStruct{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.Evaluate(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.Evaluate(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)
}
}