github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/stateauthenticator/context_test.go (about)

     1  // Copyright 2018 Canonical Ltd. All rights reserved.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package stateauthenticator_test
     5  
     6  import (
     7  	"net/http"
     8  
     9  	"github.com/juju/clock"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  	"gopkg.in/macaroon-bakery.v2-unstable/bakery"
    13  	"gopkg.in/macaroon-bakery.v2-unstable/bakery/checkers"
    14  	"gopkg.in/macaroon-bakery.v2-unstable/bakerytest"
    15  	"gopkg.in/macaroon-bakery.v2-unstable/httpbakery"
    16  
    17  	"github.com/juju/juju/apiserver/stateauthenticator"
    18  	"github.com/juju/juju/controller"
    19  	statetesting "github.com/juju/juju/state/testing"
    20  )
    21  
    22  // TODO(babbageclunk): These have been extracted pretty mechanically
    23  // from the API server tests as part of the apiserver/httpserver
    24  // split. They should be updated to test via the public interface
    25  // rather than the export_test functions.
    26  
    27  type macaroonCommonSuite struct {
    28  	statetesting.StateSuite
    29  	discharger    *bakerytest.Discharger
    30  	authenticator *stateauthenticator.Authenticator
    31  }
    32  
    33  func (s *macaroonCommonSuite) SetUpTest(c *gc.C) {
    34  	s.StateSuite.SetUpTest(c)
    35  	authenticator, err := stateauthenticator.NewAuthenticator(s.StatePool, clock.WallClock)
    36  	c.Assert(err, jc.ErrorIsNil)
    37  	s.authenticator = authenticator
    38  }
    39  
    40  func (s *macaroonCommonSuite) TearDownTest(c *gc.C) {
    41  	if s.discharger != nil {
    42  		s.discharger.Close()
    43  	}
    44  	s.StateSuite.TearDownTest(c)
    45  }
    46  
    47  type macaroonAuthSuite struct {
    48  	macaroonCommonSuite
    49  }
    50  
    51  var _ = gc.Suite(&macaroonAuthSuite{})
    52  
    53  func (s *macaroonAuthSuite) SetUpTest(c *gc.C) {
    54  	s.discharger = bakerytest.NewDischarger(nil, noCheck)
    55  	s.ControllerConfig = map[string]interface{}{
    56  		controller.IdentityURL: s.discharger.Location(),
    57  	}
    58  	s.macaroonCommonSuite.SetUpTest(c)
    59  }
    60  
    61  func (s *macaroonAuthSuite) TestServerBakery(c *gc.C) {
    62  	m, err := stateauthenticator.ServerMacaroon(s.authenticator)
    63  	c.Assert(err, gc.IsNil)
    64  	bsvc, err := stateauthenticator.ServerBakeryService(s.authenticator)
    65  	c.Assert(err, gc.IsNil)
    66  
    67  	// Check that we can add a third party caveat addressed to the
    68  	// discharger, which indirectly ensures that the discharger's public
    69  	// key has been added to the bakery service's locator.
    70  	m = m.Clone()
    71  	err = bsvc.AddCaveat(m, checkers.Caveat{
    72  		Location:  s.discharger.Location(),
    73  		Condition: "true",
    74  	})
    75  	c.Assert(err, jc.ErrorIsNil)
    76  
    77  	// Check that we can discharge the macaroon and check it with
    78  	// the service.
    79  	client := httpbakery.NewClient()
    80  	ms, err := client.DischargeAll(m)
    81  	c.Assert(err, jc.ErrorIsNil)
    82  
    83  	err = bsvc.(*bakery.Service).Check(ms, checkers.New())
    84  	c.Assert(err, gc.IsNil)
    85  }
    86  
    87  func noCheck(_ *http.Request, _, _ string) ([]checkers.Caveat, error) {
    88  	return nil, nil
    89  }
    90  
    91  type macaroonAuthWrongPublicKeySuite struct {
    92  	macaroonCommonSuite
    93  }
    94  
    95  var _ = gc.Suite(&macaroonAuthWrongPublicKeySuite{})
    96  
    97  func (s *macaroonAuthWrongPublicKeySuite) SetUpTest(c *gc.C) {
    98  	s.discharger = bakerytest.NewDischarger(nil, noCheck)
    99  	wrongKey, err := bakery.GenerateKey()
   100  	c.Assert(err, gc.IsNil)
   101  	s.ControllerConfig = map[string]interface{}{
   102  		controller.IdentityURL:       s.discharger.Location(),
   103  		controller.IdentityPublicKey: wrongKey.Public.String(),
   104  	}
   105  	s.macaroonCommonSuite.SetUpTest(c)
   106  }
   107  
   108  func (s *macaroonAuthWrongPublicKeySuite) TearDownTest(c *gc.C) {
   109  	s.discharger.Close()
   110  	s.StateSuite.TearDownTest(c)
   111  }
   112  
   113  func (s *macaroonAuthWrongPublicKeySuite) TestDischargeFailsWithWrongPublicKey(c *gc.C) {
   114  	m, err := stateauthenticator.ServerMacaroon(s.authenticator)
   115  	c.Assert(err, gc.IsNil)
   116  	m = m.Clone()
   117  	bsvc, err := stateauthenticator.ServerBakeryService(s.authenticator)
   118  	c.Assert(err, gc.IsNil)
   119  	err = bsvc.AddCaveat(m, checkers.Caveat{
   120  		Location:  s.discharger.Location(),
   121  		Condition: "true",
   122  	})
   123  	c.Assert(err, gc.IsNil)
   124  	client := httpbakery.NewClient()
   125  
   126  	_, err = client.DischargeAll(m)
   127  	c.Assert(err, gc.ErrorMatches, `cannot get discharge from ".*": third party refused discharge: cannot discharge: discharger cannot decode caveat id: public key mismatch`)
   128  }
   129  
   130  type macaroonNoURLSuite struct {
   131  	macaroonCommonSuite
   132  }
   133  
   134  var _ = gc.Suite(&macaroonNoURLSuite{})
   135  
   136  func (s *macaroonNoURLSuite) TestNoBakeryWhenNoIdentityURL(c *gc.C) {
   137  	// By default, when there is no identity location, no
   138  	// bakery service or macaroon is created.
   139  	_, err := stateauthenticator.ServerMacaroon(s.authenticator)
   140  	c.Assert(err, gc.ErrorMatches, "macaroon authentication is not configured")
   141  	_, err = stateauthenticator.ServerBakeryService(s.authenticator)
   142  	c.Assert(err, gc.ErrorMatches, "macaroon authentication is not configured")
   143  }