github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/apiserver/client_auth_root_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package apiserver
     5  
     6  import (
     7  	"reflect"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/juju/apiserver/common"
    11  	"github.com/juju/juju/testing/factory"
    12  
    13  	jc "github.com/juju/testing/checkers"
    14  	gc "gopkg.in/check.v1"
    15  
    16  	"github.com/juju/juju/rpc/rpcreflect"
    17  	"github.com/juju/juju/state"
    18  	"github.com/juju/juju/state/testing"
    19  )
    20  
    21  type clientAuthRootSuite struct {
    22  	testing.StateSuite
    23  }
    24  
    25  var _ = gc.Suite(&clientAuthRootSuite{})
    26  
    27  func (*clientAuthRootSuite) AssertCallGood(c *gc.C, client *clientAuthRoot, rootName string, version int, methodName string) {
    28  	caller, err := client.FindMethod(rootName, version, methodName)
    29  	c.Check(err, jc.ErrorIsNil)
    30  	c.Assert(caller, gc.NotNil)
    31  }
    32  
    33  func (*clientAuthRootSuite) AssertCallNotImplemented(c *gc.C, client *clientAuthRoot, rootName string, version int, methodName string) {
    34  	caller, err := client.FindMethod(rootName, version, methodName)
    35  	c.Check(errors.Cause(err), jc.Satisfies, isCallNotImplementedError)
    36  	c.Assert(caller, gc.IsNil)
    37  }
    38  
    39  func (s *clientAuthRootSuite) AssertCallErrPerm(c *gc.C, client *clientAuthRoot, rootName string, version int, methodName string) {
    40  	caller, err := client.FindMethod(rootName, version, methodName)
    41  	c.Check(errors.Cause(err), gc.Equals, common.ErrPerm)
    42  	c.Assert(caller, gc.IsNil)
    43  }
    44  
    45  func (s *clientAuthRootSuite) TestNormalUser(c *gc.C) {
    46  	envUser := s.Factory.MakeModelUser(c, nil)
    47  	client := newClientAuthRoot(&fakeFinder{}, envUser)
    48  	s.AssertCallGood(c, client, "Service", 3, "Deploy")
    49  	s.AssertCallGood(c, client, "UserManager", 1, "UserInfo")
    50  	s.AssertCallNotImplemented(c, client, "Client", 1, "Unknown")
    51  	s.AssertCallNotImplemented(c, client, "Unknown", 1, "Method")
    52  }
    53  
    54  func (s *clientAuthRootSuite) TestReadOnlyUser(c *gc.C) {
    55  	envUser := s.Factory.MakeModelUser(c, &factory.ModelUserParams{Access: state.ModelReadAccess})
    56  	client := newClientAuthRoot(&fakeFinder{}, envUser)
    57  	// deploys are bad
    58  	s.AssertCallErrPerm(c, client, "Service", 3, "Deploy")
    59  	// read only commands are fine
    60  	s.AssertCallGood(c, client, "Client", 1, "FullStatus")
    61  	// calls on the restricted root is also fine
    62  	s.AssertCallGood(c, client, "UserManager", 1, "AddUser")
    63  	s.AssertCallNotImplemented(c, client, "Client", 1, "Unknown")
    64  	s.AssertCallNotImplemented(c, client, "Unknown", 1, "Method")
    65  }
    66  
    67  func isCallNotImplementedError(err error) bool {
    68  	_, ok := err.(*rpcreflect.CallNotImplementedError)
    69  	return ok
    70  }
    71  
    72  type fakeFinder struct{}
    73  
    74  // FindMethod is the only thing we need to implement rpc.MethodFinder.
    75  func (f *fakeFinder) FindMethod(rootName string, version int, methodName string) (rpcreflect.MethodCaller, error) {
    76  	_, _, err := lookupMethod(rootName, version, methodName)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	// Just return a valid caller.
    81  	return &fakeCaller{}, nil
    82  }
    83  
    84  // fakeCaller implements a rpcreflect.MethodCaller. We don't care what the
    85  // actual reflect.Types or values actually are, the caller just has to be
    86  // valid.
    87  type fakeCaller struct{}
    88  
    89  func (*fakeCaller) ParamsType() reflect.Type {
    90  	return reflect.TypeOf("")
    91  }
    92  
    93  func (*fakeCaller) ResultType() reflect.Type {
    94  	return reflect.TypeOf("")
    95  }
    96  
    97  func (*fakeCaller) Call(_ /*objId*/ string, _ /*arg*/ reflect.Value) (reflect.Value, error) {
    98  	return reflect.ValueOf(""), nil
    99  }