veyron/services/identity: MacaroonBlesser supports the new security model.

The OAuthBlesser does not yet, that will have to be done in a separate CL.
Also, listblessings will have to be updated to handle audit entries with
the new model.

Change-Id: Ia5539f936ad07a6d5d922ff6a955edc0e36efa74
diff --git a/services/identity/blesser/macaroon.go b/services/identity/blesser/macaroon.go
index 3cee53a..5233788 100644
--- a/services/identity/blesser/macaroon.go
+++ b/services/identity/blesser/macaroon.go
@@ -32,6 +32,8 @@
 //
 // Blessings generated by this server expire after duration. If domain is non-empty, then blessings
 // are generated only for email addresses from that domain.
+//
+// TODO(ashankar): Remove the veyron2.Runtime parameter once the old security model is ripped out.
 func NewMacaroonBlesserServer(r veyron2.Runtime, key []byte) interface{} {
 	return identity.NewServerMacaroonBlesser(&macaroonBlesser{
 		rt:  r,
@@ -49,17 +51,20 @@
 		return nil, err
 	}
 	if time.Now().After(m.Creation.Add(time.Minute * 5)) {
-		return nil, fmt.Errorf("bless failed: macaroon has expired")
+		return nil, fmt.Errorf("macaroon has expired")
 	}
-	return b.bless(ctx, m.Name, m.Caveats)
-}
-
-func (b *macaroonBlesser) bless(ctx ipc.ServerContext, name string, caveats []security.Caveat) (vdlutil.Any, error) {
-	self := b.rt.Identity()
-	var err error
-	// Use the blessing that was used to authenticate with the client to bless it.
-	if self, err = self.Derive(ctx.LocalID()); err != nil {
-		return nil, err
+	if ctx.LocalPrincipal() == nil || ctx.RemoteBlessings() == nil {
+		// TODO(ashankar): Old security model, remove this block.
+		self := b.rt.Identity()
+		var err error
+		// Use the blessing that was used to authenticate with the client to bless it.
+		if self, err = self.Derive(ctx.LocalID()); err != nil {
+			return nil, err
+		}
+		return self.Bless(ctx.RemoteID(), m.Name, time.Hour*24*365, m.Caveats)
 	}
-	return self.Bless(ctx.RemoteID(), name, time.Hour*24*365, caveats)
+	if len(m.Caveats) == 0 {
+		m.Caveats = []security.Caveat{security.UnconstrainedUse()}
+	}
+	return ctx.LocalPrincipal().Bless(ctx.RemoteBlessings().PublicKey(), ctx.LocalBlessings(), m.Name, m.Caveats[0], m.Caveats[1:]...)
 }
diff --git a/services/identity/blesser/macaroon_test.go b/services/identity/blesser/macaroon_test.go
new file mode 100644
index 0000000..4c6a7d2
--- /dev/null
+++ b/services/identity/blesser/macaroon_test.go
@@ -0,0 +1,123 @@
+package blesser
+
+import (
+	"bytes"
+	"crypto/rand"
+	"reflect"
+	"testing"
+	"time"
+
+	"veyron.io/veyron/veyron/services/identity"
+	"veyron.io/veyron/veyron/services/identity/util"
+
+	"veyron.io/veyron/veyron2/ipc"
+	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/security/sectest"
+	"veyron.io/veyron/veyron2/vom"
+)
+
+func TestMacaroonBlesser(t *testing.T) {
+	var (
+		key            = make([]byte, 16)
+		provider, user = newPrincipal(t), newPrincipal(t)
+		cOnlyMethodFoo = newCaveat(security.MethodCaveat("Foo"))
+		context        = &serverCall{
+			p:      provider,
+			local:  blessSelf(t, provider, "provider"),
+			remote: blessSelf(t, user, "self-signed-user"),
+		}
+	)
+	if _, err := rand.Read(key); err != nil {
+		t.Fatal(err)
+	}
+	blesser := NewMacaroonBlesserServer(nil, key).(*identity.ServerStubMacaroonBlesser)
+
+	m := BlessingMacaroon{Creation: time.Now().Add(-1 * time.Hour), Name: "foo"}
+	if got, err := blesser.Bless(context, newMacaroon(t, key, m)); got != nil || err == nil || err.Error() != "macaroon has expired" {
+		t.Errorf("Got (%v, %v)", got, err)
+	}
+	m = BlessingMacaroon{Creation: time.Now(), Name: "user", Caveats: []security.Caveat{cOnlyMethodFoo}}
+	if result, err := blesser.Bless(context, newMacaroon(t, key, m)); err != nil || result == nil {
+		t.Errorf("Got (%v, %v)", result, err)
+	} else if _, ok := result.(security.Blessings); !ok {
+		t.Errorf("Got %T, want security.Blessings", result)
+	} else {
+		b := result.(security.Blessings)
+		if !reflect.DeepEqual(b.PublicKey(), user.PublicKey()) {
+			t.Errorf("Received blessing for public key %v. Client:%v, Blesser:%v", b.PublicKey(), user.PublicKey(), provider.PublicKey())
+		}
+		// Context at a server to which the user will present her blessings.
+		server := newPrincipal(t)
+		serverCtxNoMethod := &serverCall{
+			p:      server,
+			remote: b,
+		}
+		serverCtxFoo := &serverCall{
+			p:      server,
+			remote: b,
+			method: "Foo",
+		}
+		// When the server does not recognize the provider, it should not see any strings for the client's blessings.
+		if got := b.ForContext(serverCtxNoMethod); len(got) > 0 {
+			t.Errorf("Got blessing that returned %v for an empty security.Context (%v)", got, b)
+		}
+		if got := b.ForContext(serverCtxFoo); len(got) > 0 {
+			t.Errorf("Got blessing that returned %v for an empty security.Context (%v)", got, b)
+		}
+		// But once it recognizes the provider, serverCtxFoo should see the "provider/user" name.
+		server.AddToRoots(b)
+		if got := b.ForContext(serverCtxNoMethod); len(got) > 0 {
+			t.Errorf("Got blessing that returned %v for an empty security.Context (%v)", got, b)
+		}
+		if got, want := b.ForContext(serverCtxFoo), []string{"provider/user"}; !reflect.DeepEqual(got, want) {
+			t.Errorf("Got %v, want %v", got, want)
+		}
+	}
+}
+
+type serverCall struct {
+	ipc.ServerCall
+	method        string
+	p             security.Principal
+	local, remote security.Blessings
+}
+
+func (c *serverCall) Method() string                      { return c.method }
+func (c *serverCall) LocalPrincipal() security.Principal  { return c.p }
+func (c *serverCall) LocalBlessings() security.Blessings  { return c.local }
+func (c *serverCall) RemoteBlessings() security.Blessings { return c.remote }
+
+func newPrincipal(t *testing.T) security.Principal {
+	_, key, err := sectest.NewKey()
+	if err != nil {
+		t.Fatal(err)
+	}
+	p, err := security.CreatePrincipal(security.NewInMemoryECDSASigner(key), nil, sectest.NewBlessingRoots())
+	if err != nil {
+		t.Fatal(err)
+	}
+	return p
+}
+
+func blessSelf(t *testing.T, p security.Principal, name string) security.Blessings {
+	b, err := p.BlessSelf(name)
+	if err != nil {
+		t.Fatal(err)
+	}
+	return b
+}
+
+func newCaveat(c security.Caveat, err error) security.Caveat {
+	if err != nil {
+		panic(err)
+	}
+	return c
+}
+
+func newMacaroon(t *testing.T, key []byte, m BlessingMacaroon) string {
+	buf := new(bytes.Buffer)
+	if err := vom.NewEncoder(buf).Encode(m); err != nil {
+		t.Fatal(err)
+	}
+	return string(util.NewMacaroon(key, buf.Bytes()))
+}