Example #1
0
func (s *ClientSuite) TestDoWithBodyAndCustomError(c *gc.C) {
	d := bakerytest.NewDischarger(nil, noCaveatChecker)
	defer d.Close()

	// Create a target service.
	svc := newService("loc", d)

	type customError struct {
		CustomError *httpbakery.Error
	}
	callCount := 0
	handler := func(w http.ResponseWriter, req *http.Request) {
		callCount++
		if _, checkErr := httpbakery.CheckRequest(svc, req, nil, checkers.New()); checkErr != nil {
			httprequest.WriteJSON(w, http.StatusTeapot, customError{
				CustomError: newDischargeRequiredError(svc, d.Location(), nil, checkErr, req).(*httpbakery.Error),
			})
			return
		}
		fmt.Fprintf(w, "hello there")
	}
	srv := httptest.NewServer(http.HandlerFunc(handler))
	defer srv.Close()

	req, err := http.NewRequest("GET", srv.URL, nil)
	c.Assert(err, gc.IsNil)

	// First check that a normal request fails.
	resp, err := httpbakery.NewClient().Do(req)
	c.Assert(err, gc.IsNil)
	defer resp.Body.Close()
	c.Assert(resp.StatusCode, gc.Equals, http.StatusTeapot)
	c.Assert(callCount, gc.Equals, 1)
	callCount = 0

	// Then check that a request with a custom error getter succeeds.
	errorGetter := func(resp *http.Response) error {
		if resp.StatusCode != http.StatusTeapot {
			return nil
		}
		data, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			panic(err)
		}
		var respErr customError
		if err := json.Unmarshal(data, &respErr); err != nil {
			panic(err)
		}
		return respErr.CustomError
	}

	resp, err = httpbakery.NewClient().DoWithBodyAndCustomError(req, nil, errorGetter)
	c.Assert(err, gc.IsNil)

	data, err := ioutil.ReadAll(resp.Body)
	c.Assert(err, gc.IsNil)
	c.Assert(string(data), gc.Equals, "hello there")
	c.Assert(callCount, gc.Equals, 2)
}
Example #2
0
func (s *registrationSuite) TestMeteredCharmDeployError(c *gc.C) {
	client := httpbakery.NewClient().Client
	d := DeploymentInfo{
		CharmURL:    charm.MustParseURL("cs:quantal/metered-1"),
		ServiceName: "service name",
		ModelUUID:   "environment uuid",
	}
	err := s.register.RunPre(&mockAPIConnection{Stub: s.stub}, client, s.ctx, d)
	c.Assert(err, jc.ErrorIsNil)
	deployError := errors.New("deployment failed")
	err = s.register.RunPost(&mockAPIConnection{Stub: s.stub}, client, s.ctx, d, deployError)
	c.Assert(err, jc.ErrorIsNil)
	authorization, err := json.Marshal([]byte("hello registration"))
	authorization = append(authorization, byte(0xa))
	c.Assert(err, jc.ErrorIsNil)
	s.stub.CheckCalls(c, []testing.StubCall{{
		"APICall", []interface{}{"Charms", "IsMetered", params.CharmInfo{CharmURL: "cs:quantal/metered-1"}},
	}, {
		"Authorize", []interface{}{metricRegistrationPost{
			ModelUUID:   "environment uuid",
			CharmURL:    "cs:quantal/metered-1",
			ServiceName: "service name",
			PlanURL:     "someplan",
		}},
	}})
}
Example #3
0
func (s *suite) TestInteractiveDischargerURL(c *gc.C) {
	var d *bakerytest.InteractiveDischarger
	d = bakerytest.NewInteractiveDischarger(nil, http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			http.Redirect(w, r, d.URL("/redirect", r), http.StatusFound)
		},
	))
	defer d.Close()
	d.Mux.Handle("/redirect", http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			d.FinishInteraction(w, r, nil, nil)
		},
	))
	svc, err := bakery.NewService(bakery.NewServiceParams{
		Location: "here",
		Locator:  d,
	})
	c.Assert(err, gc.IsNil)
	m, err := svc.NewMacaroon("", nil, []checkers.Caveat{{
		Location:  d.Location(),
		Condition: "something",
	}})
	c.Assert(err, gc.IsNil)
	client := httpbakery.NewClient()
	client.VisitWebPage = func(u *url.URL) error {
		var c httprequest.Client
		return c.Get(u.String(), nil)
	}
	ms, err := client.DischargeAll(m)
	c.Assert(err, gc.IsNil)
	c.Assert(ms, gc.HasLen, 2)

	err = svc.Check(ms, failChecker)
	c.Assert(err, gc.IsNil)
}
Example #4
0
func (s *suite) TestLoginDischargerError(c *gc.C) {
	var d *bakerytest.InteractiveDischarger
	d = bakerytest.NewInteractiveDischarger(nil, http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			d.FinishInteraction(w, r, nil, errors.New("test error"))
		},
	))
	defer d.Close()

	svc, err := bakery.NewService(bakery.NewServiceParams{
		Location: "here",
		Locator:  d,
	})
	c.Assert(err, gc.IsNil)
	m, err := svc.NewMacaroon("", nil, []checkers.Caveat{{
		Location:  d.Location(),
		Condition: "something",
	}})
	c.Assert(err, gc.IsNil)
	client := httpbakery.NewClient()
	client.VisitWebPage = func(u *url.URL) error {
		c.Logf("visiting %s", u)
		var c httprequest.Client
		return c.Get(u.String(), nil)
	}
	_, err = client.DischargeAll(m)
	c.Assert(err, gc.ErrorMatches, `cannot get discharge from ".*": failed to acquire macaroon after waiting: third party refused discharge: test error`)
}
Example #5
0
func (s *registrationSuite) TestMeteredCharmNoDefaultPlan(c *gc.C) {
	s.stub.SetErrors(nil, errors.NotFoundf("default plan"))
	s.register = &RegisterMeteredCharm{
		AllocationSpec: "personal:100",
		RegisterURL:    s.server.URL,
		QueryURL:       s.server.URL}
	client := httpbakery.NewClient()
	d := DeploymentInfo{
		CharmID: charmstore.CharmID{
			URL: charm.MustParseURL("cs:quantal/metered-1"),
		},
		ApplicationName: "application name",
		ModelUUID:       "model uuid",
		CharmInfo: &apicharms.CharmInfo{
			Metrics: &charm.Metrics{
				Plan: &charm.Plan{Required: true},
			},
		},
	}
	err := s.register.RunPre(&mockMeteredDeployAPI{Stub: s.stub}, client, s.ctx, d)
	c.Assert(err, gc.ErrorMatches, `cs:quantal/metered-1 has no default plan. Try "juju deploy --plan <plan-name> with one of thisplan, thisotherplan"`)
	s.stub.CheckCalls(c, []testing.StubCall{{
		"IsMetered", []interface{}{"cs:quantal/metered-1"},
	}, {
		"DefaultPlan", []interface{}{"cs:quantal/metered-1"},
	}, {
		"ListPlans", []interface{}{"cs:quantal/metered-1"},
	}})
}
Example #6
0
func (s *agentSuite) TestAgentLogin(c *gc.C) {
	u, err := url.Parse(s.discharger.URL)
	c.Assert(err, gc.IsNil)
	for i, test := range agentLoginTests {
		c.Logf("%d. %s", i, test.about)
		s.discharger.LoginHandler = test.loginHandler
		client := httpbakery.NewClient()
		client.Key, err = bakery.GenerateKey()
		c.Assert(err, gc.IsNil)
		err = agent.SetUpAuth(client, u, "test-user")
		c.Assert(err, gc.IsNil)
		m, err := s.bakery.NewMacaroon("", nil, []checkers.Caveat{{
			Location:  s.discharger.URL,
			Condition: "test condition",
		}})
		c.Assert(err, gc.IsNil)
		ms, err := client.DischargeAll(m)
		if test.expectError != "" {
			c.Assert(err, gc.ErrorMatches, test.expectError)
			continue
		}
		c.Assert(err, gc.IsNil)
		err = s.bakery.Check(ms, bakery.FirstPartyCheckerFunc(
			func(caveat string) error {
				return nil
			},
		))
		c.Assert(err, gc.IsNil)
	}
}
Example #7
0
func (s *registrationSuite) TestMeteredCharmNoPlanSet(c *gc.C) {
	s.register = &RegisterMeteredCharm{RegisterURL: s.server.URL, QueryURL: s.server.URL}
	client := httpbakery.NewClient().Client
	d := DeploymentInfo{
		CharmURL:    charm.MustParseURL("local:quantal/metered-1"),
		ServiceName: "service name",
		EnvUUID:     "environment uuid",
	}
	err := s.register.RunPre(&mockAPIConnection{Stub: s.stub}, client, d)
	c.Assert(err, jc.ErrorIsNil)
	err = s.register.RunPost(&mockAPIConnection{Stub: s.stub}, client, d)
	c.Assert(err, jc.ErrorIsNil)
	authorization, err := json.Marshal([]byte("hello registration"))
	authorization = append(authorization, byte(0xa))
	c.Assert(err, jc.ErrorIsNil)
	s.stub.CheckCalls(c, []testing.StubCall{{
		"APICall", []interface{}{"Charms", "IsMetered", params.CharmInfo{CharmURL: "local:quantal/metered-1"}},
	}, {
		"DefaultPlan", []interface{}{"local:quantal/metered-1"},
	}, {
		"Authorize", []interface{}{metricRegistrationPost{
			EnvironmentUUID: "environment uuid",
			CharmURL:        "local:quantal/metered-1",
			ServiceName:     "service name",
			PlanURL:         "thisplan",
		}},
	}, {
		"APICall", []interface{}{"Service", "SetMetricCredentials", params.ServiceMetricCredentials{
			Creds: []params.ServiceMetricCredential{params.ServiceMetricCredential{
				ServiceName:       "service name",
				MetricCredentials: authorization,
			}},
		}},
	}})
}
Example #8
0
func (s *registrationSuite) TestMeteredCharmAPIError(c *gc.C) {
	s.stub.SetErrors(nil, errors.New("something failed"))
	client := httpbakery.NewClient()
	d := DeploymentInfo{
		CharmID: charmstore.CharmID{
			URL: charm.MustParseURL("cs:quantal/metered-1"),
		},
		ServiceName: "service name",
		ModelUUID:   "model uuid",
	}
	err := s.register.RunPre(&mockAPIConnection{Stub: s.stub}, client, s.ctx, d)
	c.Assert(err, gc.ErrorMatches, `authorization failed: something failed`)
	s.stub.CheckCalls(c, []testing.StubCall{{
		"APICall", []interface{}{"Charms", "IsMetered", params.CharmInfo{CharmURL: "cs:quantal/metered-1"}},
	}, {
		"Authorize", []interface{}{metricRegistrationPost{
			ModelUUID:   "model uuid",
			CharmURL:    "cs:quantal/metered-1",
			ServiceName: "service name",
			PlanURL:     "someplan",
			Budget:      "personal",
			Limit:       "100",
		}},
	}})
}
Example #9
0
func (*VisitorSuite) TestMultiVisitorSequence(c *gc.C) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		fmt.Fprint(w, `{"method": "http://somewhere/something"}`)
	}))
	defer srv.Close()

	firstCalled, secondCalled := 0, 0
	v := httpbakery.NewMultiVisitor(
		visitorFunc(func(_ *httpbakery.Client, m map[string]*url.URL) error {
			c.Check(m["method"], gc.NotNil)
			firstCalled++
			return httpbakery.ErrMethodNotSupported
		}),
		visitorFunc(func(_ *httpbakery.Client, m map[string]*url.URL) error {
			c.Check(m["method"], gc.NotNil)
			secondCalled++
			return nil
		}),
	)
	err := v.VisitWebPage(httpbakery.NewClient(), map[string]*url.URL{
		httpbakery.UserInteractionMethod: mustParseURL(srv.URL),
	})
	c.Assert(err, gc.IsNil)
	c.Assert(firstCalled, gc.Equals, 1)
	c.Assert(secondCalled, gc.Equals, 1)
}
Example #10
0
func (s *formSuite) TestFormLogin(c *gc.C) {
	d := &formDischarger{}
	d.discharger = bakerytest.NewInteractiveDischarger(nil, http.HandlerFunc(d.login))
	defer d.discharger.Close()
	d.discharger.Mux.Handle("/form", http.HandlerFunc(d.form))
	svc, err := bakery.NewService(bakery.NewServiceParams{
		Locator: d.discharger,
	})
	c.Assert(err, gc.IsNil)
	for i, test := range formLoginTests {
		c.Logf("%d. %s", i, test.about)
		d.dischargeOptions = test.opts
		m, err := svc.NewMacaroon("", nil, []checkers.Caveat{{
			Location:  d.discharger.Location(),
			Condition: "test condition",
		}})
		c.Assert(err, gc.Equals, nil)
		client := httpbakery.NewClient()
		h := defaultFiller
		if test.filler != nil {
			h = test.filler
		}
		client.VisitWebPage = test.fallback
		form.SetUpAuth(client, h)

		ms, err := client.DischargeAll(m)
		if test.expectError != "" {
			c.Assert(err, gc.ErrorMatches, test.expectError)
			continue
		}
		c.Assert(err, gc.IsNil)
		c.Assert(len(ms), gc.Equals, 2)
	}
}
Example #11
0
func (*VisitorSuite) TestUserInteractionFallback(c *gc.C) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		fmt.Fprint(w, `{"method": "http://somewhere/something"}`)
	}))
	defer srv.Close()

	called := 0
	// Check that even though the methods didn't explicitly
	// include the "interactive" method, it is still supplied.
	v := httpbakery.NewMultiVisitor(
		visitorFunc(func(_ *httpbakery.Client, m map[string]*url.URL) error {
			c.Check(m, jc.DeepEquals, map[string]*url.URL{
				"method": mustParseURL("http://somewhere/something"),
				httpbakery.UserInteractionMethod: mustParseURL(srv.URL),
			})
			called++
			return nil
		}),
	)
	err := v.VisitWebPage(httpbakery.NewClient(), map[string]*url.URL{
		httpbakery.UserInteractionMethod: mustParseURL(srv.URL),
	})
	c.Assert(err, gc.IsNil)
	c.Assert(called, gc.Equals, 1)
}
Example #12
0
func (s *macaroonServerSuite) TestServerBakery(c *gc.C) {
	srv := newServer(c, s.State)
	defer srv.Stop()
	m, err := apiserver.ServerMacaroon(srv)
	c.Assert(err, gc.IsNil)
	bsvc, err := apiserver.ServerBakeryService(srv)
	c.Assert(err, gc.IsNil)

	// Check that we can add a third party caveat addressed to the
	// discharger, which indirectly ensures that the discharger's public
	// key has been added to the bakery service's locator.
	m = m.Clone()
	err = bsvc.AddCaveat(m, checkers.Caveat{
		Location:  s.discharger.Location(),
		Condition: "true",
	})
	c.Assert(err, jc.ErrorIsNil)

	// Check that we can discharge the macaroon and check it with
	// the service.
	client := httpbakery.NewClient()
	ms, err := client.DischargeAll(m)
	c.Assert(err, jc.ErrorIsNil)

	err = bsvc.Check(ms, checkers.New())
	c.Assert(err, gc.IsNil)
}
Example #13
0
func (s *ClientSuite) TestThirdPartyDischargeRefused(c *gc.C) {
	d := bakerytest.NewDischarger(nil, func(_ *http.Request, cond, arg string) ([]checkers.Caveat, error) {
		return nil, errgo.New("boo! cond " + cond)
	})
	defer d.Close()

	// Create a target service.
	svc := newService("loc", d)

	ts := httptest.NewServer(serverHandler(serverHandlerParams{
		service:      svc,
		authLocation: d.Location(),
	}))
	defer ts.Close()

	// Create a client request.
	req, err := http.NewRequest("GET", ts.URL, nil)
	c.Assert(err, gc.IsNil)

	client := httpbakery.NewClient()

	// Make the request to the server.
	resp, err := client.Do(req)
	c.Assert(errgo.Cause(err), gc.FitsTypeOf, (*httpbakery.DischargeError)(nil))
	c.Assert(err, gc.ErrorMatches, `cannot get discharge from ".*": third party refused discharge: cannot discharge: boo! cond is-ok`)
	c.Assert(resp, gc.IsNil)
}
Example #14
0
func (s ClientSuite) TestWithLargeBody(c *gc.C) {
	// This test is designed to fail when run with the race
	// checker enabled and when go issue #12796
	// is not fixed.

	d := bakerytest.NewDischarger(nil, noCaveatChecker)
	defer d.Close()

	// Create a target service.
	svc := newService("loc", d)

	ts := httptest.NewServer(serverHandler(serverHandlerParams{
		service:      svc,
		authLocation: d.Location(),
	}))
	defer ts.Close()

	// Create a client request.
	req, err := http.NewRequest("POST", ts.URL+"/no-body", nil)
	c.Assert(err, gc.IsNil)

	body := &largeReader{total: 3 * 1024 * 1024}
	resp, err := httpbakery.NewClient().DoWithBody(req, body)
	c.Assert(err, gc.IsNil)
	resp.Body.Close()
	body.Close()

	c.Assert(resp.StatusCode, gc.Equals, http.StatusOK)
}
Example #15
0
func (s *formSuite) TestFormTitle(c *gc.C) {
	d := &formDischarger{}
	d.discharger = bakerytest.NewInteractiveDischarger(nil, http.HandlerFunc(d.login))
	defer d.discharger.Close()
	d.discharger.Mux.Handle("/form", http.HandlerFunc(d.form))
	svc, err := bakery.NewService(bakery.NewServiceParams{
		Locator: testLocator{
			loc:     d.discharger.Location(),
			locator: d.discharger,
		},
	})
	c.Assert(err, gc.IsNil)
	for i, test := range formTitleTests {
		c.Logf("%d. %s", i, test.host)
		m, err := svc.NewMacaroon("", nil, []checkers.Caveat{{
			Location:  "https://" + test.host,
			Condition: "test condition",
		}})
		c.Assert(err, gc.Equals, nil)
		client := httpbakery.NewClient()
		client.Client.Transport = httptesting.URLRewritingTransport{
			MatchPrefix:  "https://" + test.host,
			Replace:      d.discharger.Location(),
			RoundTripper: http.DefaultTransport,
		}
		f := new(titleTestFiller)
		form.SetUpAuth(client, f)

		ms, err := client.DischargeAll(m)
		c.Assert(err, gc.IsNil)
		c.Assert(len(ms), gc.Equals, 2)
		c.Assert(f.title, gc.Equals, test.expect)
	}
}
Example #16
0
func (s *ClientSuite) TestDischargeAcquirer(c *gc.C) {
	rootKey := []byte("secret")
	m, err := macaroon.New(rootKey, "", "here")
	c.Assert(err, gc.IsNil)

	dischargeRootKey := []byte("shared root key")
	thirdPartyCaveatId := "3rd party caveat"
	err = m.AddThirdPartyCaveat(dischargeRootKey, thirdPartyCaveatId, "there")
	c.Assert(err, gc.IsNil)

	dm, err := macaroon.New(dischargeRootKey, thirdPartyCaveatId, "there")
	c.Assert(err, gc.IsNil)

	ta := &testAcquirer{dischargeMacaroon: dm}
	cl := httpbakery.NewClient()
	cl.DischargeAcquirer = ta

	ms, err := cl.DischargeAll(m)
	c.Assert(err, gc.IsNil)
	c.Assert(ms, gc.HasLen, 2)

	c.Assert(ta.acquireLocation, gc.Equals, "here") // should be first-party location
	c.Assert(ta.acquireCaveat.Id, gc.Equals, thirdPartyCaveatId)
	expectCaveat := "must foo"
	var lastCaveat string
	err = ms[0].Verify(rootKey, func(s string) error {
		if s != expectCaveat {
			return errgo.Newf(`expected %q, got %q`, expectCaveat, s)
		}
		lastCaveat = s
		return nil
	}, ms[1:])
	c.Assert(err, gc.IsNil)
	c.Assert(lastCaveat, gc.Equals, expectCaveat)
}
Example #17
0
func (*suite) TestDoRequest(c *gc.C) {
	var h handler
	srv := httptest.NewServer(&h)
	for i, test := range doRequestTests {
		c.Logf("test %d: %s", i, test.about)
		client := httpbakery.NewClient()
		u, err := url.Parse(srv.URL + test.url)
		c.Assert(err, gc.IsNil)
		test.ctxt.url = u
		if test.ctxt.header == nil {
			test.ctxt.header = make(http.Header)
		}
		resp, err := test.ctxt.doRequest(client, strings.NewReader(test.stdin))
		c.Assert(err, gc.IsNil)
		c.Assert(resp.StatusCode, gc.Equals, http.StatusOK)
		resp.Body.Close()

		// Don't do a DeepEquals on the expected request,
		// as it will contain all kinds of stuff that we aren't
		// that concerned with. Instead, test that the
		// data we've specified is there in the request.
		c.Assert(h.request.Method, gc.Equals, test.expectRequest.Method)
		for attr, vals := range test.expectRequest.Header {
			c.Assert(h.request.Header[attr], jc.DeepEquals, vals, gc.Commentf("attr %s", attr))
		}
		h.request.URL.Host = ""
		c.Assert(h.request.URL, jc.DeepEquals, test.expectRequest.URL)
		c.Assert(string(h.requestBody), gc.Equals, test.expectRequestBody)
	}
}
Example #18
0
func (s *registrationSuite) TestMeteredLocalCharmWithPlan(c *gc.C) {
	client := httpbakery.NewClient()
	d := DeploymentInfo{
		CharmID: charmstore.CharmID{
			URL: charm.MustParseURL("local:quantal/metered-1"),
		},
		ServiceName: "service name",
		ModelUUID:   "model uuid",
	}
	err := s.register.RunPre(&mockAPIConnection{Stub: s.stub}, client, s.ctx, d)
	c.Assert(err, jc.ErrorIsNil)
	err = s.register.RunPost(&mockAPIConnection{Stub: s.stub}, client, s.ctx, d, nil)
	c.Assert(err, jc.ErrorIsNil)
	authorization, err := json.Marshal([]byte("hello registration"))
	authorization = append(authorization, byte(0xa))
	s.stub.CheckCalls(c, []testing.StubCall{{
		"APICall", []interface{}{"Charms", "IsMetered", params.CharmInfo{CharmURL: "local:quantal/metered-1"}},
	}, {
		"Authorize", []interface{}{metricRegistrationPost{
			ModelUUID:   "model uuid",
			CharmURL:    "local:quantal/metered-1",
			ServiceName: "service name",
			PlanURL:     "someplan",
			Budget:      "personal",
			Limit:       "100",
		}},
	}, {
		"APICall", []interface{}{"Service", "SetMetricCredentials", params.ServiceMetricCredentials{
			Creds: []params.ServiceMetricCredential{params.ServiceMetricCredential{
				ServiceName:       "service name",
				MetricCredentials: authorization,
			}},
		}},
	}})
}
Example #19
0
func (s *registrationSuite) TestFailedAuth(c *gc.C) {
	s.stub.SetErrors(nil, fmt.Errorf("could not authorize"))
	client := httpbakery.NewClient()
	d := DeploymentInfo{
		CharmID: charmstore.CharmID{
			URL: charm.MustParseURL("cs:quantal/metered-1"),
		},
		ServiceName: "service name",
		ModelUUID:   "model uuid",
	}
	err := s.register.RunPre(&mockAPIConnection{Stub: s.stub}, client, s.ctx, d)
	c.Assert(err, gc.ErrorMatches, `authorization failed:.*`)
	authorization, err := json.Marshal([]byte("hello registration"))
	authorization = append(authorization, byte(0xa))
	c.Assert(err, jc.ErrorIsNil)
	s.stub.CheckCalls(c, []testing.StubCall{{
		"APICall", []interface{}{"Charms", "IsMetered", params.CharmInfo{CharmURL: "cs:quantal/metered-1"}},
	}, {
		"Authorize", []interface{}{metricRegistrationPost{
			ModelUUID:   "model uuid",
			CharmURL:    "cs:quantal/metered-1",
			ServiceName: "service name",
			PlanURL:     "someplan",
			Budget:      "personal",
			Limit:       "100",
		}},
	}})
}
Example #20
0
func (s *registrationSuite) TestMeteredCharmFailToQueryDefaultCharm(c *gc.C) {
	s.stub.SetErrors(nil, errors.New("something failed"))
	s.register = &RegisterMeteredCharm{
		AllocationSpec: "personal:100",
		RegisterURL:    s.server.URL,
		QueryURL:       s.server.URL}
	client := httpbakery.NewClient()
	d := DeploymentInfo{
		CharmID: charmstore.CharmID{
			URL: charm.MustParseURL("cs:quantal/metered-1"),
		},
		ApplicationName: "application name",
		ModelUUID:       "model uuid",
		CharmInfo: &apicharms.CharmInfo{
			Metrics: &charm.Metrics{
				Plan: &charm.Plan{Required: true},
			},
		},
	}
	err := s.register.RunPre(&mockMeteredDeployAPI{Stub: s.stub}, client, s.ctx, d)
	c.Assert(err, gc.ErrorMatches, `failed to query default plan:.*`)
	s.stub.CheckCalls(c, []testing.StubCall{{
		"IsMetered", []interface{}{"cs:quantal/metered-1"},
	}, {
		"DefaultPlan", []interface{}{"cs:quantal/metered-1"},
	}})
}
Example #21
0
// NewAPIContext returns an API context that will use the given
// context for user interactions when authorizing.
// The returned API context must be closed after use.
//
// If ctxt is nil, no command-line authorization
// will be supported.
//
// This function is provided for use by commands that cannot use
// JujuCommandBase. Most clients should use that instead.
func NewAPIContext(ctxt *cmd.Context) (*APIContext, error) {
	jar, err := cookiejar.New(&cookiejar.Options{
		Filename: cookieFile(),
	})
	if err != nil {
		return nil, errors.Trace(err)
	}
	client := httpbakery.NewClient()
	client.Jar = jar
	if ctxt != nil {
		filler := &form.IOFiller{
			In:  ctxt.Stdin,
			Out: ctxt.Stdout,
		}
		client.VisitWebPage = ussologin.VisitWebPage(
			"juju",
			&http.Client{},
			filler,
			jujuclient.NewTokenStore(),
		)
	} else {
		client.VisitWebPage = httpbakery.OpenWebBrowser
	}
	return &APIContext{
		Jar:          jar,
		BakeryClient: client,
	}, nil
}
Example #22
0
func (s *registrationSuite) TestMeteredCharmDeployError(c *gc.C) {
	client := httpbakery.NewClient()
	d := DeploymentInfo{
		CharmID: charmstore.CharmID{
			URL: charm.MustParseURL("cs:quantal/metered-1"),
		},
		ApplicationName: "application name",
		ModelUUID:       "model uuid",
		CharmInfo: &apicharms.CharmInfo{
			Metrics: &charm.Metrics{
				Plan: &charm.Plan{Required: true},
			},
		},
	}
	err := s.register.RunPre(&mockMeteredDeployAPI{Stub: s.stub}, client, s.ctx, d)
	c.Assert(err, jc.ErrorIsNil)
	deployError := errors.New("deployment failed")
	err = s.register.RunPost(&mockMeteredDeployAPI{Stub: s.stub}, client, s.ctx, d, deployError)
	c.Assert(err, jc.ErrorIsNil)
	authorization, err := json.Marshal([]byte("hello registration"))
	authorization = append(authorization, byte(0xa))
	c.Assert(err, jc.ErrorIsNil)
	s.stub.CheckCalls(c, []testing.StubCall{{
		"IsMetered", []interface{}{"cs:quantal/metered-1"},
	}, {
		"Authorize", []interface{}{metricRegistrationPost{
			ModelUUID:       "model uuid",
			CharmURL:        "cs:quantal/metered-1",
			ApplicationName: "application name",
			PlanURL:         "someplan",
			Budget:          "personal",
			Limit:           "100",
		}},
	}})
}
Example #23
0
File: http.go Project: nathj07/http
func newClient(p *params) (*cookiejar.Jar, *httpbakery.Client, error) {
	client := httpbakery.NewClient()
	var jar *cookiejar.Jar
	if p.cookieFile != "" {
		var err error
		jar, err = cookiejar.New(&cookiejar.Options{
			PublicSuffixList: publicsuffix.List,
		})
		if err != nil {
			panic(err)
		}
		if err := jar.Load(p.cookieFile); err != nil {
			return nil, nil, fmt.Errorf("cannot load cookie jar: %v", err)
		}
		client.Client.Jar = jar
	}
	client.VisitWebPage = httpbakery.OpenWebBrowser
	if p.insecure {
		rt := *http.DefaultTransport.(*http.Transport)
		rt.TLSClientConfig = &tls.Config{
			InsecureSkipVerify: true,
		}
		client.Transport = &rt
	}

	return jar, client, nil
}
Example #24
0
func (s *ClientSuite) TestDoWithBodyFailsWithBodyInRequest(c *gc.C) {
	body := strings.NewReader("foo")
	// Create a client request.
	req, err := http.NewRequest("POST", "http://0.1.2.3/", body)
	c.Assert(err, gc.IsNil)
	_, err = httpbakery.NewClient().DoWithBody(req, body)
	c.Assert(err, gc.ErrorMatches, "body unexpectedly supplied in Request struct")
}
Example #25
0
func (s *formSuite) TestFormLoginNewRequestError(c *gc.C) {
	client := httpbakery.NewClient()
	form.SetUpAuth(client, defaultFiller)
	u := url.URL{
		Scheme: ":",
	}
	err := client.VisitWebPage(&u)
	c.Assert(err, gc.ErrorMatches, "cannot create request: parse :://: missing protocol scheme")
}
Example #26
0
func (s *ClientSuite) TestHandleErrorDifferentError(c *gc.C) {
	berr := &httpbakery.Error{
		Message: "an error",
		Code:    "another code",
	}
	client := httpbakery.NewClient()
	err := client.HandleError(&url.URL{}, berr)
	c.Assert(err, gc.Equals, berr)
}
Example #27
0
func ExampleVisitWebPage() {
	var key *bakery.KeyPair
	var u *url.URL

	client := httpbakery.NewClient()
	client.Key = key
	agent.SetCookie(client.Jar, u, "agent-username", &client.Key.Public)
	client.VisitWebPage = agent.VisitWebPage(client)
}
Example #28
0
func (s *ClientSuite) TestRepeatedRequestWithBody(c *gc.C) {
	d := bakerytest.NewDischarger(nil, noCaveatChecker)
	defer d.Close()

	// Create a target service.
	svc := newService("loc", d)

	ts := httptest.NewServer(serverHandler(serverHandlerParams{
		service:        svc,
		authLocation:   d.Location(),
		alwaysReadBody: true,
	}))
	defer ts.Close()

	// Create a client request.
	req, err := http.NewRequest("POST", ts.URL, nil)
	c.Assert(err, gc.IsNil)

	// Make the request to the server.

	// First try with a body in the request, which should be denied
	// because we must use DoWithBody.
	req.Body = ioutil.NopCloser(strings.NewReader("postbody"))
	resp, err := httpbakery.NewClient().Do(req)
	c.Assert(err, gc.ErrorMatches, "body unexpectedly provided in request - use DoWithBody")
	c.Assert(resp, gc.IsNil)

	// Then try with no authorization, so make sure that httpbakery.Do
	// really will retry the request.

	req.Body = nil

	bodyText := "postbody"
	bodyReader := &readCounter{ReadSeeker: strings.NewReader(bodyText)}

	resp, err = httpbakery.NewClient().DoWithBody(req, bodyReader)
	c.Assert(err, gc.IsNil)
	defer resp.Body.Close()
	assertResponse(c, resp, "done postbody")

	// Sanity check that the body really was read twice and hence
	// that we are checking the logic we intend to check.
	c.Assert(bodyReader.byteCount, gc.Equals, len(bodyText)*2)
}
Example #29
0
func (*suite) TestMacaraq(c *gc.C) {
	checked := false
	d := bakerytest.NewDischarger(nil, func(_ *http.Request, cond, arg string) ([]checkers.Caveat, error) {
		if cond != "something" {
			return nil, fmt.Errorf("unexpected 3rd party cond")
		}
		checked = true
		return nil, nil
	})

	bsvc, err := bakery.NewService(bakery.NewServiceParams{
		Location: "here",
		Locator:  d,
	})
	c.Assert(err, gc.IsNil)
	svc := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		req.ParseForm()
		_, checkErr := httpbakery.CheckRequest(bsvc, req, nil, checkers.New())
		if checkErr == nil {
			w.Header().Set("Content-Type", "application/json")
			data, err := json.Marshal(req.Form)
			c.Check(err, gc.IsNil)
			w.Write(data)
			return
		}
		m, err := bsvc.NewMacaroon("", nil, []checkers.Caveat{{
			Location:  d.Service.Location(),
			Condition: "something",
		}})
		c.Check(err, gc.IsNil)
		httpbakery.WriteDischargeRequiredError(w, m, "/", checkErr)
	}))

	fset := flag.NewFlagSet("http", flag.ContinueOnError)
	ctxt, params, err := newContext(fset, []string{
		svc.URL,
		"x=y",
	})
	c.Assert(err, gc.IsNil)
	client := httpbakery.NewClient()
	resp, err := ctxt.doRequest(client, nil)
	c.Assert(err, gc.IsNil)
	defer resp.Body.Close()
	c.Assert(resp.StatusCode, gc.Equals, http.StatusOK)
	c.Assert(checked, jc.IsTrue)

	var stdout bytes.Buffer
	err = showResponse(params, resp, &stdout)
	c.Assert(err, gc.IsNil)
	c.Assert(stdout.String(), gc.Equals, `{
	x: [
		"y"
	]
}
`)
}
Example #30
0
func (s *registrationSuite) TestHttpMetricsRegistrar(c *gc.C) {
	client := httpbakery.NewClient()
	data, err := registerMetrics(s.server.URL, "environment uuid", "charm url", "service name", client)
	c.Assert(err, gc.IsNil)
	var b []byte
	err = json.Unmarshal(data, &b)
	c.Assert(err, gc.IsNil)
	c.Assert(string(b), gc.Equals, "hello registration")
	c.Assert(s.handler.registrationCalls, gc.HasLen, 1)
	c.Assert(s.handler.registrationCalls[0], gc.DeepEquals, metricRegistrationPost{EnvironmentUUID: "environment uuid", CharmURL: "charm url", ServiceName: "service name"})
}