"veyron/tools/principal": Fork Command
In order to make it easy to set up a new credentials directory
that is blessed by an existing principal (e.g., setting up an
'alice-phone' directory blessed by 'alice'), this CL adds the
'fork' command to the principal tool.
Usage:
principal --veyron.credentials=<parent dir> <child-dir> <extension>
This command populates <child-dir> with a new principal that is
blessed by the principal in <parent-dir>. <child-dir> must not have
a principal already specified in it unless an --overwrite flag is
provided. The blessing for <child-dir> comes form the default blessing
of the <parent-dir> principal, unless a --with flag is provided.
Change-Id: Icfe53c551ac0a0d9083b5280b0cc4b6a9a9d2ede
diff --git a/tools/principal/main.go b/tools/principal/main.go
index dfbfd1a..62b4f61 100644
--- a/tools/principal/main.go
+++ b/tools/principal/main.go
@@ -39,11 +39,9 @@
flagSeekBlessingsSetDefault bool
flagSeekBlessingsForPeer string
- // Flag for the create command
- flagCreateOverwrite bool
-
// Flags common to many commands
- flagAddToRoots bool
+ flagAddToRoots bool
+ flagCreateOverwrite bool
// Flags for the "recvblessings" command
flagRecvBlessingsSetDefault bool
@@ -172,7 +170,7 @@
Long: `
Bless another principal.
-The blesser is obtained from the runtime this tool is using. The blessing that
+The blesser is obtained from the runtime this tool is using. The blessing that
will be extended is the default one from the blesser's store, or specified by
the --with flag. Caveats on the blessing are controlled via the --for flag.
@@ -456,16 +454,16 @@
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.
+to the provided directory. The same directory can then be used to set the
+VEYRON_CREDENTIALS environment variable for other veyron applications.
The operation fails if the directory already contains a principal. In this case
-the --overwrite flag can be provided to clear the directory and write out a
+the --overwrite flag can be provided to clear the directory and write out the
new principal.
`,
ArgsName: "<directory> <blessing>",
ArgsLong: `
- <directory> is the directory to which the principal will be persisted.
+ <directory> is the directory to which the new principal will be persisted.
<blessing> is the self-blessed blessing that the principal will be setup to use by default.
`,
Run: func(cmd *cmdline.Command, args []string) error {
@@ -474,18 +472,12 @@
}
dir, name := args[0], args[1]
// TODO(suharshs,ashankar,ataly): How should we make an ecrypted pk... or is that up to the agent?
- var (
- p security.Principal
- err error
- )
if flagCreateOverwrite {
- if err = os.RemoveAll(dir); err != nil {
+ if err := os.RemoveAll(dir); err != nil {
return err
}
- p, err = vsecurity.CreatePersistentPrincipal(dir, nil)
- } else {
- p, err = vsecurity.CreatePersistentPrincipal(dir, nil)
}
+ p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
if err != nil {
return err
}
@@ -493,14 +485,81 @@
if err != nil {
return fmt.Errorf("BlessSelf(%q) failed: %v", name, err)
}
- if err := p.BlessingStore().SetDefault(blessings); err != nil {
- return fmt.Errorf("BlessingStore.SetDefault(%v) failed: %v", blessings, err)
+ if err := vsecurity.SetDefaultBlessings(p, blessings); err != nil {
+ return fmt.Errorf("could not set blessings %v as default: %v", blessings, err)
}
- if _, err := p.BlessingStore().Set(blessings, security.AllPrincipals); err != nil {
- return fmt.Errorf("BlessingStore.Set(%v, %q) failed: %v", blessings, security.AllPrincipals, err)
+ return nil
+ },
+ }
+
+ cmdFork = &cmdline.Command{
+ Name: "fork",
+ Short: "Fork a new principal from the principal that this tool is running as and persist it into a directory",
+ Long: `
+Creates a new principal with a blessing from the principal specified by the
+environment that this tool is running in, and writes it out to the provided
+directory. The blessing that will be extended is the default one from the
+blesser's store, or specified by the --with flag. Caveats on the blessing
+are controlled via the --for flag. The blessing is marked as default and
+shareable with all peers on the new principal's blessing store.
+
+The operation fails if the directory already contains a principal. In this case
+the --overwrite flag can be provided to clear the directory and write out the
+forked principal.
+`,
+ ArgsName: "<directory> <extension>",
+ ArgsLong: `
+ <directory> is the directory to which the forked principal will be persisted.
+ <extension> is the extension under which the forked principal is blessed.
+ `,
+ Run: func(cmd *cmdline.Command, args []string) error {
+ if len(args) != 2 {
+ return fmt.Errorf("requires exactly two arguments: <directory> and <extension>, provided %d", len(args))
}
- if err := p.AddToRoots(blessings); err != nil {
- return fmt.Errorf("AddToRoots(%v) failed: %v", blessings, err)
+ dir, extension := args[0], args[1]
+
+ if flagCreateOverwrite {
+ if err := os.RemoveAll(dir); err != nil {
+ return err
+ }
+ }
+ p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
+ if err != nil {
+ return err
+ }
+
+ runtime, err := rt.New()
+ if err != nil {
+ return err
+ }
+ defer runtime.Cleanup()
+
+ var (
+ with security.Blessings
+ caveats []security.Caveat
+ )
+ if len(flagBlessWith) > 0 {
+ if with, err = decodeBlessings(flagBlessWith); err != nil {
+ return fmt.Errorf("failed to read blessings from --with=%q: %v", flagBlessWith, err)
+ }
+ } else {
+ with = runtime.Principal().BlessingStore().Default()
+ }
+ if c, err := security.ExpiryCaveat(time.Now().Add(flagBlessFor)); err != nil {
+ return fmt.Errorf("failed to create ExpiryCaveat: %v", err)
+ } else {
+ caveats = append(caveats, c)
+ }
+ // TODO(ashankar,ataly,suharshs): Work out how to add additional caveats, like maybe
+ // revocation, method etc.
+
+ key := p.PublicKey()
+ blessings, err := runtime.Principal().Bless(key, with, extension, caveats[0], caveats[1:]...)
+ if err != nil {
+ return fmt.Errorf("Bless(%v, %v, %q, ...) failed: %v", key, with, extension, err)
+ }
+ if err := vsecurity.SetDefaultBlessings(p, blessings); err != nil {
+ return fmt.Errorf("could not set blessings %v as default: %v", blessings, err)
}
return nil
},
@@ -671,6 +730,9 @@
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")
+ cmdFork.Flags.BoolVar(&flagCreateOverwrite, "overwrite", false, "If true, any existing principal data in the directory will be overwritten")
+ cmdFork.Flags.DurationVar(&flagBlessFor, "for", time.Minute, "Duration of blessing validity")
+ cmdFork.Flags.StringVar(&flagBlessWith, "with", "", "Path to file containing blessing to extend")
cmdRecvBlessings.Flags.BoolVar(&flagRecvBlessingsSetDefault, "set_default", true, "If true, the blessings received will be set as the default blessing in the store")
cmdRecvBlessings.Flags.StringVar(&flagRecvBlessingsForPeer, "for_peer", string(security.AllPrincipals), "If non-empty, the blessings received will be marked for peers matching this pattern in the store")
@@ -695,7 +757,7 @@
All objects are printed using base64-VOM-encoding.
`,
- Children: []*cmdline.Command{cmdCreate, cmdSeekBlessings, cmdRecvBlessings, cmdDump, cmdDumpBlessings, cmdBlessSelf, cmdBless, cmdStore},
+ Children: []*cmdline.Command{cmdCreate, cmdFork, cmdSeekBlessings, cmdRecvBlessings, cmdDump, cmdDumpBlessings, cmdBlessSelf, cmdBless, cmdStore},
}).Main()
}