// authenticateUser will add the store expected Macaroon Authorization header for user func authenticateUser(r *http.Request, user *auth.UserState) { var buf bytes.Buffer fmt.Fprintf(&buf, `Macaroon root="%s"`, user.StoreMacaroon) // deserialize root macaroon (we need its signature to do the discharge binding) root, err := auth.MacaroonDeserialize(user.StoreMacaroon) if err != nil { logger.Debugf("cannot deserialize root macaroon: %v", err) return } for _, d := range user.StoreDischarges { // prepare discharge for request discharge, err := auth.MacaroonDeserialize(d) if err != nil { logger.Debugf("cannot deserialize discharge macaroon: %v", err) return } discharge.Bind(root.Signature()) serializedDischarge, err := auth.MacaroonSerialize(discharge) if err != nil { logger.Debugf("cannot re-serialize discharge macaroon: %v", err) return } fmt.Fprintf(&buf, `, discharge="%s"`, serializedDischarge) } r.Header.Set("Authorization", buf.String()) }
func (as *authSuite) TestNewUser(c *C) { as.state.Lock() user, err := auth.NewUser(as.state, "username", "*****@*****.**", "macaroon", []string{"discharge"}) as.state.Unlock() c.Check(err, IsNil) // check snapd macaroon was generated for the local user var authStateData auth.AuthState as.state.Lock() err = as.state.Get("auth", &authStateData) as.state.Unlock() c.Check(err, IsNil) c.Check(authStateData.MacaroonKey, NotNil) expectedMacaroon, err := macaroon.New(authStateData.MacaroonKey, "1", "snapd") c.Check(err, IsNil) expectedSerializedMacaroon, err := auth.MacaroonSerialize(expectedMacaroon) c.Check(err, IsNil) expected := &auth.UserState{ ID: 1, Username: "******", Email: "*****@*****.**", Macaroon: expectedSerializedMacaroon, Discharges: nil, StoreMacaroon: "macaroon", StoreDischarges: []string{"discharge"}, } c.Check(user, DeepEquals, expected) }
func (s *authSuite) TestMacaroonSerialize(c *C) { m, err := macaroon.New([]byte("secret"), "some-id", "location") c.Check(err, IsNil) serialized, err := auth.MacaroonSerialize(m) c.Check(err, IsNil) deserialized, err := auth.MacaroonDeserialize(serialized) c.Check(err, IsNil) c.Check(deserialized, DeepEquals, m) }
func (s *authSuite) TestMacaroonSerializeDeserializeStoreMacaroon(c *C) { // sample serialized macaroon using store server setup. serialized := `MDAxNmxvY2F0aW9uIGxvY2F0aW9uCjAwMTdpZGVudGlmaWVyIHNvbWUgaWQKMDAwZmNpZCBjYXZlYXQKMDAxOWNpZCAzcmQgcGFydHkgY2F2ZWF0CjAwNTF2aWQgcyvpXSVlMnj9wYw5b-WPCLjTnO_8lVzBrRr8tJfu9tOhPORbsEOFyBwPOM_YiiXJ_qh-Pp8HY0HsUueCUY4dxONLIxPWTdMzCjAwMTJjbCByZW1vdGUuY29tCjAwMmZzaWduYXR1cmUgcm_Gdz75wUCWF9KGXZQEANhwfvBcLNt9xXGfAmxurPMK` deserialized, err := auth.MacaroonDeserialize(serialized) c.Check(err, IsNil) // expected json serialization of the above macaroon jsonData := []byte(`{"caveats":[{"cid":"caveat"},{"cid":"3rd party caveat","vid":"cyvpXSVlMnj9wYw5b-WPCLjTnO_8lVzBrRr8tJfu9tOhPORbsEOFyBwPOM_YiiXJ_qh-Pp8HY0HsUueCUY4dxONLIxPWTdMz","cl":"remote.com"}],"location":"location","identifier":"some id","signature":"726fc6773ef9c1409617d2865d940400d8707ef05c2cdb7dc5719f026c6eacf3"}`) var expected macaroon.Macaroon err = expected.UnmarshalJSON(jsonData) c.Check(err, IsNil) c.Check(deserialized, DeepEquals, &expected) // reserializing the macaroon should give us the same original store serialization reserialized, err := auth.MacaroonSerialize(deserialized) c.Check(err, IsNil) c.Check(reserialized, Equals, serialized) }
func (as *authSuite) TestCheckMacaroonInvalidAuthMalformedMacaroon(c *C) { var authStateData auth.AuthState as.state.Lock() // create a new user to ensure there is a MacaroonKey setup _, err := auth.NewUser(as.state, "username", "*****@*****.**", "macaroon", []string{"discharge"}) c.Check(err, IsNil) // get AuthState to get signing MacaroonKey err = as.state.Get("auth", &authStateData) c.Check(err, IsNil) as.state.Unlock() // setup a macaroon for an invalid user invalidMacaroon, err := macaroon.New(authStateData.MacaroonKey, "invalid", "snapd") c.Check(err, IsNil) serializedInvalidMacaroon, err := auth.MacaroonSerialize(invalidMacaroon) c.Check(err, IsNil) as.state.Lock() user, err := auth.CheckMacaroon(as.state, serializedInvalidMacaroon, nil) as.state.Unlock() c.Check(err, Equals, auth.ErrInvalidAuth) c.Check(user, IsNil) }
func (as *authSuite) TestCheckMacaroonValidUserOldStyle(c *C) { // create a fake store-deserializable macaroon m, err := macaroon.New([]byte("secret"), "some-id", "location") c.Check(err, IsNil) serializedMacaroon, err := auth.MacaroonSerialize(m) c.Check(err, IsNil) as.state.Lock() expectedUser, err := auth.NewUser(as.state, "username", "*****@*****.**", serializedMacaroon, []string{"discharge"}) c.Check(err, IsNil) // set user local macaroons with store macaroons expectedUser.Macaroon = expectedUser.StoreMacaroon expectedUser.Discharges = expectedUser.StoreDischarges err = auth.UpdateUser(as.state, expectedUser) c.Check(err, IsNil) as.state.Unlock() as.state.Lock() user, err := auth.CheckMacaroon(as.state, expectedUser.Macaroon, expectedUser.Discharges) as.state.Unlock() c.Check(err, IsNil) c.Check(user, DeepEquals, expectedUser) }