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

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package inquire
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  
    13  	"github.com/golang/protobuf/proto"
    14  	"github.com/hyperledger/fabric-protos-go/msp"
    15  	"github.com/hyperledger/fabric/common/policies"
    16  )
    17  
    18  // ComparablePrincipal defines an MSPPrincipal that can be compared to other principals
    19  type ComparablePrincipal struct {
    20  	principal *msp.MSPPrincipal
    21  	ou        *msp.OrganizationUnit
    22  	role      *msp.MSPRole
    23  	mspID     string
    24  }
    25  
    26  // NewComparablePrincipal creates a ComparablePrincipal out of the given MSPPrincipal.
    27  // Returns nil if a failure occurs.
    28  func NewComparablePrincipal(principal *msp.MSPPrincipal) *ComparablePrincipal {
    29  	if principal == nil {
    30  		logger.Warning("Principal is nil")
    31  		return nil
    32  	}
    33  	cp := &ComparablePrincipal{
    34  		principal: principal,
    35  	}
    36  	switch principal.PrincipalClassification {
    37  	case msp.MSPPrincipal_ROLE:
    38  		return cp.ToRole()
    39  	case msp.MSPPrincipal_ORGANIZATION_UNIT:
    40  		return cp.ToOURole()
    41  	}
    42  	mapping := msp.MSPPrincipal_Classification_name[int32(principal.PrincipalClassification)]
    43  	logger.Warning("Received an unsupported principal type:", principal.PrincipalClassification, "mapped to", mapping)
    44  	return nil
    45  }
    46  
    47  // IsFound returns whether the ComparablePrincipal is found among the given set of ComparablePrincipals
    48  // For the ComparablePrincipal x to be found, there needs to be some ComparablePrincipal y in the set
    49  // such that x.IsA(y) will be true.
    50  func (cp *ComparablePrincipal) IsFound(set ...*ComparablePrincipal) bool {
    51  	for _, cp2 := range set {
    52  		if cp.IsA(cp2) {
    53  			return true
    54  		}
    55  	}
    56  	return false
    57  }
    58  
    59  // IsA determines whether all identities that satisfy this ComparablePrincipal
    60  // also satisfy the other ComparablePrincipal.
    61  // Example: if this ComparablePrincipal is a Peer role,
    62  // and the other ComparablePrincipal is a Member role, then
    63  // all identities that satisfy this ComparablePrincipal (are peers)
    64  // also satisfy the other principal (are members).
    65  func (cp *ComparablePrincipal) IsA(other *ComparablePrincipal) bool {
    66  	this := cp
    67  
    68  	if other == nil {
    69  		return false
    70  	}
    71  	if this.principal == nil || other.principal == nil {
    72  		logger.Warning("Used an un-initialized ComparablePrincipal")
    73  		return false
    74  	}
    75  	// Compare the MSP ID
    76  	if this.mspID != other.mspID {
    77  		return false
    78  	}
    79  
    80  	// If the other Principal is a member, then any role or OU role
    81  	// fits, because every role or OU role is also a member of the MSP
    82  	if other.role != nil && other.role.Role == msp.MSPRole_MEMBER {
    83  		return true
    84  	}
    85  
    86  	// Check if we're both OU roles
    87  	if this.ou != nil && other.ou != nil {
    88  		sameOU := this.ou.OrganizationalUnitIdentifier == other.ou.OrganizationalUnitIdentifier
    89  		sameIssuer := bytes.Equal(this.ou.CertifiersIdentifier, other.ou.CertifiersIdentifier)
    90  		return sameOU && sameIssuer
    91  	}
    92  
    93  	// Check if we're both the same MSP Role
    94  	if this.role != nil && other.role != nil {
    95  		return this.role.Role == other.role.Role
    96  	}
    97  
    98  	// Else, we can't say anything, because we have no knowledge
    99  	// about the OUs that make up the MSP roles - so return false
   100  	return false
   101  }
   102  
   103  // ToOURole converts this ComparablePrincipal to OU principal, and returns nil on failure
   104  func (cp *ComparablePrincipal) ToOURole() *ComparablePrincipal {
   105  	ouRole := &msp.OrganizationUnit{}
   106  	err := proto.Unmarshal(cp.principal.Principal, ouRole)
   107  	if err != nil {
   108  		logger.Warning("Failed unmarshaling principal:", err)
   109  		return nil
   110  	}
   111  	cp.mspID = ouRole.MspIdentifier
   112  	cp.ou = ouRole
   113  	return cp
   114  }
   115  
   116  // ToRole converts this ComparablePrincipal to MSP Role, and returns nil if the conversion failed
   117  func (cp *ComparablePrincipal) ToRole() *ComparablePrincipal {
   118  	mspRole := &msp.MSPRole{}
   119  	err := proto.Unmarshal(cp.principal.Principal, mspRole)
   120  	if err != nil {
   121  		logger.Warning("Failed unmarshaling principal:", err)
   122  		return nil
   123  	}
   124  	cp.mspID = mspRole.MspIdentifier
   125  	cp.role = mspRole
   126  	return cp
   127  }
   128  
   129  // ComparablePrincipalSet aggregates ComparablePrincipals
   130  type ComparablePrincipalSet []*ComparablePrincipal
   131  
   132  // ToPrincipalSet converts this ComparablePrincipalSet to a PrincipalSet
   133  func (cps ComparablePrincipalSet) ToPrincipalSet() policies.PrincipalSet {
   134  	var res policies.PrincipalSet
   135  	for _, cp := range cps {
   136  		res = append(res, cp.principal)
   137  	}
   138  	return res
   139  }
   140  
   141  // String returns a string representation of this ComparablePrincipalSet
   142  func (cps ComparablePrincipalSet) String() string {
   143  	buff := bytes.Buffer{}
   144  	buff.WriteString("[")
   145  	for i, cp := range cps {
   146  		buff.WriteString(cp.mspID)
   147  		buff.WriteString(".")
   148  		if cp.role != nil {
   149  			buff.WriteString(fmt.Sprintf("%v", cp.role.Role))
   150  		}
   151  		if cp.ou != nil {
   152  			buff.WriteString(fmt.Sprintf("%v", cp.ou.OrganizationalUnitIdentifier))
   153  		}
   154  		if i < len(cps)-1 {
   155  			buff.WriteString(", ")
   156  		}
   157  	}
   158  	buff.WriteString("]")
   159  	return buff.String()
   160  }
   161  
   162  // NewComparablePrincipalSet constructs a ComparablePrincipalSet out of the given PrincipalSet
   163  func NewComparablePrincipalSet(set policies.PrincipalSet) ComparablePrincipalSet {
   164  	var res ComparablePrincipalSet
   165  	for _, principal := range set {
   166  		cp := NewComparablePrincipal(principal)
   167  		if cp == nil {
   168  			return nil
   169  		}
   170  		res = append(res, cp)
   171  	}
   172  	return res
   173  }
   174  
   175  // Clone returns a copy of this ComparablePrincipalSet
   176  func (cps ComparablePrincipalSet) Clone() ComparablePrincipalSet {
   177  	res := make(ComparablePrincipalSet, len(cps))
   178  	for i, cp := range cps {
   179  		res[i] = cp
   180  	}
   181  	return res
   182  }