blob: 2aa9e3e5ba10f91090e71e2c2a595adf4e83ae2c [file] [log] [blame]
package blesser
import (
"bytes"
"crypto/rand"
"reflect"
"testing"
"time"
vsecurity "veyron.io/veyron/veyron/security"
"veyron.io/veyron/veyron/services/identity/util"
"veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/security"
"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(key)
m := BlessingMacaroon{Creation: time.Now().Add(-1 * time.Hour), Name: "foo"}
if got, err := blesser.Bless(context, newMacaroon(t, key, m)); 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 {
t.Errorf("Got (%v, %v)", result, err)
} else {
b, err := security.NewBlessings(result)
if err != nil {
t.Fatalf("Unable to decode response into a security.Blessings object: %v", err)
}
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 {
p, err := vsecurity.NewPrincipal()
if err != nil {
panic(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()))
}