"veyron/tools/principal": Overwrite flag for create

At the moment, the create command on the principal tools
complains if it is provided with a directly that already
contains a principal object. This causes some inconvenience
in tests and tutorials.

This CL resolves the issues by adding a --overwrite flag to
the principal that overwrites any existing principal data in
the directory.

Change-Id: I08ed5abb89c4a2d74de42586846b49df73a6f0f4
diff --git a/security/principal.go b/security/principal.go
index a351f00..ab23b09 100644
--- a/security/principal.go
+++ b/security/principal.go
@@ -57,21 +57,49 @@
 	return newPersistentPrincipalFromSigner(security.NewInMemoryECDSASigner(key), dir)
 }
 
-// CreatePersistentPrincipal creates a new principal (private key, BlessingRoots, BlessingStore) and commits all state changes to the provided directory.
-// The generated private key is serialized and saved encrypted if the 'passphrase' is non-nil, and unencrypted otherwise.
-// If the directory has any preexisting key, CreatePersistentPrincipal will return an error.
-// The specified directory may not exist, in which case it gets created by this function.
-func CreatePersistentPrincipal(dir string, passphrase []byte) (security.Principal, error) {
+// CreatePersistentPrincipal creates a new principal (private key, BlessingRoots,
+// BlessingStore) and commits all state changes to the provided directory.
+//
+// The generated private key is serialized and saved encrypted if the 'passphrase'
+// is non-nil, and unencrypted otherwise.
+//
+// If the directory has any preexisting principal data, CreatePersistentPrincipal
+// will return an error.
+//
+// The specified directory may not exist, in which case it gets created by this
+// function.
+func CreatePersistentPrincipal(dir string, passphrase []byte) (principal security.Principal, err error) {
 	if err := mkDir(dir); err != nil {
 		return nil, err
 	}
 	key, err := initKey(dir, nil)
 	if err != nil {
-		return nil, fmt.Errorf("could not initialize private key from credentials directory %v: %v", dir, err)
+		return nil, fmt.Errorf("failed to initialize private key: %v", err)
 	}
 	return newPersistentPrincipalFromSigner(security.NewInMemoryECDSASigner(key), dir)
 }
 
+// CreateOrOverwritePersistentPrincipal behaves like CreatePersistentPrincipal except that
+// if the provided directory holds any preexisting principal data then the data gets
+// overwritten.  Any prexising private key, BlessingRoots and BlessingStore would get lost
+// as a result of calling this function.
+func CreateOrOverwritePersistentPrincipal(dir string, passphrase []byte) (principal security.Principal, err error) {
+	if err := removePersistentPrincipal(dir); err != nil {
+		return nil, err
+	}
+	return CreatePersistentPrincipal(dir, passphrase)
+}
+
+func removePersistentPrincipal(dir string) error {
+	files := []string{privateKeyFile, blessingRootsDataFile, blessingRootsSigFile, blessingStoreDataFile, blessingStoreSigFile}
+	for _, f := range files {
+		if err := os.Remove(path.Join(dir, f)); err != nil && !os.IsNotExist(err) {
+			return err
+		}
+	}
+	return nil
+}
+
 func newPersistentPrincipalFromSigner(signer security.Signer, dir string) (security.Principal, error) {
 	serializationSigner, err := security.CreatePrincipal(signer, nil, nil)
 	if err != nil {
@@ -124,7 +152,6 @@
 
 func initKey(dir string, passphrase []byte) (*ecdsa.PrivateKey, error) {
 	keyFile := path.Join(dir, privateKeyFile)
-	// O_EXCL returns an error if file exists.
 	f, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
 	if err != nil {
 		return nil, fmt.Errorf("failed to open %q for writing: %v", keyFile, err)
diff --git a/security/principal_test.go b/security/principal_test.go
index d2d18ce..467d37a 100644
--- a/security/principal_test.go
+++ b/security/principal_test.go
@@ -66,20 +66,25 @@
 	if err != nil {
 		t.Fatal(err)
 	}
+	p, err = CreatePersistentPrincipal(dir, passphrase)
+	if err == nil {
+		t.Error("CreatePersistentPrincipal passed unexpectedly")
+	}
+	p, err = CreateOrOverwritePersistentPrincipal(dir, passphrase)
+	if err != nil {
+		t.Errorf("CreateOrOverwritePersistentPrincipal failed unexpectedly: %v", err)
+	}
+
 	sig, err := p.Sign(message)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	p2, err := CreatePersistentPrincipal(dir, passphrase)
-	if err == nil {
-		t.Errorf("p2 CreatePersistentPrincipal should have failed")
-	}
-	p2, err = LoadPersistentPrincipal(dir, passphrase)
+	p2, err := LoadPersistentPrincipal(dir, passphrase)
 	if err != nil {
 		t.Fatal(err)
 	}
-	if !sig.Verify(p.PublicKey(), message) {
+	if !sig.Verify(p2.PublicKey(), message) {
 		t.Errorf("%s failed: p.PublicKey=%v, p2.PublicKey=%v", message, p.PublicKey(), p2.PublicKey())
 	}
 }
diff --git a/tools/principal/main.go b/tools/principal/main.go
index ecfaf16..d2bebca 100644
--- a/tools/principal/main.go
+++ b/tools/principal/main.go
@@ -36,6 +36,9 @@
 	flagSeekBlessingsSetDefault bool
 	flagSeekBlessingsForPeer    string
 
+	// Flag for the create command
+	flagCreateOverwrite bool
+
 	// Flags common to many commands
 	flagAddToRoots bool
 
@@ -357,10 +360,14 @@
 		Name:  "create",
 		Short: "Create a new principal and persist it into a directory",
 		Long: `
-	Creates a new principal with a single self-blessed blessing and writes it out
-	to the provided directory. The same directory can be used to set the VEYRON_CREDENTIALS
-	environment variables for other veyron applications.
-	`,
+Creates a new principal with a single self-blessed blessing and writes it out
+to the provided directory. The same directory can be used to set the VEYRON_CREDENTIALS
+environment variables for other veyron applications.
+
+The operation fails if the directory already contains a principal. In this case
+the --overwrite flag can be provided to overwrite the existing principal data in
+the directory.
+`,
 		ArgsName: "<directory> <blessing>",
 		ArgsLong: `
 	<directory> is the directory to which the principal will be persisted.
@@ -372,7 +379,15 @@
 			}
 			dir, name := args[0], args[1]
 			// TODO(suharshs,ashankar,ataly): How should we make an ecrypted pk... or is that up to the agent?
-			p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
+			var (
+				p   security.Principal
+				err error
+			)
+			if flagCreateOverwrite {
+				p, err = vsecurity.CreateOrOverwritePersistentPrincipal(dir, nil)
+			} else {
+				p, err = vsecurity.CreatePersistentPrincipal(dir, nil)
+			}
 			if err != nil {
 				return err
 			}
@@ -477,6 +492,7 @@
 	cmdSeekBlessings.Flags.BoolVar(&flagAddToRoots, "add_to_roots", true, "If true, the root certificate of the blessing will be added to the principal's set of recognized root certificates")
 	cmdStoreSet.Flags.BoolVar(&flagAddToRoots, "add_to_roots", true, "If true, the root certificate of the blessing will be added to the principal's set of recognized root certificates")
 	cmdStoreSetDefault.Flags.BoolVar(&flagAddToRoots, "add_to_roots", true, "If true, the root certificate of the blessing will be added to the principal's set of recognized root certificates")
+	cmdCreate.Flags.BoolVar(&flagCreateOverwrite, "overwrite", false, "If true, any existing principal data in the directory will be overwritten")
 
 	cmdStore := &cmdline.Command{
 		Name:  "store",
diff --git a/tools/principal/test.sh b/tools/principal/test.sh
index 9d26963..c5afe4a 100755
--- a/tools/principal/test.sh
+++ b/tools/principal/test.sh
@@ -36,8 +36,9 @@
   # Prevent any VEYRON_CREDENTIALS in the environment from interfering with this test.
   unset VEYRON_CREDENTIALS
   # Create two principals, one called "alice" one called "bob"
-  ./principal create ./alice alice >/dev/null || shell_test::fail "line ${LINENO}: create failed"
+  ./principal create --overwrite=true ./alice alice >/dev/null || shell_test::fail "line ${LINENO}: create failed"
   ./principal create ./bob bob >/dev/null || shell_test::fail "line ${LINENO}: create failed"
+  ./principal create --overwrite=true ./bob bob >/dev/null || shell_test::fail "line ${LINENO}: create failed"
   # Run dump, bless, blessself on alice
   export VEYRON_CREDENTIALS=./alice
   ./principal blessself alicereborn >alice.blessself || shell_test::fail "line ${LINENO}: blessself failed"