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 }