Esempio n. 1
0
File: visitor.go Progetto: bac/juju
// VisitWebPage is part of the httpbakery.Visitor interface.
func (v *Visitor) VisitWebPage(client *httpbakery.Client, methodURLs map[string]*url.URL) error {
	methodURL := methodURLs[authMethod]
	if methodURL == nil {
		return httpbakery.ErrMethodNotSupported
	}

	password, err := v.getPassword(v.username)
	if err != nil {
		return err
	}

	// POST to the URL with username and password.
	resp, err := client.PostForm(methodURL.String(), url.Values{
		"user":     {v.username},
		"password": {password},
	})
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusOK {
		return nil
	}
	var jsonError httpbakery.Error
	if err := json.NewDecoder(resp.Body).Decode(&jsonError); err != nil {
		return errors.Annotate(err, "unmarshalling error")
	}
	return &jsonError
}
Esempio n. 2
0
File: register.go Progetto: bac/juju
func (r *RegisterMeteredCharm) registerMetrics(modelUUID, charmURL, serviceName, budget, limit string, client *httpbakery.Client) ([]byte, error) {
	if r.RegisterURL == "" {
		return nil, errors.Errorf("no metric registration url is specified")
	}
	registerURL, err := url.Parse(r.RegisterURL)
	if err != nil {
		return nil, errors.Trace(err)
	}

	registrationPost := metricRegistrationPost{
		ModelUUID:       modelUUID,
		CharmURL:        charmURL,
		ApplicationName: serviceName,
		PlanURL:         r.Plan,
		Budget:          budget,
		Limit:           limit,
	}

	buff := &bytes.Buffer{}
	encoder := json.NewEncoder(buff)
	err = encoder.Encode(registrationPost)
	if err != nil {
		return nil, errors.Trace(err)
	}

	req, err := http.NewRequest("POST", registerURL.String(), nil)
	if err != nil {
		return nil, errors.Trace(err)
	}
	req.Header.Set("Content-Type", "application/json")

	response, err := client.DoWithBody(req, bytes.NewReader(buff.Bytes()))
	if err != nil {
		return nil, errors.Trace(err)
	}
	defer response.Body.Close()

	if response.StatusCode == http.StatusOK {
		b, err := ioutil.ReadAll(response.Body)
		if err != nil {
			return nil, errors.Annotatef(err, "failed to read the response")
		}
		return b, nil
	}
	var respError struct {
		Error string `json:"error"`
	}
	err = json.NewDecoder(response.Body).Decode(&respError)
	if err != nil {
		return nil, errors.Errorf("authorization failed: http response is %d", response.StatusCode)
	}
	return nil, errors.Errorf("authorization failed: %s", respError.Error)
}
Esempio n. 3
0
File: http.go Progetto: nathj07/http
func (ctxt *context) doRequest(client *httpbakery.Client, stdin io.Reader) (*http.Response, error) {
	req := &http.Request{
		URL:        ctxt.url,
		Proto:      "HTTP/1.1",
		ProtoMajor: 1,
		ProtoMinor: 1,
		Method:     ctxt.method,
		Header:     ctxt.header,
	}
	if len(ctxt.urlValues) > 0 {
		if req.URL.RawQuery != "" {
			req.URL.RawQuery += "&"
		}
		req.URL.RawQuery += ctxt.urlValues.Encode()
	}
	var body []byte
	switch {
	case len(ctxt.form) > 0:
		req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		body = []byte(ctxt.form.Encode())

	case len(ctxt.jsonObj) > 0:
		data, err := json.Marshal(ctxt.jsonObj)
		if err != nil {
			return nil, fmt.Errorf("cannot marshal JSON: %v", err)
		}
		body = data
	case req.Method != "GET" && req.Method != "HEAD" && stdin != nil:
		// No fields specified and it looks like we need a body.

		// TODO check if it's seekable or make a temp file.
		data, err := ioutil.ReadAll(stdin)
		if err != nil {
			return nil, fmt.Errorf("error reading stdin: %v", err)
		}
		// TODO if we're expecting JSON, accept rjson too.
		body = data
	}
	req.ContentLength = int64(len(body))

	resp, err := client.DoWithBody(req, bytes.NewReader(body))
	if err != nil {
		return nil, fmt.Errorf("cannot do HTTP request: %v", err)
	}
	return resp, nil
}
Esempio n. 4
0
File: agent.go Progetto: cmars/oo
// SetUpAuth configures agent authentication on c. A cookie is created in
// c's cookie jar containing credentials derived from the username and
// c.Key. c.VisitWebPage is set to VisitWebPage(c). The return is
// non-nil only if c.Key is nil.
func SetUpAuth(c *httpbakery.Client, u *url.URL, username string) error {
	if c.Key == nil {
		return errgo.New("cannot set-up authentication: client key not configured")
	}
	SetCookie(c.Jar, u, username, &c.Key.Public)
	c.VisitWebPage = VisitWebPage(c)
	return nil
}
Esempio n. 5
0
func (r *RegisterMeteredCharm) registerMetrics(environmentUUID, charmURL, serviceName string, client *httpbakery.Client) ([]byte, error) {
	if r.RegisterURL == "" {
		return nil, errors.Errorf("no metric registration url is specified")
	}
	registerURL, err := url.Parse(r.RegisterURL)
	if err != nil {
		return nil, errors.Trace(err)
	}

	registrationPost := metricRegistrationPost{
		ModelUUID:   environmentUUID,
		CharmURL:    charmURL,
		ServiceName: serviceName,
		PlanURL:     r.Plan,
	}

	buff := &bytes.Buffer{}
	encoder := json.NewEncoder(buff)
	err = encoder.Encode(registrationPost)
	if err != nil {
		return nil, errors.Trace(err)
	}

	req, err := http.NewRequest("POST", registerURL.String(), nil)
	if err != nil {
		return nil, errors.Trace(err)
	}
	req.Header.Set("Content-Type", "application/json")

	response, err := client.DoWithBody(req, bytes.NewReader(buff.Bytes()))
	if err != nil {
		return nil, errors.Trace(err)
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return nil, errors.Errorf("failed to register metrics: http response is %d", response.StatusCode)
	}

	b, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, errors.Annotatef(err, "failed to read the response")
	}
	return b, nil
}
Esempio n. 6
0
File: register.go Progetto: bac/juju
func (r *RegisterMeteredCharm) getCharmPlans(client *httpbakery.Client, cURL string) ([]string, error) {
	if r.QueryURL == "" {
		return nil, errors.Errorf("no plan query url specified")
	}
	qURL, err := url.Parse(r.QueryURL)
	if err != nil {
		return nil, errors.Trace(err)
	}

	query := qURL.Query()
	query.Set("charm-url", cURL)
	qURL.RawQuery = query.Encode()

	req, err := http.NewRequest("GET", qURL.String(), nil)
	if err != nil {
		return nil, errors.Trace(err)
	}

	response, err := client.Do(req)
	if err != nil {
		return nil, errors.Trace(err)
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return nil, errors.Errorf("failed to query plans: http response is %d", response.StatusCode)
	}

	var planInfo []struct {
		URL string `json:"url"`
	}
	dec := json.NewDecoder(response.Body)
	err = dec.Decode(&planInfo)
	if err != nil {
		return nil, errors.Trace(err)
	}
	info := make([]string, len(planInfo))
	for i, p := range planInfo {
		info[i] = p.URL
	}
	return info, nil
}
Esempio n. 7
0
File: register.go Progetto: bac/juju
func (r *RegisterMeteredCharm) getDefaultPlan(client *httpbakery.Client, cURL string) (string, error) {
	if r.QueryURL == "" {
		return "", errors.Errorf("no plan query url specified")
	}

	qURL, err := url.Parse(r.QueryURL + "/default")
	if err != nil {
		return "", errors.Trace(err)
	}

	query := qURL.Query()
	query.Set("charm-url", cURL)
	qURL.RawQuery = query.Encode()

	req, err := http.NewRequest("GET", qURL.String(), nil)
	if err != nil {
		return "", errors.Trace(err)
	}

	response, err := client.Do(req)
	if err != nil {
		return "", errors.Trace(err)
	}
	defer response.Body.Close()

	if response.StatusCode == http.StatusNotFound {
		return "", &noDefaultPlanError{cURL}
	}
	if response.StatusCode != http.StatusOK {
		return "", errors.Errorf("failed to query default plan: http response is %d", response.StatusCode)
	}

	var planInfo struct {
		URL string `json:"url"`
	}
	dec := json.NewDecoder(response.Body)
	err = dec.Decode(&planInfo)
	if err != nil {
		return "", errors.Trace(err)
	}
	return planInfo.URL, nil
}
Esempio n. 8
0
File: client.go Progetto: cmars/oo
// client represents a client of the target service.
// In this simple example, it just tries a GET
// request, which will fail unless the client
// has the required authorization.
func clientRequest(client *httpbakery.Client, serverEndpoint string) (string, error) {
	// The Do function implements the mechanics
	// of actually gathering discharge macaroons
	// when required, and retrying the request
	// when necessary.
	req, err := http.NewRequest("GET", serverEndpoint, nil)
	if err != nil {
		return "", errgo.Notef(err, "cannot make new HTTP request")
	}
	resp, err := client.Do(req)
	if err != nil {
		return "", errgo.NoteMask(err, "GET failed", errgo.Any)
	}
	defer resp.Body.Close()
	// TODO(rog) unmarshal error
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("cannot read response: %v", err)
	}
	return string(data), nil
}
Esempio n. 9
0
File: base.go Progetto: bac/juju
func newAPIConnectionParams(
	store jujuclient.ClientStore,
	controllerName,
	modelName string,
	accountDetails *jujuclient.AccountDetails,
	bakery *httpbakery.Client,
	apiOpen api.OpenFunc,
	getPassword func(string) (string, error),
) (juju.NewAPIConnectionParams, error) {
	if controllerName == "" {
		return juju.NewAPIConnectionParams{}, errors.Trace(errNoNameSpecified)
	}
	var modelUUID string
	if modelName != "" {
		modelDetails, err := store.ModelByName(controllerName, modelName)
		if err != nil {
			return juju.NewAPIConnectionParams{}, errors.Trace(err)
		}
		modelUUID = modelDetails.ModelUUID
	}
	dialOpts := api.DefaultDialOpts()
	dialOpts.BakeryClient = bakery

	if accountDetails != nil {
		bakery.WebPageVisitor = httpbakery.NewMultiVisitor(
			authentication.NewVisitor(accountDetails.User, getPassword),
			bakery.WebPageVisitor,
		)
	}

	return juju.NewAPIConnectionParams{
		Store:          store,
		ControllerName: controllerName,
		AccountDetails: accountDetails,
		ModelUUID:      modelUUID,
		DialOpts:       dialOpts,
		OpenAPI:        apiOpen,
	}, nil
}
Esempio n. 10
0
func (s *ClientSuite) TestMacaroonCookiePath(c *gc.C) {
	svc := newService("loc", nil)

	cookiePath := ""
	ts := httptest.NewServer(serverHandler(svc, "", func() string {
		return cookiePath
	}))
	defer ts.Close()

	var client *httpbakery.Client
	doRequest := func() {
		req, err := http.NewRequest("GET", ts.URL+"/foo/bar/", nil)
		c.Assert(err, gc.IsNil)
		client = httpbakery.NewClient()
		resp, err := client.Do(req)
		c.Assert(err, gc.IsNil)
		defer resp.Body.Close()
		assertResponse(c, resp, "done")
	}
	assertCookieCount := func(path string, n int) {
		u, err := url.Parse(ts.URL + path)
		c.Assert(err, gc.IsNil)
		c.Assert(client.Jar.Cookies(u), gc.HasLen, n)
	}
	cookiePath = ""
	c.Logf("- cookie path %q", cookiePath)
	doRequest()
	assertCookieCount("", 0)
	assertCookieCount("/foo", 0)
	assertCookieCount("/foo", 0)
	assertCookieCount("/foo/", 0)
	assertCookieCount("/foo/bar/", 1)
	assertCookieCount("/foo/bar/baz", 1)

	cookiePath = "/foo/"
	c.Logf("- cookie path %q", cookiePath)
	doRequest()
	assertCookieCount("", 0)
	assertCookieCount("/foo", 0)
	assertCookieCount("/foo/", 1)
	assertCookieCount("/foo/bar/", 1)
	assertCookieCount("/foo/bar/baz", 1)

	cookiePath = "/foo"
	c.Logf("- cookie path %q", cookiePath)
	doRequest()
	assertCookieCount("", 0)
	assertCookieCount("/bar", 0)
	assertCookieCount("/foo", 1)
	assertCookieCount("/foo/", 1)
	assertCookieCount("/foo/bar/", 1)
	assertCookieCount("/foo/bar/baz", 1)

	cookiePath = "../"
	c.Logf("- cookie path %q", cookiePath)
	doRequest()
	assertCookieCount("", 0)
	assertCookieCount("/bar", 0)
	assertCookieCount("/foo", 0)
	assertCookieCount("/foo/", 1)
	assertCookieCount("/foo/bar/", 1)
	assertCookieCount("/foo/bar/baz", 1)

	cookiePath = "../bar"
	c.Logf("- cookie path %q", cookiePath)
	doRequest()
	assertCookieCount("", 0)
	assertCookieCount("/bar", 0)
	assertCookieCount("/foo", 0)
	assertCookieCount("/foo/", 0)
	assertCookieCount("/foo/bar/", 1)
	assertCookieCount("/foo/bar/baz", 1)
	assertCookieCount("/foo/baz", 0)
	assertCookieCount("/foo/baz/", 0)
	assertCookieCount("/foo/baz/bar", 0)

	cookiePath = "/"
	c.Logf("- cookie path %q", cookiePath)
	doRequest()
	assertCookieCount("", 1)
	assertCookieCount("/bar", 1)
	assertCookieCount("/foo", 1)
	assertCookieCount("/foo/", 1)
	assertCookieCount("/foo/bar/", 1)
	assertCookieCount("/foo/bar/baz", 1)
}
Esempio n. 11
0
File: form.go Progetto: cmars/oo
// SetUpAuth configures form authentication on c. The VisitWebPage field
// in c will be set to a function that will attempt form-based
// authentication using f to perform the interaction with the user and
// fall back to using the current value of VisitWebPage if form-based
// authentication is not supported.
func SetUpAuth(c *httpbakery.Client, f form.Filler) {
	c.VisitWebPage = VisitWebPage(c, f, c.VisitWebPage)
}
Esempio n. 12
0
File: agent.go Progetto: cmars/oo
// VisitWebPage creates a function that can be used with
// httpbakery.Client.VisitWebPage. The function uses c to access the
// visit URL. If no agent-login cookie has been configured for u an error
// with the cause of ErrNoAgentLoginCookie will be returned. If the login
// fails the returned error will be of type *httpbakery.Error. If the
// response from the visitURL cannot be interpreted the error will be of
// type *UnexpectedResponseError.
//
// If using SetUpAuth, it should not be necessary to use
// this function.
func VisitWebPage(c *httpbakery.Client) func(u *url.URL) error {
	return func(u *url.URL) error {
		err := ErrNoAgentLoginCookie
		for _, c := range c.Jar.Cookies(u) {
			if c.Name == cookieName {
				err = nil
				break
			}
		}
		if err != nil {
			return errgo.WithCausef(err, http.ErrNoCookie, "cannot perform agent login")
		}
		req, err := http.NewRequest("GET", u.String(), nil)
		if err != nil {
			return errgo.Notef(err, "cannot create request")
		}
		resp, err := c.Do(req)
		if err != nil {
			return errgo.Notef(err, "cannot perform request")
		}
		defer resp.Body.Close()
		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			logger.Errorf("cannot read response body: %s", err)
			b = []byte{}
		}
		mt, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
		if err != nil {
			logger.Warningf("cannot parse response content type: %s", err)
			mt = ""
		}
		if mt != "application/json" {
			uerr := (*UnexpectedResponseError)(resp)
			uerr.Body = ioutil.NopCloser(bytes.NewReader(b))
			return uerr
		}
		if resp.StatusCode != http.StatusOK {
			var herr httpbakery.Error
			err := json.Unmarshal(b, &herr)
			if err == nil && herr.Message != "" {
				return &herr
			}
			if err != nil {
				logger.Warningf("cannot unmarshal error response: %s", err)
			}
			uerr := (*UnexpectedResponseError)(resp)
			uerr.Body = ioutil.NopCloser(bytes.NewReader(b))
			return uerr
		}
		var ar agentResponse
		err = json.Unmarshal(b, &ar)
		if err == nil && ar.AgentLogin {
			return nil
		}
		if err != nil {
			logger.Warningf("cannot unmarshal response: %s", err)
		}
		uerr := (*UnexpectedResponseError)(resp)
		uerr.Body = ioutil.NopCloser(bytes.NewReader(b))
		return uerr
	}
}