github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/apiserver/admin_test.go (about)

     1  // Copyright 2012-2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package apiserver_test
     5  
     6  import (
     7  	"fmt"
     8  	"net"
     9  	"net/url"
    10  	"strconv"
    11  	"sync"
    12  	"time"
    13  
    14  	"github.com/juju/errors"
    15  	"github.com/juju/loggo"
    16  	jc "github.com/juju/testing/checkers"
    17  	"github.com/juju/utils"
    18  	gc "gopkg.in/check.v1"
    19  	"gopkg.in/juju/names.v2"
    20  	"gopkg.in/macaroon-bakery.v1/httpbakery"
    21  
    22  	"github.com/juju/juju/api"
    23  	apimachiner "github.com/juju/juju/api/machiner"
    24  	apitesting "github.com/juju/juju/api/testing"
    25  	"github.com/juju/juju/apiserver"
    26  	"github.com/juju/juju/apiserver/common"
    27  	"github.com/juju/juju/apiserver/controller"
    28  	"github.com/juju/juju/apiserver/params"
    29  	"github.com/juju/juju/constraints"
    30  	jujutesting "github.com/juju/juju/juju/testing"
    31  	"github.com/juju/juju/network"
    32  	"github.com/juju/juju/permission"
    33  	"github.com/juju/juju/rpc"
    34  	"github.com/juju/juju/state"
    35  	coretesting "github.com/juju/juju/testing"
    36  	"github.com/juju/juju/testing/factory"
    37  )
    38  
    39  type baseLoginSuite struct {
    40  	jujutesting.JujuConnSuite
    41  	setAdminAPI func(*apiserver.Server)
    42  }
    43  
    44  type loginSuite struct {
    45  	baseLoginSuite
    46  }
    47  
    48  var _ = gc.Suite(&loginSuite{
    49  	baseLoginSuite{
    50  		setAdminAPI: func(srv *apiserver.Server) {
    51  			apiserver.SetAdminAPIVersions(srv, 3)
    52  		},
    53  	},
    54  })
    55  
    56  func (s *baseLoginSuite) SetUpTest(c *gc.C) {
    57  	s.JujuConnSuite.SetUpTest(c)
    58  	loggo.GetLogger("juju.apiserver").SetLogLevel(loggo.TRACE)
    59  }
    60  
    61  func (s *baseLoginSuite) newMachineAndServer(c *gc.C) (*api.Info, *apiserver.Server) {
    62  	machine, password := s.Factory.MakeMachineReturningPassword(
    63  		c, &factory.MachineParams{Nonce: "fake_nonce"})
    64  	info, srv := newServer(c, s.State)
    65  	info.Tag = machine.Tag()
    66  	info.Password = password
    67  	info.Nonce = "fake_nonce"
    68  	return info, srv
    69  }
    70  
    71  func (s *loginSuite) TestLoginWithInvalidTag(c *gc.C) {
    72  	info := s.APIInfo(c)
    73  	info.Tag = nil
    74  	info.Password = ""
    75  	st := s.openAPIWithoutLogin(c, info)
    76  
    77  	request := &params.LoginRequest{
    78  		AuthTag:     "bar",
    79  		Credentials: "password",
    80  	}
    81  
    82  	var response params.LoginResult
    83  	err := st.APICall("Admin", 3, "", "Login", request, &response)
    84  	c.Assert(err, gc.ErrorMatches, `.*"bar" is not a valid tag.*`)
    85  }
    86  
    87  func (s *loginSuite) TestBadLogin(c *gc.C) {
    88  	// Start our own server so we can control when the first login
    89  	// happens. Otherwise in JujuConnSuite.SetUpTest api.Open is
    90  	// called with user-admin permissions automatically.
    91  	info, srv := newServer(c, s.State)
    92  	defer assertStop(c, srv)
    93  	info.ModelTag = s.State.ModelTag()
    94  
    95  	adminUser := s.AdminUserTag(c)
    96  
    97  	for i, t := range []struct {
    98  		tag      names.Tag
    99  		password string
   100  		err      error
   101  		code     string
   102  	}{{
   103  		tag:      adminUser,
   104  		password: "wrong password",
   105  		err: &rpc.RequestError{
   106  			Message: "invalid entity name or password",
   107  			Code:    "unauthorized access",
   108  		},
   109  		code: params.CodeUnauthorized,
   110  	}, {
   111  		tag:      names.NewUserTag("unknown"),
   112  		password: "password",
   113  		err: &rpc.RequestError{
   114  			Message: "invalid entity name or password",
   115  			Code:    "unauthorized access",
   116  		},
   117  		code: params.CodeUnauthorized,
   118  	}} {
   119  		c.Logf("test %d; entity %q; password %q", i, t.tag, t.password)
   120  		func() {
   121  			// Open the API without logging in, so we can perform
   122  			// operations on the connection before calling Login.
   123  			st := s.openAPIWithoutLogin(c, info)
   124  
   125  			_, err := apimachiner.NewState(st).Machine(names.NewMachineTag("0"))
   126  			c.Assert(errors.Cause(err), gc.DeepEquals, &rpc.RequestError{
   127  				Message: `unknown object type "Machiner"`,
   128  				Code:    "not implemented",
   129  			})
   130  
   131  			// Since these are user login tests, the nonce is empty.
   132  			err = st.Login(t.tag, t.password, "", nil)
   133  			c.Assert(errors.Cause(err), gc.DeepEquals, t.err)
   134  			c.Assert(params.ErrCode(err), gc.Equals, t.code)
   135  
   136  			_, err = apimachiner.NewState(st).Machine(names.NewMachineTag("0"))
   137  			c.Assert(errors.Cause(err), gc.DeepEquals, &rpc.RequestError{
   138  				Message: `unknown object type "Machiner"`,
   139  				Code:    "not implemented",
   140  			})
   141  		}()
   142  	}
   143  }
   144  
   145  func (s *loginSuite) TestLoginAsDeactivatedUser(c *gc.C) {
   146  	info, srv := newServer(c, s.State)
   147  	defer assertStop(c, srv)
   148  	info.ModelTag = s.State.ModelTag()
   149  
   150  	st := s.openAPIWithoutLogin(c, info)
   151  	password := "password"
   152  	u := s.Factory.MakeUser(c, &factory.UserParams{Password: password, Disabled: true})
   153  
   154  	_, err := st.Client().Status([]string{})
   155  	c.Assert(errors.Cause(err), gc.DeepEquals, &rpc.RequestError{
   156  		Message: `unknown object type "Client"`,
   157  		Code:    "not implemented",
   158  	})
   159  
   160  	// Since these are user login tests, the nonce is empty.
   161  	err = st.Login(u.Tag(), password, "", nil)
   162  	assertInvalidEntityPassword(c, err)
   163  
   164  	_, err = st.Client().Status([]string{})
   165  	c.Assert(errors.Cause(err), gc.DeepEquals, &rpc.RequestError{
   166  		Message: `unknown object type "Client"`,
   167  		Code:    "not implemented",
   168  	})
   169  }
   170  
   171  func (s *baseLoginSuite) runLoginSetsLogIdentifier(c *gc.C) {
   172  	info, srv := newServer(c, s.State)
   173  	defer assertStop(c, srv)
   174  
   175  	machine, password := s.Factory.MakeMachineReturningPassword(
   176  		c, &factory.MachineParams{Nonce: "fake_nonce"})
   177  
   178  	info.Tag = machine.Tag()
   179  	info.Password = password
   180  	info.Nonce = "fake_nonce"
   181  
   182  	apiConn, err := api.Open(info, fastDialOpts)
   183  	c.Assert(err, jc.ErrorIsNil)
   184  	defer apiConn.Close()
   185  
   186  	apiMachine, err := apimachiner.NewState(apiConn).Machine(machine.MachineTag())
   187  	c.Assert(err, jc.ErrorIsNil)
   188  	c.Assert(apiMachine.Tag(), gc.Equals, machine.Tag())
   189  }
   190  
   191  func (s *loginSuite) TestLoginAddrs(c *gc.C) {
   192  	info, srv := s.newMachineAndServer(c)
   193  	defer assertStop(c, srv)
   194  
   195  	err := s.State.SetAPIHostPorts(nil)
   196  	c.Assert(err, jc.ErrorIsNil)
   197  
   198  	// Initially just the address we connect with is returned,
   199  	// despite there being no APIHostPorts in state.
   200  	connectedAddr, hostPorts := s.loginHostPorts(c, info)
   201  	connectedAddrHost, connectedAddrPortString, err := net.SplitHostPort(connectedAddr)
   202  	c.Assert(err, jc.ErrorIsNil)
   203  	connectedAddrPort, err := strconv.Atoi(connectedAddrPortString)
   204  	c.Assert(err, jc.ErrorIsNil)
   205  	connectedAddrHostPorts := [][]network.HostPort{
   206  		network.NewHostPorts(connectedAddrPort, connectedAddrHost),
   207  	}
   208  	c.Assert(hostPorts, gc.DeepEquals, connectedAddrHostPorts)
   209  
   210  	// After storing APIHostPorts in state, Login should store
   211  	// all of them and the address we connected with.
   212  	server1Addresses := []network.Address{{
   213  		Value: "server-1",
   214  		Type:  network.HostName,
   215  		Scope: network.ScopePublic,
   216  	}, {
   217  		Value: "10.0.0.1",
   218  		Type:  network.IPv4Address,
   219  		Scope: network.ScopeCloudLocal,
   220  	}}
   221  	server2Addresses := []network.Address{{
   222  		Value: "::1",
   223  		Type:  network.IPv6Address,
   224  		Scope: network.ScopeMachineLocal,
   225  	}}
   226  	stateAPIHostPorts := [][]network.HostPort{
   227  		network.AddressesWithPort(server1Addresses, 123),
   228  		network.AddressesWithPort(server2Addresses, 456),
   229  	}
   230  	err = s.State.SetAPIHostPorts(stateAPIHostPorts)
   231  	c.Assert(err, jc.ErrorIsNil)
   232  	_, hostPorts = s.loginHostPorts(c, info)
   233  	// Now that we connected, we add the other stateAPIHostPorts. However,
   234  	// the one we connected to comes first.
   235  	stateAPIHostPorts = append(connectedAddrHostPorts, stateAPIHostPorts...)
   236  	c.Assert(hostPorts, gc.DeepEquals, stateAPIHostPorts)
   237  }
   238  
   239  func (s *baseLoginSuite) loginHostPorts(c *gc.C, info *api.Info) (connectedAddr string, hostPorts [][]network.HostPort) {
   240  	st, err := api.Open(info, fastDialOpts)
   241  	c.Assert(err, jc.ErrorIsNil)
   242  	defer st.Close()
   243  	return st.Addr(), st.APIHostPorts()
   244  }
   245  
   246  func startNLogins(c *gc.C, n int, info *api.Info) (chan error, *sync.WaitGroup) {
   247  	errResults := make(chan error, 100)
   248  	var doneWG sync.WaitGroup
   249  	var startedWG sync.WaitGroup
   250  	c.Logf("starting %d concurrent logins to %v", n, info.Addrs)
   251  	for i := 0; i < n; i++ {
   252  		i := i
   253  		c.Logf("starting login request %d", i)
   254  		startedWG.Add(1)
   255  		doneWG.Add(1)
   256  		go func() {
   257  			c.Logf("started login %d", i)
   258  			startedWG.Done()
   259  			st, err := api.Open(info, fastDialOpts)
   260  			errResults <- err
   261  			if err == nil {
   262  				st.Close()
   263  			}
   264  			doneWG.Done()
   265  			c.Logf("finished login %d: %v", i, err)
   266  		}()
   267  	}
   268  	startedWG.Wait()
   269  	return errResults, &doneWG
   270  }
   271  
   272  func (s *loginSuite) TestDelayLogins(c *gc.C) {
   273  	info, srv := s.newMachineAndServer(c)
   274  	defer assertStop(c, srv)
   275  	delayChan, cleanup := apiserver.DelayLogins()
   276  	defer cleanup()
   277  
   278  	// numConcurrentLogins is how many logins will fire off simultaneously.
   279  	// It doesn't really matter, as long as it is less than LoginRateLimit
   280  	const numConcurrentLogins = 5
   281  	c.Assert(numConcurrentLogins, jc.LessThan, apiserver.LoginRateLimit)
   282  	// Trigger a bunch of login requests
   283  	errResults, wg := startNLogins(c, numConcurrentLogins, info)
   284  	select {
   285  	case err := <-errResults:
   286  		c.Fatalf("we should not have gotten any logins yet: %v", err)
   287  	case <-time.After(coretesting.ShortWait):
   288  	}
   289  	// Allow one login to proceed
   290  	c.Logf("letting one login through")
   291  	select {
   292  	case delayChan <- struct{}{}:
   293  	default:
   294  		c.Fatalf("we should have been able to unblock a login")
   295  	}
   296  	select {
   297  	case err := <-errResults:
   298  		c.Check(err, jc.ErrorIsNil)
   299  	case <-time.After(coretesting.LongWait):
   300  		c.Fatalf("timed out while waiting for Login to finish")
   301  	}
   302  	c.Logf("checking no other logins succeeded")
   303  	// It should have only let 1 login through
   304  	select {
   305  	case err := <-errResults:
   306  		c.Fatalf("we should not have gotten more logins: %v", err)
   307  	case <-time.After(coretesting.ShortWait):
   308  	}
   309  	// Now allow the rest of the logins to proceed
   310  	c.Logf("letting %d logins through", numConcurrentLogins-1)
   311  	for i := 0; i < numConcurrentLogins-1; i++ {
   312  		delayChan <- struct{}{}
   313  	}
   314  	c.Logf("waiting for Logins to finish")
   315  	wg.Wait()
   316  	close(errResults)
   317  	successCount := 0
   318  	for err := range errResults {
   319  		c.Check(err, jc.ErrorIsNil)
   320  		if err == nil {
   321  			successCount += 1
   322  		}
   323  	}
   324  	// All the logins should succeed, they were just delayed after
   325  	// connecting.
   326  	c.Check(successCount, gc.Equals, numConcurrentLogins-1)
   327  	c.Logf("done")
   328  }
   329  
   330  func (s *loginSuite) TestLoginRateLimited(c *gc.C) {
   331  	info, srv := s.newMachineAndServer(c)
   332  	defer assertStop(c, srv)
   333  	delayChan, cleanup := apiserver.DelayLogins()
   334  	defer cleanup()
   335  
   336  	// Start enough concurrent Login requests so that we max out our
   337  	// LoginRateLimit. Do one extra so we know we are in overload
   338  	errResults, wg := startNLogins(c, apiserver.LoginRateLimit+1, info)
   339  	select {
   340  	case err := <-errResults:
   341  		c.Check(err, jc.Satisfies, params.IsCodeTryAgain)
   342  	case <-time.After(coretesting.LongWait):
   343  		c.Fatalf("timed out waiting for login to get rejected.")
   344  	}
   345  
   346  	// Let one request through, we should see that it succeeds without
   347  	// error, and then be able to start a new request, but it will block
   348  	delayChan <- struct{}{}
   349  	select {
   350  	case err := <-errResults:
   351  		c.Check(err, jc.ErrorIsNil)
   352  	case <-time.After(coretesting.LongWait):
   353  		c.Fatalf("timed out expecting one login to succeed")
   354  	}
   355  	chOne := make(chan error, 1)
   356  	wg.Add(1)
   357  	go func() {
   358  		st, err := api.Open(info, fastDialOpts)
   359  		chOne <- err
   360  		if err == nil {
   361  			st.Close()
   362  		}
   363  		wg.Done()
   364  	}()
   365  	select {
   366  	case err := <-chOne:
   367  		c.Fatalf("the open request should not have completed: %v", err)
   368  	case <-time.After(coretesting.ShortWait):
   369  	}
   370  	// Let all the logins finish. We started with LoginRateLimit, let one
   371  	// proceed, but we issued another one, so there should be
   372  	// LoginRateLimit logins pending.
   373  	for i := 0; i < apiserver.LoginRateLimit; i++ {
   374  		delayChan <- struct{}{}
   375  	}
   376  	wg.Wait()
   377  	close(errResults)
   378  	for err := range errResults {
   379  		c.Check(err, jc.ErrorIsNil)
   380  	}
   381  }
   382  
   383  func (s *loginSuite) TestUsersLoginWhileRateLimited(c *gc.C) {
   384  	info, srv := s.newMachineAndServer(c)
   385  	defer assertStop(c, srv)
   386  	delayChan, cleanup := apiserver.DelayLogins()
   387  	defer cleanup()
   388  
   389  	// Start enough concurrent Login requests so that we max out our
   390  	// LoginRateLimit. Do one extra so we know we are in overload
   391  	machineResults, machineWG := startNLogins(c, apiserver.LoginRateLimit+1, info)
   392  	select {
   393  	case err := <-machineResults:
   394  		c.Check(err, jc.Satisfies, params.IsCodeTryAgain)
   395  	case <-time.After(coretesting.LongWait):
   396  		c.Fatalf("timed out waiting for login to get rejected.")
   397  	}
   398  
   399  	userInfo := *info
   400  	userInfo.Tag = s.AdminUserTag(c)
   401  	userInfo.Password = "dummy-secret"
   402  	userResults, userWG := startNLogins(c, apiserver.LoginRateLimit+1, &userInfo)
   403  	// all of them should have started, and none of them in TryAgain state
   404  	select {
   405  	case err := <-userResults:
   406  		c.Fatalf("we should not have gotten any logins yet: %v", err)
   407  	case <-time.After(coretesting.ShortWait):
   408  	}
   409  	totalLogins := apiserver.LoginRateLimit*2 + 1
   410  	for i := 0; i < totalLogins; i++ {
   411  		delayChan <- struct{}{}
   412  	}
   413  	machineWG.Wait()
   414  	close(machineResults)
   415  	userWG.Wait()
   416  	close(userResults)
   417  	machineCount := 0
   418  	for err := range machineResults {
   419  		machineCount += 1
   420  		c.Check(err, jc.ErrorIsNil)
   421  	}
   422  	c.Check(machineCount, gc.Equals, apiserver.LoginRateLimit)
   423  	userCount := 0
   424  	for err := range userResults {
   425  		userCount += 1
   426  		c.Check(err, jc.ErrorIsNil)
   427  	}
   428  	c.Check(userCount, gc.Equals, apiserver.LoginRateLimit+1)
   429  }
   430  
   431  func (s *loginSuite) TestUsersAreNotRateLimited(c *gc.C) {
   432  	info, srv := newServer(c, s.State)
   433  	defer assertStop(c, srv)
   434  
   435  	info.Tag = s.AdminUserTag(c)
   436  	info.Password = "dummy-secret"
   437  	info.ModelTag = s.State.ModelTag()
   438  
   439  	delayChan, cleanup := apiserver.DelayLogins()
   440  	defer cleanup()
   441  	// We can login more than LoginRateLimit users
   442  	nLogins := apiserver.LoginRateLimit * 2
   443  	errResults, wg := startNLogins(c, nLogins, info)
   444  	select {
   445  	case err := <-errResults:
   446  		c.Fatalf("we should not have gotten any logins yet: %v", err)
   447  	case <-time.After(coretesting.ShortWait):
   448  	}
   449  	c.Logf("letting %d logins complete", nLogins)
   450  	for i := 0; i < nLogins; i++ {
   451  		delayChan <- struct{}{}
   452  	}
   453  	c.Logf("waiting for original requests to finish")
   454  	wg.Wait()
   455  	close(errResults)
   456  	for err := range errResults {
   457  		c.Check(err, jc.ErrorIsNil)
   458  	}
   459  }
   460  
   461  func (s *loginSuite) TestNonModelUserLoginFails(c *gc.C) {
   462  	info, srv := newServer(c, s.State)
   463  	defer assertStop(c, srv)
   464  	info.ModelTag = s.State.ModelTag()
   465  	user := s.Factory.MakeUser(c, &factory.UserParams{Password: "dummy-password", NoModelUser: true})
   466  	ctag := names.NewControllerTag(s.State.ControllerUUID())
   467  	err := s.State.RemoveUserAccess(user.UserTag(), ctag)
   468  	c.Assert(err, jc.ErrorIsNil)
   469  	info.Password = "dummy-password"
   470  	info.Tag = user.UserTag()
   471  	_, err = api.Open(info, fastDialOpts)
   472  	assertInvalidEntityPassword(c, err)
   473  }
   474  
   475  func (s *loginSuite) TestLoginValidationSuccess(c *gc.C) {
   476  	validator := func(params.LoginRequest) error {
   477  		return nil
   478  	}
   479  	checker := func(c *gc.C, loginErr error, st api.Connection) {
   480  		c.Assert(loginErr, gc.IsNil)
   481  
   482  		// Ensure an API call that would be restricted during
   483  		// upgrades works after a normal login.
   484  		err := st.APICall("Client", 1, "", "ModelSet", params.ModelSet{}, nil)
   485  		c.Assert(err, jc.ErrorIsNil)
   486  	}
   487  	s.checkLoginWithValidator(c, validator, checker)
   488  }
   489  
   490  func (s *loginSuite) TestLoginValidationFail(c *gc.C) {
   491  	validator := func(params.LoginRequest) error {
   492  		return errors.New("Login not allowed")
   493  	}
   494  	checker := func(c *gc.C, loginErr error, _ api.Connection) {
   495  		// error is wrapped in API server
   496  		c.Assert(loginErr, gc.ErrorMatches, "Login not allowed")
   497  	}
   498  	s.checkLoginWithValidator(c, validator, checker)
   499  }
   500  
   501  func (s *loginSuite) TestLoginValidationDuringUpgrade(c *gc.C) {
   502  	validator := func(params.LoginRequest) error {
   503  		return params.UpgradeInProgressError
   504  	}
   505  	checker := func(c *gc.C, loginErr error, st api.Connection) {
   506  		c.Assert(loginErr, gc.IsNil)
   507  
   508  		var statusResult params.FullStatus
   509  		err := st.APICall("Client", 1, "", "FullStatus", params.StatusParams{}, &statusResult)
   510  		c.Assert(err, jc.ErrorIsNil)
   511  
   512  		err = st.APICall("Client", 1, "", "ModelSet", params.ModelSet{}, nil)
   513  		c.Assert(err, jc.Satisfies, params.IsCodeUpgradeInProgress)
   514  	}
   515  	s.checkLoginWithValidator(c, validator, checker)
   516  }
   517  
   518  func (s *loginSuite) TestFailedLoginDuringMaintenance(c *gc.C) {
   519  	cfg := defaultServerConfig(c)
   520  	cfg.Validator = func(params.LoginRequest) error {
   521  		return errors.New("something")
   522  	}
   523  	info, srv := newServerWithConfig(c, s.State, cfg)
   524  	defer assertStop(c, srv)
   525  	info.ModelTag = s.State.ModelTag()
   526  
   527  	checkLogin := func(tag names.Tag) {
   528  		st := s.openAPIWithoutLogin(c, info)
   529  		err := st.Login(tag, "dummy-secret", "nonce", nil)
   530  		c.Assert(err, gc.ErrorMatches, "something")
   531  	}
   532  	checkLogin(names.NewUserTag("definitelywontexist"))
   533  	checkLogin(names.NewMachineTag("99999"))
   534  }
   535  
   536  type validationChecker func(c *gc.C, err error, st api.Connection)
   537  
   538  func (s *baseLoginSuite) checkLoginWithValidator(c *gc.C, validator apiserver.LoginValidator, checker validationChecker) {
   539  	cfg := defaultServerConfig(c)
   540  	cfg.Validator = validator
   541  	info, srv := newServerWithConfig(c, s.State, cfg)
   542  	defer assertStop(c, srv)
   543  	info.ModelTag = s.State.ModelTag()
   544  
   545  	st := s.openAPIWithoutLogin(c, info)
   546  
   547  	// Ensure not already logged in.
   548  	_, err := apimachiner.NewState(st).Machine(names.NewMachineTag("0"))
   549  	c.Assert(errors.Cause(err), gc.DeepEquals, &rpc.RequestError{
   550  		Message: `unknown object type "Machiner"`,
   551  		Code:    "not implemented",
   552  	})
   553  
   554  	adminUser := s.AdminUserTag(c)
   555  	// Since these are user login tests, the nonce is empty.
   556  	err = st.Login(adminUser, "dummy-secret", "", nil)
   557  
   558  	checker(c, err, st)
   559  }
   560  
   561  func (s *baseLoginSuite) openAPIWithoutLogin(c *gc.C, info0 *api.Info) api.Connection {
   562  	info := *info0
   563  	info.Tag = nil
   564  	info.Password = ""
   565  	info.SkipLogin = true
   566  	st, err := api.Open(&info, fastDialOpts)
   567  	c.Assert(err, jc.ErrorIsNil)
   568  	s.AddCleanup(func(*gc.C) { st.Close() })
   569  	return st
   570  }
   571  
   572  func (s *loginSuite) TestControllerModel(c *gc.C) {
   573  	info, srv := newServer(c, s.State)
   574  	defer assertStop(c, srv)
   575  
   576  	info.ModelTag = s.State.ModelTag()
   577  	st := s.openAPIWithoutLogin(c, info)
   578  
   579  	adminUser := s.AdminUserTag(c)
   580  	err := st.Login(adminUser, "dummy-secret", "", nil)
   581  	c.Assert(err, jc.ErrorIsNil)
   582  
   583  	s.assertRemoteModel(c, st, s.State.ModelTag())
   584  }
   585  
   586  func (s *loginSuite) TestControllerModelBadCreds(c *gc.C) {
   587  	info, srv := newServer(c, s.State)
   588  	defer assertStop(c, srv)
   589  
   590  	info.ModelTag = s.State.ModelTag()
   591  	st := s.openAPIWithoutLogin(c, info)
   592  
   593  	adminUser := s.AdminUserTag(c)
   594  	err := st.Login(adminUser, "bad-password", "", nil)
   595  	assertInvalidEntityPassword(c, err)
   596  }
   597  
   598  func (s *loginSuite) TestNonExistentModel(c *gc.C) {
   599  	info, srv := newServer(c, s.State)
   600  	defer assertStop(c, srv)
   601  
   602  	uuid, err := utils.NewUUID()
   603  	c.Assert(err, jc.ErrorIsNil)
   604  	info.ModelTag = names.NewModelTag(uuid.String())
   605  	st := s.openAPIWithoutLogin(c, info)
   606  
   607  	adminUser := s.AdminUserTag(c)
   608  	err = st.Login(adminUser, "dummy-secret", "", nil)
   609  	c.Assert(errors.Cause(err), gc.DeepEquals, &rpc.RequestError{
   610  		Message: fmt.Sprintf("unknown model: %q", uuid),
   611  		Code:    "model not found",
   612  	})
   613  }
   614  
   615  func (s *loginSuite) TestInvalidModel(c *gc.C) {
   616  	info, srv := newServer(c, s.State)
   617  	defer assertStop(c, srv)
   618  	info.ModelTag = names.NewModelTag("rubbish")
   619  
   620  	st := s.openAPIWithoutLogin(c, info)
   621  
   622  	adminUser := s.AdminUserTag(c)
   623  	err := st.Login(adminUser, "dummy-secret", "", nil)
   624  	c.Assert(errors.Cause(err), gc.DeepEquals, &rpc.RequestError{
   625  		Message: `unknown model: "rubbish"`,
   626  		Code:    "model not found",
   627  	})
   628  }
   629  
   630  func (s *loginSuite) TestOtherModel(c *gc.C) {
   631  	info, srv := newServer(c, s.State)
   632  	defer assertStop(c, srv)
   633  
   634  	envOwner := s.Factory.MakeUser(c, nil)
   635  	envState := s.Factory.MakeModel(c, &factory.ModelParams{
   636  		Owner: envOwner.UserTag(),
   637  	})
   638  	defer envState.Close()
   639  	info.ModelTag = envState.ModelTag()
   640  	st := s.openAPIWithoutLogin(c, info)
   641  
   642  	err := st.Login(envOwner.UserTag(), "password", "", nil)
   643  	c.Assert(err, jc.ErrorIsNil)
   644  	s.assertRemoteModel(c, st, envState.ModelTag())
   645  }
   646  
   647  func (s *loginSuite) TestMachineLoginOtherModel(c *gc.C) {
   648  	// User credentials are checked against a global user list.
   649  	// Machine credentials are checked against environment specific
   650  	// machines, so this makes sure that the credential checking is
   651  	// using the correct state connection.
   652  	info, srv := newServer(c, s.State)
   653  	defer assertStop(c, srv)
   654  
   655  	envOwner := s.Factory.MakeUser(c, nil)
   656  	envState := s.Factory.MakeModel(c, &factory.ModelParams{
   657  		Owner: envOwner.UserTag(),
   658  		ConfigAttrs: map[string]interface{}{
   659  			"controller": false,
   660  		},
   661  	})
   662  	defer envState.Close()
   663  
   664  	f2 := factory.NewFactory(envState)
   665  	machine, password := f2.MakeMachineReturningPassword(c, &factory.MachineParams{
   666  		Nonce: "nonce",
   667  	})
   668  
   669  	info.ModelTag = envState.ModelTag()
   670  	st := s.openAPIWithoutLogin(c, info)
   671  
   672  	err := st.Login(machine.Tag(), password, "nonce", nil)
   673  	c.Assert(err, jc.ErrorIsNil)
   674  }
   675  
   676  func (s *loginSuite) TestMachineLoginOtherModelNotProvisioned(c *gc.C) {
   677  	info, srv := newServer(c, s.State)
   678  	defer assertStop(c, srv)
   679  
   680  	envOwner := s.Factory.MakeUser(c, nil)
   681  	envState := s.Factory.MakeModel(c, &factory.ModelParams{
   682  		Owner: envOwner.UserTag(),
   683  		ConfigAttrs: map[string]interface{}{
   684  			"controller": false,
   685  		},
   686  	})
   687  	defer envState.Close()
   688  
   689  	f2 := factory.NewFactory(envState)
   690  	machine, password := f2.MakeUnprovisionedMachineReturningPassword(c, &factory.MachineParams{})
   691  
   692  	info.ModelTag = envState.ModelTag()
   693  	st := s.openAPIWithoutLogin(c, info)
   694  
   695  	// If the agent attempts Login before the provisioner has recorded
   696  	// the machine's nonce in state, then the agent should get back an
   697  	// error with code "not provisioned".
   698  	err := st.Login(machine.Tag(), password, "nonce", nil)
   699  	c.Assert(err, gc.ErrorMatches, `machine 0 not provisioned \(not provisioned\)`)
   700  	c.Assert(err, jc.Satisfies, params.IsCodeNotProvisioned)
   701  }
   702  
   703  func (s *loginSuite) TestOtherEnvironmentFromController(c *gc.C) {
   704  	info, srv := newServer(c, s.State)
   705  	defer assertStop(c, srv)
   706  
   707  	machine, password := s.Factory.MakeMachineReturningPassword(c, &factory.MachineParams{
   708  		Jobs: []state.MachineJob{state.JobManageModel},
   709  	})
   710  
   711  	envState := s.Factory.MakeModel(c, nil)
   712  	defer envState.Close()
   713  	info.ModelTag = envState.ModelTag()
   714  	st := s.openAPIWithoutLogin(c, info)
   715  
   716  	err := st.Login(machine.Tag(), password, "nonce", nil)
   717  	c.Assert(err, jc.ErrorIsNil)
   718  }
   719  
   720  func (s *loginSuite) TestOtherEnvironmentFromControllerOtherNotProvisioned(c *gc.C) {
   721  	info, srv := newServer(c, s.State)
   722  	defer assertStop(c, srv)
   723  
   724  	managerMachine, password := s.Factory.MakeMachineReturningPassword(c, &factory.MachineParams{
   725  		Jobs: []state.MachineJob{state.JobManageModel},
   726  	})
   727  
   728  	// Create a hosted model with an unprovisioned machine that has the
   729  	// same tag as the manager machine.
   730  	hostedModelState := s.Factory.MakeModel(c, nil)
   731  	defer hostedModelState.Close()
   732  	f2 := factory.NewFactory(hostedModelState)
   733  	workloadMachine, _ := f2.MakeUnprovisionedMachineReturningPassword(c, &factory.MachineParams{})
   734  	c.Assert(managerMachine.Tag(), gc.Equals, workloadMachine.Tag())
   735  
   736  	info.ModelTag = hostedModelState.ModelTag()
   737  	st := s.openAPIWithoutLogin(c, info)
   738  
   739  	// The fact that the machine with the same tag in the hosted
   740  	// model is unprovisioned should not cause the login to fail
   741  	// with "not provisioned", because the passwords don't match.
   742  	err := st.Login(managerMachine.Tag(), password, "nonce", nil)
   743  	c.Assert(err, jc.ErrorIsNil)
   744  }
   745  
   746  func (s *loginSuite) TestOtherEnvironmentWhenNotController(c *gc.C) {
   747  	info, srv := newServer(c, s.State)
   748  	defer assertStop(c, srv)
   749  
   750  	machine, password := s.Factory.MakeMachineReturningPassword(c, nil)
   751  
   752  	envState := s.Factory.MakeModel(c, nil)
   753  	defer envState.Close()
   754  	info.ModelTag = envState.ModelTag()
   755  	st := s.openAPIWithoutLogin(c, info)
   756  
   757  	err := st.Login(machine.Tag(), password, "nonce", nil)
   758  	assertPermissionDenied(c, err)
   759  }
   760  
   761  func (s *loginSuite) loginLocalUser(c *gc.C, info *api.Info) (*state.User, params.LoginResult) {
   762  	password := "shhh..."
   763  	user := s.Factory.MakeUser(c, &factory.UserParams{
   764  		Password: password,
   765  	})
   766  	conn := s.openAPIWithoutLogin(c, info)
   767  
   768  	var result params.LoginResult
   769  	request := &params.LoginRequest{
   770  		AuthTag:     user.Tag().String(),
   771  		Credentials: password,
   772  	}
   773  	err := conn.APICall("Admin", 3, "", "Login", request, &result)
   774  	c.Assert(err, jc.ErrorIsNil)
   775  	c.Assert(result.UserInfo, gc.NotNil)
   776  	return user, result
   777  }
   778  
   779  func (s *loginSuite) TestLoginResultLocalUser(c *gc.C) {
   780  	info, srv := newServer(c, s.State)
   781  	defer assertStop(c, srv)
   782  	info.ModelTag = s.State.ModelTag()
   783  
   784  	user, result := s.loginLocalUser(c, info)
   785  	c.Check(result.UserInfo.Identity, gc.Equals, user.Tag().String())
   786  	c.Check(result.UserInfo.ControllerAccess, gc.Equals, "login")
   787  	c.Check(result.UserInfo.ModelAccess, gc.Equals, "admin")
   788  }
   789  
   790  func (s *loginSuite) TestLoginResultLocalUserEveryoneCreateOnlyNonLocal(c *gc.C) {
   791  	info, srv := newServer(c, s.State)
   792  	defer assertStop(c, srv)
   793  	info.ModelTag = s.State.ModelTag()
   794  
   795  	setEveryoneAccess(c, s.State, s.AdminUserTag(c), permission.AddModelAccess)
   796  
   797  	user, result := s.loginLocalUser(c, info)
   798  	c.Check(result.UserInfo.Identity, gc.Equals, user.Tag().String())
   799  	c.Check(result.UserInfo.ControllerAccess, gc.Equals, "login")
   800  	c.Check(result.UserInfo.ModelAccess, gc.Equals, "admin")
   801  }
   802  
   803  func (s *loginSuite) assertRemoteModel(c *gc.C, api api.Connection, expected names.ModelTag) {
   804  	// Look at what the api thinks it has.
   805  	tag, ok := api.ModelTag()
   806  	c.Assert(ok, jc.IsTrue)
   807  	c.Assert(tag, gc.Equals, expected)
   808  	// Look at what the api Client thinks it has.
   809  	client := api.Client()
   810  
   811  	// ModelUUID looks at the env tag on the api state connection.
   812  	uuid, ok := client.ModelUUID()
   813  	c.Assert(ok, jc.IsTrue)
   814  	c.Assert(uuid, gc.Equals, expected.Id())
   815  
   816  	// The code below is to verify that the API connection is operating on
   817  	// the expected model. We make a change in state on that model, and
   818  	// then check that it is picked up by a call to the API.
   819  
   820  	st, err := s.State.ForModel(tag)
   821  	c.Assert(err, jc.ErrorIsNil)
   822  	defer st.Close()
   823  
   824  	expectedCons := constraints.MustParse("mem=8G")
   825  	err = st.SetModelConstraints(expectedCons)
   826  	c.Assert(err, jc.ErrorIsNil)
   827  
   828  	cons, err := client.GetModelConstraints()
   829  	c.Assert(err, jc.ErrorIsNil)
   830  	c.Assert(cons, jc.DeepEquals, expectedCons)
   831  }
   832  
   833  func (s *loginSuite) TestLoginUpdatesLastLoginAndConnection(c *gc.C) {
   834  	// Since the login and connection times truncate time to the second,
   835  	// we need to make sure our start time is just before now.
   836  	startTime := time.Now().Add(-time.Second)
   837  
   838  	password := "shhh..."
   839  	user := s.Factory.MakeUser(c, &factory.UserParams{
   840  		Password: password,
   841  	})
   842  
   843  	info := s.APIInfo(c)
   844  	info.Tag = user.Tag()
   845  	info.Password = password
   846  	apiState, err := api.Open(info, api.DialOpts{})
   847  	c.Assert(err, jc.ErrorIsNil)
   848  	defer apiState.Close()
   849  
   850  	// The user now has last login updated.
   851  	err = user.Refresh()
   852  	c.Assert(err, jc.ErrorIsNil)
   853  	lastLogin, err := user.LastLogin()
   854  	c.Assert(err, jc.ErrorIsNil)
   855  	c.Assert(lastLogin, gc.NotNil)
   856  	c.Assert(lastLogin.After(startTime), jc.IsTrue)
   857  
   858  	// The env user is also updated.
   859  	modelUser, err := s.State.UserAccess(user.UserTag(), s.State.ModelTag())
   860  	c.Assert(err, jc.ErrorIsNil)
   861  	when, err := s.State.LastModelConnection(modelUser.UserTag)
   862  	c.Assert(err, jc.ErrorIsNil)
   863  	c.Assert(when, gc.NotNil)
   864  	c.Assert(when.After(startTime), jc.IsTrue)
   865  }
   866  
   867  var _ = gc.Suite(&macaroonLoginSuite{})
   868  
   869  type macaroonLoginSuite struct {
   870  	apitesting.MacaroonSuite
   871  }
   872  
   873  func (s *macaroonLoginSuite) TestLoginToController(c *gc.C) {
   874  	// Note that currently we cannot use macaroon auth
   875  	// to log into the controller rather than an environment
   876  	// because there's no place to store the fact that
   877  	// a given external user is allowed access to the controller.
   878  	s.DischargerLogin = func() string {
   879  		return "test@somewhere"
   880  	}
   881  	info := s.APIInfo(c)
   882  
   883  	// Zero the environment tag so that we log into the controller
   884  	// not the environment.
   885  	info.ModelTag = names.ModelTag{}
   886  
   887  	client, err := api.Open(info, api.DialOpts{})
   888  	assertInvalidEntityPassword(c, err)
   889  	c.Assert(client, gc.Equals, nil)
   890  }
   891  
   892  func (s *macaroonLoginSuite) login(c *gc.C, info *api.Info) (params.LoginResult, error) {
   893  	info.SkipLogin = true
   894  
   895  	cookieJar := apitesting.NewClearableCookieJar()
   896  
   897  	client := s.OpenAPI(c, info, cookieJar)
   898  	defer client.Close()
   899  
   900  	var (
   901  		// Remote users start with an empty login request.
   902  		request params.LoginRequest
   903  		result  params.LoginResult
   904  	)
   905  	err := client.APICall("Admin", 3, "", "Login", &request, &result)
   906  	c.Assert(err, jc.ErrorIsNil)
   907  
   908  	cookieURL := &url.URL{
   909  		Scheme: "https",
   910  		Host:   "localhost",
   911  		Path:   "/",
   912  	}
   913  
   914  	bakeryClient := httpbakery.NewClient()
   915  
   916  	err = bakeryClient.HandleError(cookieURL, &httpbakery.Error{
   917  		Message: result.DischargeRequiredReason,
   918  		Code:    httpbakery.ErrDischargeRequired,
   919  		Info: &httpbakery.ErrorInfo{
   920  			Macaroon:     result.DischargeRequired,
   921  			MacaroonPath: "/",
   922  		},
   923  	})
   924  	c.Assert(err, jc.ErrorIsNil)
   925  	// Add the macaroons that have been saved by HandleError to our login request.
   926  	request.Macaroons = httpbakery.MacaroonsForURL(bakeryClient.Client.Jar, cookieURL)
   927  
   928  	err = client.APICall("Admin", 3, "", "Login", &request, &result)
   929  	return result, err
   930  }
   931  
   932  func (s *macaroonLoginSuite) TestRemoteUserLoginToControllerNoAccess(c *gc.C) {
   933  	s.DischargerLogin = func() string {
   934  		return "test@somewhere"
   935  	}
   936  	info := s.APIInfo(c)
   937  	// Log in to the controller, not the model.
   938  	info.ModelTag = names.ModelTag{}
   939  
   940  	_, err := s.login(c, info)
   941  	assertInvalidEntityPassword(c, err)
   942  }
   943  
   944  func (s *macaroonLoginSuite) TestRemoteUserLoginToControllerLoginAccess(c *gc.C) {
   945  	setEveryoneAccess(c, s.State, s.AdminUserTag(c), permission.LoginAccess)
   946  	const remoteUser = "test@somewhere"
   947  	var remoteUserTag = names.NewUserTag(remoteUser)
   948  
   949  	s.DischargerLogin = func() string {
   950  		return remoteUser
   951  	}
   952  	info := s.APIInfo(c)
   953  	// Log in to the controller, not the model.
   954  	info.ModelTag = names.ModelTag{}
   955  
   956  	result, err := s.login(c, info)
   957  	c.Check(err, jc.ErrorIsNil)
   958  	c.Assert(result.UserInfo, gc.NotNil)
   959  	c.Check(result.UserInfo.Identity, gc.Equals, remoteUserTag.String())
   960  	c.Check(result.UserInfo.ControllerAccess, gc.Equals, "login")
   961  	c.Check(result.UserInfo.ModelAccess, gc.Equals, "")
   962  }
   963  
   964  func (s *macaroonLoginSuite) TestRemoteUserLoginToControllerAddModelAccess(c *gc.C) {
   965  	setEveryoneAccess(c, s.State, s.AdminUserTag(c), permission.AddModelAccess)
   966  	const remoteUser = "test@somewhere"
   967  	var remoteUserTag = names.NewUserTag(remoteUser)
   968  
   969  	s.DischargerLogin = func() string {
   970  		return remoteUser
   971  	}
   972  	info := s.APIInfo(c)
   973  	// Log in to the controller, not the model.
   974  	info.ModelTag = names.ModelTag{}
   975  
   976  	result, err := s.login(c, info)
   977  	c.Check(err, jc.ErrorIsNil)
   978  	c.Assert(result.UserInfo, gc.NotNil)
   979  	c.Check(result.UserInfo.Identity, gc.Equals, remoteUserTag.String())
   980  	c.Check(result.UserInfo.ControllerAccess, gc.Equals, "add-model")
   981  	c.Check(result.UserInfo.ModelAccess, gc.Equals, "")
   982  }
   983  
   984  func (s *macaroonLoginSuite) TestRemoteUserLoginToModelNoExplicitAccess(c *gc.C) {
   985  	// If we have a remote user which the controller knows nothing about,
   986  	// and the macaroon is discharged successfully, and the user is attempting
   987  	// to log into a model, that is permission denied.
   988  	setEveryoneAccess(c, s.State, s.AdminUserTag(c), permission.LoginAccess)
   989  	s.DischargerLogin = func() string {
   990  		return "test@somewhere"
   991  	}
   992  	info := s.APIInfo(c)
   993  
   994  	_, err := s.login(c, info)
   995  	assertPermissionDenied(c, err)
   996  }
   997  
   998  func (s *macaroonLoginSuite) TestRemoteUserLoginToModelWithExplicitAccess(c *gc.C) {
   999  	s.testRemoteUserLoginToModelWithExplicitAccess(c, false)
  1000  }
  1001  
  1002  func (s *macaroonLoginSuite) TestRemoteUserLoginToModelWithExplicitAccessAndAllowModelAccess(c *gc.C) {
  1003  	s.testRemoteUserLoginToModelWithExplicitAccess(c, true)
  1004  }
  1005  
  1006  func (s *macaroonLoginSuite) testRemoteUserLoginToModelWithExplicitAccess(c *gc.C, allowModelAccess bool) {
  1007  	cfg := defaultServerConfig(c)
  1008  	cfg.AllowModelAccess = allowModelAccess
  1009  
  1010  	info, srv := newServerWithConfig(c, s.State, cfg)
  1011  	defer assertStop(c, srv)
  1012  	info.ModelTag = s.State.ModelTag()
  1013  
  1014  	// If we have a remote user which has explict model access, but neither
  1015  	// controller access nor 'everyone' access, the user will have access
  1016  	// only if the AllowModelAccess configuration flag is true.
  1017  	const remoteUser = "test@somewhere"
  1018  	s.Factory.MakeModelUser(c, &factory.ModelUserParams{
  1019  		User: remoteUser,
  1020  
  1021  		Access: permission.WriteAccess,
  1022  	})
  1023  	s.DischargerLogin = func() string {
  1024  		return remoteUser
  1025  	}
  1026  
  1027  	_, err := s.login(c, info)
  1028  	if allowModelAccess {
  1029  		c.Assert(err, jc.ErrorIsNil)
  1030  	} else {
  1031  		assertPermissionDenied(c, err)
  1032  	}
  1033  }
  1034  
  1035  func (s *macaroonLoginSuite) TestRemoteUserLoginToModelWithControllerAccess(c *gc.C) {
  1036  	const remoteUser = "test@somewhere"
  1037  	var remoteUserTag = names.NewUserTag(remoteUser)
  1038  	s.Factory.MakeModelUser(c, &factory.ModelUserParams{
  1039  		User:   remoteUser,
  1040  		Access: permission.WriteAccess,
  1041  	})
  1042  	s.AddControllerUser(c, remoteUser, permission.AddModelAccess)
  1043  
  1044  	s.DischargerLogin = func() string {
  1045  		return remoteUser
  1046  	}
  1047  	info := s.APIInfo(c)
  1048  
  1049  	result, err := s.login(c, info)
  1050  	c.Check(err, jc.ErrorIsNil)
  1051  	c.Assert(result.UserInfo, gc.NotNil)
  1052  	c.Check(result.UserInfo.Identity, gc.Equals, remoteUserTag.String())
  1053  	c.Check(result.UserInfo.ControllerAccess, gc.Equals, "add-model")
  1054  	c.Check(result.UserInfo.ModelAccess, gc.Equals, "write")
  1055  }
  1056  
  1057  func (s *macaroonLoginSuite) TestLoginToEnvironmentSuccess(c *gc.C) {
  1058  	const remoteUser = "test@somewhere"
  1059  	s.AddModelUser(c, remoteUser)
  1060  	s.AddControllerUser(c, remoteUser, permission.LoginAccess)
  1061  	s.DischargerLogin = func() string {
  1062  		return "test@somewhere"
  1063  	}
  1064  	loggo.GetLogger("juju.apiserver").SetLogLevel(loggo.TRACE)
  1065  	client, err := api.Open(s.APIInfo(c), api.DialOpts{})
  1066  	c.Assert(err, jc.ErrorIsNil)
  1067  	defer client.Close()
  1068  
  1069  	// The auth tag has been correctly returned by the server.
  1070  	c.Assert(client.AuthTag(), gc.Equals, names.NewUserTag(remoteUser))
  1071  }
  1072  
  1073  func (s *macaroonLoginSuite) TestFailedToObtainDischargeLogin(c *gc.C) {
  1074  	s.DischargerLogin = func() string {
  1075  		return ""
  1076  	}
  1077  	client, err := api.Open(s.APIInfo(c), api.DialOpts{})
  1078  	c.Assert(err, gc.ErrorMatches, `cannot get discharge from "https://.*": third party refused discharge: cannot discharge: login denied by discharger`)
  1079  	c.Assert(client, gc.Equals, nil)
  1080  }
  1081  
  1082  func (s *macaroonLoginSuite) TestUnknownUserLogin(c *gc.C) {
  1083  	s.DischargerLogin = func() string {
  1084  		return "testUnknown@somewhere"
  1085  	}
  1086  	client, err := api.Open(s.APIInfo(c), api.DialOpts{})
  1087  	assertInvalidEntityPassword(c, err)
  1088  	c.Assert(client, gc.Equals, nil)
  1089  }
  1090  
  1091  func assertInvalidEntityPassword(c *gc.C, err error) {
  1092  	c.Assert(errors.Cause(err), gc.DeepEquals, &rpc.RequestError{
  1093  		Message: "invalid entity name or password",
  1094  		Code:    "unauthorized access",
  1095  	})
  1096  }
  1097  
  1098  func assertPermissionDenied(c *gc.C, err error) {
  1099  	c.Assert(errors.Cause(err), gc.DeepEquals, &rpc.RequestError{
  1100  		Message: "permission denied",
  1101  		Code:    "unauthorized access",
  1102  	})
  1103  }
  1104  
  1105  func setEveryoneAccess(c *gc.C, st *state.State, adminUser names.UserTag, access permission.Access) {
  1106  	err := controller.ChangeControllerAccess(
  1107  		st, adminUser, names.NewUserTag(common.EveryoneTagName),
  1108  		params.GrantControllerAccess, access)
  1109  	c.Assert(err, jc.ErrorIsNil)
  1110  }
  1111  
  1112  var _ = gc.Suite(&migrationSuite{
  1113  	baseLoginSuite{
  1114  		setAdminAPI: func(srv *apiserver.Server) {
  1115  			apiserver.SetAdminAPIVersions(srv, 3)
  1116  		},
  1117  	},
  1118  })
  1119  
  1120  type migrationSuite struct {
  1121  	baseLoginSuite
  1122  }
  1123  
  1124  func (s *migrationSuite) TestImportingModel(c *gc.C) {
  1125  	m, password := s.Factory.MakeMachineReturningPassword(c, &factory.MachineParams{
  1126  		Nonce: "nonce",
  1127  	})
  1128  	model, err := s.State.Model()
  1129  	c.Assert(err, jc.ErrorIsNil)
  1130  	err = model.SetMigrationMode(state.MigrationModeImporting)
  1131  	c.Assert(err, jc.ErrorIsNil)
  1132  
  1133  	// Users should be able to log in but RPC requests should fail.
  1134  	info := s.APIInfo(c)
  1135  	userConn := s.OpenAPIAs(c, info.Tag, info.Password)
  1136  	defer userConn.Close()
  1137  	_, err = userConn.Client().Status(nil)
  1138  	c.Check(err, gc.ErrorMatches, "migration in progress, model is importing")
  1139  
  1140  	// Machines should be able to use the API.
  1141  	machineConn := s.OpenAPIAsMachine(c, m.Tag(), password, "nonce")
  1142  	defer machineConn.Close()
  1143  	_, err = apimachiner.NewState(machineConn).Machine(m.MachineTag())
  1144  	c.Check(err, jc.ErrorIsNil)
  1145  }