github.com/true-sqn/fabric@v2.1.1+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  // Equal returns whether this ComparablePrincipal is equal to the given ComparablePrincipal.
    27  func (cp *ComparablePrincipal) Equal(cp2 *ComparablePrincipal) bool {
    28  	return cp.mspID == cp2.mspID &&
    29  		cp.equalPrincipals(cp2) && cp.equalRoles(cp2) && cp.equalOUs(cp2)
    30  }
    31  
    32  // NewComparablePrincipal creates a ComparablePrincipal out of the given MSPPrincipal.
    33  // Returns nil if a failure occurs.
    34  func NewComparablePrincipal(principal *msp.MSPPrincipal) *ComparablePrincipal {
    35  	if principal == nil {
    36  		logger.Warning("Principal is nil")
    37  		return nil
    38  	}
    39  	cp := &ComparablePrincipal{
    40  		principal: principal,
    41  	}
    42  	switch principal.PrincipalClassification {
    43  	case msp.MSPPrincipal_ROLE:
    44  		return cp.ToRole()
    45  	case msp.MSPPrincipal_ORGANIZATION_UNIT:
    46  		return cp.ToOURole()
    47  	}
    48  	mapping := msp.MSPPrincipal_Classification_name[int32(principal.PrincipalClassification)]
    49  	logger.Warning("Received an unsupported principal type:", principal.PrincipalClassification, "mapped to", mapping)
    50  	return nil
    51  }
    52  
    53  // IsFound returns whether the ComparablePrincipal is found among the given set of ComparablePrincipals
    54  // For the ComparablePrincipal x to be found, there needs to be some ComparablePrincipal y in the set
    55  // such that x.IsA(y) will be true.
    56  func (cp *ComparablePrincipal) IsFound(set ...*ComparablePrincipal) bool {
    57  	for _, cp2 := range set {
    58  		if cp.IsA(cp2) {
    59  			return true
    60  		}
    61  	}
    62  	return false
    63  }
    64  
    65  // IsA determines whether all identities that satisfy this ComparablePrincipal
    66  // also satisfy the other ComparablePrincipal.
    67  // Example: if this ComparablePrincipal is a Peer role,
    68  // and the other ComparablePrincipal is a Member role, then
    69  // all identities that satisfy this ComparablePrincipal (are peers)
    70  // also satisfy the other principal (are members).
    71  func (cp *ComparablePrincipal) IsA(other *ComparablePrincipal) bool {
    72  	this := cp
    73  
    74  	if other == nil {
    75  		return false
    76  	}
    77  	if this.principal == nil || other.principal == nil {
    78  		logger.Warning("Used an un-initialized ComparablePrincipal")
    79  		return false
    80  	}
    81  	// Compare the MSP ID
    82  	if this.mspID != other.mspID {
    83  		return false
    84  	}
    85  
    86  	// If the other Principal is a member, then any role or OU role
    87  	// fits, because every role or OU role is also a member of the MSP
    88  	if other.role != nil && other.role.Role == msp.MSPRole_MEMBER {
    89  		return true
    90  	}
    91  
    92  	// Check if we're both OU roles
    93  	if this.ou != nil && other.ou != nil {
    94  		sameOU := this.ou.OrganizationalUnitIdentifier == other.ou.OrganizationalUnitIdentifier
    95  		sameIssuer := bytes.Equal(this.ou.CertifiersIdentifier, other.ou.CertifiersIdentifier)
    96  		return sameOU && sameIssuer
    97  	}
    98  
    99  	// Check if we're both the same MSP Role
   100  	if this.role != nil && other.role != nil {
   101  		return this.role.Role == other.role.Role
   102  	}
   103  
   104  	// Else, we can't say anything, because we have no knowledge
   105  	// about the OUs that make up the MSP roles - so return false
   106  	return false
   107  }
   108  
   109  // ToOURole converts this ComparablePrincipal to OU principal, and returns nil on failure
   110  func (cp *ComparablePrincipal) ToOURole() *ComparablePrincipal {
   111  	ouRole := &msp.OrganizationUnit{}
   112  	err := proto.Unmarshal(cp.principal.Principal, ouRole)
   113  	if err != nil {
   114  		logger.Warning("Failed unmarshaling principal:", err)
   115  		return nil
   116  	}
   117  	cp.mspID = ouRole.MspIdentifier
   118  	cp.ou = ouRole
   119  	return cp
   120  }
   121  
   122  // ToRole converts this ComparablePrincipal to MSP Role, and returns nil if the conversion failed
   123  func (cp *ComparablePrincipal) ToRole() *ComparablePrincipal {
   124  	mspRole := &msp.MSPRole{}
   125  	err := proto.Unmarshal(cp.principal.Principal, mspRole)
   126  	if err != nil {
   127  		logger.Warning("Failed unmarshaling principal:", err)
   128  		return nil
   129  	}
   130  	cp.mspID = mspRole.MspIdentifier
   131  	cp.role = mspRole
   132  	return cp
   133  }
   134  
   135  // ComparablePrincipalSet aggregates ComparablePrincipals
   136  type ComparablePrincipalSet []*ComparablePrincipal
   137  
   138  // ToPrincipalSet converts this ComparablePrincipalSet to a PrincipalSet
   139  func (cps ComparablePrincipalSet) ToPrincipalSet() policies.PrincipalSet {
   140  	var res policies.PrincipalSet
   141  	for _, cp := range cps {
   142  		res = append(res, cp.principal)
   143  	}
   144  	return res
   145  }
   146  
   147  // String returns a string representation of this ComparablePrincipalSet
   148  func (cps ComparablePrincipalSet) String() string {
   149  	buff := bytes.Buffer{}
   150  	buff.WriteString("[")
   151  	for i, cp := range cps {
   152  		buff.WriteString(cp.mspID)
   153  		buff.WriteString(".")
   154  		if cp.role != nil {
   155  			buff.WriteString(fmt.Sprintf("%v", cp.role.Role))
   156  		}
   157  		if cp.ou != nil {
   158  			buff.WriteString(fmt.Sprintf("%v", cp.ou.OrganizationalUnitIdentifier))
   159  		}
   160  		if i < len(cps)-1 {
   161  			buff.WriteString(", ")
   162  		}
   163  	}
   164  	buff.WriteString("]")
   165  	return buff.String()
   166  }
   167  
   168  // NewComparablePrincipalSet constructs a ComparablePrincipalSet out of the given PrincipalSet
   169  func NewComparablePrincipalSet(set policies.PrincipalSet) ComparablePrincipalSet {
   170  	var res ComparablePrincipalSet
   171  	for _, principal := range set {
   172  		cp := NewComparablePrincipal(principal)
   173  		if cp == nil {
   174  			return nil
   175  		}
   176  		res = append(res, cp)
   177  	}
   178  	return res
   179  }
   180  
   181  // Clone returns a copy of this ComparablePrincipalSet
   182  func (cps ComparablePrincipalSet) Clone() ComparablePrincipalSet {
   183  	res := make(ComparablePrincipalSet, len(cps))
   184  	for i, cp := range cps {
   185  		res[i] = cp
   186  	}
   187  	return res
   188  }
   189  
   190  func (cp *ComparablePrincipal) equalRoles(cp2 *ComparablePrincipal) bool {
   191  	if cp.role == nil && cp2.role == nil {
   192  		return true
   193  	}
   194  
   195  	if cp.role == nil || cp2.role == nil {
   196  		return false
   197  	}
   198  
   199  	return cp.role.MspIdentifier == cp2.role.MspIdentifier &&
   200  		cp.role.Role == cp2.role.Role
   201  }
   202  
   203  func (cp *ComparablePrincipal) equalOUs(cp2 *ComparablePrincipal) bool {
   204  	if cp.ou == nil && cp2.ou == nil {
   205  		return true
   206  	}
   207  
   208  	if cp.ou == nil || cp2.ou == nil {
   209  		return false
   210  	}
   211  
   212  	if cp.ou.OrganizationalUnitIdentifier != cp2.ou.OrganizationalUnitIdentifier {
   213  		return false
   214  	}
   215  
   216  	if cp.ou.MspIdentifier != cp2.ou.MspIdentifier {
   217  		return false
   218  	}
   219  
   220  	return bytes.Equal(cp.ou.CertifiersIdentifier, cp2.ou.CertifiersIdentifier)
   221  }
   222  
   223  func (cp *ComparablePrincipal) equalPrincipals(cp2 *ComparablePrincipal) bool {
   224  	if cp.principal == nil && cp2.principal == nil {
   225  		return true
   226  	}
   227  
   228  	if cp.principal == nil || cp2.principal == nil {
   229  		return false
   230  	}
   231  
   232  	if cp.principal.PrincipalClassification != cp2.principal.PrincipalClassification {
   233  		return false
   234  	}
   235  
   236  	return bytes.Equal(cp.principal.Principal, cp2.principal.Principal)
   237  }