-
Notifications
You must be signed in to change notification settings - Fork 8
/
policydsl_builder.go
206 lines (170 loc) · 6.89 KB
/
policydsl_builder.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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*
Copyright IBM Corp. 2016 All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
/*
Notice: This file has been modified for Hyperledger Fabric SDK Go usage.
Please review third_party pinning scripts and patches for more details.
*/
package policydsl
import (
"sort"
"github.com/golang/protobuf/proto"
cb "github.com/hyperledger/fabric-protos-go/common"
mb "github.com/hyperledger/fabric-protos-go/msp"
)
// AcceptAllPolicy always evaluates to true
var AcceptAllPolicy *cb.SignaturePolicyEnvelope
// MarshaledAcceptAllPolicy is the Marshaled version of AcceptAllPolicy
var MarshaledAcceptAllPolicy []byte
// RejectAllPolicy always evaluates to false
var RejectAllPolicy *cb.SignaturePolicyEnvelope
// MarshaledRejectAllPolicy is the Marshaled version of RejectAllPolicy
var MarshaledRejectAllPolicy []byte
func init() {
AcceptAllPolicy = Envelope(NOutOf(0, []*cb.SignaturePolicy{}), [][]byte{})
MarshaledAcceptAllPolicy = protoMarshalOrPanic(AcceptAllPolicy)
RejectAllPolicy = Envelope(NOutOf(1, []*cb.SignaturePolicy{}), [][]byte{})
MarshaledRejectAllPolicy = protoMarshalOrPanic(RejectAllPolicy)
}
// Envelope builds an envelope message embedding a SignaturePolicy
func Envelope(policy *cb.SignaturePolicy, identities [][]byte) *cb.SignaturePolicyEnvelope {
ids := make([]*mb.MSPPrincipal, len(identities))
for i := range ids {
ids[i] = &mb.MSPPrincipal{PrincipalClassification: mb.MSPPrincipal_IDENTITY, Principal: identities[i]}
}
return &cb.SignaturePolicyEnvelope{
Version: 0,
Rule: policy,
Identities: ids,
}
}
// SignedBy creates a SignaturePolicy requiring a given signer's signature
func SignedBy(index int32) *cb.SignaturePolicy {
return &cb.SignaturePolicy{
Type: &cb.SignaturePolicy_SignedBy{
SignedBy: index,
},
}
}
// SignedByMspMember creates a SignaturePolicyEnvelope
// requiring 1 signature from any member of the specified MSP
func SignedByMspMember(mspId string) *cb.SignaturePolicyEnvelope {
return signedByFabricEntity(mspId, mb.MSPRole_MEMBER)
}
// SignedByMspClient creates a SignaturePolicyEnvelope
// requiring 1 signature from any client of the specified MSP
func SignedByMspClient(mspId string) *cb.SignaturePolicyEnvelope {
return signedByFabricEntity(mspId, mb.MSPRole_CLIENT)
}
// SignedByMspPeer creates a SignaturePolicyEnvelope
// requiring 1 signature from any peer of the specified MSP
func SignedByMspPeer(mspId string) *cb.SignaturePolicyEnvelope {
return signedByFabricEntity(mspId, mb.MSPRole_PEER)
}
// SignedByFabricEntity creates a SignaturePolicyEnvelope
// requiring 1 signature from any fabric entity, having the passed role, of the specified MSP
func signedByFabricEntity(mspId string, role mb.MSPRole_MSPRoleType) *cb.SignaturePolicyEnvelope {
// specify the principal: it's a member of the msp we just found
principal := &mb.MSPPrincipal{
PrincipalClassification: mb.MSPPrincipal_ROLE,
Principal: protoMarshalOrPanic(&mb.MSPRole{Role: role, MspIdentifier: mspId})}
// create the policy: it requires exactly 1 signature from the first (and only) principal
p := &cb.SignaturePolicyEnvelope{
Version: 0,
Rule: NOutOf(1, []*cb.SignaturePolicy{SignedBy(0)}),
Identities: []*mb.MSPPrincipal{principal},
}
return p
}
// SignedByMspAdmin creates a SignaturePolicyEnvelope
// requiring 1 signature from any admin of the specified MSP
func SignedByMspAdmin(mspId string) *cb.SignaturePolicyEnvelope {
// specify the principal: it's a member of the msp we just found
principal := &mb.MSPPrincipal{
PrincipalClassification: mb.MSPPrincipal_ROLE,
Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_ADMIN, MspIdentifier: mspId})}
// create the policy: it requires exactly 1 signature from the first (and only) principal
p := &cb.SignaturePolicyEnvelope{
Version: 0,
Rule: NOutOf(1, []*cb.SignaturePolicy{SignedBy(0)}),
Identities: []*mb.MSPPrincipal{principal},
}
return p
}
//wrapper for generating "any of a given role" type policies
func signedByAnyOfGivenRole(role mb.MSPRole_MSPRoleType, ids []string) *cb.SignaturePolicyEnvelope {
return SignedByNOutOfGivenRole(1, role, ids)
}
func SignedByNOutOfGivenRole(n int32, role mb.MSPRole_MSPRoleType, ids []string) *cb.SignaturePolicyEnvelope {
// we create an array of principals, one principal
// per application MSP defined on this chain
sort.Strings(ids)
principals := make([]*mb.MSPPrincipal, len(ids))
sigspolicy := make([]*cb.SignaturePolicy, len(ids))
for i, id := range ids {
principals[i] = &mb.MSPPrincipal{
PrincipalClassification: mb.MSPPrincipal_ROLE,
Principal: protoMarshalOrPanic(&mb.MSPRole{Role: role, MspIdentifier: id})}
sigspolicy[i] = SignedBy(int32(i))
}
// create the policy: it requires exactly 1 signature from any of the principals
p := &cb.SignaturePolicyEnvelope{
Version: 0,
Rule: NOutOf(n, sigspolicy),
Identities: principals,
}
return p
}
// SignedByAnyMember returns a policy that requires one valid
// signature from a member of any of the orgs whose ids are
// listed in the supplied string array
func SignedByAnyMember(ids []string) *cb.SignaturePolicyEnvelope {
return signedByAnyOfGivenRole(mb.MSPRole_MEMBER, ids)
}
// SignedByAnyClient returns a policy that requires one valid
// signature from a client of any of the orgs whose ids are
// listed in the supplied string array
func SignedByAnyClient(ids []string) *cb.SignaturePolicyEnvelope {
return signedByAnyOfGivenRole(mb.MSPRole_CLIENT, ids)
}
// SignedByAnyPeer returns a policy that requires one valid
// signature from an orderer of any of the orgs whose ids are
// listed in the supplied string array
func SignedByAnyPeer(ids []string) *cb.SignaturePolicyEnvelope {
return signedByAnyOfGivenRole(mb.MSPRole_PEER, ids)
}
// SignedByAnyAdmin returns a policy that requires one valid
// signature from a admin of any of the orgs whose ids are
// listed in the supplied string array
func SignedByAnyAdmin(ids []string) *cb.SignaturePolicyEnvelope {
return signedByAnyOfGivenRole(mb.MSPRole_ADMIN, ids)
}
// And is a convenience method which utilizes NOutOf to produce And equivalent behavior
func And(lhs, rhs *cb.SignaturePolicy) *cb.SignaturePolicy {
return NOutOf(2, []*cb.SignaturePolicy{lhs, rhs})
}
// Or is a convenience method which utilizes NOutOf to produce Or equivalent behavior
func Or(lhs, rhs *cb.SignaturePolicy) *cb.SignaturePolicy {
return NOutOf(1, []*cb.SignaturePolicy{lhs, rhs})
}
// NOutOf creates a policy which requires N out of the slice of policies to evaluate to true
func NOutOf(n int32, policies []*cb.SignaturePolicy) *cb.SignaturePolicy {
return &cb.SignaturePolicy{
Type: &cb.SignaturePolicy_NOutOf_{
NOutOf: &cb.SignaturePolicy_NOutOf{
N: n,
Rules: policies,
},
},
}
}
// protoMarshalOrPanic serializes a protobuf message and panics if this
// operation fails
func protoMarshalOrPanic(pb proto.Message) []byte {
data, err := proto.Marshal(pb)
if err != nil {
panic(err)
}
return data
}