206 lines
6.8 KiB
Go
206 lines
6.8 KiB
Go
/*
|
|
Copyright IBM Corp. 2016 All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
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
|
|
}
|