Merge "android: Save go panics to file and then send to logcat on load"
diff --git a/examples/bank/bank/main.go b/examples/bank/bank/main.go
index 92228f6..1145486 100644
--- a/examples/bank/bank/main.go
+++ b/examples/bank/bank/main.go
@@ -95,7 +95,7 @@
}
// Make a NewClient and update the other one. Do not close the old client; we need its connection to the Mount Table.
- client, err = runtime.NewClient(veyron2.LocalID(derivedIdentity))
+ client, err = runtime.NewClient(veyron2.LocalID(newPublicID))
if err != nil {
log.Fatalf("failed to create new client: %s\n", err)
}
diff --git a/examples/boxes/android/src/boxesp2p/main.go b/examples/boxes/android/src/boxesp2p/main.go
index 8b0b724..a4748e3 100644
--- a/examples/boxes/android/src/boxesp2p/main.go
+++ b/examples/boxes/android/src/boxesp2p/main.go
@@ -398,7 +398,7 @@
// Initialize veyron runtime and bind to the signalling server used to rendezvous with
// another peer device. TODO(gauthamt): Switch to using the nameserver for signalling.
- gs.runtime = rt.Init(veyron2.LocalID(privateID))
+ gs.runtime = rt.Init(veyron2.RuntimeID(privateID))
if gs.signalling, err = boxes.BindBoxSignalling(naming.JoinAddressName("@2@tcp@162.222.181.93:8509@08a93d90836cd94d4dc1acbe40b9048d@1@1@@", "signalling")); err != nil {
panic(fmt.Errorf("failed to bind to signalling server:%v\n", err))
}
diff --git a/examples/todos/test/util.go b/examples/todos/test/util.go
index e3555c9..9f10a45 100644
--- a/examples/todos/test/util.go
+++ b/examples/todos/test/util.go
@@ -21,7 +21,7 @@
// getRuntime initializes the veyron2.Runtime if needed, then returns it.
func getRuntime() veyron2.Runtime {
// returns Runtime if already initialized
- return rt.Init(veyron2.LocalID(security.FakePrivateID("todos")))
+ return rt.Init(veyron2.RuntimeID(security.FakePrivateID("todos")))
}
// startServer starts a store server and returns the server name as well as a
diff --git a/examples/todos/todos_init/main.go b/examples/todos/todos_init/main.go
index 6121a38..44db7c2 100644
--- a/examples/todos/todos_init/main.go
+++ b/examples/todos/todos_init/main.go
@@ -166,7 +166,7 @@
// (since only the admin can put data). The identity here matches with that
// used for server.ServerConfig.Admin in todos_stored/main.go. An alternative
// would be to relax the ACLs on the store.
- rt.Init(veyron2.LocalID(security.FakePrivateID("anonymous")))
+ rt.Init(veyron2.RuntimeID(security.FakePrivateID("anonymous")))
vlog.Infof("Binding to store on %s", storeName)
st, err := vstore.New(storeName)
diff --git a/runtimes/google/ipc/flow_test.go b/runtimes/google/ipc/flow_test.go
index 8850b21..47dfb93 100644
--- a/runtimes/google/ipc/flow_test.go
+++ b/runtimes/google/ipc/flow_test.go
@@ -9,12 +9,16 @@
"time"
_ "veyron/lib/testutil"
+ isecurity "veyron/runtimes/google/security"
+
"veyron2/ipc"
"veyron2/naming"
"veyron2/security"
"veyron2/verror"
)
+var testID = newID("test")
+
// newTestFlows returns the two ends of a bidirectional flow. Each end has its
// own bookkeeping, to allow testing of method calls.
func newTestFlows() (*testFlow, *testFlow) {
@@ -34,8 +38,8 @@
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 security.FakePublicID("test") }
-func (f *testFlow) RemoteID() security.PublicID { return security.FakePublicID("test") }
+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 }
@@ -139,3 +143,7 @@
}
}
}
+
+func init() {
+ isecurity.TrustIdentityProviders(testID)
+}
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index 9b24996..03a3d5a 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -39,8 +39,8 @@
var (
errAuthorizer = errors.New("ipc: application Authorizer denied access")
errMethod = verror.Abortedf("server returned an error")
- clientID security.PrivateID
- serverID security.PrivateID
+ clientID = newID("client")
+ serverID = newID("server")
clock = new(fakeClock)
)
@@ -259,7 +259,7 @@
func startServer(t *testing.T, serverID security.PrivateID, sm stream.Manager, ns naming.Namespace, ts interface{}) (naming.Endpoint, ipc.Server) {
vlog.VI(1).Info("InternalNewServer")
- server, err := InternalNewServer(InternalNewContext(), sm, ns, listenerID(serverID))
+ server, err := InternalNewServer(InternalNewContext(), sm, ns, vc.FixedLocalID(serverID))
if err != nil {
t.Errorf("InternalNewServer failed: %v", err)
}
@@ -327,18 +327,25 @@
}
func (b bundle) cleanup(t *testing.T) {
- stopServer(t, b.server, b.ns)
- b.client.Close()
+ if b.server != nil {
+ stopServer(t, b.server, b.ns)
+ }
+ if b.client != nil {
+ b.client.Close()
+ }
}
func createBundle(t *testing.T, clientID, serverID security.PrivateID, ts interface{}) (b bundle) {
b.sm = imanager.InternalNew(naming.FixedRoutingID(0x555555555))
b.ns = newNamespace()
- b.ep, b.server = startServer(t, serverID, b.sm, b.ns, ts)
- var err error
- b.client, err = InternalNewClient(b.sm, b.ns, veyron2.LocalID(clientID))
- if err != nil {
- t.Fatalf("InternalNewClient failed: %v", err)
+ if serverID != nil {
+ b.ep, b.server = startServer(t, serverID, b.sm, b.ns, ts)
+ }
+ if clientID != nil {
+ var err error
+ if b.client, err = InternalNewClient(b.sm, b.ns, vc.FixedLocalID(clientID)); err != nil {
+ t.Fatalf("InternalNewClient failed: %v", err)
+ }
}
return
}
@@ -352,10 +359,7 @@
}
func derive(blessor security.PrivateID, name string, caveats ...security.ServiceCaveat) security.PrivateID {
- id, err := isecurity.NewPrivateID("irrelevant")
- if err != nil {
- panic(err)
- }
+ id := newID("irrelevant")
derivedID, err := id.Derive(bless(blessor, id.PublicID(), name, caveats...))
if err != nil {
panic(err)
@@ -394,7 +398,7 @@
func TestMultipleCallsToServe(t *testing.T) {
sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
ns := newNamespace()
- server, err := InternalNewServer(InternalNewContext(), sm, ns, listenerID(serverID))
+ server, err := InternalNewServer(InternalNewContext(), sm, ns, vc.FixedLocalID(serverID))
if err != nil {
t.Errorf("InternalNewServer failed: %v", err)
}
@@ -484,7 +488,7 @@
for _, test := range tests {
name := fmt.Sprintf("(clientID:%q serverID:%q)", test.clientID, test.serverID)
_, server := startServer(t, test.serverID, mgr, ns, &testServer{})
- client, err := InternalNewClient(mgr, ns, veyron2.LocalID(test.clientID))
+ client, err := InternalNewClient(mgr, ns, vc.FixedLocalID(test.clientID))
if err != nil {
t.Errorf("%s: Client creation failed: %v", name, err)
stopServer(t, server, ns)
@@ -715,10 +719,10 @@
return fmt.Sprintf("%q RPCing %s.%s(%v)", t.clientID.PublicID(), t.name, t.method, t.args)
}
- b := createBundle(t, nil, serverID, &testServer{})
+ b := createBundle(t, nil, serverID, &testServer{}) // we only create the server, a separate client will be created for each test.
defer b.cleanup(t)
for _, test := range tests {
- client, err := InternalNewClient(b.sm, b.ns, veyron2.LocalID(test.clientID))
+ client, err := InternalNewClient(b.sm, b.ns, vc.FixedLocalID(test.clientID))
if err != nil {
t.Fatalf("InternalNewClient failed: %v", err)
}
@@ -969,7 +973,7 @@
{[]ipc.ServerOpt{veyron2.PublishFirst, veyron2.EndpointRewriteOpt("example.com")}, []string{"example.com"}},
}
for i, c := range cases {
- server, err := InternalNewServer(InternalNewContext(), sm, ns, append([]ipc.ServerOpt{listenerID(serverID)}, c.opts...)...)
+ server, err := InternalNewServer(InternalNewContext(), sm, ns, append(c.opts, vc.FixedLocalID(serverID))...)
if err != nil {
t.Errorf("InternalNewServer failed: %v", err)
continue
@@ -1102,12 +1106,12 @@
func TestProxy(t *testing.T) {
sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
ns := newNamespace()
- client, err := InternalNewClient(sm, ns, veyron2.LocalID(clientID))
+ client, err := InternalNewClient(sm, ns, vc.FixedLocalID(clientID))
if err != nil {
t.Fatal(err)
}
defer client.Close()
- server, err := InternalNewServer(InternalNewContext(), sm, ns, listenerID(serverID))
+ server, err := InternalNewServer(InternalNewContext(), sm, ns, vc.FixedLocalID(serverID))
if err != nil {
t.Fatal(err)
}
@@ -1189,7 +1193,7 @@
ns := newNamespace()
id := loadIdentityFromFile(argv[1])
isecurity.TrustIdentityProviders(id)
- server, err := InternalNewServer(InternalNewContext(), mgr, ns, listenerID(id))
+ server, err := InternalNewServer(InternalNewContext(), mgr, ns, vc.FixedLocalID(id))
if err != nil {
vlog.Fatalf("InternalNewServer failed: %v", err)
}
@@ -1225,13 +1229,6 @@
}
func init() {
- var err error
- if clientID, err = isecurity.NewPrivateID("client"); err != nil {
- vlog.Fatalf("failed isecurity.NewPrivateID: %s", err)
- }
- if serverID, err = isecurity.NewPrivateID("server"); err != nil {
- vlog.Fatalf("failed isecurity.NewPrivateID: %s", err)
- }
isecurity.TrustIdentityProviders(clientID)
isecurity.TrustIdentityProviders(serverID)
diff --git a/runtimes/google/ipc/stream/crypto/crypto_test.go b/runtimes/google/ipc/stream/crypto/crypto_test.go
index 8720ccc..84b0d76 100644
--- a/runtimes/google/ipc/stream/crypto/crypto_test.go
+++ b/runtimes/google/ipc/stream/crypto/crypto_test.go
@@ -37,8 +37,7 @@
crypter.String() // Only to test that String does not crash.
}
-func testSimple(t *testing.T, crypters func(testing.TB) (Crypter, Crypter)) {
- c1, c2 := crypters(t)
+func testSimple(t *testing.T, c1, c2 Crypter) {
// Execute String just to check that it does not crash.
c1.String()
c2.String()
@@ -63,11 +62,21 @@
t.Logf("Byte overhead of encryption: %v", overhead)
}
-func TestTLS(t *testing.T) { testSimple(t, tlsCrypters) }
-func TestBox(t *testing.T) { testSimple(t, boxCrypters) }
+func TestTLS(t *testing.T) {
+ server, client := net.Pipe()
+ c1, c2 := tlsCrypters(t, server, client)
+ testSimple(t, c1, c2)
+}
+
+func TestBox(t *testing.T) {
+ server, client := net.Pipe()
+ c1, c2 := boxCrypters(t, server, client)
+ testSimple(t, c1, c2)
+}
func TestTLSNil(t *testing.T) {
- c1, c2 := tlsCrypters(t)
+ conn1, conn2 := net.Pipe()
+ c1, c2 := tlsCrypters(t, conn1, conn2)
if t.Failed() {
return
}
@@ -89,7 +98,8 @@
// 16K (it is represented by a uint16).
// http://tools.ietf.org/html/rfc5246#section-6.2.1
const dataLen = 16384 + 1
- enc, dec := tlsCrypters(t)
+ conn1, conn2 := net.Pipe()
+ enc, dec := tlsCrypters(t, conn1, conn2)
cipher, err := enc.Encrypt(iobuf.NewSlice(make([]byte, dataLen)))
if err != nil {
t.Fatal(err)
@@ -103,8 +113,9 @@
}
}
-func tlsCrypters(t testing.TB) (Crypter, Crypter) {
- serverConn, clientConn := net.Pipe()
+type factory func(t testing.TB, server, client net.Conn) (Crypter, Crypter)
+
+func tlsCrypters(t testing.TB, serverConn, clientConn net.Conn) (Crypter, Crypter) {
crypters := make(chan Crypter)
go func() {
server, err := NewTLSServer(serverConn, iobuf.NewPool(0))
@@ -126,8 +137,7 @@
return c1, c2
}
-func boxCrypters(t testing.TB) (Crypter, Crypter) {
- serverConn, clientConn := net.Pipe()
+func boxCrypters(t testing.TB, serverConn, clientConn net.Conn) (Crypter, Crypter) {
crypters := make(chan Crypter)
for _, conn := range []net.Conn{serverConn, clientConn} {
go func(conn net.Conn) {
@@ -141,12 +151,15 @@
return <-crypters, <-crypters
}
-func benchmarkEncrypt(b *testing.B, crypters func(testing.TB) (Crypter, Crypter), size int) {
+func benchmarkEncrypt(b *testing.B, crypters factory, size int) {
plaintext := make([]byte, size)
if _, err := rand.Read(plaintext); err != nil {
b.Fatal(err)
}
- e, _ := crypters(b)
+ conn1, conn2 := net.Pipe()
+ defer conn1.Close()
+ defer conn2.Close()
+ e, _ := crypters(b, conn1, conn2)
b.SetBytes(int64(size))
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -170,12 +183,15 @@
func BenchmarkBoxEncrypt_1M(b *testing.B) { benchmarkEncrypt(b, boxCrypters, 1<<20) }
func BenchmarkBoxEncrypt_5M(b *testing.B) { benchmarkEncrypt(b, boxCrypters, 5<<20) }
-func benchmarkRoundTrip(b *testing.B, crypters func(testing.TB) (Crypter, Crypter), size int) {
+func benchmarkRoundTrip(b *testing.B, crypters factory, size int) {
plaintext := make([]byte, size)
if _, err := rand.Read(plaintext); err != nil {
b.Fatal(err)
}
- e, d := crypters(b)
+ conn1, conn2 := net.Pipe()
+ defer conn1.Close()
+ defer conn2.Close()
+ e, d := crypters(b, conn1, conn2)
b.SetBytes(int64(size))
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -201,3 +217,15 @@
func BenchmarkBoxRoundTrip_10K(b *testing.B) { benchmarkRoundTrip(b, boxCrypters, 10<<10) }
func BenchmarkBoxRoundTrip_1M(b *testing.B) { benchmarkRoundTrip(b, boxCrypters, 1<<20) }
func BenchmarkBoxRoundTrip_5M(b *testing.B) { benchmarkRoundTrip(b, boxCrypters, 5<<20) }
+
+func benchmarkSetup(b *testing.B, crypters factory) {
+ for i := 0; i < b.N; i++ {
+ conn1, conn2 := net.Pipe()
+ crypters(b, conn1, conn2)
+ conn1.Close()
+ conn2.Close()
+ }
+}
+
+func BenchmarkTLSSetup(b *testing.B) { benchmarkSetup(b, tlsCrypters) }
+func BenchmarkBoxSetup(b *testing.B) { benchmarkSetup(b, boxCrypters) }
diff --git a/runtimes/google/ipc/stream/manager/manager_test.go b/runtimes/google/ipc/stream/manager/manager_test.go
index 943a667..2e02ffb 100644
--- a/runtimes/google/ipc/stream/manager/manager_test.go
+++ b/runtimes/google/ipc/stream/manager/manager_test.go
@@ -15,14 +15,22 @@
"veyron/runtimes/google/ipc/stream/vc"
"veyron/runtimes/google/ipc/version"
inaming "veyron/runtimes/google/naming"
+ isecurity "veyron/runtimes/google/security"
- "veyron2"
"veyron2/ipc/stream"
"veyron2/naming"
"veyron2/security"
"veyron2/vlog"
)
+func newID(name string) security.PrivateID {
+ id, err := isecurity.NewPrivateID(name)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
func init() {
// The testutil package's init sets GOMAXPROCS to NumCPU. We want to
// force GOMAXPROCS to remain at 1, in order to trigger a particular
@@ -121,12 +129,11 @@
server := InternalNew(naming.FixedRoutingID(0x55555555))
client := InternalNew(naming.FixedRoutingID(0xcccccccc))
- serverID := security.FakePrivateID("server")
- clientID := security.FakePrivateID("client")
-
+ clientID := newID("client")
+ serverID := newID("server")
// VCSecurityLevel is intentionally not provided to Listen - to test
// default behavior.
- ln, ep, err := server.Listen("tcp", "localhost:0", vc.ListenerID(serverID))
+ ln, ep, err := server.Listen("tcp", "localhost:0", vc.FixedLocalID(serverID))
if err != nil {
t.Fatal(err)
}
@@ -156,7 +163,7 @@
go func() {
// VCSecurityLevel is intentionally not provided to Dial - to
// test default behavior.
- vc, err := client.Dial(ep, veyron2.LocalID(clientID))
+ vc, err := client.Dial(ep, vc.FixedLocalID(clientID))
if err != nil {
errs <- err
return
@@ -287,16 +294,14 @@
}
func TestSessionTicketCache(t *testing.T) {
- serverID := vc.ListenerID(security.FakePrivateID("TestSessionTicketCacheServer"))
server := InternalNew(naming.FixedRoutingID(0x55555555))
- _, ep, err := server.Listen("tcp", "localhost:0", serverID)
+ _, ep, err := server.Listen("tcp", "localhost:0", vc.FixedLocalID(newID("server")))
if err != nil {
t.Fatal(err)
}
- clientID := veyron2.LocalID(security.FakePrivateID("TestSessionTicketCacheClient"))
client := InternalNew(naming.FixedRoutingID(0xcccccccc))
- if _, err = client.Dial(ep, clientID); err != nil {
+ if _, err = client.Dial(ep, vc.FixedLocalID(newID("TestSessionTicketCacheClient"))); err != nil {
t.Fatalf("Dial(%q) failed: %v", ep, err)
}
@@ -314,7 +319,7 @@
// Have the server read from each flow and write to rchan.
rchan := make(chan string)
- ln, ep, err := server.Listen("tcp", "localhost:0", vc.ListenerID(security.FakePrivateID("server")))
+ ln, ep, err := server.Listen("tcp", "localhost:0", vc.FixedLocalID(newID("server")))
if err != nil {
t.Fatal(err)
}
@@ -350,7 +355,7 @@
var vcs [nVCs]stream.VC
for i := 0; i < nVCs; i++ {
var err error
- vcs[i], err = client.Dial(ep, veyron2.LocalID(security.FakePrivateID("client")))
+ vcs[i], err = client.Dial(ep, vc.FixedLocalID(newID("client")))
if err != nil {
t.Fatal(err)
}
@@ -399,7 +404,7 @@
}
go acceptLoop(ln)
- // We'd like an enpoint that contains an address that's different
+ // We'd like an endpoint that contains an address that's different
// to the one used for the connection. In practice this is awkward
// to achieve since we don't want to listen on ":0" since that will
// annoy firewalls. Instead we listen on 127.0.0.1 and we fabricate an
@@ -465,7 +470,7 @@
func runServer(argv []string) {
server := InternalNew(naming.FixedRoutingID(0x55555555))
- _, ep, err := server.Listen("tcp", argv[0], vc.ListenerID(security.FakePrivateID("server")))
+ _, ep, err := server.Listen("tcp", argv[0], vc.FixedLocalID(newID("server")))
if err != nil {
fmt.Println(err)
return
diff --git a/runtimes/google/ipc/stream/proxy/proxy.go b/runtimes/google/ipc/stream/proxy/proxy.go
index e0022d5..433ad73 100644
--- a/runtimes/google/ipc/stream/proxy/proxy.go
+++ b/runtimes/google/ipc/stream/proxy/proxy.go
@@ -31,7 +31,7 @@
type Proxy struct {
ln net.Listener
rid naming.RoutingID
- id security.PrivateID
+ id vc.LocalID
mu sync.RWMutex
servers *servermap
processes map[*process]struct{}
@@ -135,14 +135,17 @@
proxy := &Proxy{
ln: ln,
rid: rid,
- id: identity,
servers: &servermap{m: make(map[naming.RoutingID]*server)},
processes: make(map[*process]struct{}),
pubAddress: pubAddress,
}
+ if identity != nil {
+ proxy.id = vc.FixedLocalID(identity)
+ }
go proxy.listenLoop()
return proxy, nil
}
+
func (p *Proxy) listenLoop() {
proxyLog().Infof("Proxy listening on (%q, %q): %v", p.ln.Addr().Network(), p.ln.Addr(), p.Endpoint())
for {
@@ -313,7 +316,7 @@
p.routeCounters(process, m.Counters)
if vcObj != nil {
server := &server{Process: process, VC: vcObj}
- go p.runServer(server, vcObj.HandshakeAcceptedVC(vc.ListenerID(p.id)))
+ go p.runServer(server, vcObj.HandshakeAcceptedVC(p.id))
}
break
}
diff --git a/runtimes/google/ipc/stream/proxy/proxy_test.go b/runtimes/google/ipc/stream/proxy/proxy_test.go
index c28e618..7b3e1dd 100644
--- a/runtimes/google/ipc/stream/proxy/proxy_test.go
+++ b/runtimes/google/ipc/stream/proxy/proxy_test.go
@@ -4,6 +4,7 @@
"bytes"
"fmt"
"io"
+ "reflect"
"strings"
"testing"
@@ -11,12 +12,21 @@
"veyron/runtimes/google/ipc/stream/manager"
"veyron/runtimes/google/ipc/stream/proxy"
"veyron/runtimes/google/ipc/stream/vc"
+ isecurity "veyron/runtimes/google/security"
"veyron2/ipc/stream"
"veyron2/naming"
"veyron2/security"
)
+func newID(name string) security.PrivateID {
+ id, err := isecurity.NewPrivateID(name)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
func TestProxy(t *testing.T) {
// Using "tcp4" instead of "tcp" because the latter can end up with
// IPv6 addresses and our Google Compute Engine integration test
@@ -110,7 +120,8 @@
}
func TestProxyIdentity(t *testing.T) {
- proxy, err := proxy.New(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), security.FakePrivateID("proxy"), "tcp4", "127.0.0.1:0", "")
+ proxyID := newID("proxy")
+ proxy, err := proxy.New(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), proxyID, "tcp4", "127.0.0.1:0", "")
if err != nil {
t.Fatal(err)
}
@@ -128,7 +139,7 @@
if err != nil {
t.Fatal(err)
}
- if got, want := fmt.Sprintf("%v", flow.RemoteID()), "fake/proxy"; got != want {
+ if got, want := fmt.Sprintf("%v", flow.RemoteID()), fmt.Sprintf("%v", proxyID.PublicID()); got != want {
t.Errorf("Proxy has identity %q want %q", flow.RemoteID(), want)
}
}
@@ -141,8 +152,11 @@
server := manager.InternalNew(naming.FixedRoutingID(0x5555555555555555))
defer server.Shutdown()
- serverID := security.FakePrivateID("server")
- ln, ep, err := server.Listen(proxy.Endpoint().Network(), proxy.Endpoint().String(), vc.ListenerID(serverID))
+ serverID := newID("server")
+ if err != nil {
+ t.Fatal(err)
+ }
+ ln, ep, err := server.Listen(proxy.Endpoint().Network(), proxy.Endpoint().String(), vc.FixedLocalID(serverID))
if err != nil {
t.Fatal(err)
}
@@ -165,7 +179,7 @@
if err != nil {
t.Fatal(err)
}
- if got, want := fmt.Sprintf("%v", flow.RemoteID()), "fake/server"; got != want {
+ if got, want := flow.RemoteID(), serverID.PublicID(); !reflect.DeepEqual(got, want) {
t.Errorf("Got %q want %q", got, want)
}
}
diff --git a/runtimes/google/ipc/stream/vc/auth.go b/runtimes/google/ipc/stream/vc/auth.go
index 0378b31..0d4b094 100644
--- a/runtimes/google/ipc/stream/vc/auth.go
+++ b/runtimes/google/ipc/stream/vc/auth.go
@@ -21,15 +21,19 @@
)
// authenticateAsServer executes the authentication protocol at the server and
-// returns the identity of the client.
-func authenticateAsServer(conn io.ReadWriteCloser, serverID security.PrivateID, crypter crypto.Crypter) (clientID security.PublicID, err error) {
+// returns the identity of the client and server.
+func authenticateAsServer(conn io.ReadWriteCloser, localID LocalID, crypter crypto.Crypter) (clientID, serverID security.PublicID, err error) {
// The authentication protocol has the server doing the final read, so
// it is the one that closes the connection.
defer conn.Close()
- if err = writeIdentity(conn, serverChannelEnd, crypter, serverID); err != nil {
+ if serverID, err = localID.AsServer(); err != nil {
return
}
- return readIdentity(conn, clientChannelEnd, crypter)
+ if err = writeIdentity(conn, serverChannelEnd, crypter, localID, serverID); err != nil {
+ return
+ }
+ clientID, err = readIdentity(conn, clientChannelEnd, crypter)
+ return
}
// authenticateAsClient executes the authentication protocol at the client and
@@ -37,12 +41,17 @@
//
// If serverName is non-nil, the authentication protocol will be considered
// successfull iff the server identity matches the provided regular expression.
-func authenticateAsClient(conn io.ReadWriteCloser, clientID security.PrivateID, crypter crypto.Crypter) (serverID security.PublicID, err error) {
+func authenticateAsClient(conn io.ReadWriteCloser, localID LocalID, crypter crypto.Crypter) (serverID, clientID security.PublicID, err error) {
defer conn.Close()
if serverID, err = readIdentity(conn, serverChannelEnd, crypter); err != nil {
return
}
- err = writeIdentity(conn, clientChannelEnd, crypter, clientID)
+ // TODO(ashankar,ataly): Have the ability to avoid talking to a server we do not want to.
+ // Will require calling Authorize on the server id?
+ if clientID, err = localID.AsClient(serverID); err != nil {
+ return
+ }
+ err = writeIdentity(conn, clientChannelEnd, crypter, localID, clientID)
return
}
@@ -64,7 +73,7 @@
errSingleCertificateRequired = errors.New("exactly one X.509 certificate chain with exactly one certificate is required")
)
-func writeIdentity(w io.Writer, chEnd string, enc crypto.Encrypter, id security.PrivateID) error {
+func writeIdentity(w io.Writer, chEnd string, enc crypto.Encrypter, id LocalID, pub security.PublicID) error {
// Compute channel id - encrypted chEnd string
chid, err := enc.Encrypt(iobuf.NewSlice([]byte(chEnd)))
if err != nil {
@@ -74,7 +83,7 @@
// VOM-encode and encrypt the (public) identity.
var buf bytes.Buffer
- if err := vom.NewEncoder(&buf).Encode(id.PublicID()); err != nil {
+ if err := vom.NewEncoder(&buf).Encode(pub); err != nil {
return err
}
eid, err := enc.Encrypt(iobuf.NewSlice(buf.Bytes()))
diff --git a/runtimes/google/ipc/stream/vc/init.go b/runtimes/google/ipc/stream/vc/init.go
new file mode 100644
index 0000000..a801353
--- /dev/null
+++ b/runtimes/google/ipc/stream/vc/init.go
@@ -0,0 +1,17 @@
+package vc
+
+import (
+ isecurity "veyron/runtimes/google/security"
+
+ "veyron2/security"
+ "veyron2/vlog"
+)
+
+var anonymousID security.PrivateID
+
+func init() {
+ var err error
+ if anonymousID, err = isecurity.NewPrivateID("anonymous"); err != nil {
+ vlog.Fatalf("could create anonymousID for IPCs: %s", err)
+ }
+}
diff --git a/runtimes/google/ipc/stream/vc/listener_test.go b/runtimes/google/ipc/stream/vc/listener_test.go
index a449242..a621b97 100644
--- a/runtimes/google/ipc/stream/vc/listener_test.go
+++ b/runtimes/google/ipc/stream/vc/listener_test.go
@@ -5,12 +5,24 @@
"testing"
"time"
+ isecurity "veyron/runtimes/google/security"
+
"veyron2/naming"
"veyron2/security"
)
+var testID = newID("test")
+
type noopFlow struct{}
+func newID(name string) security.PrivateID {
+ id, err := isecurity.NewPrivateID(name)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
// net.Conn methods
func (*noopFlow) Read([]byte) (int, error) { return 0, nil }
func (*noopFlow) Write([]byte) (int, error) { return 0, nil }
@@ -27,8 +39,8 @@
func (*noopFlow) SetWriteDeadline(t time.Time) error { return nil }
// Other stream.Flow methods
-func (*noopFlow) LocalID() security.PublicID { return security.FakePublicID("test") }
-func (*noopFlow) RemoteID() security.PublicID { return security.FakePublicID("test") }
+func (*noopFlow) LocalID() security.PublicID { return testID.PublicID() }
+func (*noopFlow) RemoteID() security.PublicID { return testID.PublicID() }
func TestListener(t *testing.T) {
ln := newListener()
diff --git a/runtimes/google/ipc/stream/vc/vc.go b/runtimes/google/ipc/stream/vc/vc.go
index 09d719d..7f70721 100644
--- a/runtimes/google/ipc/stream/vc/vc.go
+++ b/runtimes/google/ipc/stream/vc/vc.go
@@ -90,27 +90,48 @@
Helper Helper
}
-// ListenerIDOpt is the interface for providing an identity to an ipc.StreamListener.
-type ListenerIDOpt interface {
+// LocalID is the interface for providing a PrivateID and a PublicIDStore to
+// be used at the local end of VCs.
+type LocalID interface {
stream.ListenerOpt
- // Identity returns the identity to be used by the ipc.StreamListener.
- Identity() security.PrivateID
+ stream.VCOpt
+ // Sign signs an arbitrary length message (often the hash of a larger message)
+ // using a private key.
+ Sign(message []byte) (security.Signature, error)
+
+ // AsClient returns a PublicID to be used while authenticating as a client to the
+ // provided server as a client. An error is returned if no such PublicID can be returned.
+ AsClient(server security.PublicID) (security.PublicID, error)
+
+ // AsServer returns a PublicID to be used while authenticating as a server to other
+ // clients. An error is returned if no such PublicID can be returned.
+ AsServer() (security.PublicID, error)
+ IPCClientOpt()
+ IPCServerOpt()
}
-// listenerIDOpt implements ListenerIDOpt.
-type listenerIDOpt struct {
- id security.PrivateID
+// fixedLocalID implements vc.LocalID.
+type fixedLocalID struct {
+ security.PrivateID
}
-func (opt *listenerIDOpt) Identity() security.PrivateID {
- return opt.id
+func (f fixedLocalID) AsClient(security.PublicID) (security.PublicID, error) {
+ return f.PrivateID.PublicID(), nil
}
-func (*listenerIDOpt) IPCStreamListenerOpt() {}
+func (f fixedLocalID) AsServer() (security.PublicID, error) {
+ return f.PrivateID.PublicID(), nil
+}
-// ListenerID provides an implementation of ListenerIDOpt with a fixed identity.
-func ListenerID(id security.PrivateID) ListenerIDOpt {
- return &listenerIDOpt{id}
+func (fixedLocalID) IPCStreamListenerOpt() {}
+func (fixedLocalID) IPCStreamVCOpt() {}
+func (fixedLocalID) IPCClientOpt() {}
+func (fixedLocalID) IPCServerOpt() {}
+
+// FixedLocalID creates a LocalID using the provided PrivateID. The
+// provided PrivateID must always be non-nil.
+func FixedLocalID(id security.PrivateID) LocalID {
+ return fixedLocalID{id}
}
// InternalNew creates a new VC, which implements the stream.VC interface.
@@ -347,13 +368,13 @@
// authentication etc.) under the assumption that the VC was initiated by the
// local process (i.e., the local process "Dial"ed to create the VC).
func (vc *VC) HandshakeDialedVC(opts ...stream.VCOpt) error {
- var localID security.PrivateID
+ var localID LocalID
var tlsSessionCache tls.ClientSessionCache
var securityLevel veyron2.VCSecurityLevel
for _, o := range opts {
switch v := o.(type) {
- case veyron2.LocalIDOpt:
- localID = v.PrivateID
+ case LocalID:
+ localID = v
case veyron2.VCSecurityLevel:
securityLevel = v
case crypto.TLSClientSessionCache:
@@ -362,7 +383,9 @@
}
switch securityLevel {
case veyron2.VCSecurityConfidential:
- localID = anonymousIfNilPrivateID(localID)
+ if localID == nil {
+ localID = FixedLocalID(anonymousID)
+ }
case veyron2.VCSecurityNone:
return nil
default:
@@ -394,7 +417,7 @@
if err != nil {
return vc.err(fmt.Errorf("failed to create a Flow for authentication: %v", err))
}
- remoteID, err := authenticateAsClient(authConn, localID, crypter)
+ rID, lID, err := authenticateAsClient(authConn, localID, crypter)
if err != nil {
return vc.err(fmt.Errorf("authentication failed: %v", err))
}
@@ -403,11 +426,11 @@
vc.handshakeFID = handshakeFID
vc.authFID = authFID
vc.crypter = crypter
- vc.localID = localID.PublicID()
- vc.remoteID = remoteID
+ vc.localID = lID
+ vc.remoteID = rID
vc.mu.Unlock()
- vlog.VI(1).Infof("Client VC %v authenticated. RemoteID:%v LocalID:%v", vc, remoteID, localID)
+ vlog.VI(1).Infof("Client VC %v authenticated. RemoteID:%v LocalID:%v", vc, rID, lID)
return nil
}
@@ -430,12 +453,12 @@
result <- HandshakeResult{ln, err}
return result
}
- var localID security.PrivateID
+ var localID LocalID
var securityLevel veyron2.VCSecurityLevel
for _, o := range opts {
switch v := o.(type) {
- case ListenerIDOpt:
- localID = v.Identity()
+ case LocalID:
+ localID = v
case veyron2.VCSecurityLevel:
securityLevel = v
}
@@ -450,7 +473,9 @@
vc.helper.AddReceiveBuffers(vc.VCI(), SharedFlowID, DefaultBytesBufferedPerFlow)
switch securityLevel {
case veyron2.VCSecurityConfidential:
- localID = anonymousIfNilPrivateID(localID)
+ if localID == nil {
+ localID = FixedLocalID(anonymousID)
+ }
case veyron2.VCSecurityNone:
return finish(ln, nil)
default:
@@ -493,7 +518,7 @@
vc.mu.Lock()
vc.authFID = vc.findFlowLocked(authConn)
vc.mu.Unlock()
- remoteID, err := authenticateAsServer(authConn, localID, crypter)
+ rID, lID, err := authenticateAsServer(authConn, localID, crypter)
if err != nil {
sendErr(fmt.Errorf("Authentication failed: %v", err))
return
@@ -501,12 +526,12 @@
vc.mu.Lock()
vc.crypter = crypter
- vc.localID = localID.PublicID()
- vc.remoteID = remoteID
+ vc.localID = lID
+ vc.remoteID = rID
close(vc.acceptHandshakeDone)
vc.acceptHandshakeDone = nil
vc.mu.Unlock()
- vlog.VI(1).Infof("Server VC %v authenticated. RemoteID:%v LocalID:%v", vc, remoteID, localID)
+ vlog.VI(1).Infof("Server VC %v authenticated. RemoteID:%v LocalID:%v", vc, rID, lID)
result <- HandshakeResult{ln, nil}
}()
return result
@@ -641,15 +666,5 @@
if id != nil {
return id
}
- // TODO(ashankar): Have an Anonymous identity that also encodes the
- // public key so that changing the keys in code doesn't prevent new
- // binaries from talking to old ones.
- return security.FakePublicID("anonymous")
-}
-
-func anonymousIfNilPrivateID(id security.PrivateID) security.PrivateID {
- if id != nil {
- return id
- }
- return security.FakePrivateID("anonymous")
+ return anonymousID.PublicID()
}
diff --git a/runtimes/google/ipc/stream/vc/vc_test.go b/runtimes/google/ipc/stream/vc/vc_test.go
index ae93fd8..f1b1e2e 100644
--- a/runtimes/google/ipc/stream/vc/vc_test.go
+++ b/runtimes/google/ipc/stream/vc/vc_test.go
@@ -4,6 +4,7 @@
import (
"bytes"
+ "fmt"
"io"
"net"
"reflect"
@@ -18,6 +19,7 @@
"veyron/runtimes/google/lib/bqueue"
"veyron/runtimes/google/lib/bqueue/drrqueue"
"veyron/runtimes/google/lib/iobuf"
+ isecurity "veyron/runtimes/google/security"
"veyron2"
"veyron2/ipc/stream"
@@ -35,10 +37,18 @@
)
var (
- clientID = security.FakePrivateID("client")
- serverID = security.FakePrivateID("server")
+ clientID = newID("client")
+ serverID = newID("server")
)
+func newID(name string) security.PrivateID {
+ id, err := isecurity.NewPrivateID(name)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
// testFlowEcho writes a random string of 'size' bytes on the flow and then
// ensures that the same string is read back.
func testFlowEcho(t *testing.T, flow stream.Flow, size int) {
@@ -73,30 +83,43 @@
}
}
+func matchID(got, want security.PublicID) error {
+ if want == nil {
+ if got.Names() != nil {
+ return fmt.Errorf("got identity with names: %v, want one with names: nil", got.Names())
+ }
+ return nil
+ }
+ if g, w := got.Names(), want.Names(); !reflect.DeepEqual(got.Names(), want.Names()) {
+ return fmt.Errorf("got identity with names: %v, want one with names: %v", g, w)
+ }
+ if g, w := got.PublicKey(), want.PublicKey(); !reflect.DeepEqual(got.PublicKey(), want.PublicKey()) {
+ return fmt.Errorf("got identity with public key: %v, want one with public key: %v", g, w)
+ }
+ return nil
+}
+
func testHandshake(t *testing.T, security veyron2.VCSecurityLevel, localID, remoteID security.PublicID) {
h, vc := New(security)
flow, err := vc.Connect()
if err != nil {
t.Fatal(err)
}
- lID := flow.LocalID()
- if !reflect.DeepEqual(lID.Names(), localID.Names()) {
- t.Errorf("Client says LocalID is %q want %q", lID, localID)
+ lID, rID := flow.LocalID(), flow.RemoteID()
+ if (lID == nil) || (rID == nil) {
+ t.Error("Either the LocalID or the RemoteID of the flow is nil")
}
- rID := flow.RemoteID()
- if !reflect.DeepEqual(rID.Names(), remoteID.Names()) {
- t.Errorf("Client says RemoteID is %q want %q", rID, remoteID)
+ if err := matchID(lID, localID); err != nil {
+ t.Errorf("Client identity mismatch: %s", err)
}
- if g, w := lID.PublicKey(), localID.PublicKey(); !reflect.DeepEqual(g, w) {
- t.Errorf("Client identity public key mismatch. Got %v want %v", g, w)
- }
- if g, w := rID.PublicKey(), remoteID.PublicKey(); !reflect.DeepEqual(g, w) {
- t.Errorf("Server identity public key mismatch. Got %v want %v", g, w)
+ if err := matchID(rID, remoteID); err != nil {
+ t.Errorf("Server identity mismatch: %s", err)
}
h.Close()
}
+
func TestHandshake(t *testing.T) {
- testHandshake(t, SecurityNone, security.FakePublicID("anonymous"), security.FakePublicID("anonymous"))
+ testHandshake(t, SecurityNone, nil, nil)
}
func TestHandshakeTLS(t *testing.T) {
testHandshake(t, SecurityTLS, clientID.PublicID(), serverID.PublicID())
@@ -273,8 +296,8 @@
go clientH.pipeLoop(serverH.VC)
go serverH.pipeLoop(clientH.VC)
- c := serverH.VC.HandshakeAcceptedVC(security, vc.ListenerID(serverID))
- if err := clientH.VC.HandshakeDialedVC(security, veyron2.LocalID(clientID)); err != nil {
+ c := serverH.VC.HandshakeAcceptedVC(security, vc.FixedLocalID(serverID))
+ if err := clientH.VC.HandshakeDialedVC(security, vc.FixedLocalID(clientID)); err != nil {
panic(err)
}
hr := <-c
diff --git a/runtimes/google/ipc/stream/vif/vif_test.go b/runtimes/google/ipc/stream/vif/vif_test.go
index ab377f4..a743542 100644
--- a/runtimes/google/ipc/stream/vif/vif_test.go
+++ b/runtimes/google/ipc/stream/vif/vif_test.go
@@ -18,14 +18,21 @@
"veyron/runtimes/google/ipc/stream/vc"
"veyron/runtimes/google/ipc/stream/vif"
iversion "veyron/runtimes/google/ipc/version"
+ isecurity "veyron/runtimes/google/security"
- "veyron2"
"veyron2/ipc/stream"
"veyron2/ipc/version"
"veyron2/naming"
- "veyron2/security"
)
+func newLocalID(name string) vc.LocalID {
+ id, err := isecurity.NewPrivateID(name)
+ if err != nil {
+ panic(err)
+ }
+ return vc.FixedLocalID(id)
+}
+
func TestSingleFlowCreatedAtClient(t *testing.T) {
client, server := NewClientServer()
defer client.Close()
@@ -415,8 +422,7 @@
if client, err = vif.InternalNewDialedVIF(c1, naming.FixedRoutingID(0xc), clientVersions); err != nil {
panic(err)
}
- serverID := vc.ListenerID(security.FakePrivateID("server"))
- if server, err = vif.InternalNewAcceptedVIF(c2, naming.FixedRoutingID(0x5), serverVersions, serverID); err != nil {
+ if server, err = vif.InternalNewAcceptedVIF(c2, naming.FixedRoutingID(0x5), serverVersions, newLocalID("server")); err != nil {
panic(err)
}
return
@@ -456,8 +462,7 @@
scChan := make(chan stream.Connector)
errChan := make(chan error)
go func() {
- clientID := veyron2.LocalID(security.FakePrivateID("client"))
- vc, err := client.Dial(ep, clientID)
+ vc, err := client.Dial(ep, newLocalID("client"))
errChan <- err
vcChan <- vc
}()
diff --git a/runtimes/google/ipc/testutil_test.go b/runtimes/google/ipc/testutil_test.go
index e726013..f990ca7 100644
--- a/runtimes/google/ipc/testutil_test.go
+++ b/runtimes/google/ipc/testutil_test.go
@@ -5,7 +5,10 @@
"testing"
_ "veyron/lib/testutil"
+ "veyron/runtimes/google/ipc/stream/vc"
+ isecurity "veyron/runtimes/google/security"
+ "veyron2/ipc"
"veyron2/security"
"veyron2/verror"
)
@@ -38,19 +41,13 @@
}
}
-// listenerIDOpt implements vc.ListenerIDOpt and veyron2/ipc.ServerOpt.
-type listenerIDOpt struct {
- id security.PrivateID
+func newID(name string) security.PrivateID {
+ id, err := isecurity.NewPrivateID(name)
+ if err != nil {
+ panic(err)
+ }
+ return id
}
-func (opt *listenerIDOpt) Identity() security.PrivateID {
- return opt.id
-}
-
-func (*listenerIDOpt) IPCStreamListenerOpt() {}
-
-func (*listenerIDOpt) IPCServerOpt() {}
-
-func listenerID(id security.PrivateID) *listenerIDOpt {
- return &listenerIDOpt{id}
-}
+var _ ipc.ClientOpt = vc.FixedLocalID(newID("irrelevant"))
+var _ ipc.ServerOpt = vc.FixedLocalID(newID("irrelevant"))
diff --git a/runtimes/google/rt/ipc.go b/runtimes/google/rt/ipc.go
index 2b54fad..150bfdf 100644
--- a/runtimes/google/rt/ipc.go
+++ b/runtimes/google/rt/ipc.go
@@ -1,22 +1,81 @@
package rt
import (
+ "errors"
"fmt"
iipc "veyron/runtimes/google/ipc"
imanager "veyron/runtimes/google/ipc/stream/manager"
+ "veyron/runtimes/google/ipc/stream/vc"
"veyron2"
"veyron2/context"
"veyron2/ipc"
"veyron2/ipc/stream"
"veyron2/naming"
+ "veyron2/security"
)
+// fixedPublicIDStore implements security.PublicIDStore. It embeds a (fixed) PublicID that
+// is both the default and the PublicID to be used for any peer. Adding a new PublicID
+// to the store is disallowed, and setting the default principal-pattern is a no-op.
+type fixedPublicIDStore struct {
+ id security.PublicID
+}
+
+func (fixedPublicIDStore) Add(id security.PublicID, peerPattern security.PrincipalPattern) error {
+ return errors.New("adding new PublicIDs is disallowed for this PublicIDStore")
+}
+
+func (s fixedPublicIDStore) ForPeer(peer security.PublicID) (security.PublicID, error) {
+ return s.id, nil
+}
+
+func (s fixedPublicIDStore) DefaultPublicID() (security.PublicID, error) {
+ return s.id, nil
+}
+
+func (fixedPublicIDStore) SetDefaultPrincipalPattern(pattern security.PrincipalPattern) {}
+
+// localID is an option for passing a PrivateID and PublicIDStore
+// to a server or client.
+type localID struct {
+ id security.PrivateID
+ store security.PublicIDStore
+}
+
+func (lID *localID) Sign(message []byte) (security.Signature, error) {
+ return lID.id.Sign(message)
+}
+
+func (lID *localID) AsClient(server security.PublicID) (security.PublicID, error) {
+ return lID.store.ForPeer(server)
+}
+
+func (lID *localID) AsServer() (security.PublicID, error) {
+ return lID.store.DefaultPublicID()
+}
+
+func (*localID) IPCClientOpt() {}
+func (*localID) IPCStreamVCOpt() {}
+func (*localID) IPCServerOpt() {}
+func (*localID) IPCStreamListenerOpt() {}
+
+// newLocalID returns a localID embedding the runtime's PrivateID and a fixed
+// PublicIDStore constructed from the provided PublicID or the runtiume's PublicIDStore
+// if the provided PublicID is nil.
+func (rt *vrt) newLocalID(id security.PublicID) vc.LocalID {
+ lID := &localID{id: rt.id, store: rt.store}
+ if id != nil {
+ lID.store = fixedPublicIDStore{id}
+ }
+ return lID
+}
+
func (rt *vrt) NewClient(opts ...ipc.ClientOpt) (ipc.Client, error) {
sm := rt.sm
ns := rt.ns
- cIDOpt := veyron2.LocalID(rt.id.Identity())
+ var id security.PublicID
var otherOpts []ipc.ClientOpt
for _, opt := range opts {
switch topt := opt.(type) {
@@ -25,14 +84,14 @@
case veyron2.NamespaceOpt:
ns = topt.Namespace
case veyron2.LocalIDOpt:
- cIDOpt = topt
+ id = topt.PublicID
default:
otherOpts = append(otherOpts, opt)
}
}
- if cIDOpt.PrivateID != nil {
- otherOpts = append(otherOpts, cIDOpt)
- }
+ // Add the option that provides the local identity to the client.
+ otherOpts = append(otherOpts, rt.newLocalID(id))
+
return iipc.InternalNewClient(sm, ns, otherOpts...)
}
@@ -68,17 +127,20 @@
// Start the http debug server exactly once for this runtime.
rt.startHTTPDebugServerOnce()
ns := rt.ns
+ var id security.PublicID
var otherOpts []ipc.ServerOpt
for _, opt := range opts {
switch topt := opt.(type) {
case veyron2.NamespaceOpt:
ns = topt
+ case veyron2.LocalIDOpt:
+ id = topt.PublicID
default:
otherOpts = append(otherOpts, opt)
}
}
- // Add the option that provides the identity currently used by the runtime.
- otherOpts = append(otherOpts, rt.id)
+ // Add the option that provides the local identity to the server.
+ otherOpts = append(otherOpts, rt.newLocalID(id))
ctx := rt.NewContext()
return iipc.InternalNewServer(ctx, sm, ns, otherOpts...)
diff --git a/runtimes/google/rt/ipc_test.go b/runtimes/google/rt/ipc_test.go
new file mode 100644
index 0000000..1822541
--- /dev/null
+++ b/runtimes/google/rt/ipc_test.go
@@ -0,0 +1,188 @@
+package rt_test
+
+import (
+ "fmt"
+ "reflect"
+ "sort"
+ "testing"
+ "time"
+
+ _ "veyron/lib/testutil"
+ isecurity "veyron/runtimes/google/security"
+
+ "veyron2"
+ "veyron2/ipc"
+ "veyron2/naming"
+ "veyron2/rt"
+ "veyron2/security"
+)
+
+type testService struct{}
+
+func (*testService) EchoIDs(call ipc.ServerCall) (server, client []string) {
+ return call.LocalID().Names(), call.RemoteID().Names()
+}
+
+type S []string
+
+func newID(name string) security.PrivateID {
+ id, err := isecurity.NewPrivateID(name)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
+func bless(blessor security.PrivateID, blessee security.PublicID, name string) security.PublicID {
+ blessedID, err := blessor.Bless(blessee, name, 5*time.Minute, nil)
+ if err != nil {
+ panic(err)
+ }
+ return blessedID
+}
+
+func add(store security.PublicIDStore, id security.PublicID, pattern security.PrincipalPattern) {
+ if err := store.Add(id, pattern); err != nil {
+ panic(err)
+ }
+}
+
+func call(r veyron2.Runtime, client ipc.Client, name string) (clientNames, serverNames []string, err error) {
+ c, err := client.StartCall(r.NewContext(), name, "EchoIDs", nil)
+ if err != nil {
+ return nil, nil, err
+ }
+ if err := c.Finish(&serverNames, &clientNames); err != nil {
+ return nil, nil, err
+ }
+ sort.Strings(clientNames)
+ sort.Strings(serverNames)
+ return
+}
+
+func TestClientServerIDs(t *testing.T) {
+ stopServer := func(server ipc.Server) {
+ if err := server.Stop(); err != nil {
+ t.Fatalf("server.Stop failed: %s", err)
+ }
+ }
+ var (
+ self = newID("self")
+ google = newID("google")
+ veyron = newID("veyron")
+
+ googleGmailService = bless(google, self.PublicID(), "gmail")
+ googleYoutubeService = bless(google, self.PublicID(), "youtube")
+ veyronService = bless(veyron, self.PublicID(), "service")
+ googleGmailClient = bless(google, self.PublicID(), "gmailClient")
+ googleYoutubeClient = bless(google, self.PublicID(), "youtubeClient")
+ veyronClient = bless(veyron, self.PublicID(), "client")
+ )
+ isecurity.TrustIdentityProviders(google)
+ isecurity.TrustIdentityProviders(veyron)
+
+ serverR, err := rt.New(veyron2.RuntimeID(self))
+ if err != nil {
+ t.Fatalf("rt.New() failed: %s", err)
+ }
+ clientR, err := rt.New(veyron2.RuntimeID(self))
+ if err != nil {
+ t.Fatalf("rt.New() failed: %s", err)
+ }
+
+ // Add PublicIDs for running "google/gmail" and "google/youtube" services to
+ // serverR's PublicIDStore. Since these PublicIDs are meant to be by
+ // servers only they are tagged with "".
+ add(serverR.PublicIDStore(), googleGmailService, "")
+ add(serverR.PublicIDStore(), googleYoutubeService, "")
+ // Add PublicIDs for communicating the "google/gmail" and "google/youtube" services
+ // to the clientR's PublicIDStore.
+ add(clientR.PublicIDStore(), googleGmailClient, "google/*")
+ add(clientR.PublicIDStore(), googleYoutubeClient, "google/youtube")
+
+ type testcase struct {
+ server, client security.PublicID
+ defaultPattern security.PrincipalPattern
+ wantServerNames, wantClientNames []string
+ }
+ tests := []testcase{
+ {
+ defaultPattern: security.AllPrincipals,
+ wantServerNames: S{"self", "google/gmail", "google/youtube"},
+ wantClientNames: S{"self", "google/gmailClient", "google/youtubeClient"},
+ },
+ {
+ defaultPattern: "google/gmail",
+ wantServerNames: S{"google/gmail"},
+ wantClientNames: S{"self", "google/gmailClient"},
+ },
+ {
+ defaultPattern: "google/youtube",
+ wantServerNames: S{"google/youtube"},
+ wantClientNames: S{"self", "google/gmailClient", "google/youtubeClient"},
+ },
+ {
+ server: veyronService,
+ defaultPattern: security.AllPrincipals,
+ wantServerNames: S{"veyron/service"},
+ wantClientNames: S{"self"},
+ },
+ {
+ client: veyronClient,
+ defaultPattern: security.AllPrincipals,
+ wantServerNames: S{"self", "google/gmail", "google/youtube"},
+ wantClientNames: S{"veyron/client"},
+ },
+ {
+ server: veyronService,
+ client: veyronClient,
+ defaultPattern: security.AllPrincipals,
+ wantServerNames: S{"veyron/service"},
+ wantClientNames: S{"veyron/client"},
+ },
+ }
+ name := func(t testcase) string {
+ return fmt.Sprintf("TestCase{clientPublicIDStore: %v, serverPublicIDStore: %v, client option: %v, server option: %v}", clientR.PublicIDStore(), serverR.PublicIDStore(), t.client, t.server)
+ }
+ for _, test := range tests {
+ serverR.PublicIDStore().SetDefaultPrincipalPattern(test.defaultPattern)
+ server, err := serverR.NewServer(veyron2.LocalID(test.server))
+ if err != nil {
+ t.Errorf("serverR.NewServer(...) failed: %s", err)
+ continue
+ }
+ endpoint, err := server.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Errorf("error listening to service: ", err)
+ continue
+ }
+ defer stopServer(server)
+ if err := server.Serve("", ipc.SoloDispatcher(&testService{}, security.NewACLAuthorizer(security.ACL{security.AllPrincipals: security.AllLabels}))); err != nil {
+ t.Errorf("error serving service: ", err)
+ continue
+ }
+
+ client, err := clientR.NewClient(veyron2.LocalID(test.client))
+ if err != nil {
+ t.Errorf("clientR.NewClient(...) failed: %s", err)
+ continue
+ }
+ defer client.Close()
+
+ clientNames, serverNames, err := call(clientR, client, naming.JoinAddressName(fmt.Sprintf("%v", endpoint), ""))
+ if err != nil {
+ t.Errorf("IPC failed: %s", err)
+ continue
+ }
+ sort.Strings(test.wantClientNames)
+ sort.Strings(test.wantServerNames)
+ if !reflect.DeepEqual(clientNames, test.wantClientNames) {
+ t.Errorf("TestCase: %s, Got clientNames: %v, want: %v", name(test), clientNames, test.wantClientNames)
+ continue
+ }
+ if !reflect.DeepEqual(serverNames, test.wantServerNames) {
+ t.Errorf("TestCase: %s, Got serverNames: %v, want: %v", name(test), serverNames, test.wantServerNames)
+ continue
+ }
+ }
+}
diff --git a/runtimes/google/rt/rt.go b/runtimes/google/rt/rt.go
index 805adf4..3f4f429 100644
--- a/runtimes/google/rt/rt.go
+++ b/runtimes/google/rt/rt.go
@@ -15,6 +15,7 @@
"veyron2/ipc/stream"
"veyron2/naming"
"veyron2/product"
+ "veyron2/security"
"veyron2/vlog"
)
@@ -23,7 +24,8 @@
sm stream.Manager
ns naming.Namespace
signals chan os.Signal
- id *currentIDOpt
+ id security.PrivateID
+ store security.PublicIDStore
client ipc.Client
mgmt *mgmtImpl
debug debugServer
@@ -61,13 +63,13 @@
func (rt *vrt) init(opts ...veyron2.ROpt) error {
flag.Parse()
rt.initHTTPDebugServer()
- rt.id = ¤tIDOpt{}
nsRoots := []string{}
-
for _, o := range opts {
switch v := o.(type) {
- case veyron2.LocalIDOpt:
- rt.id.setIdentity(v.PrivateID)
+ case veyron2.RuntimeIDOpt:
+ rt.id = v.PrivateID
+ case veyron2.RuntimePublicIDStoreOpt:
+ rt.store = v
case veyron2.ProductOpt:
rt.product = v.T
case veyron2.NamespaceRoots:
@@ -123,11 +125,11 @@
return err
}
- if err = rt.initIdentity(); err != nil {
+ if err = rt.initSecurity(); err != nil {
return err
}
- if rt.client, err = rt.NewClient(veyron2.LocalID(rt.id.Identity())); err != nil {
+ if rt.client, err = rt.NewClient(); err != nil {
return err
}
diff --git a/runtimes/google/rt/security.go b/runtimes/google/rt/security.go
index b25b95d..b14babf 100644
--- a/runtimes/google/rt/security.go
+++ b/runtimes/google/rt/security.go
@@ -4,7 +4,6 @@
"fmt"
"os"
"os/user"
- "sync"
isecurity "veyron/runtimes/google/security"
@@ -12,61 +11,53 @@
"veyron2/vlog"
)
-// currentIDOpt is an option that can be used to pass the identity currently used
-// by the runtime to an ipc.Server or ipc.StreamListener.
-type currentIDOpt struct {
- id security.PrivateID
- mu sync.RWMutex
-}
-
-func (id *currentIDOpt) Identity() security.PrivateID {
- id.mu.RLock()
- defer id.mu.RUnlock()
- return id.id
-}
-
-func (id *currentIDOpt) setIdentity(newID security.PrivateID) {
- // TODO(ataly): Whenever setIdentity is invoked on the identity currently used by
- // the runtime, the following changes must also be performed:
- // * the identity provider of the new identity must be tursted.
- // * the default client used by the runtime must also be replaced with
- // a client using the new identity.
- id.mu.Lock()
- defer id.mu.Unlock()
- id.id = newID
-}
-
-func (*currentIDOpt) IPCServerOpt() {}
-
-func (*currentIDOpt) IPCStreamListenerOpt() {}
-
func (rt *vrt) NewIdentity(name string) (security.PrivateID, error) {
return isecurity.NewPrivateID(name)
}
func (rt *vrt) Identity() security.PrivateID {
- return rt.id.Identity()
+ return rt.id
+}
+
+func (rt *vrt) PublicIDStore() security.PublicIDStore {
+ return rt.store
+}
+
+func (rt *vrt) initSecurity() error {
+ if err := rt.initIdentity(); err != nil {
+ return err
+ }
+ if rt.store == nil {
+ rt.store = isecurity.NewPublicIDStore()
+ // TODO(ashankar,ataly): What should the tag for the runtime's PublicID in the
+ // runtime's store be? Below we use security.AllPrincipals but this means that
+ // the PublicID *always* gets used for any peer. This may not be desirable.
+ if err := rt.store.Add(rt.id.PublicID(), security.AllPrincipals); err != nil {
+ return fmt.Errorf("could not initialize a PublicIDStore for the runtime: %s", err)
+ }
+ }
+ // Always trust our own identity providers.
+ // TODO(ataly, ashankar): We should trust the identity providers of all PublicIDs in the store.
+ trustIdentityProviders(rt.id)
+ return nil
}
func (rt *vrt) initIdentity() error {
- if rt.id.Identity() == nil {
- var id security.PrivateID
- var err error
- if file := os.Getenv("VEYRON_IDENTITY"); len(file) > 0 {
- if id, err = loadIdentityFromFile(file); err != nil {
- return fmt.Errorf("Could not load identity from %q: %v", file, err)
- }
- } else {
- name := defaultIdentityName()
- vlog.VI(2).Infof("No identity provided to the runtime, minting one for %q", name)
- if id, err = rt.NewIdentity(name); err != nil {
- return fmt.Errorf("Could not create new identity: %v", err)
- }
- }
- rt.id.setIdentity(id)
+ if rt.id != nil {
+ return nil
}
- // Always trust our own identity providers.
- trustIdentityProviders(rt.id.Identity())
+ var err error
+ if file := os.Getenv("VEYRON_IDENTITY"); len(file) > 0 {
+ if rt.id, err = loadIdentityFromFile(file); err != nil || rt.id == nil {
+ return fmt.Errorf("Could not load identity from %q: %v", file, err)
+ }
+ } else {
+ name := defaultIdentityName()
+ vlog.VI(2).Infof("No identity provided to the runtime, minting one for %q", name)
+ if rt.id, err = rt.NewIdentity(name); err != nil || rt.id == nil {
+ return fmt.Errorf("Could not create new identity: %v", err)
+ }
+ }
return nil
}
diff --git a/services/mounttable/lib/mounttable_test.go b/services/mounttable/lib/mounttable_test.go
index e961bc5..cfea7f8 100644
--- a/services/mounttable/lib/mounttable_test.go
+++ b/services/mounttable/lib/mounttable_test.go
@@ -29,9 +29,9 @@
}
var (
- rootID = veyron2.LocalID(security.FakePrivateID("root"))
- bobID = veyron2.LocalID(security.FakePrivateID("bob"))
- aliceID = veyron2.LocalID(security.FakePrivateID("alice"))
+ rootID = veyron2.LocalID(security.FakePublicID("root"))
+ bobID = veyron2.LocalID(security.FakePublicID("bob"))
+ aliceID = veyron2.LocalID(security.FakePublicID("alice"))
)
const ttlSecs = 60 * 60
@@ -169,7 +169,12 @@
}
func newMT(t *testing.T, acl string) (ipc.Server, string) {
- r := rt.Init()
+ // It is necessary for the private key of runtime's identity and
+ // the public key of the LocalIDOpts passed to clients to correspond.
+ // Since the LocalIDOpts are FakePublicIDs, we initialize the runtime
+ // below with a FakePrivateID. (Note all FakePublicIDs and FakePrivateIDs
+ // always have corresponding public and private keys respectively.)
+ r := rt.Init(veyron2.RuntimeID(security.FakePrivateID("irrelevant")))
server, err := r.NewServer(veyron2.ServesMountTableOpt(true))
if err != nil {
boom(t, "r.NewServer: %s", err)
diff --git a/services/mounttable/lib/neighborhood_test.go b/services/mounttable/lib/neighborhood_test.go
index 471edba..4c5bbb3 100644
--- a/services/mounttable/lib/neighborhood_test.go
+++ b/services/mounttable/lib/neighborhood_test.go
@@ -25,7 +25,7 @@
func TestNeighborhood(t *testing.T) {
r := rt.Init()
- id := veyron2.LocalID(rt.R().Identity())
+ id := veyron2.LocalID(rt.R().Identity().PublicID())
vlog.Infof("TestNeighborhood")
server, err := r.NewServer()
if err != nil {
diff --git a/services/wsprd/wspr/wspr_test.go b/services/wsprd/wspr/wspr_test.go
index d03d7fa..fd697ee 100644
--- a/services/wsprd/wspr/wspr_test.go
+++ b/services/wsprd/wspr/wspr_test.go
@@ -410,9 +410,8 @@
defer rt.mounttableServer.Stop()
defer rt.proxyServer.Shutdown()
defer rt.wsp.cleanup()
-
if err != nil {
- t.Errorf("could not serve server %v", err)
+ t.Fatalf("could not serve server %v", err)
}
if len(rt.writer.stream) != 1 {