blob: 0643fe9797c1efa7dfbaba587ab9dfd7d2952a8a [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package namespace_test
import (
"fmt"
"reflect"
"testing"
"v.io/v23"
"v.io/v23/context"
"v.io/v23/naming"
"v.io/v23/rpc"
"v.io/v23/security"
"v.io/v23/security/access"
_ "v.io/x/ref/runtime/factories/generic"
"v.io/x/ref/services/mounttable/mounttablelib"
"v.io/x/ref/test"
"v.io/x/ref/test/testutil"
)
func initTest() (rootCtx *context.T, aliceCtx *context.T, bobCtx *context.T, shutdown v23.Shutdown) {
ctx, shutdown := test.V23Init()
var err error
if rootCtx, err = v23.WithPrincipal(ctx, testutil.NewPrincipal("root")); err != nil {
panic("failed to set root principal")
}
if aliceCtx, err = v23.WithPrincipal(ctx, testutil.NewPrincipal("alice")); err != nil {
panic("failed to set alice principal")
}
if bobCtx, err = v23.WithPrincipal(ctx, testutil.NewPrincipal("bob")); err != nil {
panic("failed to set bob principal")
}
for _, r := range []*context.T{rootCtx, aliceCtx, bobCtx} {
// A hack to set the namespace roots to a value that won't work.
v23.GetNamespace(r).SetRoots()
// And have all principals recognize each others blessings.
p1 := v23.GetPrincipal(r)
for _, other := range []*context.T{rootCtx, aliceCtx, bobCtx} {
// testutil.NewPrincipal has already setup each
// principal to use the same blessing for both server
// and client activities.
b, _ := v23.GetPrincipal(other).BlessingStore().Default()
if err := security.AddToRoots(p1, b); err != nil {
panic(err)
}
}
}
return rootCtx, aliceCtx, bobCtx, shutdown
}
// Create a new mounttable service.
func newMT(t *testing.T, ctx *context.T) (func(), string) {
estr, stopFunc, err := mounttablelib.StartServers(ctx, v23.GetListenSpec(ctx), "", "", "", "", "mounttable")
if err != nil {
t.Fatalf("r.NewServer: %s", err)
}
return stopFunc, estr
}
type nopServer struct{ x int }
func (s *nopServer) NOP(*context.T, rpc.ServerCall) error {
return nil
}
var nobody = []security.BlessingPattern{""}
var everybody = []security.BlessingPattern{"..."}
var closedPerms = access.Permissions{
"Resolve": access.AccessList{
In: nobody,
},
"Read": access.AccessList{
In: nobody,
},
"Admin": access.AccessList{
In: nobody,
},
"Create": access.AccessList{
In: nobody,
},
"Mount": access.AccessList{
In: nobody,
},
}
var closedPermsWithOwnerAdded = access.Permissions{
"Resolve": access.AccessList{
In: nobody,
},
"Read": access.AccessList{
In: nobody,
},
"Admin": access.AccessList{
In: []security.BlessingPattern{"", "root"},
},
"Create": access.AccessList{
In: nobody,
},
"Mount": access.AccessList{
In: nobody,
},
}
var openPerms = access.Permissions{
"Resolve": access.AccessList{
In: everybody,
},
"Read": access.AccessList{
In: everybody,
},
"Admin": access.AccessList{
In: everybody,
},
"Create": access.AccessList{
In: everybody,
},
"Mount": access.AccessList{
In: everybody,
},
}
func TestPermissions(t *testing.T) {
// Create three different personalities.
// TODO(p): Use the multiple personalities to test Permissions functionality.
rootCtx, aliceCtx, _, shutdown := initTest()
defer shutdown()
// Create root mounttable.
stop, rmtAddr := newMT(t, rootCtx)
fmt.Printf("rmt at %s\n", rmtAddr)
defer stop()
ns := v23.GetNamespace(rootCtx)
ns.SetRoots("/" + rmtAddr)
// Create lower mount table.
stop1, mt1Addr := newMT(t, rootCtx)
fmt.Printf("mt1 at %s\n", mt1Addr)
defer stop1()
// Mount them into the root.
if err := ns.Mount(rootCtx, "a/b/c", mt1Addr, 0, naming.ServesMountTable(true)); err != nil {
t.Fatalf("Failed to Mount %s onto a/b/c: %s", "/"+mt1Addr, err)
}
// Set/Get the mount point's Permissions.
_, version, err := ns.GetPermissions(rootCtx, "a/b/c")
if err != nil {
t.Fatalf("GetPermissions a/b/c: %s", err)
}
if err := ns.SetPermissions(rootCtx, "a/b/c", openPerms, version); err != nil {
t.Fatalf("SetPermissions a/b/c: %s", err)
}
nacl, _, err := ns.GetPermissions(rootCtx, "a/b/c")
if err != nil {
t.Fatalf("GetPermissions a/b/c: %s", err)
}
if !reflect.DeepEqual(openPerms, nacl) {
t.Fatalf("want %v, got %v", openPerms, nacl)
}
// Now Set/Get the in lower mount table.
name := "a/b/c/d/e"
version = "" // Parallel setperms with any other value is dangerous
if err := ns.SetPermissions(rootCtx, name, openPerms, version); err != nil {
t.Fatalf("SetPermissions %s: %s", name, err)
}
nacl, _, err = ns.GetPermissions(rootCtx, name)
if err != nil {
t.Fatalf("GetPermissions %s: %s", name, err)
}
if !reflect.DeepEqual(openPerms, nacl) {
t.Fatalf("want %v, got %v", openPerms, nacl)
}
// Create mount points accessible only by root's key and owner.
name = "a/b/c/d/f"
deadbody := "/the:8888/rain"
if err := ns.SetPermissions(rootCtx, name, closedPerms, version); err != nil {
t.Fatalf("SetPermissions %s: %s", name, err)
}
nacl, _, err = ns.GetPermissions(rootCtx, name)
if err != nil {
t.Fatalf("GetPermissions %s: %s", name, err)
}
if !reflect.DeepEqual(closedPermsWithOwnerAdded, nacl) {
t.Fatalf("want %v, got %v", closedPermsWithOwnerAdded, nacl)
}
if err := ns.Mount(rootCtx, name, deadbody, 10000); err != nil {
t.Fatalf("Mount %s: %s", name, err)
}
// Alice shouldn't be able to resolve it.
_, err = v23.GetNamespace(aliceCtx).Resolve(aliceCtx, name)
if err == nil {
t.Fatalf("as alice we shouldn't be able to Resolve %s", name)
}
// Root should be able to resolve it.
_, err = ns.Resolve(rootCtx, name)
if err != nil {
t.Fatalf("as root Resolve %s: %s", name, err)
}
// Create a mount point via Serve accessible only by root's key and owner.
name = "a/b/c/d/g"
if err := ns.SetPermissions(rootCtx, name, closedPerms, version); err != nil {
t.Fatalf("SetPermissions %s: %s", name, err)
}
if rootCtx, _, err = v23.WithNewServer(rootCtx, name, &nopServer{1}, nil); err != nil {
t.Fatalf("v23.WithNewServer failed: %v", err)
}
// Alice shouldn't be able to resolve it.
_, err = v23.GetNamespace(aliceCtx).Resolve(aliceCtx, name)
if err == nil {
t.Fatalf("as alice we shouldn't be able to Resolve %s", name)
}
// Root should be able to resolve it.
resolveWithRetry(rootCtx, name)
}