github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/common/policies/policy.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package policies
     8  
     9  import (
    10  	"fmt"
    11  	"strings"
    12  
    13  	"github.com/golang/protobuf/proto"
    14  	cb "github.com/hyperledger/fabric-protos-go/common"
    15  	"github.com/hyperledger/fabric-protos-go/msp"
    16  	"github.com/hyperledger/fabric/common/flogging"
    17  	mspi "github.com/hyperledger/fabric/msp"
    18  	"github.com/hyperledger/fabric/protoutil"
    19  	"github.com/pkg/errors"
    20  	"go.uber.org/zap/zapcore"
    21  )
    22  
    23  const (
    24  	// Path separator is used to separate policy names in paths
    25  	PathSeparator = "/"
    26  
    27  	// ChannelPrefix is used in the path of standard channel policy managers
    28  	ChannelPrefix = "Channel"
    29  
    30  	// ApplicationPrefix is used in the path of standard application policy paths
    31  	ApplicationPrefix = "Application"
    32  
    33  	// OrdererPrefix is used in the path of standard orderer policy paths
    34  	OrdererPrefix = "Orderer"
    35  
    36  	// ChannelReaders is the label for the channel's readers policy (encompassing both orderer and application readers)
    37  	ChannelReaders = PathSeparator + ChannelPrefix + PathSeparator + "Readers"
    38  
    39  	// ChannelWriters is the label for the channel's writers policy (encompassing both orderer and application writers)
    40  	ChannelWriters = PathSeparator + ChannelPrefix + PathSeparator + "Writers"
    41  
    42  	// ChannelApplicationReaders is the label for the channel's application readers policy
    43  	ChannelApplicationReaders = PathSeparator + ChannelPrefix + PathSeparator + ApplicationPrefix + PathSeparator + "Readers"
    44  
    45  	// ChannelApplicationWriters is the label for the channel's application writers policy
    46  	ChannelApplicationWriters = PathSeparator + ChannelPrefix + PathSeparator + ApplicationPrefix + PathSeparator + "Writers"
    47  
    48  	// ChannelApplicationAdmins is the label for the channel's application admin policy
    49  	ChannelApplicationAdmins = PathSeparator + ChannelPrefix + PathSeparator + ApplicationPrefix + PathSeparator + "Admins"
    50  
    51  	// BlockValidation is the label for the policy which should validate the block signatures for the channel
    52  	BlockValidation = PathSeparator + ChannelPrefix + PathSeparator + OrdererPrefix + PathSeparator + "BlockValidation"
    53  
    54  	// ChannelOrdererAdmins is the label for the channel's orderer admin policy
    55  	ChannelOrdererAdmins = PathSeparator + ChannelPrefix + PathSeparator + OrdererPrefix + PathSeparator + "Admins"
    56  
    57  	// ChannelOrdererWriters is the label for the channel's orderer writers policy
    58  	ChannelOrdererWriters = PathSeparator + ChannelPrefix + PathSeparator + OrdererPrefix + PathSeparator + "Writers"
    59  
    60  	// ChannelOrdererReaders is the label for the channel's orderer readers policy
    61  	ChannelOrdererReaders = PathSeparator + ChannelPrefix + PathSeparator + OrdererPrefix + PathSeparator + "Readers"
    62  )
    63  
    64  var logger = flogging.MustGetLogger("policies")
    65  
    66  // PrincipalSet is a collection of MSPPrincipals
    67  type PrincipalSet []*msp.MSPPrincipal
    68  
    69  // PrincipalSets aggregates PrincipalSets
    70  type PrincipalSets []PrincipalSet
    71  
    72  // ContainingOnly returns PrincipalSets that contain only principals of the given predicate
    73  func (psSets PrincipalSets) ContainingOnly(f func(*msp.MSPPrincipal) bool) PrincipalSets {
    74  	var res PrincipalSets
    75  	for _, set := range psSets {
    76  		if !set.ContainingOnly(f) {
    77  			continue
    78  		}
    79  		res = append(res, set)
    80  	}
    81  	return res
    82  }
    83  
    84  // ContainingOnly returns whether the given PrincipalSet contains only Principals
    85  // that satisfy the given predicate
    86  func (ps PrincipalSet) ContainingOnly(f func(*msp.MSPPrincipal) bool) bool {
    87  	for _, principal := range ps {
    88  		if !f(principal) {
    89  			return false
    90  		}
    91  	}
    92  	return true
    93  }
    94  
    95  // UniqueSet returns a histogram that is induced by the PrincipalSet
    96  func (ps PrincipalSet) UniqueSet() map[*msp.MSPPrincipal]int {
    97  	// Create a histogram that holds the MSPPrincipals and counts them
    98  	histogram := make(map[struct {
    99  		cls       int32
   100  		principal string
   101  	}]int)
   102  	// Now, populate the histogram
   103  	for _, principal := range ps {
   104  		key := struct {
   105  			cls       int32
   106  			principal string
   107  		}{
   108  			cls:       int32(principal.PrincipalClassification),
   109  			principal: string(principal.Principal),
   110  		}
   111  		histogram[key]++
   112  	}
   113  	// Finally, convert to a histogram of MSPPrincipal pointers
   114  	res := make(map[*msp.MSPPrincipal]int)
   115  	for principal, count := range histogram {
   116  		res[&msp.MSPPrincipal{
   117  			PrincipalClassification: msp.MSPPrincipal_Classification(principal.cls),
   118  			Principal:               []byte(principal.principal),
   119  		}] = count
   120  	}
   121  	return res
   122  }
   123  
   124  // Converter represents a policy
   125  // which may be translated into a SignaturePolicyEnvelope
   126  type Converter interface {
   127  	Convert() (*cb.SignaturePolicyEnvelope, error)
   128  }
   129  
   130  // Policy is used to determine if a signature is valid
   131  type Policy interface {
   132  	// EvaluateSignedData takes a set of SignedData and evaluates whether
   133  	// 1) the signatures are valid over the related message
   134  	// 2) the signing identities satisfy the policy
   135  	EvaluateSignedData(signatureSet []*protoutil.SignedData) error
   136  
   137  	// EvaluateIdentities takes an array of identities and evaluates whether
   138  	// they satisfy the policy
   139  	EvaluateIdentities(identities []mspi.Identity) error
   140  }
   141  
   142  // InquireablePolicy is a Policy that one can inquire
   143  type InquireablePolicy interface {
   144  	// SatisfiedBy returns a slice of PrincipalSets that each of them
   145  	// satisfies the policy.
   146  	SatisfiedBy() []PrincipalSet
   147  }
   148  
   149  // Manager is a read only subset of the policy ManagerImpl
   150  type Manager interface {
   151  	// GetPolicy returns a policy and true if it was the policy requested, or false if it is the default policy
   152  	GetPolicy(id string) (Policy, bool)
   153  
   154  	// Manager returns the sub-policy manager for a given path and whether it exists
   155  	Manager(path []string) (Manager, bool)
   156  }
   157  
   158  // Provider provides the backing implementation of a policy
   159  type Provider interface {
   160  	// NewPolicy creates a new policy based on the policy bytes
   161  	NewPolicy(data []byte) (Policy, proto.Message, error)
   162  }
   163  
   164  // ChannelPolicyManagerGetter is a support interface
   165  // to get access to the policy manager of a given channel
   166  type ChannelPolicyManagerGetter interface {
   167  	// Returns the policy manager associated with the specified channel.
   168  	Manager(channelID string) Manager
   169  }
   170  
   171  // PolicyManagerGetterFunc is a function adapater for ChannelPolicyManagerGetter.
   172  type PolicyManagerGetterFunc func(channelID string) Manager
   173  
   174  func (p PolicyManagerGetterFunc) Manager(channelID string) Manager { return p(channelID) }
   175  
   176  // ManagerImpl is an implementation of Manager and configtx.ConfigHandler
   177  // In general, it should only be referenced as an Impl for the configtx.ConfigManager
   178  type ManagerImpl struct {
   179  	path     string // The group level path
   180  	Policies map[string]Policy
   181  	managers map[string]*ManagerImpl
   182  }
   183  
   184  // NewManagerImpl creates a new ManagerImpl with the given CryptoHelper
   185  func NewManagerImpl(path string, providers map[int32]Provider, root *cb.ConfigGroup) (*ManagerImpl, error) {
   186  	var err error
   187  	_, ok := providers[int32(cb.Policy_IMPLICIT_META)]
   188  	if ok {
   189  		logger.Panicf("ImplicitMetaPolicy type must be provider by the policy manager")
   190  	}
   191  
   192  	managers := make(map[string]*ManagerImpl)
   193  
   194  	for groupName, group := range root.Groups {
   195  		managers[groupName], err = NewManagerImpl(path+PathSeparator+groupName, providers, group)
   196  		if err != nil {
   197  			return nil, err
   198  		}
   199  	}
   200  
   201  	policies := make(map[string]Policy)
   202  	for policyName, configPolicy := range root.Policies {
   203  		policy := configPolicy.Policy
   204  		if policy == nil {
   205  			return nil, fmt.Errorf("policy %s at path %s was nil", policyName, path)
   206  		}
   207  
   208  		var cPolicy Policy
   209  
   210  		if policy.Type == int32(cb.Policy_IMPLICIT_META) {
   211  			imp, err := NewImplicitMetaPolicy(policy.Value, managers)
   212  			if err != nil {
   213  				return nil, errors.Wrapf(err, "implicit policy %s at path %s did not compile", policyName, path)
   214  			}
   215  			cPolicy = imp
   216  		} else {
   217  			provider, ok := providers[int32(policy.Type)]
   218  			if !ok {
   219  				return nil, fmt.Errorf("policy %s at path %s has unknown policy type: %v", policyName, path, policy.Type)
   220  			}
   221  
   222  			var err error
   223  			cPolicy, _, err = provider.NewPolicy(policy.Value)
   224  			if err != nil {
   225  				return nil, errors.Wrapf(err, "policy %s at path %s did not compile", policyName, path)
   226  			}
   227  		}
   228  
   229  		policies[policyName] = cPolicy
   230  
   231  		logger.Debugf("Proposed new policy %s for %s", policyName, path)
   232  	}
   233  
   234  	for groupName, manager := range managers {
   235  		for policyName, policy := range manager.Policies {
   236  			policies[groupName+PathSeparator+policyName] = policy
   237  		}
   238  	}
   239  
   240  	return &ManagerImpl{
   241  		path:     path,
   242  		Policies: policies,
   243  		managers: managers,
   244  	}, nil
   245  }
   246  
   247  type rejectPolicy string
   248  
   249  func (rp rejectPolicy) EvaluateSignedData(signedData []*protoutil.SignedData) error {
   250  	return errors.Errorf("no such policy: '%s'", rp)
   251  }
   252  
   253  func (rp rejectPolicy) EvaluateIdentities(identities []mspi.Identity) error {
   254  	return errors.Errorf("no such policy: '%s'", rp)
   255  }
   256  
   257  // Manager returns the sub-policy manager for a given path and whether it exists
   258  func (pm *ManagerImpl) Manager(path []string) (Manager, bool) {
   259  	logger.Debugf("Manager %s looking up path %v", pm.path, path)
   260  	for manager := range pm.managers {
   261  		logger.Debugf("Manager %s has managers %s", pm.path, manager)
   262  	}
   263  	if len(path) == 0 {
   264  		return pm, true
   265  	}
   266  
   267  	m, ok := pm.managers[path[0]]
   268  	if !ok {
   269  		return nil, false
   270  	}
   271  
   272  	return m.Manager(path[1:])
   273  }
   274  
   275  type PolicyLogger struct {
   276  	Policy     Policy
   277  	policyName string
   278  }
   279  
   280  func (pl *PolicyLogger) EvaluateSignedData(signatureSet []*protoutil.SignedData) error {
   281  	if logger.IsEnabledFor(zapcore.DebugLevel) {
   282  		logger.Debugf("== Evaluating %T Policy %s ==", pl.Policy, pl.policyName)
   283  		defer logger.Debugf("== Done Evaluating %T Policy %s", pl.Policy, pl.policyName)
   284  	}
   285  
   286  	err := pl.Policy.EvaluateSignedData(signatureSet)
   287  	if err != nil {
   288  		logger.Debugf("Signature set did not satisfy policy %s", pl.policyName)
   289  	} else {
   290  		logger.Debugf("Signature set satisfies policy %s", pl.policyName)
   291  	}
   292  	return err
   293  }
   294  
   295  func (pl *PolicyLogger) EvaluateIdentities(identities []mspi.Identity) error {
   296  	if logger.IsEnabledFor(zapcore.DebugLevel) {
   297  		logger.Debugf("== Evaluating %T Policy %s ==", pl.Policy, pl.policyName)
   298  		defer logger.Debugf("== Done Evaluating %T Policy %s", pl.Policy, pl.policyName)
   299  	}
   300  
   301  	err := pl.Policy.EvaluateIdentities(identities)
   302  	if err != nil {
   303  		logger.Debugf("Signature set did not satisfy policy %s", pl.policyName)
   304  	} else {
   305  		logger.Debugf("Signature set satisfies policy %s", pl.policyName)
   306  	}
   307  	return err
   308  }
   309  
   310  func (pl *PolicyLogger) Convert() (*cb.SignaturePolicyEnvelope, error) {
   311  	logger.Debugf("== Converting %T Policy %s ==", pl.Policy, pl.policyName)
   312  
   313  	convertiblePolicy, ok := pl.Policy.(Converter)
   314  	if !ok {
   315  		logger.Errorf("policy (name='%s',type='%T') is not convertible to SignaturePolicyEnvelope", pl.policyName, pl.Policy)
   316  		return nil, errors.Errorf("policy (name='%s',type='%T') is not convertible to SignaturePolicyEnvelope", pl.policyName, pl.Policy)
   317  	}
   318  
   319  	cp, err := convertiblePolicy.Convert()
   320  	if err != nil {
   321  		logger.Errorf("== Error Converting %T Policy %s, err %s", pl.Policy, pl.policyName, err.Error())
   322  	} else {
   323  		logger.Debugf("== Done Converting %T Policy %s", pl.Policy, pl.policyName)
   324  	}
   325  
   326  	return cp, err
   327  }
   328  
   329  // GetPolicy returns a policy and true if it was the policy requested, or false if it is the default reject policy
   330  func (pm *ManagerImpl) GetPolicy(id string) (Policy, bool) {
   331  	if id == "" {
   332  		logger.Errorf("Returning dummy reject all policy because no policy ID supplied")
   333  		return rejectPolicy(id), false
   334  	}
   335  	var relpath string
   336  
   337  	if strings.HasPrefix(id, PathSeparator) {
   338  		if !strings.HasPrefix(id, PathSeparator+pm.path) {
   339  			logger.Debugf("Requested absolute policy %s from %s, returning rejectAll", id, pm.path)
   340  			return rejectPolicy(id), false
   341  		}
   342  		// strip off the leading slash, the path, and the trailing slash
   343  		relpath = id[1+len(pm.path)+1:]
   344  	} else {
   345  		relpath = id
   346  	}
   347  
   348  	policy, ok := pm.Policies[relpath]
   349  	if !ok {
   350  		logger.Debugf("Returning dummy reject all policy because %s could not be found in %s/%s", id, pm.path, relpath)
   351  		return rejectPolicy(relpath), false
   352  	}
   353  
   354  	return &PolicyLogger{
   355  		Policy:     policy,
   356  		policyName: PathSeparator + pm.path + PathSeparator + relpath,
   357  	}, true
   358  }
   359  
   360  // SignatureSetToValidIdentities takes a slice of pointers to signed data,
   361  // checks the validity of the signature and of the signer and returns a
   362  // slice of associated identities. The returned identities are deduplicated.
   363  func SignatureSetToValidIdentities(signedData []*protoutil.SignedData, identityDeserializer mspi.IdentityDeserializer) []mspi.Identity {
   364  	idMap := map[string]struct{}{}
   365  	identities := make([]mspi.Identity, 0, len(signedData))
   366  
   367  	for i, sd := range signedData {
   368  		identity, err := identityDeserializer.DeserializeIdentity(sd.Identity)
   369  		if err != nil {
   370  			logger.Warningf("principal deserialization failure (%s) for identity %x", err, sd.Identity)
   371  			continue
   372  		}
   373  
   374  		key := identity.GetIdentifier().Mspid + identity.GetIdentifier().Id
   375  
   376  		// We check if this identity has already appeared before doing a signature check, to ensure that
   377  		// someone cannot force us to waste time checking the same signature thousands of times
   378  		if _, ok := idMap[key]; ok {
   379  			logger.Warningf("De-duplicating identity [%s] at index %d in signature set", key, i)
   380  			continue
   381  		}
   382  
   383  		err = identity.Verify(sd.Data, sd.Signature)
   384  		if err != nil {
   385  			logger.Warningf("signature for identity %d is invalid: %s", i, err)
   386  			continue
   387  		}
   388  		logger.Debugf("signature for identity %d validated", i)
   389  
   390  		idMap[key] = struct{}{}
   391  		identities = append(identities, identity)
   392  	}
   393  
   394  	return identities
   395  }