forked from hyperledger/fabric
-
Notifications
You must be signed in to change notification settings - Fork 0
/
policy.go
141 lines (115 loc) · 3.94 KB
/
policy.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
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package cauthdsl
import (
"errors"
"fmt"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/common/policies"
"github.com/hyperledger/fabric/msp"
cb "github.com/hyperledger/fabric/protos/common"
mspp "github.com/hyperledger/fabric/protos/msp"
)
type Identity interface {
// SatisfiesPrincipal checks whether this instance matches
// the description supplied in MSPPrincipal. The check may
// involve a byte-by-byte comparison (if the principal is
// a serialized identity) or may require MSP validation
SatisfiesPrincipal(principal *mspp.MSPPrincipal) error
// GetIdentifier returns the identifier of that identity
GetIdentifier() *msp.IdentityIdentifier
}
type IdentityAndSignature interface {
// Identity returns the identity associated to this instance
Identity() (Identity, error)
// Verify returns the validity status of this identity's signature over the message
Verify() error
}
type deserializeAndVerify struct {
signedData *cb.SignedData
deserializer msp.IdentityDeserializer
deserializedIdentity msp.Identity
}
func (d *deserializeAndVerify) Identity() (Identity, error) {
deserializedIdentity, err := d.deserializer.DeserializeIdentity(d.signedData.Identity)
if err != nil {
return nil, err
}
d.deserializedIdentity = deserializedIdentity
return deserializedIdentity, nil
}
func (d *deserializeAndVerify) Verify() error {
if d.deserializedIdentity == nil {
cauthdslLogger.Panicf("programming error, Identity must be called prior to Verify")
}
return d.deserializedIdentity.Verify(d.signedData.Data, d.signedData.Signature)
}
type provider struct {
deserializer msp.IdentityDeserializer
}
// NewProviderImpl provides a policy generator for cauthdsl type policies
func NewPolicyProvider(deserializer msp.IdentityDeserializer) policies.Provider {
return &provider{
deserializer: deserializer,
}
}
// NewPolicy creates a new policy based on the policy bytes
func (pr *provider) NewPolicy(data []byte) (policies.Policy, proto.Message, error) {
sigPolicy := &cb.SignaturePolicyEnvelope{}
if err := proto.Unmarshal(data, sigPolicy); err != nil {
return nil, nil, fmt.Errorf("Error unmarshaling to SignaturePolicy: %s", err)
}
if sigPolicy.Version != 0 {
return nil, nil, fmt.Errorf("This evaluator only understands messages of version 0, but version was %d", sigPolicy.Version)
}
compiled, err := compile(sigPolicy.Rule, sigPolicy.Identities, pr.deserializer)
if err != nil {
return nil, nil, err
}
return &policy{
evaluator: compiled,
deserializer: pr.deserializer,
}, sigPolicy, nil
}
// EnvelopeBasedPolicyProvider allows to create a new policy from SignaturePolicyEnvelope struct instead of []byte
type EnvelopeBasedPolicyProvider struct {
Deserializer msp.IdentityDeserializer
}
// NewPolicy creates a new policy from the policy envelope
func (pp *EnvelopeBasedPolicyProvider) NewPolicy(sigPolicy *cb.SignaturePolicyEnvelope) (policies.Policy, error) {
if sigPolicy == nil {
return nil, errors.New("invalid arguments")
}
compiled, err := compile(sigPolicy.Rule, sigPolicy.Identities, pp.Deserializer)
if err != nil {
return nil, err
}
return &policy{
evaluator: compiled,
deserializer: pp.Deserializer,
}, nil
}
type policy struct {
evaluator func([]IdentityAndSignature, []bool) bool
deserializer msp.IdentityDeserializer
}
// Evaluate takes a set of SignedData and evaluates whether this set of signatures satisfies the policy
func (p *policy) Evaluate(signatureSet []*cb.SignedData) error {
if p == nil {
return fmt.Errorf("No such policy")
}
idAndS := make([]IdentityAndSignature, len(signatureSet))
for i, sd := range signatureSet {
idAndS[i] = &deserializeAndVerify{
signedData: sd,
deserializer: p.deserializer,
}
}
ok := p.evaluator(deduplicate(idAndS), make([]bool, len(signatureSet)))
if !ok {
return errors.New("signature set did not satisfy policy")
}
return nil
}