"veyron/lib/modules": Fresh VEYRON_CREDENTIALS for each command

This CL changes modules.Shell to ensure that (by default) a fresh
VeyronCredentials environement variable is set for each child process.

Currently, the shell sets up a single credentials directory that is
shared by all its child processes. This leads to the risk that children
may concurrently access the directory and therefore step on each other's
blessings. In order to prevent this here and elsewhere, we plan to lock
the VeyronCredentials directory to a single runtime that accesses it and
unlock it only when the runtime is cleaned up. Making this work requires
changing all code where multiple processes/runtime share the same
credentials directory. This CL is the first step in this direction, and
changes modules.Shell to ensure that all its children are provided with
a different credentials directory.

In particular this CL makes the following changes:
* modules.NewShell initializes a credentials directory for the shell.
  - It is set to the OS's VeyronCredentials variable if that is set,
    otherwise, to a freshly created directory.
  - Subsequent SetVar and  ClearVar calls on the shell's VeyronCredentials
    variable can modify the shell's credentials directory.
* Every command started by the shell has its VeyronCredentials
  environment variable set up as follows:
  - If the variable is set on the parameters provided to the 'Start'
    call then that value is used.
  - Otherwise, a the shell creates a new credentials directory and
    blesses it with the principal specified by its credentials. The same
    extension (in particular, 'child') is used for the blessing granted
    to all children. However, each child has its own seperate directory.
* A cleanup on the Shell deletes any new credentials directories
  created by the shell.

Change-Id: I5c809eca67fde20745735a51876a700a48090e3b
diff --git a/lib/modules/modules_test.go b/lib/modules/modules_test.go
index 5eb1366..ffdd2a0 100644
--- a/lib/modules/modules_test.go
+++ b/lib/modules/modules_test.go
@@ -3,6 +3,7 @@
 import (
 	"bufio"
 	"bytes"
+	"errors"
 	"fmt"
 	"io"
 	"os"
@@ -14,10 +15,18 @@
 	"time"
 
 	"veyron.io/veyron/veyron/lib/exec"
+	"veyron.io/veyron/veyron/lib/flags/consts"
 	"veyron.io/veyron/veyron/lib/modules"
 	"veyron.io/veyron/veyron/lib/testutil"
+	tsecurity "veyron.io/veyron/veyron/lib/testutil/security"
+	_ "veyron.io/veyron/veyron/profiles"
+	vsecurity "veyron.io/veyron/veyron/security"
+
+	"veyron.io/veyron/veyron2/security"
 )
 
+const credentialsEnvPrefix = "\"" + consts.VeyronCredentials + "="
+
 func init() {
 	testutil.Init()
 	modules.RegisterChild("envtest", "envtest: <variables to print>...", PrintFromEnv)
@@ -304,19 +313,133 @@
 		}
 	}
 
+	foundVeyronCredentials := false
 	for _, want := range shEnv {
+		if strings.HasPrefix(want, credentialsEnvPrefix) {
+			foundVeyronCredentials = true
+			continue
+		}
 		if !find(want, childEnv) {
 			t.Errorf("failed to find %s in %#v", want, childEnv)
 		}
 	}
+	if !foundVeyronCredentials {
+		t.Errorf("%v environment variable not set in command envelope", consts.VeyronCredentials)
+	}
+
+	foundVeyronCredentials = false
 	for _, want := range childEnv {
 		if want == "\""+exec.VersionVariable+"=\"" {
 			continue
 		}
+		if strings.HasPrefix(want, credentialsEnvPrefix) {
+			foundVeyronCredentials = true
+			continue
+		}
 		if !find(want, shEnv) {
 			t.Errorf("failed to find %s in %#v", want, shEnv)
 		}
 	}
+	if !foundVeyronCredentials {
+		t.Errorf("%v environment variable not set for command", consts.VeyronCredentials)
+	}
+}
+
+func TestEnvCredentials(t *testing.T) {
+	startChildAndGetCredentials := func(sh *modules.Shell, env []string) string {
+		h, err := sh.Start("printenv", env)
+		if err != nil {
+			t.Fatalf("unexpected error: %s", err)
+		}
+		defer h.Shutdown(os.Stderr, os.Stderr)
+		scanner := bufio.NewScanner(h.Stdout())
+		for scanner.Scan() {
+			o := scanner.Text()
+			if strings.HasPrefix(o, credentialsEnvPrefix) {
+				return strings.TrimSuffix(strings.TrimPrefix(o, credentialsEnvPrefix), "\"")
+			}
+		}
+		return ""
+	}
+	validateCredentials := func(dir string, wantBlessing string) error {
+		if len(dir) == 0 {
+			return errors.New("credentials directory not found")
+		}
+		p, err := vsecurity.LoadPersistentPrincipal(dir, nil)
+		if err != nil {
+			return err
+		}
+		def := p.BlessingStore().Default()
+		if blessingsSharedWithAll := p.BlessingStore().ForPeer("random_peer"); !reflect.DeepEqual(blessingsSharedWithAll, def) {
+			return fmt.Errorf("Blessing shared with all peers: %v is different from default Blessings: %v", blessingsSharedWithAll, def)
+		}
+		if got := def.ForContext(security.NewContext(&security.ContextParams{LocalPrincipal: p})); len(got) != 1 || got[0] != wantBlessing {
+			return fmt.Errorf("got blessings: %v, want exactly one blessing: %v", got, wantBlessing)
+		}
+		return nil
+	}
+
+	// Test child credentials when runtime is not initialized and VeyronCredentials
+	// is not set.
+	sh := modules.NewShell()
+	defer sh.Cleanup(nil, nil)
+	if err := validateCredentials(startChildAndGetCredentials(sh, nil), "test-shell/child"); err != nil {
+		t.Fatal(err)
+	}
+
+	// Test that no two children have the same credentials directory.
+	if cred1, cred2 := startChildAndGetCredentials(sh, nil), startChildAndGetCredentials(sh, nil); cred1 == cred2 {
+		t.Fatalf("The same credentials directory %v was set for two children", cred1)
+	}
+
+	// Test child credentials when VeyronCredentials are set.
+	root := tsecurity.NewPrincipal("root")
+	old := os.Getenv(consts.VeyronCredentials)
+	defer os.Setenv(consts.VeyronCredentials, old)
+	dir := tsecurity.NewVeyronCredentials(root, "os")
+	defer os.RemoveAll(dir)
+	if err := os.Setenv(consts.VeyronCredentials, dir); err != nil {
+		t.Fatal(err)
+	}
+	sh = modules.NewShell()
+	if err := validateCredentials(startChildAndGetCredentials(sh, nil), "root/os/child"); err != nil {
+		t.Fatal(err)
+	}
+	sh.Cleanup(nil, nil)
+
+	// Test that os VeyronCredentials are not deleted by the Cleanup.
+	if finfo, err := os.Stat(dir); err != nil || !finfo.IsDir() {
+		t.Fatalf("%q is not a directory", dir)
+	}
+
+	// Test that VeyronCredentials specified on the shell override the OS ones.
+	dir = tsecurity.NewVeyronCredentials(root, "shell")
+	defer os.RemoveAll(dir)
+	sh = modules.NewShell()
+	sh.SetVar(consts.VeyronCredentials, dir)
+	if err := validateCredentials(startChildAndGetCredentials(sh, nil), "root/shell/child"); err != nil {
+		t.Fatal(err)
+	}
+	sh.ClearVar(consts.VeyronCredentials)
+	if credentials := startChildAndGetCredentials(sh, nil); len(credentials) != 0 {
+		t.Fatalf("found credentials %v set for child even when shell credentials were cleared", credentials)
+	}
+	anotherDir := tsecurity.NewVeyronCredentials(root, "anotherShell")
+	defer os.RemoveAll(anotherDir)
+	sh.SetVar(consts.VeyronCredentials, anotherDir)
+	if err := validateCredentials(startChildAndGetCredentials(sh, nil), "root/anotherShell/child"); err != nil {
+		t.Fatal(err)
+	}
+
+	// Test that VeyronCredentials specified as a parameter overrides the OS and
+	// shell ones.
+	dir = tsecurity.NewVeyronCredentials(root, "param")
+	defer os.RemoveAll(dir)
+	env := []string{consts.VeyronCredentials + "=" + dir}
+	if err := validateCredentials(startChildAndGetCredentials(sh, env), "root/param"); err != nil {
+		t.Fatal(err)
+	}
+
 }
 
 func TestEnvMerge(t *testing.T) {
@@ -326,7 +449,6 @@
 	os.Setenv("a", "wrong, should be 1")
 	sh.SetVar("b", "2 also wrong")
 	os.Setenv("b", "wrong, should be 2")
-
 	h, err := sh.Start("printenv", []string{"b=2"})
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
diff --git a/lib/modules/shell.go b/lib/modules/shell.go
index 7b91f1a..87aa85a 100644
--- a/lib/modules/shell.go
+++ b/lib/modules/shell.go
@@ -29,13 +29,24 @@
 // In particular stdin, stdout and stderr are provided as parameters, as is
 // a map representation of the shell's environment.
 //
-// If a Shell is created within a unit test then it will automatically
-// generate a security ID, write it to a file and set the appropriate
-// environment variable to refer to it.
+// Every Shell created by NewShell is initialized with its VeyronCredentials
+// environment variable set. The variable is set to the os's VeyronCredentials
+// if that is set, otherwise to a freshly created credentials directory. The
+// shell's VeyronCredentials can be set and cleared using the SetVar and
+// ClearVar methods respectively.
+//
+// By default, the VeyronCredentials for each command Start-ed by the shell are
+// set to a freshly created credentials directory that is blessed by the shell's
+// credentials (i.e., if shell's credentials have not been cleared). Thus, each
+// child of the shell gets its own credentials directory with a blessing from the
+// shell of the form
+//   <shell's default blessing>/child
+// These default credentials provided by the shell to each command can be
+// overridden by specifying VeyronCredentials in the environment provided as a
+// parameter to the Start method.
 package modules
 
 import (
-	"flag"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -45,22 +56,44 @@
 
 	"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 (
+	shellBlessingExtension = "test-shell"
+	childBlessingExtension = "child"
 )
 
 // Shell represents the context within which commands are run.
 type Shell struct {
-	mu                        sync.Mutex
-	env                       map[string]string
-	handles                   map[Handle]struct{}
-	credDir                   string
+	mu      sync.Mutex
+	env     map[string]string
+	handles map[Handle]struct{}
+	// tmpCredDirs are the temporary directories created by this
+	// shell. These must be removed when the shell is cleaned up.
+	tempCredDirs              []string
 	startTimeout, waitTimeout time.Duration
 	config                    exec.Config
 }
 
-// NewShell creates a new instance of Shell. If this new instance is is a test
-// and no credentials have been configured in the environment via
-// consts.VeyronCredentials then CreateAndUseNewCredentials will be used to
-// configure a new ID for the shell and its children.
+// 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 {
 	sh := &Shell{
 		env:          make(map[string]string),
@@ -69,35 +102,63 @@
 		waitTimeout:  10 * time.Second,
 		config:       exec.NewConfig(),
 	}
-	if flag.Lookup("test.run") != nil && os.Getenv(consts.VeyronCredentials) == "" {
-		if err := sh.CreateAndUseNewCredentials(); err != nil {
-			// TODO(cnicolaou): return an error rather than panic.
-			panic(err)
-		}
+	if err := sh.initShellCredentials(); err != nil {
+		// TODO(cnicolaou): return an error rather than panic.
+		panic(err)
 	}
 	return sh
 }
 
-// CreateAndUseNewCredentials setups a new credentials directory and then
-// configures the shell and all of its children to use to it.
-//
-// 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 (sh *Shell) CreateAndUseNewCredentials() error {
-	dir, err := ioutil.TempDir("", "veyron_credentials")
+func (sh *Shell) initShellCredentials() error {
+	sh.mu.Lock()
+	defer sh.mu.Unlock()
+	if dir := os.Getenv(consts.VeyronCredentials); len(dir) != 0 {
+		sh.env[consts.VeyronCredentials] = dir
+		return nil
+	}
+
+	dir, err := ioutil.TempDir("", "shell_credentials")
 	if err != nil {
 		return err
 	}
-	sh.credDir = dir
-	sh.SetVar(consts.VeyronCredentials, sh.credDir)
+	sh.env[consts.VeyronCredentials] = dir
+	sh.tempCredDirs = append(sh.tempCredDirs, dir)
 	return nil
 }
 
+func (sh *Shell) getChildCredentials(shellCredDir string) (string, error) {
+	root, err := principalFromDir(shellCredDir)
+	if err != nil {
+		return "", err
+	}
+
+	dir, err := ioutil.TempDir("", "shell_child_credentials")
+	if err != nil {
+		return "", err
+	}
+	p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
+	if err != nil {
+		return "", err
+	}
+
+	blessing, err := root.Bless(p.PublicKey(), root.BlessingStore().Default(), childBlessingExtension, security.UnconstrainedUse())
+	if err != nil {
+		return "", err
+	}
+	if err := p.BlessingStore().SetDefault(blessing); err != nil {
+		return "", err
+	}
+	if _, err := p.BlessingStore().Set(blessing, security.AllPrincipals); err != nil {
+		return "", err
+	}
+	if err := p.AddToRoots(blessing); err != nil {
+		return "", err
+	}
+
+	sh.tempCredDirs = append(sh.tempCredDirs, dir)
+	return dir, nil
+}
+
 type Main func(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error
 
 // String returns a string representation of the Shell, which is a
@@ -111,10 +172,20 @@
 	return registry.help(command)
 }
 
-// Start starts the specified command, it returns a Handle which can be used
-// for interacting with that command. The OS and shell environment variables
-// are merged with the ones supplied as a parameter; the parameter specified
-// ones override the Shell and the Shell ones override the OS ones.
+// Start starts the specified command, it returns a Handle which can be
+// used for interacting with that command.
+//
+// The environment variables for the command are set by merging variables
+// from the OS environment, those in this Shell and those provided as a
+// parameter to it. In general, it prefers values from its parameter over
+// those from the Shell, over those from the OS. However, the VeyronCredentials
+// environment variable is handled specially.
+//
+// If the VeyronCredentials environment variable is set in 'env' then that
+// is the value that gets used. If the shell's VeyronCredentials are set then
+// VeyronCredentials for the command are set to a freshly created directory
+// specifying a principal blessed by the shell's credentials. In all other
+// cases VeyronCredentials for the command remains unset.
 //
 // The Shell tracks all of the Handles that it creates so that it can shut
 // them down when asked to. The returned Handle may be non-nil even when an
@@ -124,7 +195,10 @@
 // Commands must have already been registered using RegisterFunction
 // or RegisterChild.
 func (sh *Shell) Start(name string, env []string, args ...string) (Handle, error) {
-	cenv := sh.MergedEnv(env)
+	cenv, err := sh.setupCommandEnv(env)
+	if err != nil {
+		return nil, err
+	}
 	cmd := registry.getCommand(name)
 	if cmd == nil {
 		return nil, fmt.Errorf("%s: not registered", name)
@@ -155,12 +229,20 @@
 // CommandEnvelope returns the command line and environment that would be
 // used for running the subprocess or function if it were started with the
 // specifed arguments.
+//
+// This method is not idempotent as the directory pointed to by the
+// VeyronCredentials environment variable may be freshly created with
+// each invocation.
 func (sh *Shell) CommandEnvelope(name string, env []string, args ...string) ([]string, []string) {
 	cmd := registry.getCommand(name)
 	if cmd == nil {
 		return []string{}, []string{}
 	}
-	return cmd.factory().envelope(sh, sh.MergedEnv(env), args...)
+	menv, err := sh.setupCommandEnv(env)
+	if err != nil {
+		return []string{}, []string{}
+	}
+	return cmd.factory().envelope(sh, menv, args...)
 }
 
 // Forget tells the Shell to stop tracking the supplied Handle. This is
@@ -196,6 +278,11 @@
 }
 
 // SetVar sets the value to be associated with key.
+//
+// Note that setting the VeyronCredentials environement
+// variable changes the shell's principal which is used
+// for blessing the principals supplied to the shell's
+// children.
 func (sh *Shell) SetVar(key, value string) {
 	sh.mu.Lock()
 	defer sh.mu.Unlock()
@@ -204,6 +291,11 @@
 }
 
 // ClearVar removes the speficied variable from the Shell's environment
+//
+// Note that clearing the VeyronCredentials environment variable
+// would amount to clearing the shell's principal, and therefore, any
+// children of this shell would have their VeyronCredentials environment
+// variable set only if it is explicitly set in their parameters.
 func (sh *Shell) ClearVar(key string) {
 	sh.mu.Lock()
 	defer sh.mu.Unlock()
@@ -261,28 +353,49 @@
 			err = cerr
 		}
 	}
-	if len(sh.credDir) > 0 {
-		os.RemoveAll(sh.credDir)
+
+	// TODO(ataly, ashankar, caprita): The following code may lead to
+	// removing the credential directories for child processes that are
+	// still alive (this can happen e.g. if the Wait on the child timed
+	// out). While we can hope that some error will reach the caller of
+	// Cleanup (because we harvest the error codes from Shutdown), it may
+	// lead to failures that are harder to debug because the original issue
+	// will get masked by the credentials going away. One possibility is
+	// to only remove the credentials dir when Shutdown returns no timeout
+	// error.
+	for _, dir := range sh.tempCredDirs {
+		os.RemoveAll(dir)
 	}
 	return err
 }
 
-// MergedEnv returns a slice that contains the merged set of environment
-// variables from the OS environment, those in this Shell and those provided
-// as a parameter to it. It prefers values from its parameter over those
-// from the Shell, over those from the OS.
-func (sh *Shell) MergedEnv(env []string) []string {
+func (sh *Shell) setupCommandEnv(env []string) ([]string, error) {
 	osmap := envSliceToMap(os.Environ())
 	evmap := envSliceToMap(env)
+
 	sh.mu.Lock()
-	m1 := mergeMaps(osmap, sh.env)
 	defer sh.mu.Unlock()
+	m1 := mergeMaps(osmap, sh.env)
+	// Clear any VeyronCredentials directory in m1 as we never
+	// want the child to directly use the directory specified
+	// by the shell's VeyronCredentials.
+	delete(m1, consts.VeyronCredentials)
+
+	// Set the VeyronCredentials environment variable for the child
+	// if it is not already set and the shell's VeyronCredentials are set.
+	if len(evmap[consts.VeyronCredentials]) == 0 && len(sh.env[consts.VeyronCredentials]) != 0 {
+		var err error
+		if evmap[consts.VeyronCredentials], err = sh.getChildCredentials(sh.env[consts.VeyronCredentials]); err != nil {
+			return nil, err
+		}
+	}
+
 	m2 := mergeMaps(m1, evmap)
 	r := []string{}
 	for k, v := range m2 {
 		r = append(r, k+"="+v)
 	}
-	return r
+	return r, nil
 }
 
 // Handle represents a running command.
diff --git a/lib/modules/util.go b/lib/modules/util.go
index 7ad2fcb..b38e767 100644
--- a/lib/modules/util.go
+++ b/lib/modules/util.go
@@ -8,6 +8,9 @@
 	"os"
 	"strings"
 
+	vsecurity "veyron.io/veyron/veyron/security"
+
+	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/vlog"
 )
 
@@ -72,3 +75,21 @@
 	}
 	return merged
 }
+
+func principalFromDir(dir string) (security.Principal, error) {
+	p, err := vsecurity.LoadPersistentPrincipal(dir, nil)
+	if err == nil {
+		return p, nil
+	}
+	if !os.IsNotExist(err) {
+		return nil, err
+	}
+	p, err = vsecurity.CreatePersistentPrincipal(dir, nil)
+	if err != nil {
+		return nil, err
+	}
+	if err := vsecurity.InitDefaultBlessings(p, shellBlessingExtension); err != nil {
+		return nil, err
+	}
+	return p, nil
+}
diff --git a/runtimes/google/rt/mgmt_test.go b/runtimes/google/rt/mgmt_test.go
index defc3c7..355014f 100644
--- a/runtimes/google/rt/mgmt_test.go
+++ b/runtimes/google/rt/mgmt_test.go
@@ -335,7 +335,6 @@
 	if err == nil || err.Error() != want {
 		t.Errorf("got %v, want %s", err, want)
 	}
-
 }
 
 // TestRemoteStop verifies that the child shuts down cleanly when sending it
diff --git a/runtimes/google/rt/rt_test.go b/runtimes/google/rt/rt_test.go
index 3f244fb..4872dca 100644
--- a/runtimes/google/rt/rt_test.go
+++ b/runtimes/google/rt/rt_test.go
@@ -26,7 +26,6 @@
 	testutil.Init()
 	modules.RegisterChild("child", "", child)
 	modules.RegisterChild("principal", "", principal)
-	modules.RegisterChild("mutate", "", mutatePrincipal)
 	modules.RegisterChild("runner", "", runner)
 }
 
@@ -100,7 +99,6 @@
 	blessings := p.BlessingStore().Default()
 	if blessings == nil {
 		return fmt.Errorf("rt.Principal().BlessingStore().Default() returned nil")
-
 	}
 	ctx := security.NewContext(&security.ContextParams{LocalPrincipal: p})
 	if n := len(blessings.ForContext(ctx)); n != 1 {
@@ -109,6 +107,10 @@
 	return nil
 }
 
+func defaultBlessing(p security.Principal) string {
+	return p.BlessingStore().Default().ForContext(security.NewContext(&security.ContextParams{LocalPrincipal: p}))[0]
+}
+
 func tmpDir(t *testing.T) string {
 	dir, err := ioutil.TempDir("", "rt_test_dir")
 	if err != nil {
@@ -119,10 +121,10 @@
 
 func principal(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
 	r := rt.Init()
-	err := validatePrincipal(r.Principal())
-	fmt.Fprintf(stdout, "ERROR=%v\n", err)
-	fmt.Fprintf(stdout, "PUBKEY=%s\n", r.Principal().PublicKey())
-	modules.WaitForEOF(stdin)
+	if err := validatePrincipal(r.Principal()); err != nil {
+		return err
+	}
+	fmt.Fprintf(stdout, "DEFAULT_BLESSING=%s\n", defaultBlessing(r.Principal()))
 	return nil
 }
 
@@ -130,62 +132,27 @@
 // own security info and it's childs.
 func runner(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
 	r := rt.Init()
-	err := validatePrincipal(r.Principal())
-	fmt.Fprintf(stdout, "RUNNER_ERROR=%v\n", err)
-	fmt.Fprintf(stdout, "RUNNER_PUBKEY=%s\n", r.Principal().PublicKey())
-	if err != nil {
+	if err := validatePrincipal(r.Principal()); err != nil {
 		return err
 	}
+	fmt.Fprintf(stdout, "RUNNER_DEFAULT_BLESSING=%v\n", defaultBlessing(r.Principal()))
 	sh := modules.NewShell()
-	_, err = sh.Start("principal", nil, args[1:]...)
-	if err != nil {
+	if _, err := sh.Start("principal", nil, args[1:]...); err != nil {
 		return err
 	}
 	// Cleanup copies the output of sh to these Writers.
 	sh.Cleanup(stdout, stderr)
-	modules.WaitForEOF(stdin)
 	return nil
 }
 
-func mutatePrincipal(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-	r := rt.Init()
-
-	rtPrincipal := r.Principal()
-	err := validatePrincipal(rtPrincipal)
-	fmt.Fprintf(stdout, "ERROR=%v\n", err)
-
-	// Mutate the roots and store of this principal.
-	blessing, err := rtPrincipal.BlessSelf("irrelevant")
-	if err != nil {
-		return err
-	}
-	if _, err := rtPrincipal.BlessingStore().Set(blessing, security.AllPrincipals); err != nil {
-		return err
-	}
-	if err := rtPrincipal.AddToRoots(blessing); err != nil {
-		return err
-	}
-	newRT, err := rt.New(profileOpt)
-	if err != nil {
-		return fmt.Errorf("rt.New failed: %v", err)
-	}
-	// Test that the same principal gets initialized on creating a new runtime
-	// from the same credentials directory.
-	if got := newRT.Principal(); !reflect.DeepEqual(got, rtPrincipal) {
-		return fmt.Errorf("Initialized Principal: %v, expected: %v", got.PublicKey(), rtPrincipal.PublicKey())
-	}
-	fmt.Fprintf(stdout, "PUBKEY=%s\n", newRT.Principal().PublicKey())
-	modules.WaitForEOF(stdin)
-	return nil
-}
-
-func createCredentialsInDir(t *testing.T, dir string) security.Principal {
+func createCredentialsInDir(t *testing.T, dir string, blessing string) {
 	principal, err := vsecurity.CreatePersistentPrincipal(dir, nil)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
-	vsecurity.InitDefaultBlessings(principal, "test")
-	return principal
+	if err := vsecurity.InitDefaultBlessings(principal, blessing); err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 }
 
 func TestPrincipalInheritance(t *testing.T) {
@@ -194,13 +161,13 @@
 		sh.Cleanup(os.Stdout, os.Stderr)
 	}()
 
-	// Test that the child inherits the parent's credentials correctly.
+	// Test that the child inherits from the parent's credentials correctly.
 	// The running test process may or may not have a credentials directory set
 	// up so we have to use a 'runner' process to ensure the correct setup.
 	cdir := tmpDir(t)
 	defer os.RemoveAll(cdir)
 
-	principal := createCredentialsInDir(t, cdir)
+	createCredentialsInDir(t, cdir, "test")
 
 	// directory supplied by the environment.
 	credEnv := []string{consts.VeyronCredentials + "=" + cdir}
@@ -209,41 +176,33 @@
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
+
 	s := expect.NewSession(t, h.Stdout(), 2*time.Second) //time.Minute)
-	runnerErr := s.ExpectVar("RUNNER_ERROR")
-	runnerPubKey := s.ExpectVar("RUNNER_PUBKEY")
-	principalErr := s.ExpectVar("ERROR")
-	principalPubKey := s.ExpectVar("PUBKEY")
+	runnerBlessing := s.ExpectVar("RUNNER_DEFAULT_BLESSING")
+	principalBlessing := s.ExpectVar("DEFAULT_BLESSING")
 	if err := s.Error(); err != nil {
 		t.Fatalf("failed to read input from children: %s", err)
 	}
 	h.Shutdown(os.Stdout, os.Stderr)
-	if runnerErr != "<nil>" || principalErr != "<nil>" {
-		t.Fatalf("unexpected error: runner %q, principal %q", runnerErr, principalErr)
-	}
-	pubKey := principal.PublicKey().String()
-	if runnerPubKey != pubKey || principalPubKey != pubKey {
-		t.Fatalf("unexpected pubkeys: expected %s: runner %s, principal %s",
-			pubKey, runnerPubKey, principalPubKey)
+
+	wantRunnerBlessing := "test"
+	wantPrincipalBlessing := "test/child"
+	if runnerBlessing != wantRunnerBlessing || principalBlessing != wantPrincipalBlessing {
+		t.Fatalf("unexpected default blessing: got runner %s, principal %s, want runner %s, principal %s", runnerBlessing, principalBlessing, wantRunnerBlessing, wantPrincipalBlessing)
 	}
 
 }
 
 func TestPrincipalInit(t *testing.T) {
-	// Collet the process' public key and error status
-	collect := func(sh *modules.Shell, cmd string, env []string, args ...string) (string, error) {
-		h, err := sh.Start(cmd, env, args...)
+	// Collect the process' public key and error status
+	collect := func(sh *modules.Shell, env []string, args ...string) string {
+		h, err := sh.Start("principal", env, args...)
 		if err != nil {
 			t.Fatalf("unexpected error: %s", err)
 		}
 		s := expect.NewSession(t, h.Stdout(), time.Minute)
 		s.SetVerbosity(testing.Verbose())
-		errstr := s.ExpectVar("ERROR")
-		pubkey := s.ExpectVar("PUBKEY")
-		if errstr != "<nil>" {
-			return pubkey, fmt.Errorf("%s", errstr)
-		}
-		return pubkey, nil
+		return s.ExpectVar("DEFAULT_BLESSING")
 	}
 
 	// A credentials directory may, or may, not have been already specified.
@@ -260,52 +219,30 @@
 	sh := modules.NewShell()
 	defer sh.Cleanup(os.Stderr, os.Stderr)
 
-	pubkey, err := collect(sh, "principal", nil)
-	if err != nil {
-		t.Fatalf("child failed to create+validate principal: %v", err)
-	}
-	if len(pubkey) == 0 {
-		t.Fatalf("child failed to return a public key")
+	blessing := collect(sh, nil)
+	if len(blessing) == 0 {
+		t.Fatalf("child returned an empty default blessings set")
 	}
 
-	// Test specifying credentials via VEYRON_CREDENTIALS
+	// Test specifying credentials via VEYRON_CREDENTIALS environment.
 	cdir1 := tmpDir(t)
 	defer os.RemoveAll(cdir1)
-	principal := createCredentialsInDir(t, cdir1)
-	// directory supplied by the environment.
+	createCredentialsInDir(t, cdir1, "test_env")
 	credEnv := []string{consts.VeyronCredentials + "=" + cdir1}
 
-	pubkey, err = collect(sh, "principal", credEnv)
-	if err != nil {
-		t.Errorf("unexpected error: %s", err)
-	}
-
-	if got, want := pubkey, principal.PublicKey().String(); got != want {
-		t.Errorf("got %q, want %q", got, want)
+	blessing = collect(sh, credEnv)
+	if got, want := blessing, "test_env"; got != want {
+		t.Errorf("got default blessings: %q, want %q", got, want)
 	}
 
 	// Test specifying credentials via the command line and that the
 	// comand line overrides the environment
 	cdir2 := tmpDir(t)
 	defer os.RemoveAll(cdir2)
-	clPrincipal := createCredentialsInDir(t, cdir2)
+	createCredentialsInDir(t, cdir2, "test_cmd")
 
-	pubkey, err = collect(sh, "principal", credEnv, "--veyron.credentials="+cdir2)
-	if err != nil {
-		t.Errorf("unexpected error: %s", err)
-	}
-
-	if got, want := pubkey, clPrincipal.PublicKey().String(); got != want {
-		t.Errorf("got %q, want %q", got, want)
-	}
-
-	// Mutate the roots and store of the principal in the child process.
-	pubkey, err = collect(sh, "mutate", credEnv, "--veyron.credentials="+cdir2)
-	if err != nil {
-		t.Errorf("unexpected error: %s", err)
-	}
-
-	if got, want := pubkey, clPrincipal.PublicKey().String(); got != want {
+	blessing = collect(sh, credEnv, "--veyron.credentials="+cdir2)
+	if got, want := blessing, "test_cmd"; got != want {
 		t.Errorf("got %q, want %q", got, want)
 	}
 }
diff --git a/tools/naming/simulator/driver.go b/tools/naming/simulator/driver.go
index 9242830..7826391 100644
--- a/tools/naming/simulator/driver.go
+++ b/tools/naming/simulator/driver.go
@@ -19,7 +19,6 @@
 	"veyron.io/veyron/veyron2/rt"
 
 	"veyron.io/veyron/veyron/lib/expect"
-	"veyron.io/veyron/veyron/lib/flags/consts"
 	"veyron.io/veyron/veyron/lib/modules"
 	_ "veyron.io/veyron/veyron/profiles"
 )
@@ -111,9 +110,6 @@
 
 	shell := modules.NewShell()
 	defer shell.Cleanup(os.Stderr, os.Stderr)
-	if os.Getenv(consts.VeyronCredentials) == "" {
-		shell.CreateAndUseNewCredentials()
-	}
 
 	scanner := bufio.NewScanner(os.Stdin)
 	lineno := 1
diff --git a/tools/servicerunner/main.go b/tools/servicerunner/main.go
index 839af0d..861592c 100644
--- a/tools/servicerunner/main.go
+++ b/tools/servicerunner/main.go
@@ -66,16 +66,11 @@
 
 	sh := modules.NewShell()
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	// NOTE(sadovsky): Shell only does this for tests. It would be better if it
-	// either always did it or never did it.
-	if os.Getenv(consts.VeyronCredentials) == "" {
-		panicOnError(sh.CreateAndUseNewCredentials())
-		v, ok := sh.GetVar(consts.VeyronCredentials)
-		if !ok {
-			panic("Missing " + consts.VeyronCredentials)
-		}
-		vars[consts.VeyronCredentials] = v
+	v, ok := sh.GetVar(consts.VeyronCredentials)
+	if !ok {
+		panic("modules.Shell: missing " + consts.VeyronCredentials)
 	}
+	vars[consts.VeyronCredentials] = v
 
 	h, err := sh.Start("root", nil, "--", "--veyron.tcp.address=127.0.0.1:0")
 	panicOnError(err)