Security API additions.
-Principal can now get a slice of blessings that match a name.
-Principal can now get a name for a blessing that belongs to it.
-BlessingStore exports a map of all the pattern/blessings that have been added.
Change-Id: Idaa8d9ddf8acd03a7d2b72d5bf408566d1a8cdc1
diff --git a/security/agent/agent_test.go b/security/agent/agent_test.go
index d0acb43..18b61ea 100644
--- a/security/agent/agent_test.go
+++ b/security/agent/agent_test.go
@@ -69,6 +69,8 @@
{"Sign", V{make([]byte, 10)}, security.Signature{Purpose: []byte{}, R: []byte{1}, S: []byte{1}}, nil},
{"MintDischarge", V{thirdPartyCaveat, security.UnconstrainedUse()}, discharge, nil},
{"PublicKey", V{}, mockP.PublicKey(), nil},
+ {"BlessingsByName", V{security.BlessingPattern("self")}, []security.Blessings{newBlessing(t, "blessing")}, nil},
+ {"BlessingsInfo", V{newBlessing(t, "blessing")}, []string{"blessing"}, nil},
{"AddToRoots", V{newBlessing(t, "blessing")}, nil, verror2.Make(addToRootsErr, nil)},
}
for _, test := range tests {
@@ -84,6 +86,7 @@
{"SetDefault", V{newBlessing(t, "blessing")}, nil, verror2.Make(storeSetDefaultErr, nil)},
{"Default", V{}, newBlessing(t, "root/extension"), nil},
{"PublicKey", V{}, mockP.PublicKey(), nil},
+ {"PeerBlessings", V{}, map[security.BlessingPattern]security.Blessings{"test": newBlessing(t, "root/extension")}, nil},
{"DebugString", V{}, "StoreString", nil},
}
for _, test := range storeTests {
@@ -176,6 +179,18 @@
return d, p.NextError
}
+func (p *mockPrincipal) BlessingsByName(name security.BlessingPattern) []security.Blessings {
+ defer p.reset()
+ b, _ := p.NextResult.([]security.Blessings)
+ return b
+}
+
+func (p *mockPrincipal) BlessingsInfo(blessings security.Blessings) []string {
+ defer p.reset()
+ s, _ := p.NextResult.([]string)
+ return s
+}
+
func (p *mockPrincipal) PublicKey() security.PublicKey { return p.Key }
func (p *mockPrincipal) Roots() security.BlessingRoots { return p.MockRoots }
func (p *mockPrincipal) BlessingStore() security.BlessingStore { return p.MockStore }
@@ -220,6 +235,12 @@
func (s *mockBlessingStore) PublicKey() security.PublicKey { return s.Key }
+func (s *mockBlessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
+ defer s.reset()
+ m, _ := s.NextResult.(map[security.BlessingPattern]security.Blessings)
+ return m
+}
+
func (s *mockBlessingStore) DebugString() string {
defer s.reset()
return s.NextResult.(string)
diff --git a/security/agent/client.go b/security/agent/client.go
index 6a3925f..cd26573 100644
--- a/security/agent/client.go
+++ b/security/agent/client.go
@@ -128,6 +128,33 @@
return c.key
}
+func (c *client) BlessingsByName(pattern security.BlessingPattern) []security.Blessings {
+ var wbResults []security.WireBlessings
+ err := c.caller.call("BlessingsByName", results(&wbResults), pattern)
+ if err != nil {
+ vlog.Errorf("error calling BlessingsByName: %v", err)
+ return nil
+ }
+ blessings := make([]security.Blessings, len(wbResults))
+ for i, wb := range wbResults {
+ var err error
+ blessings[i], err = security.NewBlessings(wb)
+ if err != nil {
+ vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
+ }
+ }
+ return blessings
+}
+
+func (c *client) BlessingsInfo(blessings security.Blessings) []string {
+ var names []string
+ err := c.caller.call("BlessingsInfo", results(&names), security.MarshalBlessings(blessings))
+ if err != nil {
+ vlog.Errorf("error calling BlessingsInfo: %v", err)
+ return nil
+ }
+ return names
+}
func (c *client) BlessingStore() security.BlessingStore {
return &blessingStore{c.caller, c.key}
}
@@ -192,6 +219,25 @@
return b.key
}
+func (b *blessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
+ var wbMap map[security.BlessingPattern]security.WireBlessings
+ err := b.caller.call("BlessingStorePeerBlessings", results(&wbMap))
+ if err != nil {
+ vlog.Errorf("error calling BlessingStorePeerBlessings: %v", err)
+ return nil
+ }
+ bMap := make(map[security.BlessingPattern]security.Blessings)
+ for pattern, wb := range wbMap {
+ blessings, err := security.NewBlessings(wb)
+ if err != nil {
+ vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
+ return nil
+ }
+ bMap[pattern] = blessings
+ }
+ return bMap
+}
+
func (b *blessingStore) DebugString() (s string) {
err := b.caller.call("BlessingStoreDebugString", results(&s))
if err != nil {
diff --git a/security/agent/server/server.go b/security/agent/server/server.go
index c6ff7ea..fcf25a3 100644
--- a/security/agent/server/server.go
+++ b/security/agent/server/server.go
@@ -307,6 +307,23 @@
return a.principal.PublicKey().MarshalBinary()
}
+func (a agentd) BlessingsByName(_ ipc.ServerContext, name security.BlessingPattern) ([]security.WireBlessings, error) {
+ blessings := a.principal.BlessingsByName(name)
+ ret := make([]security.WireBlessings, len(blessings))
+ for i, b := range blessings {
+ ret[i] = security.MarshalBlessings(b)
+ }
+ return ret, nil
+}
+
+func (a agentd) BlessingsInfo(_ ipc.ServerContext, blessings security.WireBlessings) ([]string, error) {
+ b, err := security.NewBlessings(blessings)
+ if err != nil {
+ return nil, err
+ }
+ return a.principal.BlessingsInfo(b), nil
+}
+
func (a agentd) AddToRoots(_ ipc.ServerContext, wireBlessings security.WireBlessings) error {
blessings, err := security.NewBlessings(wireBlessings)
if err != nil {
@@ -339,6 +356,15 @@
return a.principal.BlessingStore().SetDefault(blessings)
}
+func (a agentd) BlessingStorePeerBlessings(_ ipc.ServerContext) (map[security.BlessingPattern]security.WireBlessings, error) {
+ bMap := a.principal.BlessingStore().PeerBlessings()
+ wbMap := make(map[security.BlessingPattern]security.WireBlessings, len(bMap))
+ for p, b := range bMap {
+ wbMap[p] = security.MarshalBlessings(b)
+ }
+ return wbMap, nil
+}
+
func (a agentd) BlessingStoreDebugString(_ ipc.ServerContext) (string, error) {
return a.principal.BlessingStore().DebugString(), nil
}
diff --git a/security/agent/server/wire.vdl b/security/agent/server/wire.vdl
index dc52a7c..ee55e0b 100644
--- a/security/agent/server/wire.vdl
+++ b/security/agent/server/wire.vdl
@@ -35,12 +35,15 @@
Sign(message []byte) (security.Signature, error)
MintDischarge(tp any, caveat security.Caveat, additionalCaveats []security.Caveat) (any, error)
PublicKey() ([]byte, error)
+ BlessingsByName(name security.BlessingPattern) ([]security.WireBlessings, error)
+ BlessingsInfo(blessings security.WireBlessings) ([]string, error)
AddToRoots(blessing security.WireBlessings) error
BlessingStoreSet(blessings security.WireBlessings, forPeers security.BlessingPattern) (security.WireBlessings, error)
BlessingStoreForPeer(peerBlessings []string) (security.WireBlessings, error)
BlessingStoreSetDefault(blessings security.WireBlessings) error
BlessingStoreDefault() (security.WireBlessings, error)
+ BlessingStorePeerBlessings() (map[security.BlessingPattern]security.WireBlessings, error)
BlessingStoreDebugString() (string, error)
BlessingRootsAdd(root []byte, pattern security.BlessingPattern) error
diff --git a/security/agent/server/wire.vdl.go b/security/agent/server/wire.vdl.go
index fa5832b..3fc6f85 100644
--- a/security/agent/server/wire.vdl.go
+++ b/security/agent/server/wire.vdl.go
@@ -27,11 +27,14 @@
Sign(ctx __context.T, message []byte, opts ...__ipc.CallOpt) (security.Signature, error)
MintDischarge(ctx __context.T, tp __vdlutil.Any, caveat security.Caveat, additionalCaveats []security.Caveat, opts ...__ipc.CallOpt) (__vdlutil.Any, error)
PublicKey(__context.T, ...__ipc.CallOpt) ([]byte, error)
+ BlessingsByName(ctx __context.T, name security.BlessingPattern, opts ...__ipc.CallOpt) ([]security.WireBlessings, error)
+ BlessingsInfo(ctx __context.T, blessings security.WireBlessings, opts ...__ipc.CallOpt) ([]string, error)
AddToRoots(ctx __context.T, blessing security.WireBlessings, opts ...__ipc.CallOpt) error
BlessingStoreSet(ctx __context.T, blessings security.WireBlessings, forPeers security.BlessingPattern, opts ...__ipc.CallOpt) (security.WireBlessings, error)
BlessingStoreForPeer(ctx __context.T, peerBlessings []string, opts ...__ipc.CallOpt) (security.WireBlessings, error)
BlessingStoreSetDefault(ctx __context.T, blessings security.WireBlessings, opts ...__ipc.CallOpt) error
BlessingStoreDefault(__context.T, ...__ipc.CallOpt) (security.WireBlessings, error)
+ BlessingStorePeerBlessings(__context.T, ...__ipc.CallOpt) (map[security.BlessingPattern]security.WireBlessings, error)
BlessingStoreDebugString(__context.T, ...__ipc.CallOpt) (string, error)
BlessingRootsAdd(ctx __context.T, root []byte, pattern security.BlessingPattern, opts ...__ipc.CallOpt) error
BlessingRootsRecognized(ctx __context.T, root []byte, blessing string, opts ...__ipc.CallOpt) error
@@ -122,6 +125,28 @@
return
}
+func (c implAgentClientStub) BlessingsByName(ctx __context.T, i0 security.BlessingPattern, opts ...__ipc.CallOpt) (o0 []security.WireBlessings, err error) {
+ var call __ipc.Call
+ if call, err = c.c(ctx).StartCall(ctx, c.name, "BlessingsByName", []interface{}{i0}, opts...); err != nil {
+ return
+ }
+ if ierr := call.Finish(&o0, &err); ierr != nil {
+ err = ierr
+ }
+ return
+}
+
+func (c implAgentClientStub) BlessingsInfo(ctx __context.T, i0 security.WireBlessings, opts ...__ipc.CallOpt) (o0 []string, err error) {
+ var call __ipc.Call
+ if call, err = c.c(ctx).StartCall(ctx, c.name, "BlessingsInfo", []interface{}{i0}, opts...); err != nil {
+ return
+ }
+ if ierr := call.Finish(&o0, &err); ierr != nil {
+ err = ierr
+ }
+ return
+}
+
func (c implAgentClientStub) AddToRoots(ctx __context.T, i0 security.WireBlessings, opts ...__ipc.CallOpt) (err error) {
var call __ipc.Call
if call, err = c.c(ctx).StartCall(ctx, c.name, "AddToRoots", []interface{}{i0}, opts...); err != nil {
@@ -177,6 +202,17 @@
return
}
+func (c implAgentClientStub) BlessingStorePeerBlessings(ctx __context.T, opts ...__ipc.CallOpt) (o0 map[security.BlessingPattern]security.WireBlessings, err error) {
+ var call __ipc.Call
+ if call, err = c.c(ctx).StartCall(ctx, c.name, "BlessingStorePeerBlessings", nil, opts...); err != nil {
+ return
+ }
+ if ierr := call.Finish(&o0, &err); ierr != nil {
+ err = ierr
+ }
+ return
+}
+
func (c implAgentClientStub) BlessingStoreDebugString(ctx __context.T, opts ...__ipc.CallOpt) (o0 string, err error) {
var call __ipc.Call
if call, err = c.c(ctx).StartCall(ctx, c.name, "BlessingStoreDebugString", nil, opts...); err != nil {
@@ -240,11 +276,14 @@
Sign(ctx __ipc.ServerContext, message []byte) (security.Signature, error)
MintDischarge(ctx __ipc.ServerContext, tp __vdlutil.Any, caveat security.Caveat, additionalCaveats []security.Caveat) (__vdlutil.Any, error)
PublicKey(__ipc.ServerContext) ([]byte, error)
+ BlessingsByName(ctx __ipc.ServerContext, name security.BlessingPattern) ([]security.WireBlessings, error)
+ BlessingsInfo(ctx __ipc.ServerContext, blessings security.WireBlessings) ([]string, error)
AddToRoots(ctx __ipc.ServerContext, blessing security.WireBlessings) error
BlessingStoreSet(ctx __ipc.ServerContext, blessings security.WireBlessings, forPeers security.BlessingPattern) (security.WireBlessings, error)
BlessingStoreForPeer(ctx __ipc.ServerContext, peerBlessings []string) (security.WireBlessings, error)
BlessingStoreSetDefault(ctx __ipc.ServerContext, blessings security.WireBlessings) error
BlessingStoreDefault(__ipc.ServerContext) (security.WireBlessings, error)
+ BlessingStorePeerBlessings(__ipc.ServerContext) (map[security.BlessingPattern]security.WireBlessings, error)
BlessingStoreDebugString(__ipc.ServerContext) (string, error)
BlessingRootsAdd(ctx __ipc.ServerContext, root []byte, pattern security.BlessingPattern) error
BlessingRootsRecognized(ctx __ipc.ServerContext, root []byte, blessing string) error
@@ -308,6 +347,14 @@
return s.impl.PublicKey(ctx)
}
+func (s implAgentServerStub) BlessingsByName(ctx __ipc.ServerContext, i0 security.BlessingPattern) ([]security.WireBlessings, error) {
+ return s.impl.BlessingsByName(ctx, i0)
+}
+
+func (s implAgentServerStub) BlessingsInfo(ctx __ipc.ServerContext, i0 security.WireBlessings) ([]string, error) {
+ return s.impl.BlessingsInfo(ctx, i0)
+}
+
func (s implAgentServerStub) AddToRoots(ctx __ipc.ServerContext, i0 security.WireBlessings) error {
return s.impl.AddToRoots(ctx, i0)
}
@@ -328,6 +375,10 @@
return s.impl.BlessingStoreDefault(ctx)
}
+func (s implAgentServerStub) BlessingStorePeerBlessings(ctx __ipc.ServerContext) (map[security.BlessingPattern]security.WireBlessings, error) {
+ return s.impl.BlessingStorePeerBlessings(ctx)
+}
+
func (s implAgentServerStub) BlessingStoreDebugString(ctx __ipc.ServerContext) (string, error) {
return s.impl.BlessingStoreDebugString(ctx)
}
@@ -415,6 +466,26 @@
},
},
{
+ Name: "BlessingsByName",
+ InArgs: []__ipc.ArgDesc{
+ {"name", ``}, // security.BlessingPattern
+ },
+ OutArgs: []__ipc.ArgDesc{
+ {"", ``}, // []security.WireBlessings
+ {"", ``}, // error
+ },
+ },
+ {
+ Name: "BlessingsInfo",
+ InArgs: []__ipc.ArgDesc{
+ {"blessings", ``}, // security.WireBlessings
+ },
+ OutArgs: []__ipc.ArgDesc{
+ {"", ``}, // []string
+ {"", ``}, // error
+ },
+ },
+ {
Name: "AddToRoots",
InArgs: []__ipc.ArgDesc{
{"blessing", ``}, // security.WireBlessings
@@ -461,6 +532,13 @@
},
},
{
+ Name: "BlessingStorePeerBlessings",
+ OutArgs: []__ipc.ArgDesc{
+ {"", ``}, // map[security.BlessingPattern]security.WireBlessings
+ {"", ``}, // error
+ },
+ },
+ {
Name: "BlessingStoreDebugString",
OutArgs: []__ipc.ArgDesc{
{"", ``}, // string
@@ -579,6 +657,13 @@
{Name: "", Type: 75},
},
}
+ result.Methods["BlessingStorePeerBlessings"] = __ipc.MethodSignature{
+ InArgs: []__ipc.MethodArgument{},
+ OutArgs: []__ipc.MethodArgument{
+ {Name: "", Type: 79},
+ {Name: "", Type: 75},
+ },
+ }
result.Methods["BlessingStoreSet"] = __ipc.MethodSignature{
InArgs: []__ipc.MethodArgument{
{Name: "blessings", Type: 74},
@@ -597,6 +682,24 @@
{Name: "", Type: 75},
},
}
+ result.Methods["BlessingsByName"] = __ipc.MethodSignature{
+ InArgs: []__ipc.MethodArgument{
+ {Name: "name", Type: 77},
+ },
+ OutArgs: []__ipc.MethodArgument{
+ {Name: "", Type: 78},
+ {Name: "", Type: 75},
+ },
+ }
+ result.Methods["BlessingsInfo"] = __ipc.MethodSignature{
+ InArgs: []__ipc.MethodArgument{
+ {Name: "blessings", Type: 74},
+ },
+ OutArgs: []__ipc.MethodArgument{
+ {Name: "", Type: 61},
+ {Name: "", Type: 75},
+ },
+ }
result.Methods["MintDischarge"] = __ipc.MethodSignature{
InArgs: []__ipc.MethodArgument{
{Name: "tp", Type: 76},
@@ -652,7 +755,7 @@
__wiretype.FieldType{Type: 0x49, Name: "CertificateChains"},
},
"veyron.io/veyron/veyron2/security.WireBlessings", []string(nil)},
- __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x1, Name: "anydata", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "veyron.io/veyron/veyron2/security.BlessingPattern", Tags: []string(nil)}}
+ __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x1, Name: "anydata", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "veyron.io/veyron/veyron2/security.BlessingPattern", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x4a, Name: "", Tags: []string(nil)}, __wiretype.MapType{Key: 0x4d, Elem: 0x4a, Name: "", Tags: []string(nil)}}
return result, nil
}
diff --git a/security/audit/principal.go b/security/audit/principal.go
index efd1323..c37a8d7 100644
--- a/security/audit/principal.go
+++ b/security/audit/principal.go
@@ -55,6 +55,14 @@
return d, nil
}
+func (p *auditingPrincipal) BlessingsByName(name security.BlessingPattern) []security.Blessings {
+ return p.principal.BlessingsByName(name)
+}
+
+func (p *auditingPrincipal) BlessingsInfo(b security.Blessings) []string {
+ return p.principal.BlessingsInfo(b)
+}
+
func (p *auditingPrincipal) PublicKey() security.PublicKey { return p.principal.PublicKey() }
func (p *auditingPrincipal) Roots() security.BlessingRoots { return p.principal.Roots() }
func (p *auditingPrincipal) BlessingStore() security.BlessingStore { return p.principal.BlessingStore() }
diff --git a/security/audit/principal_test.go b/security/audit/principal_test.go
index 487154f..00b885e 100644
--- a/security/audit/principal_test.go
+++ b/security/audit/principal_test.go
@@ -162,6 +162,14 @@
return d, p.NextError
}
+func (p *mockPrincipal) BlessingsByName(name security.BlessingPattern) []security.Blessings {
+ return nil
+}
+
+func (p *mockPrincipal) BlessingsInfo(b security.Blessings) []string {
+ return nil
+}
+
func (p *mockPrincipal) PublicKey() security.PublicKey { return p.NextResult.(security.PublicKey) }
func (p *mockPrincipal) Roots() security.BlessingRoots { return nil }
func (p *mockPrincipal) BlessingStore() security.BlessingStore { return nil }
diff --git a/security/blessingstore.go b/security/blessingstore.go
index be3449b..fd004e6 100644
--- a/security/blessingstore.go
+++ b/security/blessingstore.go
@@ -135,6 +135,14 @@
return fmt.Sprintf("{state: %v, publicKey: %v}", bs.state, bs.publicKey)
}
+func (bs *blessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
+ m := make(map[security.BlessingPattern]security.Blessings)
+ for pattern, wb := range bs.state.Store {
+ m[pattern] = wb.Blessings()
+ }
+ return m
+}
+
// DebugString return a human-readable string encoding of the store
// in the following format
// Default blessing : <Default blessing of the store>
diff --git a/security/blessingstore_test.go b/security/blessingstore_test.go
index fd535d8..be7824f 100644
--- a/security/blessingstore_test.go
+++ b/security/blessingstore_test.go
@@ -30,11 +30,19 @@
{t.forAll, "...foo", "invalid BlessingPattern"},
{t.forAll, "foo/.../bar", "invalid BlessingPattern"},
}
+ added := make(map[security.BlessingPattern]security.Blessings)
for _, d := range testdata {
_, err := s.Set(d.blessings, d.pattern)
if merr := matchesError(err, d.wantErr); merr != nil {
return fmt.Errorf("Set(%v, %q): %v", d.blessings, d.pattern, merr)
}
+ if err == nil {
+ added[d.pattern] = d.blessings
+ }
+ }
+ m := s.PeerBlessings()
+ if !reflect.DeepEqual(added, m) {
+ return fmt.Errorf("PeerBlessings(%v) != added(%v)", m, added)
}
return nil
}
diff --git a/security/principal_test.go b/security/principal_test.go
index eb72f43..5f2d08c 100644
--- a/security/principal_test.go
+++ b/security/principal_test.go
@@ -7,7 +7,10 @@
"io/ioutil"
"os"
"path"
+ "reflect"
"testing"
+
+ "veyron.io/veyron/veyron2/security"
)
func TestLoadPersistentPrincipal(t *testing.T) {
@@ -116,3 +119,97 @@
}
return dir
}
+
+func TestPrincipalBlessingsByName(t *testing.T) {
+ var p1, p2, p3 security.Principal
+ var err error
+
+ if p1, err = NewPrincipal(); err != nil {
+ t.Fatal(err)
+ }
+ if p2, err = NewPrincipal(); err != nil {
+ t.Fatal(err)
+ }
+ alice, err := p1.BlessSelf("alice")
+ if err != nil {
+ t.Fatal(err)
+ }
+ p2.AddToRoots(alice)
+ var aliceworkfriend, alicegymfriend, aliceworkboss security.Blessings
+
+ if aliceworkfriend, err = p1.Bless(p2.PublicKey(), alice, "work/friend", security.UnconstrainedUse()); err != nil {
+ t.Errorf("Bless(work/friend) failed: %v", err)
+ }
+ p2.BlessingStore().Set(aliceworkfriend, "alice/work/friend")
+ if alicegymfriend, err = p1.Bless(p2.PublicKey(), alice, "gym/friend", security.UnconstrainedUse()); err != nil {
+ t.Errorf("Bless(gym/friend) failed: %v", err)
+ }
+ p2.BlessingStore().Set(alicegymfriend, "alice/gym/friend")
+ if aliceworkboss, err = p1.Bless(p2.PublicKey(), alice, "work/boss", security.UnconstrainedUse()); err != nil {
+ t.Errorf("Bless(work/friend) failed: %v", err)
+ }
+ p2.BlessingStore().Set(aliceworkboss, "alice/work/boss")
+
+ // Blessing from an untrusted principal that should never be returned
+ if p3, err = NewPrincipal(); err != nil {
+ t.Fatal(err)
+ }
+ fake, err := p3.BlessSelf("alice")
+ if err != nil {
+ t.Fatal(err)
+ }
+ fakefriend, err := p3.Bless(p2.PublicKey(), fake, "work/friend", security.UnconstrainedUse())
+ if err != nil {
+ t.Errorf("Bless(work/friend) failed: %v", err)
+ }
+ _, err = p2.BlessingStore().Set(fakefriend, "fake/work/friend")
+
+ tests := []struct {
+ matched []security.Blessings
+ pattern security.BlessingPattern
+ }{
+ {
+ matched: []security.Blessings{aliceworkfriend, aliceworkboss},
+ pattern: "alice/work/...",
+ },
+ {
+ matched: []security.Blessings{aliceworkfriend},
+ pattern: "alice/work/friend",
+ },
+ {
+ matched: []security.Blessings{alicegymfriend},
+ pattern: "alice/gym/friend",
+ },
+ {
+ matched: []security.Blessings{aliceworkfriend, alicegymfriend, aliceworkboss},
+ pattern: "alice/...",
+ },
+ {
+ matched: []security.Blessings{aliceworkfriend, alicegymfriend, aliceworkboss},
+ pattern: "...",
+ },
+ {
+ matched: nil,
+ pattern: "alice/school/...",
+ },
+ }
+
+ for _, test := range tests {
+ matched := p2.BlessingsByName(test.pattern)
+ if len(matched) != len(test.matched) {
+ t.Errorf("BlessingsByName(%s) did not return expected number of matches wanted:%d got:%d", test.pattern, len(test.matched), len(matched))
+ }
+ for _, m := range matched {
+ found := false
+ for _, tm := range test.matched {
+ if reflect.DeepEqual(m, tm) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ t.Errorf("Invalid blessing was returned as a match:%v for pattern:%s", m, test.pattern)
+ }
+ }
+ }
+}