lib/modules: change the NewShell factory to take a security.Principal arg.

- NewShell now takes a Principal as an argument and allows the
created shell and its subprocesses to share that principal. Taking
this a parameter allows the shell to be used with the runtime's
in-memory Principal when required or with any other.

Change-Id: Ib2dc07fdc4edf1c23afed9b37661eb484f56717e
diff --git a/lib/filelocker/locker_test.go b/lib/filelocker/locker_test.go
index f3ce658..fc23e17 100644
--- a/lib/filelocker/locker_test.go
+++ b/lib/filelocker/locker_test.go
@@ -63,7 +63,10 @@
 	filepath := newFile()
 	defer os.Remove(filepath)
 
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	h, err := sh.Start("testLockChild", nil, filepath)
 	if err != nil {
@@ -133,7 +136,10 @@
 	filepath := newFile()
 	defer os.Remove(filepath)
 
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	h, err := sh.Start("testLockChild", nil, filepath)
 	if err != nil {
diff --git a/lib/modules/core/core_test.go b/lib/modules/core/core_test.go
index 5f72ee9..86bbb0e 100644
--- a/lib/modules/core/core_test.go
+++ b/lib/modules/core/core_test.go
@@ -23,8 +23,8 @@
 )
 
 func TestCommands(t *testing.T) {
-	sh := modules.NewShell()
-	defer sh.Cleanup(nil, os.Stderr)
+	sh, fn := newShell(t)
+	defer fn()
 	for _, c := range []string{core.RootMTCommand, core.MTCommand} {
 		if len(sh.Help(c)) == 0 {
 			t.Fatalf("missing command %q", c)
@@ -37,8 +37,11 @@
 	rt.Init()
 }
 
-func newShell() (*modules.Shell, func()) {
-	sh := modules.NewShell()
+func newShell(t *testing.T) (*modules.Shell, func()) {
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	return sh, func() {
 		if testing.Verbose() {
 			vlog.Infof("------ cleanup ------")
@@ -55,7 +58,7 @@
 }
 
 func TestRoot(t *testing.T) {
-	sh, fn := newShell()
+	sh, fn := newShell(t)
 	defer fn()
 	root, err := sh.Start(core.RootMTCommand, nil, testArgs()...)
 	if err != nil {
@@ -128,7 +131,7 @@
 }
 
 func TestMountTableAndGlob(t *testing.T) {
-	sh, fn := newShell()
+	sh, fn := newShell(t)
 	defer fn()
 
 	mountPoints := []string{"a", "b", "c", "d", "e"}
@@ -201,7 +204,7 @@
 }
 
 func TestEcho(t *testing.T) {
-	sh, fn := newShell()
+	sh, fn := newShell(t)
 	defer fn()
 
 	srv, err := sh.Start(core.EchoServerCommand, nil, testArgs("test", "")...)
@@ -223,7 +226,7 @@
 }
 
 func TestResolve(t *testing.T) {
-	sh, fn := newShell()
+	sh, fn := newShell(t)
 	defer fn()
 
 	mountPoints := []string{"a", "b"}
diff --git a/lib/modules/modules_internal_test.go b/lib/modules/modules_internal_test.go
index 8ce9b17..b8229e3 100644
--- a/lib/modules/modules_internal_test.go
+++ b/lib/modules/modules_internal_test.go
@@ -26,7 +26,10 @@
 }
 
 func TestState(t *testing.T) {
-	sh := NewShell()
+	sh, err := NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	RegisterFunction("echoff", "[args]*", Echo)
 	assertNumHandles(t, sh, 0)
 
diff --git a/lib/modules/modules_test.go b/lib/modules/modules_test.go
index ffdd2a0..cee9708 100644
--- a/lib/modules/modules_test.go
+++ b/lib/modules/modules_test.go
@@ -133,7 +133,10 @@
 }
 
 func TestChild(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	key, val := "simpleVar", "foo & bar"
 	sh.SetVar(key, val)
@@ -141,19 +144,25 @@
 }
 
 func TestChildNoRegistration(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	key, val := "simpleVar", "foo & bar"
 	sh.SetVar(key, val)
 	testCommand(t, sh, "envtest", key, val)
-	_, err := sh.Start("non-existent-command", nil, "random", "args")
+	_, err = sh.Start("non-existent-command", nil, "random", "args")
 	if err == nil {
 		t.Fatalf("expected error")
 	}
 }
 
 func TestFunction(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	key, val := "simpleVar", "foo & bar & baz"
 	sh.SetVar(key, val)
@@ -161,7 +170,10 @@
 }
 
 func TestErrorChild(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	h, err := sh.Start("errortestChild", nil)
 	if err != nil {
@@ -198,14 +210,21 @@
 }
 
 func TestShutdownSubprocess(t *testing.T) {
-	testShutdown(t, modules.NewShell(), "echos", false)
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	testShutdown(t, sh, "echos", false)
 }
 
 // TestShutdownSubprocessIgnoresStdin verifies that Shutdown doesn't wait
 // forever if a child does not die upon closing stdin; but instead times out and
 // returns an appropriate error.
 func TestShutdownSubprocessIgnoresStdin(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	sh.SetWaitTimeout(time.Second)
 	h, err := sh.Start("ignores_stdin", nil)
 	if err != nil {
@@ -227,7 +246,10 @@
 // implementation inappropriately sets stdout to the file that is to be closed
 // in Wait.
 func TestStdoutRace(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	sh.SetWaitTimeout(time.Second)
 	h, err := sh.Start("ignores_stdin", nil)
 	if err != nil {
@@ -256,11 +278,18 @@
 }
 
 func TestShutdownFunction(t *testing.T) {
-	testShutdown(t, modules.NewShell(), "echof", true)
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	testShutdown(t, sh, "echof", true)
 }
 
 func TestErrorFunc(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	h, err := sh.Start("errortestFunc", nil)
 	if err != nil {
@@ -281,7 +310,10 @@
 }
 
 func TestEnvelope(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	sh.SetVar("a", "1")
 	sh.SetVar("b", "2")
@@ -381,7 +413,10 @@
 
 	// Test child credentials when runtime is not initialized and VeyronCredentials
 	// is not set.
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	if err := validateCredentials(startChildAndGetCredentials(sh, nil), "test-shell/child"); err != nil {
 		t.Fatal(err)
@@ -401,7 +436,10 @@
 	if err := os.Setenv(consts.VeyronCredentials, dir); err != nil {
 		t.Fatal(err)
 	}
-	sh = modules.NewShell()
+	sh, err = modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	if err := validateCredentials(startChildAndGetCredentials(sh, nil), "root/os/child"); err != nil {
 		t.Fatal(err)
 	}
@@ -415,7 +453,10 @@
 	// Test that VeyronCredentials specified on the shell override the OS ones.
 	dir = tsecurity.NewVeyronCredentials(root, "shell")
 	defer os.RemoveAll(dir)
-	sh = modules.NewShell()
+	sh, err = modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	sh.SetVar(consts.VeyronCredentials, dir)
 	if err := validateCredentials(startChildAndGetCredentials(sh, nil), "root/shell/child"); err != nil {
 		t.Fatal(err)
@@ -443,7 +484,10 @@
 }
 
 func TestEnvMerge(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	sh.SetVar("a", "1")
 	os.Setenv("a", "wrong, should be 1")
diff --git a/lib/modules/shell.go b/lib/modules/shell.go
index 87aa85a..8d4324b 100644
--- a/lib/modules/shell.go
+++ b/lib/modules/shell.go
@@ -50,15 +50,16 @@
 	"fmt"
 	"io"
 	"io/ioutil"
+	"math/rand"
 	"os"
 	"sync"
 	"time"
 
+	"veyron.io/veyron/veyron2/security"
+
 	"veyron.io/veyron/veyron/lib/exec"
 	"veyron.io/veyron/veyron/lib/flags/consts"
 	vsecurity "veyron.io/veyron/veyron/security"
-
-	"veyron.io/veyron/veyron2/security"
 )
 
 const (
@@ -76,37 +77,51 @@
 	tempCredDirs              []string
 	startTimeout, waitTimeout time.Duration
 	config                    exec.Config
+	principal                 security.Principal
+	blessing                  security.Blessings
 }
 
-// NewShell creates a new instance of Shell.
-//
-// The VeyronCredentials environment variable of the shell is set
-// as follows. If the OS's VeyronCredentials is set then the shell's
-// VeyronCredentials is set to the same value, otherwise it is set
-// to a freshly created credentials directory.
-//
-// The shell's credentials are used to bless the principal supplied
-// to any children of this shell (see Start).
-// TODO(cnicolaou): this should use the principal already setup
-// with the runtime if the runtime has been initialized, if not,
-// it should create a new principal. As of now, this approach only works
-// for child processes that talk to each other, but not to the parent
-// process that started them since it's running with a different set of
-// credentials setup elsewhere. When this change is made it should
-// be possible to remove creating credentials in many unit tests.
-func NewShell() *Shell {
+// NewShell creates a new instance of Shell. It will also add a blessing
+// to the supplied principal and ensure that any child processes are
+// created with principals that are in turn blessed with it. A typical
+// use case is to pass in the runtime's principal and hence allow the
+// process hosting the shell to interact with its children and vice
+// versa. If a nil principal is passed in then NewShell will create a new
+// principal that shares a blessing with all of its children, in this mode,
+// any child processes can interact with each other but not with the parent.
+func NewShell(p security.Principal) (*Shell, error) {
 	sh := &Shell{
 		env:          make(map[string]string),
 		handles:      make(map[Handle]struct{}),
 		startTimeout: time.Minute,
 		waitTimeout:  10 * time.Second,
 		config:       exec.NewConfig(),
+		principal:    p,
 	}
-	if err := sh.initShellCredentials(); err != nil {
-		// TODO(cnicolaou): return an error rather than panic.
-		panic(err)
+	if p == nil {
+		if err := sh.initShellCredentials(); err != nil {
+			return nil, err
+		}
+		return sh, nil
 	}
-	return sh
+	gen := rand.New(rand.NewSource(time.Now().UnixNano()))
+	// Use a unique blessing tree per shell.
+	blessingName := fmt.Sprintf("%s-%d", shellBlessingExtension, gen.Int63())
+	blessing, err := p.BlessSelf(blessingName)
+	if err != nil {
+		return nil, err
+	}
+	sh.blessing = blessing
+	if _, err := p.BlessingStore().Set(blessing, security.BlessingPattern(blessingName+"/"+childBlessingExtension+"/...")); err != nil {
+		return nil, err
+	}
+	if err := p.AddToRoots(blessing); err != nil {
+		return nil, err
+	}
+	// Our blessing store now contains a blessing with our unique prefix
+	// and the principal has that blessing's root added to its trusted
+	// list so that it will accept blessings derived from it.
+	return sh, nil
 }
 
 func (sh *Shell) initShellCredentials() error {
@@ -127,34 +142,64 @@
 }
 
 func (sh *Shell) getChildCredentials(shellCredDir string) (string, error) {
-	root, err := principalFromDir(shellCredDir)
-	if err != nil {
-		return "", err
+	root := sh.principal
+	rootBlessing := sh.blessing
+	if root == nil {
+		r, err := principalFromDir(shellCredDir)
+		if err != nil {
+			return "", err
+		}
+		root = r
+		rootBlessing = root.BlessingStore().Default()
 	}
 
 	dir, err := ioutil.TempDir("", "shell_child_credentials")
 	if err != nil {
 		return "", err
 	}
+	// Create a principal and default blessing for the child that is
+	// derived from the blessing created for this shell. This can
+	// be used by the parent to invoke RPCs on any children and for the
+	// children to invoke RPCs on each other.
 	p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
 	if err != nil {
 		return "", err
 	}
-
-	blessing, err := root.Bless(p.PublicKey(), root.BlessingStore().Default(), childBlessingExtension, security.UnconstrainedUse())
+	blessingForChild, err := root.Bless(p.PublicKey(), rootBlessing, childBlessingExtension, security.UnconstrainedUse())
 	if err != nil {
 		return "", err
 	}
-	if err := p.BlessingStore().SetDefault(blessing); err != nil {
+	if err := p.BlessingStore().SetDefault(blessingForChild); err != nil {
 		return "", err
 	}
-	if _, err := p.BlessingStore().Set(blessing, security.AllPrincipals); err != nil {
+	if _, err := p.BlessingStore().Set(blessingForChild, security.AllPrincipals); err != nil {
 		return "", err
 	}
-	if err := p.AddToRoots(blessing); err != nil {
+	if err := p.AddToRoots(blessingForChild); err != nil {
 		return "", err
 	}
 
+	if sh.blessing != nil {
+		// Create a second blessing for the child, that will be accepted
+		// by the parent, should the child choose to invoke RPCs on the parent.
+		blessingFromChild, err := root.Bless(p.PublicKey(), root.BlessingStore().Default(), childBlessingExtension, security.UnconstrainedUse())
+		if err != nil {
+			return "", err
+		}
+		// We store this blessing as the one to use with a pattern that matches
+		// the root's name.
+		// TODO(cnicolaou,caprita): at some point there will be a nicer API
+		// for getting the name of a blessing.
+		ctx := security.NewContext(&security.ContextParams{LocalPrincipal: root})
+		rootName := root.BlessingStore().Default().ForContext(ctx)[0]
+		if _, err := p.BlessingStore().Set(blessingFromChild, security.BlessingPattern(rootName)); err != nil {
+			return "", err
+		}
+
+		if err := p.AddToRoots(blessingFromChild); err != nil {
+			return "", err
+		}
+	}
 	sh.tempCredDirs = append(sh.tempCredDirs, dir)
 	return dir, nil
 }
diff --git a/lib/signals/signals_test.go b/lib/signals/signals_test.go
index d57c65c..e48e373 100644
--- a/lib/signals/signals_test.go
+++ b/lib/signals/signals_test.go
@@ -112,7 +112,10 @@
 }
 
 func newShell(t *testing.T, command string) (*modules.Shell, modules.Handle, *expect.Session) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	handle, err := sh.Start(command, nil)
 	if err != nil {
 		sh.Cleanup(os.Stderr, os.Stderr)
@@ -328,7 +331,10 @@
 	r := rt.Init()
 	defer r.Cleanup()
 
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 
 	// Set the child process up with a blessing from the parent so that
diff --git a/runtimes/google/ipc/client_test.go b/runtimes/google/ipc/client_test.go
index c4e8b8a..aa159a7 100644
--- a/runtimes/google/ipc/client_test.go
+++ b/runtimes/google/ipc/client_test.go
@@ -26,7 +26,10 @@
 }
 
 func runMountTable(t *testing.T) (*modules.Shell, func()) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	root, err := sh.Start(core.RootMTCommand, nil, testArgs()...)
 	if err != nil {
 		t.Fatalf("unexpected error for root mt: %s", err)
diff --git a/runtimes/google/ipc/server_test.go b/runtimes/google/ipc/server_test.go
index a918f00..8e43cca 100644
--- a/runtimes/google/ipc/server_test.go
+++ b/runtimes/google/ipc/server_test.go
@@ -29,7 +29,10 @@
 func TestReconnect(t *testing.T) {
 	b := createBundle(t, tsecurity.NewPrincipal("client"), nil, nil) // We only need the client from the bundle.
 	defer b.cleanup(t)
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	server, err := sh.Start("runServer", nil, "127.0.0.1:0")
 	if err != nil {
@@ -86,7 +89,10 @@
 }
 
 func (h *proxyHandle) Start(t *testing.T) error {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	server, err := sh.Start("runProxy", nil)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
diff --git a/runtimes/google/ipc/stream/manager/manager_test.go b/runtimes/google/ipc/stream/manager/manager_test.go
index 8d4d872..829800f 100644
--- a/runtimes/google/ipc/stream/manager/manager_test.go
+++ b/runtimes/google/ipc/stream/manager/manager_test.go
@@ -544,7 +544,10 @@
 
 func TestServerRestartDuringClientLifetime(t *testing.T) {
 	client := InternalNew(naming.FixedRoutingID(0xcccccccc))
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	h, err := sh.Start("runServer", nil, "127.0.0.1:0")
 	if err != nil {
@@ -583,7 +586,10 @@
 
 func TestServerRestartDuringClientLifetimeWS(t *testing.T) {
 	client := InternalNew(naming.FixedRoutingID(0xcccccccc))
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(nil, nil)
 	h, err := sh.Start("runServer", nil, "127.0.0.1:0")
 	if err != nil {
diff --git a/runtimes/google/rt/mgmt_test.go b/runtimes/google/rt/mgmt_test.go
index 355014f..cae8d50 100644
--- a/runtimes/google/rt/mgmt_test.go
+++ b/runtimes/google/rt/mgmt_test.go
@@ -116,7 +116,10 @@
 // TestNoWaiters verifies that the child process exits in the absence of any
 // wait channel being registered with its runtime.
 func TestNoWaiters(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	h, err := sh.Start(noWaitersCmd, nil)
 	if err != nil {
@@ -143,7 +146,10 @@
 // TestForceStop verifies that ForceStop causes the child process to exit
 // immediately.
 func TestForceStop(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	h, err := sh.Start(forceStopCmd, nil)
 	if err != nil {
@@ -295,7 +301,10 @@
 
 	childcreds := security.NewVeyronCredentials(r.Principal(), appCmd)
 	configServer, configServiceName, ch := createConfigServer(t, r)
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	sh.SetVar(consts.VeyronCredentials, childcreds)
 	sh.SetConfigKey(mgmt.ParentNameConfigKey, configServiceName)
 	sh.SetConfigKey(mgmt.ProtocolConfigKey, "tcp")
diff --git a/runtimes/google/rt/rt_test.go b/runtimes/google/rt/rt_test.go
index 15f9de7..0666b61 100644
--- a/runtimes/google/rt/rt_test.go
+++ b/runtimes/google/rt/rt_test.go
@@ -69,7 +69,10 @@
 }
 
 func TestInitArgs(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	h, err := sh.Start("child", nil, "--logtostderr=true", "--vv=3", "--", "foobar")
 	if err != nil {
@@ -136,7 +139,10 @@
 		return err
 	}
 	fmt.Fprintf(stdout, "RUNNER_DEFAULT_BLESSING=%v\n", defaultBlessing(r.Principal()))
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		return err
+	}
 	if _, err := sh.Start("principal", nil, args[1:]...); err != nil {
 		return err
 	}
@@ -156,7 +162,10 @@
 }
 
 func TestPrincipalInheritance(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer func() {
 		sh.Cleanup(os.Stdout, os.Stderr)
 	}()
@@ -216,7 +225,10 @@
 		t.Fatal(err)
 	}
 
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 
 	blessing := collect(sh, nil)
diff --git a/runtimes/google/rt/shutdown_test.go b/runtimes/google/rt/shutdown_test.go
index f0a57aa..4ee9468 100644
--- a/runtimes/google/rt/shutdown_test.go
+++ b/runtimes/google/rt/shutdown_test.go
@@ -25,10 +25,18 @@
 	}
 }
 
+func newShell(t *testing.T) *modules.Shell {
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	return sh
+}
+
 // TestSimpleServerSignal verifies that sending a signal to the simple server
 // causes it to exit cleanly.
 func TestSimpleServerSignal(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -44,7 +52,7 @@
 // TestSimpleServerLocalStop verifies that sending a local stop command to the
 // simple server causes it to exit cleanly.
 func TestSimpleServerLocalStop(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -61,7 +69,7 @@
 // signals to the simple server causes it to initiate the cleanup sequence on
 // the first signal and then exit immediately on the second signal.
 func TestSimpleServerDoubleSignal(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -81,7 +89,7 @@
 // TestSimpleServerLocalForceStop verifies that sending a local ForceStop
 // command to the simple server causes it to exit immediately.
 func TestSimpleServerLocalForceStop(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -100,7 +108,7 @@
 // TestSimpleServerKill demonstrates that a SIGKILL still forces the server
 // to exit regardless of our signal handling.
 func TestSimpleServerKill(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -120,7 +128,7 @@
 // corresponding to all the simulated sequential/parallel and
 // blocking/interruptible shutdown steps), and then exits cleanly.
 func TestComplexServerSignal(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -142,7 +150,7 @@
 // printouts corresponding to all the simulated sequential/parallel and
 // blocking/interruptible shutdown steps), and then exits cleanly.
 func TestComplexServerLocalStop(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -169,7 +177,7 @@
 // the corresponding printouts from the server).  Note that we have no
 // expectations on whether or not the interruptible shutdown steps execute.
 func TestComplexServerDoubleSignal(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -193,7 +201,7 @@
 // TestComplexServerLocalForceStop verifies that sending a local ForceStop
 // command to the complex server forces it to exit immediately.
 func TestComplexServerLocalForceStop(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
@@ -212,7 +220,7 @@
 // TestComplexServerKill demonstrates that a SIGKILL still forces the server to
 // exit regardless of our signal handling.
 func TestComplexServerKill(t *testing.T) {
-	sh := modules.NewShell()
+	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
 	s := expect.NewSession(t, h.Stdout(), time.Minute)
diff --git a/runtimes/google/rt/signal_test.go b/runtimes/google/rt/signal_test.go
index df93748..2d819a9 100644
--- a/runtimes/google/rt/signal_test.go
+++ b/runtimes/google/rt/signal_test.go
@@ -73,7 +73,10 @@
 }
 
 func TestWithRuntime(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	h, err := sh.Start("withRuntime", nil)
 	if err != nil {
@@ -90,7 +93,10 @@
 }
 
 func TestWithoutRuntime(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	h, err := sh.Start("withoutRuntime", nil)
 	if err != nil {
diff --git a/services/mgmt/node/impl/util_test.go b/services/mgmt/node/impl/util_test.go
index 52e1af6..a720983 100644
--- a/services/mgmt/node/impl/util_test.go
+++ b/services/mgmt/node/impl/util_test.go
@@ -79,7 +79,10 @@
 }
 
 func createShellAndMountTable(t *testing.T) (*modules.Shell, func()) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	// The shell, will, by default share credentials with its children.
 	sh.ClearVar(consts.VeyronCredentials)
 
diff --git a/tools/naming/simulator/driver.go b/tools/naming/simulator/driver.go
index 7826391..01685f9 100644
--- a/tools/naming/simulator/driver.go
+++ b/tools/naming/simulator/driver.go
@@ -108,7 +108,11 @@
 		return
 	}
 
-	shell := modules.NewShell()
+	shell, err := modules.NewShell(nil)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "unexpected error: %s\n", err)
+		os.Exit(1)
+	}
 	defer shell.Cleanup(os.Stderr, os.Stderr)
 
 	scanner := bufio.NewScanner(os.Stdin)
diff --git a/tools/naming/simulator/driver_test.go b/tools/naming/simulator/driver_test.go
index d4dac88..5ccb5cb 100644
--- a/tools/naming/simulator/driver_test.go
+++ b/tools/naming/simulator/driver_test.go
@@ -40,7 +40,10 @@
 }
 
 func TestVariables(t *testing.T) {
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	sh.SetVar("foo", "bar")
 	cases := []struct {
 		input  string
diff --git a/tools/servicerunner/main.go b/tools/servicerunner/main.go
index 861592c..2e8560e 100644
--- a/tools/servicerunner/main.go
+++ b/tools/servicerunner/main.go
@@ -64,7 +64,10 @@
 
 	vars := map[string]string{}
 
-	sh := modules.NewShell()
+	sh, err := modules.NewShell(nil)
+	if err != nil {
+		panic(fmt.Sprintf("modules.NewShell: %s", err))
+	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 	v, ok := sh.GetVar(consts.VeyronCredentials)
 	if !ok {