// 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) { client := csclient.New(csclient.Params{ URL: c.params.URL, HTTPClient: c.params.HTTPClient, VisitWebPage: c.params.VisitWebPage, }) var m *macaroon.Macaroon if err := client.Get("/delegatable-macaroon", &m); err != nil { return nil, errors.Trace(err) } if err := m.AddFirstPartyCaveat("is-entity " + curl.String()); err != nil { return nil, errors.Trace(err) } return m, nil }
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.Srv.NewClient().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 ".*": 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) }