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  }