ipc,naming: Servers generate V4 endpoints now.
Server.Listen and endpoints in server.Status now are in V4 format,
including the server's blessing names. These endpoints are the ones
that are published in the mounttable as well.
This allows for servers to specify their "identity" in the same string
as their "address", a fact which will be utilized in a subsequent change
to make server authentication easier - clients will not share any
information with servers which present blessings inconsistent with
the endpoint.
Change-Id: Ib84e5ccd495c84a0ab1b79849d9f882bb874db2e
diff --git a/profiles/internal/ipc/full_test.go b/profiles/internal/ipc/full_test.go
index bb39bdb..4bcbdc4 100644
--- a/profiles/internal/ipc/full_test.go
+++ b/profiles/internal/ipc/full_test.go
@@ -422,7 +422,7 @@
sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
ns := tnaming.NewSimpleNamespace()
ctx := testContext()
- server, err := testInternalNewServer(ctx, sm, ns, vc.LocalPrincipal{tsecurity.NewPrincipal()})
+ server, err := testInternalNewServer(ctx, sm, ns, vc.LocalPrincipal{tsecurity.NewPrincipal("server")})
if err != nil {
t.Errorf("InternalNewServer failed: %v", err)
}
@@ -488,7 +488,7 @@
allowedErr = "do not match any allowed server patterns"
)
var (
- pprovider, pclient, pserver = tsecurity.NewPrincipal("root"), tsecurity.NewPrincipal(), tsecurity.NewPrincipal()
+ pprovider, pclient, pserver = tsecurity.NewPrincipal("root"), tsecurity.NewPrincipal(), tsecurity.NewPrincipal("server")
pdischarger = pprovider
now = time.Now()
noErrID verror.IDAction
@@ -1263,14 +1263,6 @@
bserver = bless(pprovider, pserver, "server", tpCav)
bclient = bless(pprovider, pclient, "client")
)
-
- // Start the server and the discharger.
- _, server := startServer(t, pserver, mgr, ns, "mountpoint/server", testServerDisp{&testServer{}})
- defer stopServer(t, server, ns, "mountpoint/server")
-
- _, dischargeServer := startServer(t, pdischarger, mgr, ns, "mountpoint/dischargeserver", testutil.LeafDispatcher(&dischargeServer{}, &acceptAllAuthorizer{}))
- defer stopServer(t, dischargeServer, ns, "mountpoint/dischargeserver")
-
// Make the client and server principals trust root certificates from
// pprovider.
pclient.AddToRoots(pprovider.BlessingStore().Default())
@@ -1279,6 +1271,13 @@
// Make the server present bserver to all clients.
pserver.BlessingStore().SetDefault(bserver)
+ // Start the server and the discharger.
+ _, server := startServer(t, pserver, mgr, ns, "mountpoint/server", testServerDisp{&testServer{}})
+ defer stopServer(t, server, ns, "mountpoint/server")
+
+ _, dischargeServer := startServer(t, pdischarger, mgr, ns, "mountpoint/dischargeserver", testutil.LeafDispatcher(&dischargeServer{}, &acceptAllAuthorizer{}))
+ defer stopServer(t, dischargeServer, ns, "mountpoint/dischargeserver")
+
// Make the client present bclient to all servers that are blessed
// by pprovider.
pclient.BlessingStore().Set(bclient, "root")
@@ -1652,12 +1651,14 @@
pclient = tsecurity.NewPrincipal("client")
batman, _ = pserver.BlessSelf("batman")
)
- // Make the client recognize all server blessings
- if err := pclient.AddToRoots(batman); err != nil {
- t.Fatal(err)
- }
- if err := pclient.AddToRoots(pserver.BlessingStore().Default()); err != nil {
- t.Fatal(err)
+ // Client and server recognize the servers blessings
+ for _, p := range []security.Principal{pserver, pclient} {
+ if err := p.AddToRoots(pserver.BlessingStore().Default()); err != nil {
+ t.Fatal(err)
+ }
+ if err := p.AddToRoots(batman); err != nil {
+ t.Fatal(err)
+ }
}
// Start a server that uses the ServerBlessings option to configure itself
// to act as batman (as opposed to using the default blessing).
diff --git a/profiles/internal/ipc/proxy_test.go b/profiles/internal/ipc/proxy_test.go
index 26e243d..af1a7c3 100644
--- a/profiles/internal/ipc/proxy_test.go
+++ b/profiles/internal/ipc/proxy_test.go
@@ -35,9 +35,15 @@
ivtrace "v.io/x/ref/profiles/internal/vtrace"
)
-func testContext() *context.T {
- ctx, _ := context.WithTimeout(testContextWithoutDeadline(), 20*time.Second)
- return ctx
+func testContext() (*context.T, func()) {
+ ctx, shutdown := v23.Init()
+ ctx, _ = context.WithTimeout(ctx, 20*time.Second)
+ var err error
+ if ctx, err = ivtrace.Init(ctx, flags.VtraceFlags{}); err != nil {
+ panic(err)
+ }
+ ctx, _ = vtrace.SetNewTrace(ctx)
+ return ctx, shutdown
}
func proxyServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
@@ -84,16 +90,6 @@
return nil
}
-func testContextWithoutDeadline() *context.T {
- ctx, _ := context.RootContext()
- ctx, err := ivtrace.Init(ctx, flags.VtraceFlags{})
- if err != nil {
- panic(err)
- }
- ctx, _ = vtrace.SetNewTrace(ctx)
- return ctx
-}
-
type testServer struct{}
func (*testServer) Echo(call ipc.ServerCall, arg string) (string, error) {
@@ -169,6 +165,8 @@
}
func testProxy(t *testing.T, spec ipc.ListenSpec, args ...string) {
+ ctx, shutdown := testContext()
+ defer shutdown()
var (
pserver = tsecurity.NewPrincipal("server")
serverKey = pserver.PublicKey()
@@ -186,8 +184,8 @@
t.Fatal(err)
}
defer client.Close()
- ctx := testContext()
- server, err := iipc.InternalNewServer(ctx, smserver, ns, nil, vc.LocalPrincipal{pserver})
+ serverCtx, _ := v23.SetPrincipal(ctx, pserver)
+ server, err := iipc.InternalNewServer(serverCtx, smserver, ns, nil, vc.LocalPrincipal{pserver})
if err != nil {
t.Fatal(err)
}
@@ -199,7 +197,7 @@
name := "mountpoint/server/suffix"
makeCall := func(opts ...ipc.CallOpt) (string, error) {
- ctx, _ := context.WithDeadline(testContext(), time.Now().Add(5*time.Second))
+ ctx, _ := context.WithDeadline(ctx, time.Now().Add(5*time.Second))
// Let's fail fast so that the tests don't take as long to run.
call, err := client.StartCall(ctx, name, "Echo", []interface{}{"batman"}, opts...)
if err != nil {
@@ -266,6 +264,7 @@
t.Fatalf("unexpected error for %q: %s", proxyEP, err)
}
proxiedEP.RID = naming.FixedRoutingID(0x555555555)
+ proxiedEP.Blessings = []string{"server"}
expectedNames := []string{naming.JoinAddressName(proxiedEP.String(), "suffix")}
if hasLocalListener {
expectedNames = append(expectedNames, naming.JoinAddressName(eps[0].String(), "suffix"))
diff --git a/profiles/internal/ipc/server.go b/profiles/internal/ipc/server.go
index 7dddf07..29f133a 100644
--- a/profiles/internal/ipc/server.go
+++ b/profiles/internal/ipc/server.go
@@ -395,6 +395,7 @@
ls.ln, ls.lep, ls.lnerr = s.streamMgr.Listen(addr.Protocol, addr.Address, s.listenerOpts...)
lnState = append(lnState, ls)
if ls.lnerr != nil {
+ vlog.VI(2).Infof("Listen(%q, %q, ...) failed: %v", addr.Protocol, addr.Address, ls.lnerr)
continue
}
ls.ieps, ls.port, ls.roaming, ls.eperr = s.createEndpoints(ls.lep, listenSpec.AddressChooser)
@@ -510,7 +511,7 @@
if err != nil {
s.proxies[proxy] = proxyState{iep, verror.New(verror.ErrNoServers, s.ctx, err)}
} else {
- // err will be nill if we're stopping.
+ // err will be nil if we're stopping.
s.proxies[proxy] = proxyState{iep, nil}
s.Unlock()
return
diff --git a/profiles/internal/ipc/stream/manager/listener.go b/profiles/internal/ipc/stream/manager/listener.go
index f1a3f60..26ead00 100644
--- a/profiles/internal/ipc/stream/manager/listener.go
+++ b/profiles/internal/ipc/stream/manager/listener.go
@@ -137,10 +137,10 @@
return strings.Join(ret, "\n")
}
-func newProxyListener(m *manager, ep naming.Endpoint, opts []stream.ListenerOpt) (listener, naming.Endpoint, error) {
+func newProxyListener(m *manager, proxyEP naming.Endpoint, opts []stream.ListenerOpt) (listener, *inaming.Endpoint, error) {
ln := &proxyListener{
q: upcqueue.New(),
- proxyEP: ep,
+ proxyEP: proxyEP,
manager: m,
opts: opts,
}
@@ -152,7 +152,7 @@
return ln, ep, nil
}
-func (ln *proxyListener) connect() (*vif.VIF, naming.Endpoint, error) {
+func (ln *proxyListener) connect() (*vif.VIF, *inaming.Endpoint, error) {
vlog.VI(1).Infof("Connecting to proxy at %v", ln.proxyEP)
// Requires dialing a VC to the proxy, need to extract options (like the principal)
// from ln.opts to do so.
diff --git a/profiles/internal/ipc/stream/manager/manager.go b/profiles/internal/ipc/stream/manager/manager.go
index 515a2d8..b8e657a 100644
--- a/profiles/internal/ipc/stream/manager/manager.go
+++ b/profiles/internal/ipc/stream/manager/manager.go
@@ -11,18 +11,25 @@
"v.io/v23/ipc"
"v.io/v23/naming"
+ "v.io/v23/options"
+ "v.io/v23/security"
"v.io/v23/verror"
"v.io/x/lib/vlog"
"v.io/x/ref/lib/stats"
"v.io/x/ref/profiles/internal/ipc/stream"
"v.io/x/ref/profiles/internal/ipc/stream/crypto"
+ "v.io/x/ref/profiles/internal/ipc/stream/vc"
"v.io/x/ref/profiles/internal/ipc/stream/vif"
"v.io/x/ref/profiles/internal/ipc/version"
inaming "v.io/x/ref/profiles/internal/naming"
)
-var errShutDown = errors.New("manager has been shut down")
+var (
+ errShutDown = errors.New("manager has been shut down")
+ errProvidedServerBlessingsWithoutPrincipal = errors.New("options.ServerBlessings provided but no known principal")
+ errNoBlessingNames = errors.New("stream.ListenerOpts includes a principal but no blessing names could be extracted")
+)
// InternalNew creates a new stream.Manager for managing streams where the local
// process is identified by the provided RoutingID.
@@ -154,6 +161,19 @@
}
func (m *manager) Listen(protocol, address string, opts ...stream.ListenerOpt) (stream.Listener, naming.Endpoint, error) {
+ blessings, err := extractBlessings(opts)
+ if err != nil {
+ return nil, nil, err
+ }
+ ln, ep, err := m.internalListen(protocol, address, opts...)
+ if err != nil {
+ return nil, nil, err
+ }
+ ep.Blessings = blessings
+ return ln, ep, nil
+}
+
+func (m *manager) internalListen(protocol, address string, opts ...stream.ListenerOpt) (stream.Listener, *inaming.Endpoint, error) {
m.muListeners.Lock()
if m.shutdown {
m.muListeners.Unlock()
@@ -184,11 +204,10 @@
ln := newNetListener(m, netln, opts)
m.listeners[ln] = true
m.muListeners.Unlock()
- ep := version.Endpoint(protocol, netln.Addr().String(), m.rid)
- return ln, ep, nil
+ return ln, version.Endpoint(protocol, netln.Addr().String(), m.rid), nil
}
-func (m *manager) remoteListen(proxy naming.Endpoint, listenerOpts []stream.ListenerOpt) (stream.Listener, naming.Endpoint, error) {
+func (m *manager) remoteListen(proxy naming.Endpoint, listenerOpts []stream.ListenerOpt) (stream.Listener, *inaming.Endpoint, error) {
ln, ep, err := newProxyListener(m, proxy, listenerOpts)
if err != nil {
return nil, nil, err
@@ -278,3 +297,39 @@
}
return strings.Join(l, "\n")
}
+
+func extractBlessings(opts []stream.ListenerOpt) ([]string, error) {
+ var (
+ p security.Principal
+ b security.Blessings
+ )
+ for _, o := range opts {
+ switch v := o.(type) {
+ case vc.LocalPrincipal:
+ p = v.Principal
+ case options.ServerBlessings:
+ b = v.Blessings
+ }
+ }
+ // b is provided but not p, then that is an error (because the caller
+ // intended to provide blessings but there isn't enough information to
+ // extract it).
+ if !b.IsZero() && p == nil {
+ return nil, errProvidedServerBlessingsWithoutPrincipal
+ }
+ if p == nil {
+ return nil, nil
+ }
+ if b.IsZero() {
+ b = p.BlessingStore().Default()
+ }
+ // At this point, must have a name.
+ var ret []string
+ for b, _ := range p.BlessingsInfo(b) {
+ ret = append(ret, b)
+ }
+ if len(ret) == 0 {
+ return nil, errNoBlessingNames
+ }
+ return ret, nil
+}
diff --git a/profiles/internal/ipc/stream/manager/manager_test.go b/profiles/internal/ipc/stream/manager/manager_test.go
index 222387f..e5b6cb6 100644
--- a/profiles/internal/ipc/stream/manager/manager_test.go
+++ b/profiles/internal/ipc/stream/manager/manager_test.go
@@ -14,6 +14,7 @@
"v.io/v23/ipc"
"v.io/v23/naming"
+ "v.io/v23/options"
"v.io/v23/security"
"v.io/x/lib/vlog"
"v.io/x/ref/profiles/internal/ipc/stream"
@@ -185,6 +186,10 @@
if err != nil {
t.Fatal(err)
}
+ // And the server blessing should be in the endpoint.
+ if got, want := ep.BlessingNames(), []string{"server"}; !reflect.DeepEqual(got, want) {
+ t.Errorf("Got blessings %v from endpoint, want %v", got, want)
+ }
errs := make(chan error)
@@ -646,3 +651,57 @@
t.Fatal("expected error is missing (%v)", err)
}
}
+
+func TestBlessingNamesInEndpoint(t *testing.T) {
+ var (
+ p = newPrincipal("default")
+ b1, _ = p.Principal.BlessSelf("dev.v.io/users/foo@bar.com/devices/desktop/app/myapp")
+ b2, _ = p.Principal.BlessSelf("otherblessing")
+ b, _ = security.UnionOfBlessings(b1, b2)
+ bopt = options.ServerBlessings{b}
+
+ server = InternalNew(naming.FixedRoutingID(0x1))
+
+ tests = []struct {
+ opts []stream.ListenerOpt
+ blessings []string
+ err bool
+ }{
+ {
+ // Use the default blessings when only a principal is provided
+ opts: []stream.ListenerOpt{p},
+ blessings: []string{"default"},
+ },
+ {
+ // Respect options.ServerBlessings if provided
+ opts: []stream.ListenerOpt{p, bopt},
+ blessings: []string{"dev.v.io/users/foo@bar.com/devices/desktop/app/myapp", "otherblessing"},
+ },
+ {
+ // It is an error to provide options.ServerBlessings without vc.LocalPrincipal
+ opts: []stream.ListenerOpt{bopt},
+ err: true,
+ },
+ {
+ // It is an error to provide inconsistent options.ServerBlessings and vc.LocalPrincipal
+ opts: []stream.ListenerOpt{newPrincipal("random"), bopt},
+ err: true,
+ },
+ }
+ )
+ // p must recognize its own blessings!
+ p.AddToRoots(bopt.Blessings)
+ for idx, test := range tests {
+ ln, ep, err := server.Listen("tcp", "127.0.0.1:0", test.opts...)
+ if (err != nil) != test.err {
+ t.Errorf("test #%d: Got error %v, wanted error: %v", idx, err, test.err)
+ }
+ if err != nil {
+ continue
+ }
+ ln.Close()
+ if got, want := ep.BlessingNames(), test.blessings; !reflect.DeepEqual(got, want) {
+ t.Errorf("test #%d: Got %v, want %v", idx, got, want)
+ }
+ }
+}
diff --git a/profiles/internal/ipc/stream/proxy/proxy.go b/profiles/internal/ipc/stream/proxy/proxy.go
index aed07ca..30ba95b 100644
--- a/profiles/internal/ipc/stream/proxy/proxy.go
+++ b/profiles/internal/ipc/stream/proxy/proxy.go
@@ -345,6 +345,11 @@
// endpoint, processes can have their services exported through the proxy.
func (p *Proxy) endpoint() naming.Endpoint {
ep := version.Endpoint(p.ln.Addr().Network(), p.pubAddress, p.rid)
+ if prncpl := p.principal; prncpl != nil {
+ for b, _ := range prncpl.BlessingsInfo(prncpl.BlessingStore().Default()) {
+ ep.Blessings = append(ep.Blessings, b)
+ }
+ }
return ep
}
diff --git a/profiles/internal/ipc/stream/proxy/proxy_test.go b/profiles/internal/ipc/stream/proxy/proxy_test.go
index 960e34e..7cb86e0 100644
--- a/profiles/internal/ipc/stream/proxy/proxy_test.go
+++ b/profiles/internal/ipc/stream/proxy/proxy_test.go
@@ -114,6 +114,9 @@
t.Fatal(err)
}
defer shutdown()
+ if got, want := proxyEp.BlessingNames(), []string{"proxy"}; !reflect.DeepEqual(got, want) {
+ t.Errorf("Proxy endpoint blessing names: got %v, want %v", got, want)
+ }
other := manager.InternalNew(naming.FixedRoutingID(0xcccccccccccccccc))
defer other.Shutdown()
@@ -133,19 +136,28 @@
}
func TestServerBlessings(t *testing.T) {
- shutdown, proxyEp, err := proxy.InternalNew(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), nil, "tcp", "127.0.0.1:0", "")
+ var (
+ pproxy = tsecurity.NewPrincipal("proxy")
+ pserver = tsecurity.NewPrincipal("server")
+ )
+ shutdown, proxyEp, err := proxy.InternalNew(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), pproxy, "tcp", "127.0.0.1:0", "")
if err != nil {
t.Fatal(err)
}
defer shutdown()
+ if got, want := proxyEp.BlessingNames(), []string{"proxy"}; !reflect.DeepEqual(got, want) {
+ t.Errorf("Proxy endpoint blessing names: got %v, want %v", got, want)
+ }
server := manager.InternalNew(naming.FixedRoutingID(0x5555555555555555))
defer server.Shutdown()
- pserver := tsecurity.NewPrincipal("server")
ln, ep, err := server.Listen(proxyEp.Network(), proxyEp.String(), vc.LocalPrincipal{pserver})
if err != nil {
t.Fatal(err)
}
+ if got, want := ep.BlessingNames(), []string{"server"}; !reflect.DeepEqual(got, want) {
+ t.Errorf("Server endpoint %q: Got BlessingNames %v, want %v", ep, got, want)
+ }
defer ln.Close()
go func() {
for {
diff --git a/profiles/internal/ipc/stream/vc/vc.go b/profiles/internal/ipc/stream/vc/vc.go
index 0860870..5b64088 100644
--- a/profiles/internal/ipc/stream/vc/vc.go
+++ b/profiles/internal/ipc/stream/vc/vc.go
@@ -65,7 +65,7 @@
mu sync.Mutex
flowMap map[id.Flow]*flow // nil iff the VC is closed.
- acceptHandshakeDone chan struct{} // non-nil when HandshakeAcceptVC begins the handshake, closed when handshake completes.
+ acceptHandshakeDone chan struct{} // non-nil when HandshakeAcceptedVC begins the handshake, closed when handshake completes.
handshakeFID id.Flow // flow used for a TLS handshake to setup encryption.
authFID id.Flow // flow used by the authentication protocol.
nextConnectFID id.Flow
diff --git a/profiles/internal/ipc/stream/vif/vif.go b/profiles/internal/ipc/stream/vif/vif.go
index 19d051c..8e8c2c7 100644
--- a/profiles/internal/ipc/stream/vif/vif.go
+++ b/profiles/internal/ipc/stream/vif/vif.go
@@ -935,6 +935,21 @@
}
}
+// localEP creates a naming.Endpoint from the provided parameters.
+//
+// It intentionally does not include any blessings (present in endpoints in the
+// v4 format). At this point it is not clear whether the endpoint is being
+// created for a "client" or a "server". If the endpoint is used for clients
+// (i.e., for those sending an OpenVC message for example), then we do NOT want
+// to include the blessings in the endpoint to ensure client privacy.
+//
+// Servers should be happy to let anyone with access to their endpoint string
+// know their blessings, because they are willing to share those with anyone
+// that connects to them.
+//
+// The addition of the endpoints is left as an excercise to higher layers of
+// the stack, where the desire to share or hide blessings from the endpoint is
+// clearer.
func localEP(conn net.Conn, rid naming.RoutingID, versions *version.Range) naming.Endpoint {
localAddr := conn.LocalAddr()
ep := version.Endpoint(localAddr.Network(), localAddr.String(), rid)
diff --git a/profiles/internal/ipc/version/version.go b/profiles/internal/ipc/version/version.go
index a45d633..c36a0df 100644
--- a/profiles/internal/ipc/version/version.go
+++ b/profiles/internal/ipc/version/version.go
@@ -42,7 +42,7 @@
// Endpoint returns an endpoint with the Min/MaxIPCVersion properly filled in
// to match this implementations supported protocol versions.
-func (r *Range) Endpoint(protocol, address string, rid naming.RoutingID) naming.Endpoint {
+func (r *Range) Endpoint(protocol, address string, rid naming.RoutingID) *inaming.Endpoint {
return &inaming.Endpoint{
Protocol: protocol,
Address: address,
@@ -95,7 +95,7 @@
// ProxiedEndpoint returns an endpoint with the Min/MaxIPCVersion properly filled in
// to match the intersection of capabilities of this process and the proxy.
-func (r *Range) ProxiedEndpoint(rid naming.RoutingID, proxy naming.Endpoint) (naming.Endpoint, error) {
+func (r *Range) ProxiedEndpoint(rid naming.RoutingID, proxy naming.Endpoint) (*inaming.Endpoint, error) {
proxyEP, ok := proxy.(*inaming.Endpoint)
if !ok {
return nil, fmt.Errorf("unrecognized naming.Endpoint type %T", proxy)
diff --git a/profiles/internal/ipc/version/version_test.go b/profiles/internal/ipc/version/version_test.go
index 95222ec..ae20e20 100644
--- a/profiles/internal/ipc/version/version_test.go
+++ b/profiles/internal/ipc/version/version_test.go
@@ -68,7 +68,7 @@
MinIPCVersion: tc.proxyMin,
MaxIPCVersion: tc.proxyMax,
}
- if out, err := r.ProxiedEndpoint(rid, proxy); err != nil {
+ if ep, err := r.ProxiedEndpoint(rid, proxy); err != nil {
if !tc.expectError {
t.Errorf("Unexpected error for case %+v: %v", tc, err)
}
@@ -77,7 +77,6 @@
t.Errorf("Expected Error, but got result for test case %+v", tc)
continue
}
- ep := out.(*inaming.Endpoint)
if ep.MinIPCVersion != tc.outMin || ep.MaxIPCVersion != tc.outMax {
t.Errorf("Unexpected range for case %+v. Got (%d, %d) want (%d, %d)",
tc, ep.MinIPCVersion, ep.MaxIPCVersion, tc.outMin, tc.outMax)
diff --git a/profiles/internal/rt/ipc_test.go b/profiles/internal/rt/ipc_test.go
index cf36848..cec5f55 100644
--- a/profiles/internal/rt/ipc_test.go
+++ b/profiles/internal/rt/ipc_test.go
@@ -109,9 +109,9 @@
betaClient = mkBlessings(rootBeta.NewBlessings(pclient, "client"))
unrecognizedClient = mkBlessings(rootUnrecognized.NewBlessings(pclient, "client"))
- alphaServer = mkBlessings(rootAlpha.NewBlessings(pserver, "server"))
- betaServer = mkBlessings(rootBeta.NewBlessings(pserver, "server"))
- unrecognizedServer = mkBlessings(rootUnrecognized.NewBlessings(pserver, "server"))
+ alphaServer = mkBlessings(rootAlpha.NewBlessings(pserver, "server"))
+ betaServer = mkBlessings(rootBeta.NewBlessings(pserver, "server"))
+ selfServer = mkBlessings(pserver.BlessSelf("serverself"))
)
// Setup the client's blessing store
pclient.BlessingStore().Set(alphaClient, "alpha/server")
@@ -126,7 +126,7 @@
wantClient []string // Server's view fo the client's blessings
}{
{
- server: unrecognizedServer,
+ server: selfServer,
wantServer: nil,
wantClient: nil,
},
@@ -151,6 +151,10 @@
}
}
}
+ // And server trusts itself as a root
+ if err := pserver.AddToRoots(selfServer); err != nil {
+ t.Fatal(err)
+ }
// Let it rip!
for _, test := range tests {
if err := pserver.BlessingStore().SetDefault(test.server); err != nil {
@@ -182,6 +186,68 @@
}
}
+func TestServerEndpointBlessingNames(t *testing.T) {
+ ctx, shutdown := testutil.InitForTest()
+ defer shutdown()
+ ctx, _ = v23.SetPrincipal(ctx, tsecurity.NewPrincipal("default"))
+
+ var (
+ p = v23.GetPrincipal(ctx)
+ b1 = mkBlessings(p.BlessSelf("dev.v.io/users/foo@bar.com/devices/phone/applications/app"))
+ b2 = mkBlessings(p.BlessSelf("otherblessing"))
+ bopt = options.ServerBlessings{union(b1, b2)}
+
+ tests = []struct {
+ opts []ipc.ServerOpt
+ blessings []string
+ }{
+ {nil, []string{"default"}},
+ {[]ipc.ServerOpt{bopt}, []string{"dev.v.io/users/foo@bar.com/devices/phone/applications/app", "otherblessing"}},
+ }
+ )
+ if err := p.AddToRoots(bopt.Blessings); err != nil {
+ t.Fatal(err)
+ }
+ for idx, test := range tests {
+ server, err := v23.NewServer(ctx, test.opts...)
+ if err != nil {
+ t.Errorf("test #%d: %v", idx, err)
+ continue
+ }
+ endpoints, err := server.Listen(v23.GetListenSpec(ctx))
+ if err != nil {
+ t.Errorf("test #%d: Listen(%#v) failed with %v", idx, v23.GetListenSpec(ctx), err)
+ continue
+ }
+ if len(endpoints) == 0 {
+ t.Errorf("test #%d: No endpoints?", idx)
+ }
+ want := test.blessings
+ for _, ep := range endpoints {
+ if got := ep.BlessingNames(); !reflect.DeepEqual(got, want) {
+ t.Errorf("test #%d: endpoint=%q: Got blessings %v, want %v", idx, ep, got, want)
+ }
+ }
+ status := server.Status()
+ // The tests below are dubious: status.Endpoints might be empty and
+ // more likely at this point status.Proxies[i].Endpoints is
+ // empoty for all i because at the time this test was written,
+ // no proxies were started. Anyway, just to express the
+ // intent...
+ for _, ep := range status.Endpoints {
+ if got := ep.BlessingNames(); !reflect.DeepEqual(got, want) {
+ t.Errorf("test #%d: endpoint=%q: Got blessings %v, want %v", idx, ep, got, want)
+ }
+ }
+ for _, proxy := range status.Proxies {
+ ep := proxy.Endpoint
+ if got := ep.BlessingNames(); !reflect.DeepEqual(got, want) {
+ t.Errorf("test #%d: proxy=%q endpoint=%q: Got blessings %v, want %v", idx, proxy.Proxy, ep, got, want)
+ }
+ }
+ }
+}
+
type dischargeService struct {
called int
mu sync.Mutex