github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/api/state_macaroon_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package api_test 5 6 import ( 7 "net/url" 8 9 "github.com/juju/errors" 10 jc "github.com/juju/testing/checkers" 11 gc "gopkg.in/check.v1" 12 13 "github.com/juju/juju/api" 14 apitesting "github.com/juju/juju/api/testing" 15 "github.com/juju/juju/rpc" 16 ) 17 18 var _ = gc.Suite(&macaroonLoginSuite{}) 19 20 type macaroonLoginSuite struct { 21 apitesting.MacaroonSuite 22 client api.Connection 23 } 24 25 const testUserName = "testuser@somewhere" 26 27 func (s *macaroonLoginSuite) SetUpTest(c *gc.C) { 28 s.MacaroonSuite.SetUpTest(c) 29 s.AddModelUser(c, testUserName) 30 info := s.APIInfo(c) 31 info.SkipLogin = true 32 s.client = s.OpenAPI(c, info, nil) 33 } 34 35 func (s *macaroonLoginSuite) TearDownTest(c *gc.C) { 36 s.client.Close() 37 s.MacaroonSuite.TearDownTest(c) 38 } 39 40 func (s *macaroonLoginSuite) TestSuccessfulLogin(c *gc.C) { 41 s.DischargerLogin = func() string { return testUserName } 42 err := s.client.Login(nil, "", "", nil) 43 c.Assert(err, jc.ErrorIsNil) 44 } 45 46 func (s *macaroonLoginSuite) TestFailedToObtainDischargeLogin(c *gc.C) { 47 err := s.client.Login(nil, "", "", nil) 48 c.Assert(err, gc.ErrorMatches, `cannot get discharge from "https://.*": third party refused discharge: cannot discharge: login denied by discharger`) 49 } 50 51 func (s *macaroonLoginSuite) TestUnknownUserLogin(c *gc.C) { 52 s.DischargerLogin = func() string { 53 return "testUnknown" 54 } 55 err := s.client.Login(nil, "", "", nil) 56 c.Assert(errors.Cause(err), gc.DeepEquals, &rpc.RequestError{ 57 Message: "invalid entity name or password", 58 Code: "unauthorized access", 59 }) 60 } 61 62 func (s *macaroonLoginSuite) TestConnectStream(c *gc.C) { 63 catcher := urlCatcher{} 64 s.PatchValue(api.WebsocketDialConfig, catcher.recordLocation) 65 66 dischargeCount := 0 67 s.DischargerLogin = func() string { 68 dischargeCount++ 69 return testUserName 70 } 71 // First log into the regular API. 72 err := s.client.Login(nil, "", "", nil) 73 c.Assert(err, jc.ErrorIsNil) 74 c.Assert(dischargeCount, gc.Equals, 1) 75 76 // Then check that ConnectStream works OK and that it doesn't need 77 // to discharge again. 78 conn, err := s.client.ConnectStream("/path", nil) 79 c.Assert(err, gc.IsNil) 80 defer conn.Close() 81 connectURL := catcher.location 82 c.Assert(connectURL.Path, gc.Equals, "/model/"+s.State.ModelTag().Id()+"/path") 83 c.Assert(dischargeCount, gc.Equals, 1) 84 } 85 86 func (s *macaroonLoginSuite) TestConnectStreamWithoutLogin(c *gc.C) { 87 catcher := urlCatcher{} 88 s.PatchValue(api.WebsocketDialConfig, catcher.recordLocation) 89 90 conn, err := s.client.ConnectStream("/path", nil) 91 c.Assert(err, gc.ErrorMatches, `cannot use ConnectStream without logging in`) 92 c.Assert(conn, gc.Equals, nil) 93 } 94 95 func (s *macaroonLoginSuite) TestConnectStreamFailedDischarge(c *gc.C) { 96 // This is really a test for ConnectStream, but to test ConnectStream's 97 // discharge failing logic, we need an actual endpoint to test against, 98 // and the debug-log endpoint makes a convenient example. 99 100 var dischargeError bool 101 s.DischargerLogin = func() string { 102 if dischargeError { 103 return "" 104 } 105 return testUserName 106 } 107 108 // Make an API connection that uses a cookie jar 109 // that allows us to remove all cookies. 110 jar := apitesting.NewClearableCookieJar() 111 client := s.OpenAPI(c, nil, jar) 112 113 // Ensure that the discharger won't discharge and try 114 // logging in again. We should succeed in getting past 115 // authorization because we have the cookies (but 116 // the actual debug-log endpoint will return an error). 117 dischargeError = true 118 logArgs := url.Values{"noTail": []string{"true"}} 119 conn, err := client.ConnectStream("/log", logArgs) 120 c.Assert(err, jc.ErrorIsNil) 121 c.Assert(conn, gc.NotNil) 122 conn.Close() 123 124 // Then delete all the cookies by deleting the cookie jar 125 // and try again. The login should fail. 126 jar.Clear() 127 128 conn, err = client.ConnectStream("/log", logArgs) 129 c.Assert(err, gc.ErrorMatches, `cannot get discharge from "https://.*": third party refused discharge: cannot discharge: login denied by discharger`) 130 c.Assert(conn, gc.IsNil) 131 }