github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/policydsl/policydsl_builder.go (about)

     1  /*
     2  Copyright hechain. 2022 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package policydsl
     8  
     9  import (
    10  	"sort"
    11  
    12  	"github.com/golang/protobuf/proto"
    13  	cb "github.com/hyperledger/fabric-protos-go/common"
    14  	mb "github.com/hyperledger/fabric-protos-go/msp"
    15  )
    16  
    17  // AcceptAllPolicy always evaluates to true
    18  var AcceptAllPolicy *cb.SignaturePolicyEnvelope
    19  
    20  // MarshaledAcceptAllPolicy is the Marshaled version of AcceptAllPolicy
    21  var MarshaledAcceptAllPolicy []byte
    22  
    23  // RejectAllPolicy always evaluates to false
    24  var RejectAllPolicy *cb.SignaturePolicyEnvelope
    25  
    26  // MarshaledRejectAllPolicy is the Marshaled version of RejectAllPolicy
    27  var MarshaledRejectAllPolicy []byte
    28  
    29  func init() {
    30  	AcceptAllPolicy = Envelope(NOutOf(0, []*cb.SignaturePolicy{}), [][]byte{})
    31  	MarshaledAcceptAllPolicy = protoMarshalOrPanic(AcceptAllPolicy)
    32  
    33  	RejectAllPolicy = Envelope(NOutOf(1, []*cb.SignaturePolicy{}), [][]byte{})
    34  	MarshaledRejectAllPolicy = protoMarshalOrPanic(RejectAllPolicy)
    35  }
    36  
    37  // Envelope builds an envelope message embedding a SignaturePolicy
    38  func Envelope(policy *cb.SignaturePolicy, identities [][]byte) *cb.SignaturePolicyEnvelope {
    39  	ids := make([]*mb.MSPPrincipal, len(identities))
    40  	for i := range ids {
    41  		ids[i] = &mb.MSPPrincipal{PrincipalClassification: mb.MSPPrincipal_IDENTITY, Principal: identities[i]}
    42  	}
    43  
    44  	return &cb.SignaturePolicyEnvelope{
    45  		Version:    0,
    46  		Rule:       policy,
    47  		Identities: ids,
    48  	}
    49  }
    50  
    51  // SignedBy creates a SignaturePolicy requiring a given signer's signature
    52  func SignedBy(index int32) *cb.SignaturePolicy {
    53  	return &cb.SignaturePolicy{
    54  		Type: &cb.SignaturePolicy_SignedBy{
    55  			SignedBy: index,
    56  		},
    57  	}
    58  }
    59  
    60  // SignedByMspMember creates a SignaturePolicyEnvelope
    61  // requiring 1 signature from any member of the specified MSP
    62  func SignedByMspMember(mspId string) *cb.SignaturePolicyEnvelope {
    63  	return signedByFabricEntity(mspId, mb.MSPRole_MEMBER)
    64  }
    65  
    66  // SignedByMspClient creates a SignaturePolicyEnvelope
    67  // requiring 1 signature from any client of the specified MSP
    68  func SignedByMspClient(mspId string) *cb.SignaturePolicyEnvelope {
    69  	return signedByFabricEntity(mspId, mb.MSPRole_CLIENT)
    70  }
    71  
    72  // SignedByMspPeer creates a SignaturePolicyEnvelope
    73  // requiring 1 signature from any peer of the specified MSP
    74  func SignedByMspPeer(mspId string) *cb.SignaturePolicyEnvelope {
    75  	return signedByFabricEntity(mspId, mb.MSPRole_PEER)
    76  }
    77  
    78  // SignedByFabricEntity creates a SignaturePolicyEnvelope
    79  // requiring 1 signature from any fabric entity, having the passed role, of the specified MSP
    80  func signedByFabricEntity(mspId string, role mb.MSPRole_MSPRoleType) *cb.SignaturePolicyEnvelope {
    81  	// specify the principal: it's a member of the msp we just found
    82  	principal := &mb.MSPPrincipal{
    83  		PrincipalClassification: mb.MSPPrincipal_ROLE,
    84  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: role, MspIdentifier: mspId}),
    85  	}
    86  
    87  	// create the policy: it requires exactly 1 signature from the first (and only) principal
    88  	p := &cb.SignaturePolicyEnvelope{
    89  		Version:    0,
    90  		Rule:       NOutOf(1, []*cb.SignaturePolicy{SignedBy(0)}),
    91  		Identities: []*mb.MSPPrincipal{principal},
    92  	}
    93  
    94  	return p
    95  }
    96  
    97  // SignedByMspAdmin creates a SignaturePolicyEnvelope
    98  // requiring 1 signature from any admin of the specified MSP
    99  func SignedByMspAdmin(mspId string) *cb.SignaturePolicyEnvelope {
   100  	// specify the principal: it's a member of the msp we just found
   101  	principal := &mb.MSPPrincipal{
   102  		PrincipalClassification: mb.MSPPrincipal_ROLE,
   103  		Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_ADMIN, MspIdentifier: mspId}),
   104  	}
   105  
   106  	// create the policy: it requires exactly 1 signature from the first (and only) principal
   107  	p := &cb.SignaturePolicyEnvelope{
   108  		Version:    0,
   109  		Rule:       NOutOf(1, []*cb.SignaturePolicy{SignedBy(0)}),
   110  		Identities: []*mb.MSPPrincipal{principal},
   111  	}
   112  
   113  	return p
   114  }
   115  
   116  // wrapper for generating "any of a given role" type policies
   117  func signedByAnyOfGivenRole(role mb.MSPRole_MSPRoleType, ids []string) *cb.SignaturePolicyEnvelope {
   118  	return SignedByNOutOfGivenRole(1, role, ids)
   119  }
   120  
   121  func SignedByNOutOfGivenRole(n int32, role mb.MSPRole_MSPRoleType, ids []string) *cb.SignaturePolicyEnvelope {
   122  	// we create an array of principals, one principal
   123  	// per application MSP defined on this chain
   124  	sort.Strings(ids)
   125  	principals := make([]*mb.MSPPrincipal, len(ids))
   126  	sigspolicy := make([]*cb.SignaturePolicy, len(ids))
   127  
   128  	for i, id := range ids {
   129  		principals[i] = &mb.MSPPrincipal{
   130  			PrincipalClassification: mb.MSPPrincipal_ROLE,
   131  			Principal:               protoMarshalOrPanic(&mb.MSPRole{Role: role, MspIdentifier: id}),
   132  		}
   133  		sigspolicy[i] = SignedBy(int32(i))
   134  	}
   135  
   136  	// create the policy: it requires exactly 1 signature from any of the principals
   137  	p := &cb.SignaturePolicyEnvelope{
   138  		Version:    0,
   139  		Rule:       NOutOf(n, sigspolicy),
   140  		Identities: principals,
   141  	}
   142  
   143  	return p
   144  }
   145  
   146  // SignedByAnyMember returns a policy that requires one valid
   147  // signature from a member of any of the orgs whose ids are
   148  // listed in the supplied string array
   149  func SignedByAnyMember(ids []string) *cb.SignaturePolicyEnvelope {
   150  	return signedByAnyOfGivenRole(mb.MSPRole_MEMBER, ids)
   151  }
   152  
   153  // SignedByAnyClient returns a policy that requires one valid
   154  // signature from a client of any of the orgs whose ids are
   155  // listed in the supplied string array
   156  func SignedByAnyClient(ids []string) *cb.SignaturePolicyEnvelope {
   157  	return signedByAnyOfGivenRole(mb.MSPRole_CLIENT, ids)
   158  }
   159  
   160  // SignedByAnyPeer returns a policy that requires one valid
   161  // signature from an orderer of any of the orgs whose ids are
   162  // listed in the supplied string array
   163  func SignedByAnyPeer(ids []string) *cb.SignaturePolicyEnvelope {
   164  	return signedByAnyOfGivenRole(mb.MSPRole_PEER, ids)
   165  }
   166  
   167  // SignedByAnyAdmin returns a policy that requires one valid
   168  // signature from a admin of any of the orgs whose ids are
   169  // listed in the supplied string array
   170  func SignedByAnyAdmin(ids []string) *cb.SignaturePolicyEnvelope {
   171  	return signedByAnyOfGivenRole(mb.MSPRole_ADMIN, ids)
   172  }
   173  
   174  // And is a convenience method which utilizes NOutOf to produce And equivalent behavior
   175  func And(lhs, rhs *cb.SignaturePolicy) *cb.SignaturePolicy {
   176  	return NOutOf(2, []*cb.SignaturePolicy{lhs, rhs})
   177  }
   178  
   179  // Or is a convenience method which utilizes NOutOf to produce Or equivalent behavior
   180  func Or(lhs, rhs *cb.SignaturePolicy) *cb.SignaturePolicy {
   181  	return NOutOf(1, []*cb.SignaturePolicy{lhs, rhs})
   182  }
   183  
   184  // NOutOf creates a policy which requires N out of the slice of policies to evaluate to true
   185  func NOutOf(n int32, policies []*cb.SignaturePolicy) *cb.SignaturePolicy {
   186  	return &cb.SignaturePolicy{
   187  		Type: &cb.SignaturePolicy_NOutOf_{
   188  			NOutOf: &cb.SignaturePolicy_NOutOf{
   189  				N:     n,
   190  				Rules: policies,
   191  			},
   192  		},
   193  	}
   194  }
   195  
   196  // protoMarshalOrPanic serializes a protobuf message and panics if this
   197  // operation fails
   198  func protoMarshalOrPanic(pb proto.Message) []byte {
   199  	data, err := proto.Marshal(pb)
   200  	if err != nil {
   201  		panic(err)
   202  	}
   203  
   204  	return data
   205  }