| 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())) |
| } |