github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/common/policies/policy.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package policies 8 9 import ( 10 "fmt" 11 "strings" 12 13 "github.com/golang/protobuf/proto" 14 cb "github.com/hyperledger/fabric-protos-go/common" 15 "github.com/hyperledger/fabric-protos-go/msp" 16 "github.com/hyperledger/fabric/common/flogging" 17 mspi "github.com/hyperledger/fabric/msp" 18 "github.com/hyperledger/fabric/protoutil" 19 "github.com/pkg/errors" 20 "go.uber.org/zap/zapcore" 21 ) 22 23 const ( 24 // Path separator is used to separate policy names in paths 25 PathSeparator = "/" 26 27 // ChannelPrefix is used in the path of standard channel policy managers 28 ChannelPrefix = "Channel" 29 30 // ApplicationPrefix is used in the path of standard application policy paths 31 ApplicationPrefix = "Application" 32 33 // OrdererPrefix is used in the path of standard orderer policy paths 34 OrdererPrefix = "Orderer" 35 36 // ChannelReaders is the label for the channel's readers policy (encompassing both orderer and application readers) 37 ChannelReaders = PathSeparator + ChannelPrefix + PathSeparator + "Readers" 38 39 // ChannelWriters is the label for the channel's writers policy (encompassing both orderer and application writers) 40 ChannelWriters = PathSeparator + ChannelPrefix + PathSeparator + "Writers" 41 42 // ChannelApplicationReaders is the label for the channel's application readers policy 43 ChannelApplicationReaders = PathSeparator + ChannelPrefix + PathSeparator + ApplicationPrefix + PathSeparator + "Readers" 44 45 // ChannelApplicationWriters is the label for the channel's application writers policy 46 ChannelApplicationWriters = PathSeparator + ChannelPrefix + PathSeparator + ApplicationPrefix + PathSeparator + "Writers" 47 48 // ChannelApplicationAdmins is the label for the channel's application admin policy 49 ChannelApplicationAdmins = PathSeparator + ChannelPrefix + PathSeparator + ApplicationPrefix + PathSeparator + "Admins" 50 51 // BlockValidation is the label for the policy which should validate the block signatures for the channel 52 BlockValidation = PathSeparator + ChannelPrefix + PathSeparator + OrdererPrefix + PathSeparator + "BlockValidation" 53 54 // ChannelOrdererAdmins is the label for the channel's orderer admin policy 55 ChannelOrdererAdmins = PathSeparator + ChannelPrefix + PathSeparator + OrdererPrefix + PathSeparator + "Admins" 56 57 // ChannelOrdererWriters is the label for the channel's orderer writers policy 58 ChannelOrdererWriters = PathSeparator + ChannelPrefix + PathSeparator + OrdererPrefix + PathSeparator + "Writers" 59 60 // ChannelOrdererReaders is the label for the channel's orderer readers policy 61 ChannelOrdererReaders = PathSeparator + ChannelPrefix + PathSeparator + OrdererPrefix + PathSeparator + "Readers" 62 ) 63 64 var logger = flogging.MustGetLogger("policies") 65 66 // PrincipalSet is a collection of MSPPrincipals 67 type PrincipalSet []*msp.MSPPrincipal 68 69 // PrincipalSets aggregates PrincipalSets 70 type PrincipalSets []PrincipalSet 71 72 // ContainingOnly returns PrincipalSets that contain only principals of the given predicate 73 func (psSets PrincipalSets) ContainingOnly(f func(*msp.MSPPrincipal) bool) PrincipalSets { 74 var res PrincipalSets 75 for _, set := range psSets { 76 if !set.ContainingOnly(f) { 77 continue 78 } 79 res = append(res, set) 80 } 81 return res 82 } 83 84 // ContainingOnly returns whether the given PrincipalSet contains only Principals 85 // that satisfy the given predicate 86 func (ps PrincipalSet) ContainingOnly(f func(*msp.MSPPrincipal) bool) bool { 87 for _, principal := range ps { 88 if !f(principal) { 89 return false 90 } 91 } 92 return true 93 } 94 95 // UniqueSet returns a histogram that is induced by the PrincipalSet 96 func (ps PrincipalSet) UniqueSet() map[*msp.MSPPrincipal]int { 97 // Create a histogram that holds the MSPPrincipals and counts them 98 histogram := make(map[struct { 99 cls int32 100 principal string 101 }]int) 102 // Now, populate the histogram 103 for _, principal := range ps { 104 key := struct { 105 cls int32 106 principal string 107 }{ 108 cls: int32(principal.PrincipalClassification), 109 principal: string(principal.Principal), 110 } 111 histogram[key]++ 112 } 113 // Finally, convert to a histogram of MSPPrincipal pointers 114 res := make(map[*msp.MSPPrincipal]int) 115 for principal, count := range histogram { 116 res[&msp.MSPPrincipal{ 117 PrincipalClassification: msp.MSPPrincipal_Classification(principal.cls), 118 Principal: []byte(principal.principal), 119 }] = count 120 } 121 return res 122 } 123 124 // Converter represents a policy 125 // which may be translated into a SignaturePolicyEnvelope 126 type Converter interface { 127 Convert() (*cb.SignaturePolicyEnvelope, error) 128 } 129 130 // Policy is used to determine if a signature is valid 131 type Policy interface { 132 // EvaluateSignedData takes a set of SignedData and evaluates whether 133 // 1) the signatures are valid over the related message 134 // 2) the signing identities satisfy the policy 135 EvaluateSignedData(signatureSet []*protoutil.SignedData) error 136 137 // EvaluateIdentities takes an array of identities and evaluates whether 138 // they satisfy the policy 139 EvaluateIdentities(identities []mspi.Identity) error 140 } 141 142 // InquireablePolicy is a Policy that one can inquire 143 type InquireablePolicy interface { 144 // SatisfiedBy returns a slice of PrincipalSets that each of them 145 // satisfies the policy. 146 SatisfiedBy() []PrincipalSet 147 } 148 149 // Manager is a read only subset of the policy ManagerImpl 150 type Manager interface { 151 // GetPolicy returns a policy and true if it was the policy requested, or false if it is the default policy 152 GetPolicy(id string) (Policy, bool) 153 154 // Manager returns the sub-policy manager for a given path and whether it exists 155 Manager(path []string) (Manager, bool) 156 } 157 158 // Provider provides the backing implementation of a policy 159 type Provider interface { 160 // NewPolicy creates a new policy based on the policy bytes 161 NewPolicy(data []byte) (Policy, proto.Message, error) 162 } 163 164 // ChannelPolicyManagerGetter is a support interface 165 // to get access to the policy manager of a given channel 166 type ChannelPolicyManagerGetter interface { 167 // Returns the policy manager associated with the specified channel. 168 Manager(channelID string) Manager 169 } 170 171 // PolicyManagerGetterFunc is a function adapater for ChannelPolicyManagerGetter. 172 type PolicyManagerGetterFunc func(channelID string) Manager 173 174 func (p PolicyManagerGetterFunc) Manager(channelID string) Manager { return p(channelID) } 175 176 // ManagerImpl is an implementation of Manager and configtx.ConfigHandler 177 // In general, it should only be referenced as an Impl for the configtx.ConfigManager 178 type ManagerImpl struct { 179 path string // The group level path 180 Policies map[string]Policy 181 managers map[string]*ManagerImpl 182 } 183 184 // NewManagerImpl creates a new ManagerImpl with the given CryptoHelper 185 func NewManagerImpl(path string, providers map[int32]Provider, root *cb.ConfigGroup) (*ManagerImpl, error) { 186 var err error 187 _, ok := providers[int32(cb.Policy_IMPLICIT_META)] 188 if ok { 189 logger.Panicf("ImplicitMetaPolicy type must be provider by the policy manager") 190 } 191 192 managers := make(map[string]*ManagerImpl) 193 194 for groupName, group := range root.Groups { 195 managers[groupName], err = NewManagerImpl(path+PathSeparator+groupName, providers, group) 196 if err != nil { 197 return nil, err 198 } 199 } 200 201 policies := make(map[string]Policy) 202 for policyName, configPolicy := range root.Policies { 203 policy := configPolicy.Policy 204 if policy == nil { 205 return nil, fmt.Errorf("policy %s at path %s was nil", policyName, path) 206 } 207 208 var cPolicy Policy 209 210 if policy.Type == int32(cb.Policy_IMPLICIT_META) { 211 imp, err := NewImplicitMetaPolicy(policy.Value, managers) 212 if err != nil { 213 return nil, errors.Wrapf(err, "implicit policy %s at path %s did not compile", policyName, path) 214 } 215 cPolicy = imp 216 } else { 217 provider, ok := providers[int32(policy.Type)] 218 if !ok { 219 return nil, fmt.Errorf("policy %s at path %s has unknown policy type: %v", policyName, path, policy.Type) 220 } 221 222 var err error 223 cPolicy, _, err = provider.NewPolicy(policy.Value) 224 if err != nil { 225 return nil, errors.Wrapf(err, "policy %s at path %s did not compile", policyName, path) 226 } 227 } 228 229 policies[policyName] = cPolicy 230 231 logger.Debugf("Proposed new policy %s for %s", policyName, path) 232 } 233 234 for groupName, manager := range managers { 235 for policyName, policy := range manager.Policies { 236 policies[groupName+PathSeparator+policyName] = policy 237 } 238 } 239 240 return &ManagerImpl{ 241 path: path, 242 Policies: policies, 243 managers: managers, 244 }, nil 245 } 246 247 type rejectPolicy string 248 249 func (rp rejectPolicy) EvaluateSignedData(signedData []*protoutil.SignedData) error { 250 return errors.Errorf("no such policy: '%s'", rp) 251 } 252 253 func (rp rejectPolicy) EvaluateIdentities(identities []mspi.Identity) error { 254 return errors.Errorf("no such policy: '%s'", rp) 255 } 256 257 // Manager returns the sub-policy manager for a given path and whether it exists 258 func (pm *ManagerImpl) Manager(path []string) (Manager, bool) { 259 logger.Debugf("Manager %s looking up path %v", pm.path, path) 260 for manager := range pm.managers { 261 logger.Debugf("Manager %s has managers %s", pm.path, manager) 262 } 263 if len(path) == 0 { 264 return pm, true 265 } 266 267 m, ok := pm.managers[path[0]] 268 if !ok { 269 return nil, false 270 } 271 272 return m.Manager(path[1:]) 273 } 274 275 type PolicyLogger struct { 276 Policy Policy 277 policyName string 278 } 279 280 func (pl *PolicyLogger) EvaluateSignedData(signatureSet []*protoutil.SignedData) error { 281 if logger.IsEnabledFor(zapcore.DebugLevel) { 282 logger.Debugf("== Evaluating %T Policy %s ==", pl.Policy, pl.policyName) 283 defer logger.Debugf("== Done Evaluating %T Policy %s", pl.Policy, pl.policyName) 284 } 285 286 err := pl.Policy.EvaluateSignedData(signatureSet) 287 if err != nil { 288 logger.Debugf("Signature set did not satisfy policy %s", pl.policyName) 289 } else { 290 logger.Debugf("Signature set satisfies policy %s", pl.policyName) 291 } 292 return err 293 } 294 295 func (pl *PolicyLogger) EvaluateIdentities(identities []mspi.Identity) error { 296 if logger.IsEnabledFor(zapcore.DebugLevel) { 297 logger.Debugf("== Evaluating %T Policy %s ==", pl.Policy, pl.policyName) 298 defer logger.Debugf("== Done Evaluating %T Policy %s", pl.Policy, pl.policyName) 299 } 300 301 err := pl.Policy.EvaluateIdentities(identities) 302 if err != nil { 303 logger.Debugf("Signature set did not satisfy policy %s", pl.policyName) 304 } else { 305 logger.Debugf("Signature set satisfies policy %s", pl.policyName) 306 } 307 return err 308 } 309 310 func (pl *PolicyLogger) Convert() (*cb.SignaturePolicyEnvelope, error) { 311 logger.Debugf("== Converting %T Policy %s ==", pl.Policy, pl.policyName) 312 313 convertiblePolicy, ok := pl.Policy.(Converter) 314 if !ok { 315 logger.Errorf("policy (name='%s',type='%T') is not convertible to SignaturePolicyEnvelope", pl.policyName, pl.Policy) 316 return nil, errors.Errorf("policy (name='%s',type='%T') is not convertible to SignaturePolicyEnvelope", pl.policyName, pl.Policy) 317 } 318 319 cp, err := convertiblePolicy.Convert() 320 if err != nil { 321 logger.Errorf("== Error Converting %T Policy %s, err %s", pl.Policy, pl.policyName, err.Error()) 322 } else { 323 logger.Debugf("== Done Converting %T Policy %s", pl.Policy, pl.policyName) 324 } 325 326 return cp, err 327 } 328 329 // GetPolicy returns a policy and true if it was the policy requested, or false if it is the default reject policy 330 func (pm *ManagerImpl) GetPolicy(id string) (Policy, bool) { 331 if id == "" { 332 logger.Errorf("Returning dummy reject all policy because no policy ID supplied") 333 return rejectPolicy(id), false 334 } 335 var relpath string 336 337 if strings.HasPrefix(id, PathSeparator) { 338 if !strings.HasPrefix(id, PathSeparator+pm.path) { 339 logger.Debugf("Requested absolute policy %s from %s, returning rejectAll", id, pm.path) 340 return rejectPolicy(id), false 341 } 342 // strip off the leading slash, the path, and the trailing slash 343 relpath = id[1+len(pm.path)+1:] 344 } else { 345 relpath = id 346 } 347 348 policy, ok := pm.Policies[relpath] 349 if !ok { 350 logger.Debugf("Returning dummy reject all policy because %s could not be found in %s/%s", id, pm.path, relpath) 351 return rejectPolicy(relpath), false 352 } 353 354 return &PolicyLogger{ 355 Policy: policy, 356 policyName: PathSeparator + pm.path + PathSeparator + relpath, 357 }, true 358 } 359 360 // SignatureSetToValidIdentities takes a slice of pointers to signed data, 361 // checks the validity of the signature and of the signer and returns a 362 // slice of associated identities. The returned identities are deduplicated. 363 func SignatureSetToValidIdentities(signedData []*protoutil.SignedData, identityDeserializer mspi.IdentityDeserializer) []mspi.Identity { 364 idMap := map[string]struct{}{} 365 identities := make([]mspi.Identity, 0, len(signedData)) 366 367 for i, sd := range signedData { 368 identity, err := identityDeserializer.DeserializeIdentity(sd.Identity) 369 if err != nil { 370 logger.Warningf("principal deserialization failure (%s) for identity %x", err, sd.Identity) 371 continue 372 } 373 374 key := identity.GetIdentifier().Mspid + identity.GetIdentifier().Id 375 376 // We check if this identity has already appeared before doing a signature check, to ensure that 377 // someone cannot force us to waste time checking the same signature thousands of times 378 if _, ok := idMap[key]; ok { 379 logger.Warningf("De-duplicating identity [%s] at index %d in signature set", key, i) 380 continue 381 } 382 383 err = identity.Verify(sd.Data, sd.Signature) 384 if err != nil { 385 logger.Warningf("signature for identity %d is invalid: %s", i, err) 386 continue 387 } 388 logger.Debugf("signature for identity %d validated", i) 389 390 idMap[key] = struct{}{} 391 identities = append(identities, identity) 392 } 393 394 return identities 395 }