github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/common/permissions.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common 5 6 import ( 7 "github.com/juju/errors" 8 "gopkg.in/juju/names.v2" 9 10 "github.com/juju/juju/apiserver/facade" 11 "github.com/juju/juju/permission" 12 ) 13 14 // EveryoneTagName represents a special group that encompasses 15 // all external users. 16 const EveryoneTagName = "everyone@external" 17 18 type userAccessFunc func(names.UserTag, names.Tag) (permission.Access, error) 19 20 // HasPermission returns true if the specified user has the specified 21 // permission on target. 22 func HasPermission( 23 accessGetter userAccessFunc, utag names.Tag, 24 requestedPermission permission.Access, target names.Tag, 25 ) (bool, error) { 26 var validate func(permission.Access) error 27 switch target.Kind() { 28 case names.ControllerTagKind: 29 validate = permission.ValidateControllerAccess 30 case names.ModelTagKind: 31 validate = permission.ValidateModelAccess 32 case names.ApplicationOfferTagKind: 33 validate = permission.ValidateOfferAccess 34 case names.CloudTagKind: 35 validate = permission.ValidateCloudAccess 36 default: 37 return false, nil 38 } 39 if err := validate(requestedPermission); err != nil { 40 return false, nil 41 } 42 43 userTag, ok := utag.(names.UserTag) 44 if !ok { 45 // lets not reveal more than is strictly necessary 46 return false, nil 47 } 48 49 userAccess, err := GetPermission(accessGetter, userTag, target) 50 if err != nil && !errors.IsNotFound(err) { 51 return false, errors.Annotatef(err, "while obtaining %s user", target.Kind()) 52 } 53 // returning this kind of information would be too much information to reveal too. 54 if errors.IsNotFound(err) || userAccess == permission.NoAccess { 55 return false, nil 56 } 57 58 modelPermission := userAccess.EqualOrGreaterModelAccessThan(requestedPermission) && target.Kind() == names.ModelTagKind 59 controllerPermission := userAccess.EqualOrGreaterControllerAccessThan(requestedPermission) && target.Kind() == names.ControllerTagKind 60 offerPermission := userAccess.EqualOrGreaterOfferAccessThan(requestedPermission) && target.Kind() == names.ApplicationOfferTagKind 61 cloudPermission := userAccess.EqualOrGreaterCloudAccessThan(requestedPermission) && target.Kind() == names.CloudTagKind 62 if !controllerPermission && !modelPermission && !offerPermission && !cloudPermission { 63 return false, nil 64 } 65 return true, nil 66 } 67 68 // GetPermission returns the permission a user has on the specified target. 69 func GetPermission(accessGetter userAccessFunc, userTag names.UserTag, target names.Tag) (permission.Access, error) { 70 userAccess, err := accessGetter(userTag, target) 71 if err != nil && !errors.IsNotFound(err) { 72 return permission.NoAccess, errors.Annotatef(err, "while obtaining %s user", target.Kind()) 73 } 74 // there is a special case for external users, a group called everyone@external 75 if !userTag.IsLocal() { 76 // TODO(perrito666) remove the following section about everyone group 77 // when groups are implemented. 78 everyoneTag := names.NewUserTag(EveryoneTagName) 79 everyoneAccess, err := accessGetter(everyoneTag, target) 80 if err != nil && !errors.IsNotFound(err) { 81 return permission.NoAccess, errors.Trace(err) 82 } 83 if userAccess == permission.NoAccess && everyoneAccess != permission.NoAccess { 84 userAccess = everyoneAccess 85 } 86 if everyoneAccess.EqualOrGreaterControllerAccessThan(userAccess) { 87 userAccess = everyoneAccess 88 } 89 } 90 return userAccess, nil 91 } 92 93 // HasModelAdmin reports whether or not a user has admin access to the 94 // specified model. A user has model access if they are a controller 95 // superuser, or if they have been explicitly granted admin access to the 96 // model. 97 func HasModelAdmin( 98 authorizer facade.Authorizer, 99 user names.UserTag, 100 controllerTag names.ControllerTag, 101 model Model, 102 ) (bool, error) { 103 // superusers have admin for all models. 104 if isSuperUser, err := authorizer.HasPermission(permission.SuperuserAccess, controllerTag); err != nil || isSuperUser { 105 return isSuperUser, err 106 } 107 return authorizer.HasPermission(permission.AdminAccess, model.ModelTag()) 108 }