"veyron2/security": BlessingRoots and BlessingStore (part 2)
This CL hooks up BlessingRoots and BlessingStore into Principal.
It also adds additional methods to security.Context as defined
in the new security model.
Change-Id: I3aaf15fd1ded186c0fd57163f9b22806a68d65a3
diff --git a/runtimes/google/ipc/flow_test.go b/runtimes/google/ipc/flow_test.go
index ad24c2c..92a7ff3 100644
--- a/runtimes/google/ipc/flow_test.go
+++ b/runtimes/google/ipc/flow_test.go
@@ -32,20 +32,22 @@
errClose error
}
-func (f *testFlow) Read(b []byte) (int, error) { return f.r.Read(b) }
-func (f *testFlow) Write(b []byte) (int, error) { return f.w.Write(b) }
-func (f *testFlow) LocalAddr() net.Addr { return nil }
-func (f *testFlow) RemoteAddr() net.Addr { return nil }
-func (f *testFlow) LocalEndpoint() naming.Endpoint { return nil }
-func (f *testFlow) RemoteEndpoint() naming.Endpoint { return nil }
-func (f *testFlow) LocalID() security.PublicID { return testID.PublicID() }
-func (f *testFlow) RemoteID() security.PublicID { return testID.PublicID() }
-func (f *testFlow) SetReadDeadline(t time.Time) error { return nil }
-func (f *testFlow) SetWriteDeadline(t time.Time) error { return nil }
-func (f *testFlow) SetDeadline(t time.Time) error { return nil }
-func (f *testFlow) IsClosed() bool { return false }
-func (f *testFlow) Closed() <-chan struct{} { return nil }
-func (f *testFlow) Cancel() {}
+func (f *testFlow) Read(b []byte) (int, error) { return f.r.Read(b) }
+func (f *testFlow) Write(b []byte) (int, error) { return f.w.Write(b) }
+func (f *testFlow) LocalAddr() net.Addr { return nil }
+func (f *testFlow) RemoteAddr() net.Addr { return nil }
+func (f *testFlow) LocalEndpoint() naming.Endpoint { return nil }
+func (f *testFlow) RemoteEndpoint() naming.Endpoint { return nil }
+func (f *testFlow) LocalID() security.PublicID { return testID.PublicID() }
+func (f *testFlow) RemoteID() security.PublicID { return testID.PublicID() }
+func (f *testFlow) LocalPrincipal() security.Principal { return nil }
+func (f *testFlow) RemoteBlessings() security.Blessings { return nil }
+func (f *testFlow) SetReadDeadline(t time.Time) error { return nil }
+func (f *testFlow) SetWriteDeadline(t time.Time) error { return nil }
+func (f *testFlow) SetDeadline(t time.Time) error { return nil }
+func (f *testFlow) IsClosed() bool { return false }
+func (f *testFlow) Closed() <-chan struct{} { return nil }
+func (f *testFlow) Cancel() {}
func (f *testFlow) Close() error {
f.numCloseCalls++
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index d699ac7..a13910e 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -878,8 +878,10 @@
func (fs *flowServer) Suffix() string { return fs.suffix }
func (fs *flowServer) Label() security.Label { return fs.label }
-func (fs *flowServer) LocalID() security.PublicID { return fs.flow.LocalID() }
-func (fs *flowServer) RemoteID() security.PublicID { return fs.authorizedRemoteID }
-func (fs *flowServer) Blessing() security.PublicID { return fs.blessing }
-func (fs *flowServer) LocalEndpoint() naming.Endpoint { return fs.flow.LocalEndpoint() }
-func (fs *flowServer) RemoteEndpoint() naming.Endpoint { return fs.flow.RemoteEndpoint() }
+func (fs *flowServer) LocalID() security.PublicID { return fs.flow.LocalID() }
+func (fs *flowServer) RemoteID() security.PublicID { return fs.authorizedRemoteID }
+func (fs *flowServer) LocalPrincipal() security.Principal { return nil }
+func (fs *flowServer) RemoteBlessings() security.Blessings { return nil }
+func (fs *flowServer) Blessing() security.PublicID { return fs.blessing }
+func (fs *flowServer) LocalEndpoint() naming.Endpoint { return fs.flow.LocalEndpoint() }
+func (fs *flowServer) RemoteEndpoint() naming.Endpoint { return fs.flow.RemoteEndpoint() }
diff --git a/runtimes/google/ipc/stream/vc/flow.go b/runtimes/google/ipc/stream/vc/flow.go
index 9b62c4c..254fed4 100644
--- a/runtimes/google/ipc/stream/vc/flow.go
+++ b/runtimes/google/ipc/stream/vc/flow.go
@@ -20,8 +20,10 @@
RemoteID() security.PublicID
}
-func (f *flow) LocalEndpoint() naming.Endpoint { return f.localEndpoint }
-func (f *flow) RemoteEndpoint() naming.Endpoint { return f.remoteEndpoint }
+func (f *flow) LocalPrincipal() security.Principal { return nil }
+func (f *flow) RemoteBlesings() security.Blessings { return nil }
+func (f *flow) LocalEndpoint() naming.Endpoint { return f.localEndpoint }
+func (f *flow) RemoteEndpoint() naming.Endpoint { return f.remoteEndpoint }
// implement net.Conn
func (f *flow) LocalAddr() net.Addr { return f.localEndpoint }
diff --git a/runtimes/google/ipc/stream/vc/listener_test.go b/runtimes/google/ipc/stream/vc/listener_test.go
index 73020e0..c680027 100644
--- a/runtimes/google/ipc/stream/vc/listener_test.go
+++ b/runtimes/google/ipc/stream/vc/listener_test.go
@@ -42,6 +42,9 @@
func (*noopFlow) LocalID() security.PublicID { return testID.PublicID() }
func (*noopFlow) RemoteID() security.PublicID { return testID.PublicID() }
+func (*noopFlow) LocalPrincipal() security.Principal { return nil }
+func (*noopFlow) RemoteBlessings() security.Blessings { return nil }
+
func TestListener(t *testing.T) {
ln := newListener()
f1, f2 := &noopFlow{}, &noopFlow{}
diff --git a/runtimes/google/rt/blessingroots_test.go b/runtimes/google/rt/blessingroots_test.go
index 628dc73..2ce703c 100644
--- a/runtimes/google/rt/blessingroots_test.go
+++ b/runtimes/google/rt/blessingroots_test.go
@@ -7,7 +7,6 @@
"fmt"
"io/ioutil"
"os"
- "strings"
"testing"
"veyron.io/veyron/veyron2/security"
@@ -15,11 +14,11 @@
type s []string
-type tester struct {
+type rootsTester struct {
k1, k2, k3 security.PublicKey
}
-func (t *tester) testAdd(br security.BlessingRoots) error {
+func (t *rootsTester) testAdd(br security.BlessingRoots) error {
testdata := []struct {
root security.PublicKey
pattern security.BlessingPattern
@@ -36,7 +35,7 @@
return nil
}
-func (t *tester) testRecognized(br security.BlessingRoots) error {
+func (t *rootsTester) testRecognized(br security.BlessingRoots) error {
testdata := []struct {
root security.PublicKey
recognized []string
@@ -69,27 +68,17 @@
return security.NewECDSAPublicKey(&s.PublicKey)
}
-func matchesError(err error, pattern string) error {
- retErr := fmt.Errorf("got error: %v, want to match: %v", err, pattern)
- if (len(pattern) == 0) != (err == nil) {
- return retErr
- }
- if (err != nil) && (strings.Index(err.Error(), pattern) < 0) {
- return retErr
- }
- return nil
-}
-
func TestInMemoryBlessingRoots(t *testing.T) {
br := NewInMemoryBlessingRoots()
- tester := tester{mkKey(), mkKey(), mkKey()}
- if err := tester.testAdd(br); err != nil {
+ rootsTester := rootsTester{mkKey(), mkKey(), mkKey()}
+ if err := rootsTester.testAdd(br); err != nil {
t.Error(err)
}
- if err := tester.testRecognized(br); err != nil {
+ if err := rootsTester.testRecognized(br); err != nil {
t.Error(err)
}
}
+
func TestPersistingBlessingRoots(t *testing.T) {
newTempDir := func(name string) string {
dir, err := ioutil.TempDir("", name)
@@ -99,22 +88,22 @@
return dir
}
- tester := tester{mkKey(), mkKey(), mkKey()}
+ rootsTester := rootsTester{mkKey(), mkKey(), mkKey()}
// Create a new persisting BlessingRoots and add key k1 as an authority over
// blessings matching "veyron/...".
dir := newTempDir("blessingstore")
defer os.RemoveAll(dir)
- signer := newChain("signer")
+ signer := newPrincipal(t)
br, err := NewPersistingBlessingRoots(dir, signer)
if err != nil {
t.Fatalf("NewPersistingBlessingRoots failed: %s", err)
}
- if err := tester.testAdd(br); err != nil {
+ if err := rootsTester.testAdd(br); err != nil {
t.Error(err)
}
- if err := tester.testRecognized(br); err != nil {
+ if err := rootsTester.testRecognized(br); err != nil {
t.Error(err)
}
@@ -124,11 +113,7 @@
if err != nil {
t.Fatalf("NewPersistingBlessingRoots failed: %s", err)
}
-
- if err := tester.testAdd(br); err != nil {
- t.Error(err)
- }
- if err := tester.testRecognized(br); err != nil {
+ if err := rootsTester.testRecognized(br); err != nil {
t.Error(err)
}
}
diff --git a/runtimes/google/rt/blessingstore.go b/runtimes/google/rt/blessingstore.go
index a5c675c..d095530 100644
--- a/runtimes/google/rt/blessingstore.go
+++ b/runtimes/google/rt/blessingstore.go
@@ -6,7 +6,6 @@
"reflect"
"sync"
- isecurity "veyron.io/veyron/veyron/runtimes/google/security"
"veyron.io/veyron/veyron/security/serialization"
"veyron.io/veyron/veyron2/security"
@@ -21,7 +20,7 @@
var errStoreAddMismatch = errors.New("blessing's public key does not match store's public key")
type markedBlessings struct {
- Blessings security.PublicID
+ Blessings security.Blessings
Patterns []security.BlessingPattern
}
@@ -33,7 +32,7 @@
Store []markedBlessings
// Default is the default Blessings to be shared with peers for which
// no other information is available to select blessings.
- Default security.PublicID
+ Default security.Blessings
}
// blessingStore implements security.BlessingStore.
@@ -45,7 +44,7 @@
mu sync.RWMutex
}
-func (s *blessingStore) Add(blessings security.PublicID, forPeers security.BlessingPattern) error {
+func (s *blessingStore) Add(blessings security.Blessings, forPeers security.BlessingPattern) error {
if !reflect.DeepEqual(blessings.PublicKey(), s.publicKey) {
return errStoreAddMismatch
}
@@ -86,11 +85,11 @@
return nil
}
-func (s *blessingStore) ForPeer(peerBlessings ...string) security.PublicID {
+func (s *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
s.mu.RLock()
defer s.mu.RUnlock()
- var matchingBlessings []security.PublicID
+ var matchingBlessings []security.Blessings
for _, mb := range s.state.Store {
for _, p := range mb.Patterns {
if p.MatchedBy(peerBlessings...) {
@@ -100,16 +99,16 @@
}
}
- blessings, err := isecurity.NewSetPublicID(matchingBlessings...)
+ blessings, err := security.UnionOfBlessings(matchingBlessings...)
if err != nil {
// This case should never be hit.
- vlog.Errorf("BlessingStore: %s is broken, could not combine PublicIDs from it: %s", s, err)
+ vlog.Errorf("BlessingStore: %s is broken, could union Blessings obtained from it: %s", s, err)
return nil
}
return blessings
}
-func (s *blessingStore) Default() security.PublicID {
+func (s *blessingStore) Default() security.Blessings {
s.mu.RLock()
defer s.mu.RUnlock()
if s.state.Default != nil {
@@ -118,7 +117,7 @@
return s.ForPeer()
}
-func (s *blessingStore) SetDefault(blessings security.PublicID) error {
+func (s *blessingStore) SetDefault(blessings security.Blessings) error {
s.mu.Lock()
defer s.mu.Unlock()
if !reflect.DeepEqual(blessings.PublicKey(), s.publicKey) {
diff --git a/runtimes/google/rt/blessingstore_test.go b/runtimes/google/rt/blessingstore_test.go
index f071017..6699f58 100644
--- a/runtimes/google/rt/blessingstore_test.go
+++ b/runtimes/google/rt/blessingstore_test.go
@@ -2,233 +2,126 @@
import (
"bytes"
+ "fmt"
"io/ioutil"
"os"
"reflect"
- "sort"
- "strings"
"testing"
- "time"
- isecurity "veyron.io/veyron/veyron/runtimes/google/security"
"veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron2/vom"
)
-var (
- cVeyron = newChain("veyron")
- cGoogle = newChain("google")
-)
-
-func newChain(name string) security.PrivateID {
- id, err := isecurity.NewPrivateID(name, nil)
- if err != nil {
- panic(err)
- }
- return id
+type storeTester struct {
+ t *testing.T
+ bForAll, bForGoogle, bForVeyron, bDefault security.Blessings
}
-func newSetPublicID(ids ...security.PublicID) security.PublicID {
- id, err := isecurity.NewSetPublicID(ids...)
- if err != nil {
- panic(err)
- }
- return id
-}
-
-func bless(blessee security.PublicID, blessor security.PrivateID, name string, caveats []security.Caveat) security.PublicID {
- blessed, err := blessor.Bless(blessee, name, 5*time.Minute, caveats)
- if err != nil {
- panic(err)
- }
- return blessed
-}
-
-func verifyBlessingsAndPublicKey(blessings security.PublicID, wantBlessings []string, wantPublicKey security.PublicKey) bool {
- if blessings == nil {
- return len(wantBlessings) == 0
- }
- gotBlessings := blessings.Names()
- sort.Strings(gotBlessings)
- sort.Strings(wantBlessings)
- return reflect.DeepEqual(gotBlessings, wantBlessings) && reflect.DeepEqual(blessings.PublicKey(), wantPublicKey)
-}
-
-func TestStoreSetters(t *testing.T) {
- matchesErrorPattern := func(err error, pattern string) bool {
- if (len(pattern) == 0) != (err == nil) {
- return false
- }
- return err == nil || strings.Index(err.Error(), pattern) >= 0
- }
+func (t *storeTester) testAdd(s security.BlessingStore) error {
var (
- // test principals
- cAlice = newChain("alice")
- cAlicePub = cAlice.PublicID()
- cBobPub = newChain("bob").PublicID()
- cVeyronAlice = bless(cAlice.PublicID(), cVeyron, "alice", nil)
- sAlice = newSetPublicID(cAlicePub, cVeyronAlice)
-
- pkey = cAlicePub.PublicKey()
+ p = newPrincipal(t.t)
+ bOther = blessSelf(t.t, p, "irrelevant")
)
-
- s := NewInMemoryBlessingStore(pkey)
-
- testDataForAdd := []struct {
- blessings []security.PublicID
- patterns []security.BlessingPattern
+ testdata := []struct {
+ blessings security.Blessings
+ pattern security.BlessingPattern
wantErr string
}{
- {
- blessings: []security.PublicID{cAlicePub, cVeyronAlice, sAlice},
- patterns: []security.BlessingPattern{"...", "foo", "foo/bar"},
- },
- {
- blessings: []security.PublicID{cBobPub},
- patterns: []security.BlessingPattern{"...", "foo", "foo/bar"},
- wantErr: "public key does not match",
- },
- {
- blessings: []security.PublicID{cAlicePub, cVeyronAlice, sAlice},
- patterns: []security.BlessingPattern{"", "foo...", "...foo", "/bar", "foo/", "foo/.../bar"},
- wantErr: "invalid BlessingPattern",
- },
+ {t.bForAll, "...", ""},
+ {t.bForGoogle, "google/...", ""},
+ {t.bForVeyron, "veyron", ""},
+ {bOther, "...", "public key does not match"},
+ {t.bForAll, "", "invalid BlessingPattern"},
+ {t.bForAll, "foo...", "invalid BlessingPattern"},
+ {t.bForAll, "...foo", "invalid BlessingPattern"},
+ {t.bForAll, "foo/.../bar", "invalid BlessingPattern"},
}
- for _, d := range testDataForAdd {
- for _, b := range d.blessings {
- for _, p := range d.patterns {
- if got := s.Add(b, p); !matchesErrorPattern(got, d.wantErr) {
- t.Errorf("%v.Add(%v, %q): got error: %v, want to match: %q", s, b, p, got, d.wantErr)
- }
- }
+ for _, d := range testdata {
+ if err := matchesError(s.Add(d.blessings, d.pattern), d.wantErr); err != nil {
+ return fmt.Errorf("Add(%v, %q): %v", d.blessings, p, err)
}
}
- testDataForSetDefault := []struct {
- blessings []security.PublicID
+ return nil
+}
+
+func (t *storeTester) testSetDefault(s security.BlessingStore, currentDefault security.Blessings) error {
+ if got := s.Default(); !reflect.DeepEqual(got, currentDefault) {
+ return fmt.Errorf("Default(): got: %v, want: %v", got, currentDefault)
+ }
+ testdata := []struct {
+ blessings security.Blessings
wantErr string
}{
- {
- blessings: []security.PublicID{cAlicePub, cVeyronAlice, sAlice},
- },
- {
- blessings: []security.PublicID{cBobPub},
- wantErr: "public key does not match",
- },
+ {t.bDefault, ""},
+ {blessSelf(t.t, newPrincipal(t.t), "irrelevant"), "public key does not match"},
}
- for _, d := range testDataForSetDefault {
- for _, b := range d.blessings {
- if got := s.SetDefault(b); !matchesErrorPattern(got, d.wantErr) {
- t.Errorf("%v.SetDefault(%v): got error: %v, want to match: %q", s, b, got, d.wantErr)
- }
+ for _, d := range testdata {
+ if err := matchesError(s.SetDefault(d.blessings), d.wantErr); err != nil {
+ return fmt.Errorf("SetDefault(%v): %v", d.blessings, err)
+ }
+ if got, want := s.Default(), t.bDefault; !reflect.DeepEqual(got, want) {
+ return fmt.Errorf("Default(): got: %v, want: %v", got, want)
}
}
+ return nil
}
-func TestStoreGetters(t *testing.T) {
- add := func(s security.BlessingStore, blessings security.PublicID, forPeers security.BlessingPattern) {
- if err := s.Add(blessings, forPeers); err != nil {
- t.Fatalf("%v.Add(%v, %q) failed unexpectedly: %s", s, blessings, forPeers, err)
- }
- }
- var (
- // test principals
- cAlice = newChain("alice")
- cVeyronAlice = bless(cAlice.PublicID(), cVeyron, "alice", nil)
- cGoogleAlice = bless(cAlice.PublicID(), cGoogle, "alice", nil)
- sAlice = newSetPublicID(cVeyronAlice, cGoogleAlice)
-
- pkey = cAlice.PublicID().PublicKey()
- )
-
- // Create a new BlessingStore for Alice and add her blessings to it.
- s := NewInMemoryBlessingStore(pkey)
-
- add(s, cVeyronAlice, "veyron/foo/...")
- add(s, cGoogleAlice, "veyron/bar")
- add(s, sAlice, "google")
-
- // Test ForPeer
- testDataForPeer := []struct {
- peerBlessings []string
- blessings []string
+func (t *storeTester) testForPeer(s security.BlessingStore) error {
+ testdata := []struct {
+ peers []string
+ blessings security.Blessings
}{
- {nil, nil},
- {[]string{"foo"}, nil},
- {[]string{"google"}, []string{"veyron/alice", "google/alice"}},
- {[]string{"veyron"}, []string{"veyron/alice", "google/alice"}},
- {[]string{"google/foo"}, nil},
- {[]string{"veyron/baz"}, nil},
- {[]string{"veyron/foo"}, []string{"veyron/alice"}},
- {[]string{"veyron/bar"}, []string{"google/alice"}},
- {[]string{"foo", "veyron/bar"}, []string{"google/alice"}},
- {[]string{"veyron/foo/bar", "veyron/bar"}, []string{"veyron/alice", "google/alice"}},
- {[]string{"veyron/foo/bar", "veyron/bar/baz"}, []string{"veyron/alice"}},
+ {nil, t.bForAll},
+ {[]string{"foo"}, t.bForAll},
+ {[]string{"google"}, unionOfBlessings(t.t, t.bForAll, t.bForGoogle)},
+ {[]string{"veyron"}, unionOfBlessings(t.t, t.bForAll, t.bForVeyron)},
+ {[]string{"google/foo"}, unionOfBlessings(t.t, t.bForAll, t.bForGoogle)},
+ {[]string{"veyron/baz"}, t.bForAll},
+ {[]string{"google/foo/bar"}, unionOfBlessings(t.t, t.bForAll, t.bForGoogle)},
+ {[]string{"veyron/foo", "google"}, unionOfBlessings(t.t, t.bForAll, t.bForGoogle)},
+ {[]string{"veyron", "google"}, unionOfBlessings(t.t, t.bForAll, t.bForGoogle, t.bForVeyron)},
}
- for _, d := range testDataForPeer {
- if got := s.ForPeer(d.peerBlessings...); !verifyBlessingsAndPublicKey(got, d.blessings, pkey) {
- t.Errorf("%v.ForPeer(%v): got: %q, want Blessings: %q", s, d.peerBlessings, got, d.blessings)
+ for _, d := range testdata {
+ if got, want := s.ForPeer(d.peers...), d.blessings; !reflect.DeepEqual(got, want) {
+ return fmt.Errorf("ForPeer(%v): got: %v, want: %v", d.peers, got, want)
}
}
-
- // Test Default
- // Default should return nil as SetDefault has not been invoked and no blessing
- // has been marked for all peers.
- if got := s.Default(); got != nil {
- t.Errorf("%v.Default(): got: %v, want: nil", s, got)
- }
-
- // Mark the blessings: cVeyronAlice and cGoogleAlice for all peers, and check that
- // Default returns the union of those blessings
- add(s, cVeyronAlice, security.AllPrincipals)
- add(s, cGoogleAlice, security.AllPrincipals)
- defaultBlessings := []string{"veyron/alice", "google/alice"}
- if got := s.Default(); !verifyBlessingsAndPublicKey(got, defaultBlessings, pkey) {
- t.Errorf("%v.Default(): got: %v, want Blessings: %v", s, got, defaultBlessings)
- }
-
- // Set the blessing cVeyronAlice as default and check that Default returns it.
- if err := s.SetDefault(cVeyronAlice); err != nil {
- t.Fatalf("%v.SetDefault(%v) failed: %s", s, cVeyronAlice, err)
- }
- if got, want := s.Default(), cVeyronAlice; !reflect.DeepEqual(got, want) {
- t.Errorf("%v.Default(): got: %v, want: %v", s, got, want)
- }
+ return nil
}
-func TestBlessingStoreDuplicates(t *testing.T) {
- roundTrip := func(blessings security.PublicID) security.PublicID {
- var b bytes.Buffer
- if err := vom.NewEncoder(&b).Encode(blessings); err != nil {
- t.Fatalf("could not VOM-Encode Blessings: %s", err)
- }
- var decodedBlessings security.PublicID
- if err := vom.NewDecoder(&b).Decode(&decodedBlessings); err != nil {
- t.Fatalf("could not VOM-Decode Blessings: %s", err)
- }
- return decodedBlessings
- }
- add := func(s security.BlessingStore, blessings security.PublicID, forPeers security.BlessingPattern) {
- if err := s.Add(blessings, forPeers); err != nil {
- t.Fatalf("%v.Add(%v, %q) failed unexpectedly: %s", s, blessings, forPeers, err)
- }
- }
+func newStoreTester(t *testing.T) (*storeTester, security.PublicKey) {
var (
- // test principals
- cAlice = newChain("alice")
- cVeyronAlice = bless(cAlice.PublicID(), cVeyron, "alice", nil)
+ // root principals
+ v = newPrincipal(t)
+ g = newPrincipal(t)
+ veyron = blessSelf(t, v, "veyron")
+ google = blessSelf(t, g, "google")
- pkey = cAlice.PublicID().PublicKey()
+ // test principal
+ p = newPrincipal(t)
+ pkey = p.PublicKey()
)
+ s := &storeTester{
+ t: t,
+ bForAll: bless(t, v, pkey, veyron, "alice"),
+ bForGoogle: bless(t, g, pkey, google, "alice"),
+ bDefault: bless(t, g, pkey, google, "aliceDefault"),
+ }
+ s.bForVeyron = unionOfBlessings(t, s.bForAll, s.bForGoogle)
+ return s, pkey
+}
- // Create a new BlessingStore add the blessings cVeyronAlice to it twice.
+func TestInMemoryBlessingStore(t *testing.T) {
+ tester, pkey := newStoreTester(t)
s := NewInMemoryBlessingStore(pkey)
- add(s, cVeyronAlice, "google")
- add(s, roundTrip(cVeyronAlice), "google/foo")
-
- peer := "google"
- wantBlessings := []string{"veyron/alice"}
- if got := s.ForPeer(peer); !verifyBlessingsAndPublicKey(got, wantBlessings, pkey) {
- t.Errorf("%v.ForPeer(%v): got: %q, want Blessings: %q", s, peer, got, wantBlessings)
+ if err := tester.testAdd(s); err != nil {
+ t.Error(err)
+ }
+ if err := tester.testForPeer(s); err != nil {
+ t.Error(err)
+ }
+ if err := tester.testSetDefault(s, tester.bForAll); err != nil {
+ t.Error(err)
}
}
@@ -241,72 +134,70 @@
return dir
}
- var (
- signer = newChain("signer")
-
- cAlice = newChain("alice")
- cVeyronAlice = bless(cAlice.PublicID(), cVeyron, "alice", nil)
- cGoogleAlice = bless(cAlice.PublicID(), cGoogle, "alice", nil)
-
- pkey = cAlice.PublicID().PublicKey()
- )
+ tester, pkey := newStoreTester(t)
// Create a new persisting BlessingStore.
dir := newTempDir("blessingstore")
defer os.RemoveAll(dir)
-
+ signer := newPrincipal(t)
s, err := NewPersistingBlessingStore(pkey, dir, signer)
if err != nil {
- t.Fatalf("NewPersistingBlessingStore failed: %s", err)
- }
- if err := s.Add(cVeyronAlice, "veyron/..."); err != nil {
- t.Fatalf("%v.Add(%v, ...) failed: %s", s, cVeyronAlice, err)
- }
- if err := s.SetDefault(cGoogleAlice); err != nil {
- t.Fatalf("%v.SetDefault(%v) failed: %s", s, cGoogleAlice, err)
+ t.Fatalf("NewPersistingBlessingStore failed: %v", err)
}
+ if err := tester.testAdd(s); err != nil {
+ t.Error(err)
+ }
+ if err := tester.testForPeer(s); err != nil {
+ t.Error(err)
+ }
+ if err := tester.testSetDefault(s, tester.bForAll); err != nil {
+ t.Error(err)
+ }
// Test that all mutations are appropriately reflected in a BlessingStore constructed
// from same public key, directory and signer.
s, err = NewPersistingBlessingStore(pkey, dir, signer)
if err != nil {
- t.Fatalf("NewPersistingBlessingStore failed: %s", err)
+ t.Fatalf("NewPersistingBlessingStore failed: %v", err)
}
-
- if got, want := s.PublicKey(), pkey; !reflect.DeepEqual(got, want) {
- t.Errorf("%v.PublicKey(): got: %v, want: %v", s, got, want)
+ if err := tester.testForPeer(s); err != nil {
+ t.Error(err)
}
-
- testDataForPeer := []struct {
- peerBlessings []string
- blessings []string
- }{
- {peerBlessings: nil, blessings: nil},
- {peerBlessings: []string{"google"}, blessings: nil},
- {peerBlessings: []string{"veyron"}, blessings: []string{"veyron/alice"}},
- {peerBlessings: []string{"veyron/foo"}, blessings: []string{"veyron/alice"}},
- {peerBlessings: []string{"google", "veyron/foo"}, blessings: []string{"veyron/alice"}},
- }
- for _, d := range testDataForPeer {
- if got := s.ForPeer(d.peerBlessings...); !verifyBlessingsAndPublicKey(got, d.blessings, pkey) {
- t.Errorf("%v.ForPeer(%s): got: %q, want Blessings: %q", s, d.peerBlessings, got, d.blessings)
- }
- }
-
- if got, want := s.Default(), cGoogleAlice; !reflect.DeepEqual(got, want) {
- t.Errorf("%v.Default(): got: %v, want: %v", s, got, want)
- }
-
- // Test that constructing a BlesssingStore from the same directory and signer, but for a different
- // publicKey fails
- pkey = newChain("irrelevant").PublicID().PublicKey()
- _, err = NewPersistingBlessingStore(pkey, dir, signer)
- if err == nil {
- t.Fatalf("NewPersistingBlessingStore(%v, %v, %v) passed uneexpectedly", pkey, dir, signer)
+ if got, want := s.Default(), tester.bDefault; !reflect.DeepEqual(got, want) {
+ t.Fatalf("Default(): got: %v, want: %v", got, want)
}
}
-func init() {
- isecurity.TrustIdentityProviders(cVeyron)
- isecurity.TrustIdentityProviders(cGoogle)
+func TestBlessingStoreDuplicates(t *testing.T) {
+ roundTrip := func(blessings security.Blessings) security.Blessings {
+ var b bytes.Buffer
+ if err := vom.NewEncoder(&b).Encode(blessings); err != nil {
+ t.Fatalf("could not VOM-Encode Blessings: %v", err)
+ }
+ var decodedBlessings security.Blessings
+ if err := vom.NewDecoder(&b).Decode(&decodedBlessings); err != nil {
+ t.Fatalf("could not VOM-Decode Blessings: %v", err)
+ }
+ return decodedBlessings
+ }
+ add := func(s security.BlessingStore, blessings security.Blessings, forPeers security.BlessingPattern) {
+ if err := s.Add(blessings, forPeers); err != nil {
+ t.Fatalf("Add(%v, %q) failed unexpectedly: %v", blessings, forPeers, err)
+ }
+ }
+ var (
+ // root principal
+ // test blessings
+ p = newPrincipal(t)
+ alice = blessSelf(t, p, "alice")
+
+ pkey = p.PublicKey()
+ )
+ s := NewInMemoryBlessingStore(pkey)
+ add(s, alice, "...")
+ add(s, roundTrip(alice), "...")
+
+ if got, want := s.ForPeer(), alice; !reflect.DeepEqual(got, want) {
+ t.Fatalf("ForPeer(): got: %v, want: %v", got, want)
+ }
}
diff --git a/runtimes/google/rt/util_test.go b/runtimes/google/rt/util_test.go
new file mode 100644
index 0000000..7974fbe
--- /dev/null
+++ b/runtimes/google/rt/util_test.go
@@ -0,0 +1,62 @@
+package rt
+
+import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "fmt"
+ "strings"
+ "testing"
+
+ "veyron.io/veyron/veyron2/security"
+)
+
+func matchesError(got error, want string) error {
+ if (got == nil) && len(want) == 0 {
+ return nil
+ }
+ if got == nil {
+ return fmt.Errorf("Got nil error, wanted to match %q", want)
+ }
+ if !strings.Contains(got.Error(), want) {
+ return fmt.Errorf("Got error %q, wanted to match %q", got, want)
+ }
+ return nil
+}
+
+func newPrincipal(t *testing.T) security.Principal {
+ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatalf("Failed to create private key for principal: %v", err)
+ }
+ signer := security.NewInMemoryECDSASigner(key)
+ p, err := security.CreatePrincipal(signer, NewInMemoryBlessingStore(signer.PublicKey()), NewInMemoryBlessingRoots())
+ if err != nil {
+ t.Fatalf("security.CreatePrincipal failed: %v", 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 bless(t *testing.T, p security.Principal, key security.PublicKey, with security.Blessings, extension string) security.Blessings {
+ b, err := p.Bless(key, with, extension, security.UnconstrainedUse())
+ if err != nil {
+ t.Fatal(err)
+ }
+ return b
+}
+
+func unionOfBlessings(t *testing.T, blessings ...security.Blessings) security.Blessings {
+ b, err := security.UnionOfBlessings(blessings...)
+ if err != nil {
+ t.Fatal(err)
+ }
+ return b
+}
diff --git a/runtimes/google/security/identity_chain.go b/runtimes/google/security/identity_chain.go
index 2855a36..e582278 100644
--- a/runtimes/google/security/identity_chain.go
+++ b/runtimes/google/security/identity_chain.go
@@ -232,15 +232,7 @@
func (id *chainPrivateID) MintDischarge(cav security.ThirdPartyCaveat, ctx security.Context, duration time.Duration, dischargeCaveats []security.Caveat) (security.Discharge, error) {
// TODO(ashankar): HACK using new API to fit into old. This will go away anyway when we get rid of PrivateID and PublicID before release.
- principal, err := security.CreatePrincipal(id.signer)
- if err != nil {
- return nil, err
- }
- expiry, err := security.ExpiryCaveat(time.Now().Add(duration))
- if err != nil {
- return nil, err
- }
- return principal.MintDischarge(cav, ctx, expiry, dischargeCaveats...)
+ return security.MintDischargeForPrivateID(id.signer, cav, ctx, duration, dischargeCaveats)
}
func (id *chainPrivateID) Sign(message []byte) (security.Signature, error) {
diff --git a/runtimes/google/security/util.go b/runtimes/google/security/util.go
index 2d51108..812a1ba 100644
--- a/runtimes/google/security/util.go
+++ b/runtimes/google/security/util.go
@@ -29,6 +29,10 @@
// ContextArgs holds the arguments for creating a new security.Context for an IPC.
type ContextArgs struct {
+ // LocalPrincipal is the principal at the local end of a request.
+ LocalPrincipal security.Principal
+ // RemoteBlessings is the blessings held by the remote end of a request.
+ RemoteBlessings security.Blessings
// LocalID, RemoteID are the identities at the local and remote ends of a request
// respectively.
LocalID, RemoteID security.PublicID
@@ -99,6 +103,8 @@
func (c *context) Discharges() map[string]security.Discharge { return c.ContextArgs.Discharges }
func (c *context) LocalID() security.PublicID { return c.ContextArgs.LocalID }
func (c *context) RemoteID() security.PublicID { return c.ContextArgs.RemoteID }
+func (c *context) LocalPrincipal() security.Principal { return c.ContextArgs.LocalPrincipal }
+func (c *context) RemoteBlessings() security.Blessings { return c.ContextArgs.RemoteBlessings }
func (c *context) LocalEndpoint() naming.Endpoint { return c.ContextArgs.LocalEndpoint }
func (c *context) RemoteEndpoint() naming.Endpoint { return c.ContextArgs.RemoteEndpoint }
diff --git a/security/acl_authorizer_test.go b/security/acl_authorizer_test.go
index e286d8b..3d7fbfe 100644
--- a/security/acl_authorizer_test.go
+++ b/security/acl_authorizer_test.go
@@ -28,6 +28,8 @@
func (c *context) Discharges() map[string]security.Discharge { return c.discharges }
func (c *context) LocalID() security.PublicID { return c.localID }
func (c *context) RemoteID() security.PublicID { return c.remoteID }
+func (c *context) LocalPrincipal() security.Principal { return nil }
+func (c *context) RemoteBlessings() security.Blessings { return nil }
func (c *context) LocalEndpoint() naming.Endpoint { return nil }
func (c *context) RemoteEndpoint() naming.Endpoint { return nil }
diff --git a/security/audit/id_test.go b/security/audit/id_test.go
index 0af44df..d3e9bf9 100644
--- a/security/audit/id_test.go
+++ b/security/audit/id_test.go
@@ -256,6 +256,8 @@
func (context) Discharges() map[string]security.Discharge { return nil }
func (context) LocalID() security.PublicID { return nil }
func (context) RemoteID() security.PublicID { return nil }
+func (context) LocalPrincipal() security.Principal { return nil }
+func (context) RemoteBlessings() security.Blessings { return nil }
func (context) LocalEndpoint() naming.Endpoint { return nil }
func (context) RemoteEndpoint() naming.Endpoint { return nil }