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 }