blob: 4c6cc6cad0e6a7990a32e4846d5ff1cc707355a0 [file] [log] [blame]
package rt_test
import (
"reflect"
"testing"
"veyron.io/veyron/veyron2"
"veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron/lib/testutil"
"veyron.io/veyron/veyron/profiles"
vsecurity "veyron.io/veyron/veyron/security"
)
func init() { testutil.Init() }
type testService struct{}
func (testService) EchoBlessings(call ipc.ServerCall) []string {
return call.RemoteBlessings().ForContext(call)
}
func newRT() veyron2.Runtime {
r, err := rt.New()
if err != nil {
panic(err)
}
return r
}
type rootPrincipal struct {
p security.Principal
b security.Blessings
}
func newRootPrincipal(name string) *rootPrincipal {
p, err := vsecurity.NewPrincipal()
if err != nil {
panic(err)
}
b, err := p.BlessSelf(name)
if err != nil {
panic(err)
}
return &rootPrincipal{p, b}
}
func (r *rootPrincipal) Bless(p security.Principal, extension string) security.Blessings {
b, err := r.p.Bless(p.PublicKey(), r.b, extension, security.UnconstrainedUse())
if err != nil {
panic(err)
}
return b
}
func union(blessings ...security.Blessings) security.Blessings {
var ret security.Blessings
var err error
for _, b := range blessings {
if ret, err = security.UnionOfBlessings(ret, b); err != nil {
panic(err)
}
}
return ret
}
func TestClientServerBlessings(t *testing.T) {
var (
rootAlpha, rootBeta, rootUnrecognized = newRootPrincipal("alpha"), newRootPrincipal("beta"), newRootPrincipal("unrecognized")
clientRT, serverRT = newRT(), newRT()
pclient, pserver = clientRT.Principal(), serverRT.Principal()
// A bunch of blessings
alphaClient = rootAlpha.Bless(pclient, "client")
betaClient = rootBeta.Bless(pclient, "client")
unrecognizedClient = rootUnrecognized.Bless(pclient, "client")
alphaServer = rootAlpha.Bless(pserver, "server")
betaServer = rootBeta.Bless(pserver, "server")
unrecognizedServer = rootUnrecognized.Bless(pserver, "server")
)
// Setup the client's blessing store
pclient.BlessingStore().Set(alphaClient, "alpha/server")
pclient.BlessingStore().Set(betaClient, "beta/...")
pclient.BlessingStore().Set(unrecognizedClient, security.AllPrincipals)
tests := []struct {
server security.Blessings // Blessings presented by the server.
// Expected output
wantServer []string // Client's view of the server's blessings
wantClient []string // Server's view fo the client's blessings
}{
{
server: unrecognizedServer,
wantServer: nil,
wantClient: nil,
},
{
server: alphaServer,
wantServer: []string{"alpha/server"},
wantClient: []string{"alpha/client"},
},
{
server: union(alphaServer, betaServer),
wantServer: []string{"alpha/server", "beta/server"},
wantClient: []string{"alpha/client", "beta/client"},
},
}
// Have the client and server both trust both the root principals.
for _, rt := range []veyron2.Runtime{clientRT, serverRT} {
for _, root := range []*rootPrincipal{rootAlpha, rootBeta} {
if err := rt.Principal().AddToRoots(root.b); err != nil {
t.Fatal(err)
}
}
}
// Start the server process.
server, err := serverRT.NewServer()
if err != nil {
t.Fatal(err)
}
defer server.Stop()
var serverObjectName string
if endpoint, err := server.Listen(profiles.LocalListenSpec); err != nil {
t.Fatal(err)
} else {
serverObjectName = naming.JoinAddressName(endpoint.String(), "")
}
if err := server.Serve("", ipc.LeafDispatcher(testService{}, vsecurity.NewACLAuthorizer(vsecurity.OpenACL()))); err != nil {
t.Fatal(err)
}
// Let it rip!
for _, test := range tests {
// Create a new client per test so as to not re-use established authenticated VCs.
// TODO(ashankar,suharshs): Once blessings are exchanged "per-RPC", one client for all cases will suffice.
client, err := clientRT.NewClient()
if err != nil {
t.Errorf("clientRT.NewClient failed: %v", err)
continue
}
if err := pserver.BlessingStore().SetDefault(test.server); err != nil {
t.Errorf("pserver.SetDefault(%v) failed: %v", test.server, err)
continue
}
var gotClient []string
if call, err := client.StartCall(clientRT.NewContext(), serverObjectName, "EchoBlessings", nil); err != nil {
t.Errorf("client.StartCall failed: %v", err)
} else if err = call.Finish(&gotClient); err != nil {
t.Errorf("call.Finish failed: %v", err)
} else if !reflect.DeepEqual(gotClient, test.wantClient) {
t.Errorf("%v: Got %v, want %v for client blessings", test.server, gotClient, test.wantServer)
} else if gotServer, _ := call.RemoteBlessings(); !reflect.DeepEqual(gotServer, test.wantServer) {
t.Errorf("%v: Got %v, want %v for server blessings", test.server, gotServer, test.wantClient)
}
client.Close()
}
}