Beispiel #1
0
// targetService implements a "target service", representing
// an arbitrary web service that wants to delegate authorization
// to third parties.
func targetService(endpoint, authEndpoint string, authPK *bakery.PublicKey) (http.Handler, error) {
	key, err := bakery.GenerateKey()
	if err != nil {
		return nil, err
	}
	pkLocator := bakery.NewPublicKeyRing()
	svc, err := bakery.NewService(bakery.NewServiceParams{
		Key:      key,
		Location: endpoint,
		Locator:  pkLocator,
	})
	if err != nil {
		return nil, err
	}
	log.Printf("adding public key for location %s: %v", authEndpoint, authPK)
	pkLocator.AddPublicKeyForLocation(authEndpoint, true, authPK)
	mux := http.NewServeMux()
	srv := &targetServiceHandler{
		svc:          svc,
		authEndpoint: authEndpoint,
	}
	mux.HandleFunc("/gold/", srv.serveGold)
	mux.HandleFunc("/silver/", srv.serveSilver)
	return mux, nil
}
Beispiel #2
0
func (s *suite) SetUpSuite(c *gc.C) {
	key, err := bakery.GenerateKey()
	c.Assert(err, gc.IsNil)
	s.authPublicKey = &key.Public
	s.authEndpoint = serve(c, func(endpoint string) (http.Handler, error) {
		return idservice.New(idservice.Params{
			Users: map[string]*idservice.UserInfo{
				"rog": {
					Password: "******",
				},
				"root": {
					Password: "******",
					Groups: map[string]bool{
						"target-service-users": true,
					},
				},
			},
			Service: bakery.NewServiceParams{
				Location: endpoint,
				Store:    bakery.NewMemStorage(),
				Key:      key,
				Locator:  bakery.NewPublicKeyRing(),
			},
		})
	})
	c.Logf("auth endpoint at %s", s.authEndpoint)
}
Beispiel #3
0
func (s *KeyringSuite) TestCachePrepopulated(c *gc.C) {
	cache := bakery.NewPublicKeyRing()
	key, err := bakery.GenerateKey()
	c.Assert(err, gc.IsNil)
	cache.AddPublicKeyForLocation("https://0.1.2.3/", true, &key.Public)
	kr := httpbakery.NewPublicKeyRing(nil, cache)
	pk, err := kr.PublicKeyForLocation("https://0.1.2.3/")
	c.Assert(err, gc.IsNil)
	c.Assert(*pk, gc.Equals, key.Public)
}
Beispiel #4
0
// NewPublicKeyRing returns a new public keyring that uses
// the given client to find public keys and uses the
// given cache as a backing. If cache is nil, a new
// cache will be created. If client is nil, http.DefaultClient will
// be used.
func NewPublicKeyRing(client *http.Client, cache *bakery.PublicKeyRing) *PublicKeyRing {
	if cache == nil {
		cache = bakery.NewPublicKeyRing()
	}
	if client == nil {
		client = http.DefaultClient
	}
	return &PublicKeyRing{
		client: client,
		cache:  cache,
	}
}
Beispiel #5
0
// authService implements an authorization service,
// that can discharge third-party caveats added
// to other macaroons.
func authService(endpoint string, key *bakery.KeyPair) (http.Handler, error) {
	svc, err := bakery.NewService(bakery.NewServiceParams{
		Location: endpoint,
		Key:      key,
		Locator:  bakery.NewPublicKeyRing(),
	})
	if err != nil {
		return nil, err
	}
	mux := http.NewServeMux()
	httpbakery.AddDischargeHandler(mux, "/", svc, thirdPartyChecker)
	return mux, nil
}
func (s *ClientSuite) TestDischargeServerWithMacaraqOnDischarge(c *gc.C) {
	locator := bakery.NewPublicKeyRing()

	var called [3]int

	// create the services from leaf discharger to primary
	// service so that each one can know the location
	// to discharge at.
	key2, h2 := newHTTPDischarger(locator, func(svc *bakery.Service, req *http.Request, cavId, cav string) ([]checkers.Caveat, error) {
		called[2]++
		if cav != "is-ok" {
			return nil, fmt.Errorf("unrecognized caveat at srv2")
		}
		return nil, nil
	})
	srv2 := httptest.NewServer(h2)
	locator.AddPublicKeyForLocation(srv2.URL, true, key2)

	key1, h1 := newHTTPDischarger(locator, func(svc *bakery.Service, req *http.Request, cavId, cav string) ([]checkers.Caveat, error) {
		called[1]++
		if _, err := httpbakery.CheckRequest(svc, req, nil, checkers.New()); err != nil {
			return nil, newDischargeRequiredError(serverHandlerParams{
				service:      svc,
				authLocation: srv2.URL,
			}, err, req)
		}
		if cav != "is-ok" {
			return nil, fmt.Errorf("unrecognized caveat at srv1")
		}
		return nil, nil
	})
	srv1 := httptest.NewServer(h1)
	locator.AddPublicKeyForLocation(srv1.URL, true, key1)

	svc0 := newService("loc", locator)
	srv0 := httptest.NewServer(serverHandler(serverHandlerParams{
		service:      svc0,
		authLocation: srv1.URL,
	}))

	// Make a client request.
	client := httpbakery.NewClient()
	req, err := http.NewRequest("GET", srv0.URL, nil)
	c.Assert(err, gc.IsNil)
	resp, err := client.Do(req)
	c.Assert(err, gc.IsNil)
	defer resp.Body.Close()
	assertResponse(c, resp, "done")

	c.Assert(called, gc.DeepEquals, [3]int{0, 2, 1})
}
Beispiel #7
0
func (*KeysSuite) TestPublicKeyRing(c *gc.C) {
	for i, test := range publicKeyRingTests {
		c.Logf("test %d: %s", i, test.about)
		kr := bakery.NewPublicKeyRing()
		for _, add := range test.add {
			err := kr.AddPublicKeyForLocation(add.loc, add.prefix, &bakery.PublicKey{add.key})
			c.Assert(err, gc.IsNil)
		}
		key, err := kr.PublicKeyForLocation(test.loc)
		if test.expectNotFound {
			c.Assert(err, gc.Equals, bakery.ErrNotFound)
			c.Assert(key, gc.IsNil)
			continue
		}
		c.Assert(err, gc.IsNil)
		c.Assert(*key, gc.Equals, bakery.PublicKey{test.expectKey})
	}
}
Beispiel #8
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)
}