github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/policies/inquire/compare.go (about)

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