func (s *charmStoreSuite) SetUpTest(c *gc.C) {
	s.JujuConnSuite.SetUpTest(c)

	// Set up the charm store testing server.
	db := s.Session.DB("juju-testing")
	params := charmstore.ServerParams{
		AuthUsername: "******",
		AuthPassword: "******",
	}
	handler, err := charmstore.NewServer(db, nil, "", params, charmstore.V5)
	c.Assert(err, jc.ErrorIsNil)
	s.handler = handler
	s.srv = httptest.NewServer(handler)
	s.client = csclient.New(csclient.Params{
		URL:      s.srv.URL,
		User:     params.AuthUsername,
		Password: params.AuthPassword,
	})

	application.PatchNewCharmStoreClient(s, s.srv.URL)

	// Initialize the charm cache dir.
	s.PatchValue(&charmrepo.CacheDir, c.MkDir())

	// Point the CLI to the charm store testing server.

	// Point the Juju API server to the charm store testing server.
	s.PatchValue(&csclient.ServerURL, s.srv.URL)
}
Example #2
0
func (s *CharmStoreSuite) SetUpTest(c *gc.C) {
	s.CleanupSuite.SetUpTest(c)

	s.discharger = bakerytest.NewDischarger(nil, func(_ *http.Request, cond string, arg string) ([]checkers.Caveat, error) {
		if s.DischargeUser == "" {
			return nil, fmt.Errorf("discharge denied")
		}
		return []checkers.Caveat{
			checkers.DeclaredCaveat("username", s.DischargeUser),
		}, nil
	})
	db := s.Session.DB("juju-testing")
	params := charmstore.ServerParams{
		AuthUsername:     "******",
		AuthPassword:     "******",
		IdentityLocation: s.discharger.Location(),
		PublicKeyLocator: s.discharger,
	}
	handler, err := charmstore.NewServer(db, nil, "", params, charmstore.V4)
	c.Assert(err, jc.ErrorIsNil)
	s.handler = handler
	s.Srv = httptest.NewServer(handler)
	s.Client = csclient.New(csclient.Params{
		URL:      s.Srv.URL,
		User:     params.AuthUsername,
		Password: params.AuthPassword,
	})

	s.PatchValue(&charmrepo.CacheDir, c.MkDir())
	s.PatchValue(&service.NewCharmStore, func(p charmrepo.NewCharmStoreParams) charmrepo.Interface {
		p.URL = s.Srv.URL
		return charmrepo.NewCharmStore(p)
	})
}
Example #3
0
// authorize acquires and return the charm store delegatable macaroon to be
// used to add the charm corresponding to the given URL.
// The macaroon is properly attenuated so that it can only be used to deploy
// the given charm URL.
func (c *csClient) authorize(curl *charm.URL) (*macaroon.Macaroon, error) {
	if curl == nil {
		return nil, errors.New("empty charm url not allowed")
	}

	client := csclient.New(csclient.Params{
		URL:          c.params.URL,
		HTTPClient:   c.params.HTTPClient,
		VisitWebPage: c.params.VisitWebPage,
	})
	endpoint := "/delegatable-macaroon"
	endpoint += "?id=" + url.QueryEscape(curl.String())

	var m *macaroon.Macaroon
	if err := client.Get(endpoint, &m); err != nil {
		return nil, errors.Trace(err)
	}

	// We need to add the is-entity first party caveat to the
	// delegatable macaroon in case we're talking to the old
	// version of the charmstore.
	// TODO (ashipika) - remove this once the new charmstore
	// is deployed.
	if err := m.AddFirstPartyCaveat("is-entity " + curl.String()); err != nil {
		return nil, errors.Trace(err)
	}

	return m, nil
}
Example #4
0
func (s *CharmSuite) SetUpTest(c *gc.C) {
	db := s.jcSuite.Session.DB("juju-testing")
	params := charmstore.ServerParams{
		AuthUsername: "******",
		AuthPassword: "******",
	}
	handler, err := charmstore.NewServer(db, nil, "", params, charmstore.V4)
	c.Assert(err, jc.ErrorIsNil)
	s.Handler = handler
	s.Server = httptest.NewServer(handler)
	s.Client = csclient.New(csclient.Params{
		URL:      s.Server.URL,
		User:     params.AuthUsername,
		Password: params.AuthPassword,
	})
	urls := map[string]string{
		"mysql":     "quantal/mysql-23",
		"dummy":     "quantal/dummy-24",
		"riak":      "quantal/riak-25",
		"wordpress": "quantal/wordpress-26",
		"logging":   "quantal/logging-27",
	}
	for name, url := range urls {
		testcharms.UploadCharm(c, s.Client, url, name)
	}
	s.jcSuite.PatchValue(&charmrepo.CacheDir, c.MkDir())
	// Patch the charm repo initializer function: it is replaced with a charm
	// store repo pointing to the testing server.
	s.jcSuite.PatchValue(&charmrevisionupdater.NewCharmStore, func(p charmrepo.NewCharmStoreParams) *charmrepo.CharmStore {
		p.URL = s.Server.URL
		return charmrepo.NewCharmStore(p)
	})
	s.charms = make(map[string]*state.Charm)
}
Example #5
0
// ResolveCharm resolves the best available charm URLs with series, for charm
// locations without a series specified.
func ResolveCharms(st *state.State, args params.ResolveCharms) (params.ResolveCharmResults, error) {
	var results params.ResolveCharmResults

	envConfig, err := st.ModelConfig()
	if err != nil {
		return params.ResolveCharmResults{}, err
	}
	repo := config.SpecializeCharmRepo(
		NewCharmStoreRepo(csclient.New(csclient.Params{})),
		envConfig)

	for _, ref := range args.References {
		result := params.ResolveCharmResult{}
		curl, err := charm.ParseURL(ref)
		if err != nil {
			result.Error = err.Error()
		} else {
			curl, err := resolveCharm(curl, repo)
			if err != nil {
				result.Error = err.Error()
			} else {
				result.URL = curl.String()
			}
		}
		results.URLs = append(results.URLs, result)
	}
	return results, nil
}
Example #6
0
func PatchNewCharmStoreClient(s Patcher, url string) {
	s.PatchValue(&newCharmStoreClient, func(bakeryClient *httpbakery.Client) *csclient.Client {
		return csclient.New(csclient.Params{
			URL:          url,
			BakeryClient: bakeryClient,
		})
	})
}
Example #7
0
File: client.go Project: bac/juju
func makeWrapper(bakeryClient *httpbakery.Client, server *url.URL) csWrapper {
	p := csclient.Params{
		BakeryClient: bakeryClient,
	}
	if server != nil {
		p.URL = server.String()
	}
	return csclientImpl{csclient.New(p)}
}
Example #8
0
// NewClient returns a Juju charm store client for the given client
// config.
func NewClient(config ClientConfig) Client {
	var url string
	if config.URL != nil {
		url = config.URL.String()
	}
	cs := csclient.New(csclient.Params{
		URL:          url,
		BakeryClient: config.BakeryClient,
	})
	return Client{lowLevel: csclientImpl{cs}}
}
Example #9
0
File: store.go Project: OSBI/juju
// Connect implements CharmstoreSpec.
func (cs charmstoreSpec) Connect() (CharmstoreClient, error) {
	params, apiContext, err := cs.connect()
	if err != nil {
		return nil, errors.Trace(err)
	}

	baseClient := csclient.New(csclient.Params{
		URL:          params.URL,
		HTTPClient:   params.HTTPClient,
		VisitWebPage: params.VisitWebPage,
	})

	csClient := &charmstoreClient{
		Client:     baseClient,
		apiContext: apiContext,
	}
	return csClient, nil
}
Example #10
0
func (s *UpgradeCharmErrorsSuite) SetUpTest(c *gc.C) {
	s.RepoSuite.SetUpTest(c)
	// Set up the charm store testing server.
	handler, err := charmstore.NewServer(s.Session.DB("juju-testing"), nil, "", charmstore.ServerParams{
		AuthUsername: "******",
		AuthPassword: "******",
	}, charmstore.V5)
	c.Assert(err, jc.ErrorIsNil)
	s.handler = handler
	s.srv = httptest.NewServer(handler)

	s.PatchValue(&charmrepo.CacheDir, c.MkDir())
	s.PatchValue(&newCharmStoreClient, func(bakeryClient *httpbakery.Client) *csclient.Client {
		return csclient.New(csclient.Params{
			URL:          s.srv.URL,
			BakeryClient: bakeryClient,
		})
	})
}
Example #11
0
// authorize acquires and return the charm store delegatable macaroon to be
// used to add the charm corresponding to the given URL.
// The macaroon is properly attenuated so that it can only be used to deploy
// the given charm URL.
func (c *csClient) authorize(curl *charm.URL) (*macaroon.Macaroon, error) {
	if curl == nil {
		return nil, errors.New("empty charm url not allowed")
	}

	client := csclient.New(csclient.Params{
		URL:          c.params.URL,
		HTTPClient:   c.params.HTTPClient,
		VisitWebPage: c.params.VisitWebPage,
	})
	endpoint := "/delegatable-macaroon"
	endpoint += "?id=" + url.QueryEscape(curl.String())

	var m *macaroon.Macaroon
	if err := client.Get(endpoint, &m); err != nil {
		return nil, errors.Trace(err)
	}

	return m, nil
}
Example #12
0
func (s *serviceSuite) TestAddCharmWithAuthorization(c *gc.C) {
	// Upload a new charm to the charm store.
	curl, _ := s.UploadCharm(c, "cs:~restricted/precise/wordpress-3", "wordpress")

	// Change permissions on the new charm such that only bob
	// can read from it.
	s.DischargeUser = "******"
	err := s.Client.Put("/"+curl.Path()+"/meta/perm/read", []string{"bob"})
	c.Assert(err, jc.ErrorIsNil)

	// Try to add a charm to the environment without authorization.
	s.DischargeUser = ""
	err = s.APIState.Client().AddCharm(curl)
	c.Assert(err, gc.ErrorMatches, `cannot retrieve charm "cs:~restricted/precise/wordpress-3": cannot get archive: cannot get discharge from "https://.*": third party refused discharge: cannot discharge: discharge denied`)

	tryAs := func(user string) error {
		client := csclient.New(csclient.Params{
			URL: s.Srv.URL,
		})
		s.DischargeUser = user
		var m *macaroon.Macaroon
		err = client.Get("/delegatable-macaroon", &m)
		c.Assert(err, gc.IsNil)

		return service.AddCharmWithAuthorization(s.State, params.AddCharmWithAuthorization{URL: curl.String()})
	}
	// Try again with authorization for the wrong user.
	err = tryAs("joe")
	c.Assert(err, gc.ErrorMatches, `cannot retrieve charm "cs:~restricted/precise/wordpress-3": cannot get archive: unauthorized: access denied for user "joe"`)

	// Try again with the correct authorization this time.
	err = tryAs("bob")
	c.Assert(err, gc.IsNil)

	// Verify that it has actually been uploaded.
	_, err = s.State.Charm(curl)
	c.Assert(err, gc.IsNil)
}
Example #13
0
func openCSClient(args params.AddCharmWithAuthorization) (*csclient.Client, error) {
	csURL, err := url.Parse(csclient.ServerURL)
	if err != nil {
		return nil, err
	}
	csParams := csclient.Params{
		URL:        csURL.String(),
		HTTPClient: httpbakery.NewHTTPClient(),
	}

	if args.CharmStoreMacaroon != nil {
		// Set the provided charmstore authorizing macaroon
		// as a cookie in the HTTP client.
		// TODO(cmars) discharge any third party caveats in the macaroon.
		ms := []*macaroon.Macaroon{args.CharmStoreMacaroon}
		httpbakery.SetCookie(csParams.HTTPClient.Jar, csURL, ms)
	}
	csClient := csclient.New(csParams)
	channel := csparams.Channel(args.Channel)
	if channel != csparams.NoChannel {
		csClient = csClient.WithChannel(channel)
	}
	return csClient, nil
}
Example #14
0
func (s *charmStoreSuite) SetUpTest(c *gc.C) {
	s.JujuConnSuite.SetUpTest(c)

	// Set up the third party discharger.
	s.discharger = bakerytest.NewDischarger(nil, func(req *http.Request, cond string, arg string) ([]checkers.Caveat, error) {
		cookie, err := req.Cookie(clientUserCookie)
		if err != nil {
			return nil, errors.Annotate(err, "discharge denied to non-clients")
		}
		return []checkers.Caveat{
			checkers.DeclaredCaveat("username", cookie.Value),
		}, nil
	})

	s.termsDischargerError = nil
	// Set up the third party terms discharger.
	s.termsDischarger = bakerytest.NewDischarger(nil, func(req *http.Request, cond string, arg string) ([]checkers.Caveat, error) {
		s.termsString = arg
		return nil, s.termsDischargerError
	})
	s.termsString = ""

	keyring := bakery.NewPublicKeyRing()

	pk, err := httpbakery.PublicKeyForLocation(http.DefaultClient, s.discharger.Location())
	c.Assert(err, gc.IsNil)
	err = keyring.AddPublicKeyForLocation(s.discharger.Location(), true, pk)
	c.Assert(err, gc.IsNil)

	pk, err = httpbakery.PublicKeyForLocation(http.DefaultClient, s.termsDischarger.Location())
	c.Assert(err, gc.IsNil)
	err = keyring.AddPublicKeyForLocation(s.termsDischarger.Location(), true, pk)
	c.Assert(err, gc.IsNil)

	// Set up the charm store testing server.
	db := s.Session.DB("juju-testing")
	params := charmstore.ServerParams{
		AuthUsername:     "******",
		AuthPassword:     "******",
		IdentityLocation: s.discharger.Location(),
		PublicKeyLocator: keyring,
		TermsLocation:    s.termsDischarger.Location(),
	}
	handler, err := charmstore.NewServer(db, nil, "", params, charmstore.V5)
	c.Assert(err, jc.ErrorIsNil)
	s.handler = handler
	s.srv = httptest.NewServer(handler)
	c.Logf("started charmstore on %v", s.srv.URL)
	s.client = csclient.New(csclient.Params{
		URL:      s.srv.URL,
		User:     params.AuthUsername,
		Password: params.AuthPassword,
	})

	// Initialize the charm cache dir.
	s.PatchValue(&charmrepo.CacheDir, c.MkDir())

	// Point the CLI to the charm store testing server.
	s.PatchValue(&newCharmStoreClient, func(client *httpbakery.Client) *csclient.Client {
		// Add a cookie so that the discharger can detect whether the
		// HTTP client is the juju environment or the juju client.
		lurl, err := url.Parse(s.discharger.Location())
		c.Assert(err, jc.ErrorIsNil)
		client.Jar.SetCookies(lurl, []*http.Cookie{{
			Name:  clientUserCookie,
			Value: clientUserName,
		}})
		return csclient.New(csclient.Params{
			URL:          s.srv.URL,
			BakeryClient: client,
		})
	})

	// Point the Juju API server to the charm store testing server.
	s.PatchValue(&csclient.ServerURL, s.srv.URL)
}
Example #15
0
File: store.go Project: makyo/juju
		if err != nil {
			return nil, nil, maybeTermsAgreementError(err)
		}
		if err := client.AddCharmWithAuthorization(curl, channel, m); err != nil {
			return nil, nil, errors.Trace(err)
		}
		csMac = m
	}
	return curl, csMac, nil
}

// newCharmStoreClient is called to obtain a charm store client.
// It is defined as a variable so it can be changed for testing purposes.
var newCharmStoreClient = func(client *httpbakery.Client) *csclient.Client {
	return csclient.New(csclient.Params{
		BakeryClient: client,
	})
}

// TODO(natefinch): change the code in this file to use the
// github.com/juju/juju/charmstore package to interact with the charmstore.

// authorizeCharmStoreEntity acquires and return the charm store delegatable macaroon to be
// used to add the charm corresponding to the given URL.
// The macaroon is properly attenuated so that it can only be used to deploy
// the given charm URL.
func authorizeCharmStoreEntity(csClient *csclient.Client, curl *charm.URL) (*macaroon.Macaroon, error) {
	endpoint := "/delegatable-macaroon?id=" + url.QueryEscape(curl.String())
	var m *macaroon.Macaroon
	if err := csClient.Get(endpoint, &m); err != nil {
		return nil, errors.Trace(err)