github.com/lzy4123/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 }