blob: ecfaf1651df1c452aa9b0230324dd6dcd3539c15 [file] [log] [blame]
Ankurcf6a89f2014-10-06 18:33:03 -07001package main
2
3import (
4 "bytes"
5 "errors"
6 "fmt"
7 "io"
8 "os"
9 "os/user"
10 "time"
11
Asim Shankar66c52f92014-10-15 23:39:10 -070012 "veyron.io/veyron/veyron2"
Ankurcf6a89f2014-10-06 18:33:03 -070013 "veyron.io/veyron/veyron2/rt"
14 "veyron.io/veyron/veyron2/security"
Ankur1d46f552014-10-09 12:13:31 -070015 "veyron.io/veyron/veyron2/vdl/vdlutil"
Cosmos Nicolaouf889c732014-10-16 20:46:54 -070016
17 "veyron.io/veyron/veyron/lib/cmdline"
18 _ "veyron.io/veyron/veyron/profiles"
19 vsecurity "veyron.io/veyron/veyron/security"
20 "veyron.io/veyron/veyron/services/identity"
21 "veyron.io/veyron/veyron/services/identity/util"
Ankurcf6a89f2014-10-06 18:33:03 -070022)
23
Asim Shankar66c52f92014-10-15 23:39:10 -070024const VEYRON_CREDENTIALS = "VEYRON_CREDENTIALS"
25
Ankurcf6a89f2014-10-06 18:33:03 -070026var (
27 // Flags for the "blessself" command
Asim Shankar66c52f92014-10-15 23:39:10 -070028 flagBlessSelfFor time.Duration
Ankurcf6a89f2014-10-06 18:33:03 -070029
Asim Shankar66c52f92014-10-15 23:39:10 -070030 // Flags for the "bless" command
31 flagBlessFor time.Duration
32 flagBlessWith string
33
34 // Flags for the "seekblessings" command
35 flagSeekBlessingsFrom string
36 flagSeekBlessingsSetDefault bool
37 flagSeekBlessingsForPeer string
38
39 // Flags common to many commands
40 flagAddToRoots bool
Ankur1d46f552014-10-09 12:13:31 -070041
Ankur1615a7d2014-10-09 11:58:02 -070042 cmdDump = &cmdline.Command{
43 Name: "dump",
44 Short: "Dump out information about the principal",
45 Long: `
Asim Shankar66c52f92014-10-15 23:39:10 -070046Prints out information about the principal specified by the environment
Ankur1615a7d2014-10-09 11:58:02 -070047(VEYRON_CREDENTIALS) that this tool is running in.
48`,
49 Run: func(cmd *cmdline.Command, args []string) error {
Asim Shankar66c52f92014-10-15 23:39:10 -070050 p, err := principal()
51 if err != nil {
52 return err
53 }
Ankur1615a7d2014-10-09 11:58:02 -070054 fmt.Printf("Public key : %v\n", p.PublicKey())
Ankur1615a7d2014-10-09 11:58:02 -070055 fmt.Println("---------------- BlessingStore ----------------")
56 fmt.Printf("%v", p.BlessingStore().DebugString())
Ankur1615a7d2014-10-09 11:58:02 -070057 fmt.Println("---------------- BlessingRoots ----------------")
58 fmt.Printf("%v", p.Roots().DebugString())
59 return nil
60 },
61 }
62
Asim Shankar66c52f92014-10-15 23:39:10 -070063 cmdDumpBlessings = &cmdline.Command{
64 Name: "dumpblessings",
65 Short: "Dump out information about the provided blessings",
Ankurcf6a89f2014-10-06 18:33:03 -070066 Long: `
Asim Shankar66c52f92014-10-15 23:39:10 -070067Prints out information about the blessings (typically obtained from this tool)
Ankurcf6a89f2014-10-06 18:33:03 -070068encoded in the provided file.
69`,
70 ArgsName: "<file>",
71 ArgsLong: `
Asim Shankar66c52f92014-10-15 23:39:10 -070072<file> is the path to a file containing blessings typically obtained from
Ankurcf6a89f2014-10-06 18:33:03 -070073this tool. - is used for STDIN.
74`,
75 Run: func(cmd *cmdline.Command, args []string) error {
76 if len(args) != 1 {
77 return fmt.Errorf("requires exactly one argument, <file>, provided %d", len(args))
78 }
79 blessings, err := decodeBlessings(args[0])
80 if err != nil {
81 return fmt.Errorf("failed to decode provided blessings: %v", err)
82 }
Asim Shankar66c52f92014-10-15 23:39:10 -070083 wire := security.MarshalBlessings(blessings)
84 fmt.Printf("Blessings : %v\n", blessings)
85 fmt.Printf("PublicKey : %v\n", blessings.PublicKey())
Asim Shankardf88a2e2014-10-21 17:20:28 -070086 fmt.Printf("Certificate chains : %d\n", len(wire.CertificateChains))
Asim Shankar66c52f92014-10-15 23:39:10 -070087 for idx, chain := range wire.CertificateChains {
Asim Shankardf88a2e2014-10-21 17:20:28 -070088 fmt.Printf("Chain #%d (%d certificates). Root certificate public key: %v\n", idx, len(chain), rootkey(chain))
89 for certidx, cert := range chain {
90 fmt.Printf(" Certificate #%d: %v with ", certidx, cert.Extension)
91 switch n := len(cert.Caveats); n {
92 case 1:
93 fmt.Printf("1 caveat")
94 default:
95 fmt.Printf("%d caveats", n)
96 }
97 fmt.Println("")
98 for cavidx, cav := range cert.Caveats {
99 fmt.Printf(" (%d) %v\n", cavidx, &cav)
100 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700101 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700102 }
Ankurcf6a89f2014-10-06 18:33:03 -0700103 return nil
104 },
105 }
106
107 cmdBlessSelf = &cmdline.Command{
108 Name: "blessself",
109 Short: "Generate a self-signed blessing",
110 Long: `
111Returns a blessing with name <name> and self-signed by the principal
112specified by the environment (VEYRON_CREDENTIALS) that this tool is
113running in. Optionally, the blessing can be restricted with an expiry
114caveat specified using the --for flag.
115`,
116 ArgsName: "[<name>]",
117 ArgsLong: `
118<name> is the name used to create the self-signed blessing. If not
119specified, a name will be generated based on the hostname of the
120machine and the name of the user running this command.
121`,
122 Run: func(cmd *cmdline.Command, args []string) error {
Ankurcf6a89f2014-10-06 18:33:03 -0700123 var name string
124 switch len(args) {
125 case 0:
126 name = defaultBlessingName()
127 case 1:
128 name = args[0]
129 default:
130 return fmt.Errorf("requires at most one argument, provided %d", len(args))
131 }
132
133 var caveats []security.Caveat
Asim Shankar66c52f92014-10-15 23:39:10 -0700134 if flagBlessSelfFor != 0 {
135 cav, err := security.ExpiryCaveat(time.Now().Add(flagBlessSelfFor))
Ankurcf6a89f2014-10-06 18:33:03 -0700136 if err != nil {
Ankur8d304122014-10-07 10:43:43 -0700137 return fmt.Errorf("failed to create expiration Caveat: %v", err)
Ankurcf6a89f2014-10-06 18:33:03 -0700138 }
139 caveats = append(caveats, cav)
140 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700141 p, err := principal()
142 if err != nil {
143 return err
144 }
145 blessing, err := p.BlessSelf(name, caveats...)
Ankurcf6a89f2014-10-06 18:33:03 -0700146 if err != nil {
147 return fmt.Errorf("failed to create self-signed blessing for name %q: %v", name, err)
148 }
149
150 return dumpBlessings(blessing)
151 },
152 }
153
Asim Shankar66c52f92014-10-15 23:39:10 -0700154 cmdBless = &cmdline.Command{
155 Name: "bless",
156 Short: "Bless another principal",
157 Long: `
158 Returns a set of blessings obtained when one principal blesses another.
159
160 The blesser is obtained from the VEYRON_CREDENTIALS environment variable.
161 The principal to be blessed is specified as either a path to the VEYRON_CREDENTIALS directory of the other principal, or the filename (or - for STDIN) of any other blessing of that principal.
162 The blessing that the blesser uses (i.e., which is extended to create the blessing) is the default one from the blessers store, or specified via the --with flag.
163 The blessing is valid only for the duration specified in --for.
164
165 For example, let's say a principal with the default blessing "alice" wants to bless another principal as "alice/bob", the invocation would be:
166 VEYRON_CREDENTIALS=<path to alice> principal bless <path to bob> friend
167 `,
168 ArgsName: "<principal to bless> <extension>",
169 ArgsLong: `
170 <principal to bless> represents the principal to be blessed (i.e., whose public key will be provided with a name).
171 This can either be a path to a file containing any other set of blessings of that principal (or - for STDIN) or the
172 path to the VEYRON_CREDENTIALS directory of that principal.
173
174 <extension> is the string extension that will be applied to create the blessing.
175 `,
176 Run: func(cmd *cmdline.Command, args []string) error {
177 if len(args) != 2 {
178 return fmt.Errorf("require exactly two arguments, provided %d", len(args))
179 }
180 p, err := principal()
181 if err != nil {
182 return err
183 }
184
185 var with security.Blessings
186 if len(flagBlessWith) > 0 {
187 if with, err = decodeBlessings(flagBlessWith); err != nil {
188 return fmt.Errorf("failed to read blessings from --with=%q: %v", flagBlessWith, err)
189 }
190 } else {
191 with = p.BlessingStore().Default()
192 }
193
194 var key security.PublicKey
195 tobless, extension := args[0], args[1]
196 if finfo, err := os.Stat(tobless); err == nil && finfo.IsDir() {
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700197 // TODO(suharshs,ashankar,ataly): How should we make an ecrypted pk... or is that up to the agent?
198 other, err := vsecurity.LoadPersistentPrincipal(tobless, nil)
Asim Shankar66c52f92014-10-15 23:39:10 -0700199 if err != nil {
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700200 if other, err = vsecurity.CreatePersistentPrincipal(tobless, nil); err != nil {
201 return fmt.Errorf("failed to read principal in directory %q: %v", tobless, err)
202 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700203 }
204 key = other.PublicKey()
205 } else if other, err := decodeBlessings(tobless); err != nil {
206 return fmt.Errorf("failed to decode blessings in %q: %v", tobless, err)
207 } else {
208 key = other.PublicKey()
209 }
210
211 caveat, err := security.ExpiryCaveat(time.Now().Add(flagBlessFor))
212 if err != nil {
213 return fmt.Errorf("failed to create ExpirtyCaveat: %v", err)
214 }
215
216 blessings, err := p.Bless(key, with, extension, caveat)
217 if err != nil {
218 return fmt.Errorf("Bless(%v, %v, %q, ExpiryCaveat(%v)) failed: %v", key, with, extension, flagBlessFor, err)
219 }
220 return dumpBlessings(blessings)
221 },
222 }
223
224 cmdStoreForPeer = &cmdline.Command{
225 Name: "forpeer",
Ankurcf6a89f2014-10-06 18:33:03 -0700226 Short: "Return blessings marked for the provided peer",
227 Long: `
228Returns blessings that are marked for the provided peer in the
229BlessingStore specified by the environment (VEYRON_CREDENTIALS)
230that this tool is running in.
231`,
232 ArgsName: "[<peer_1> ... <peer_k>]",
233 ArgsLong: `
234<peer_1> ... <peer_k> are the (human-readable string) blessings bound
235to the peer. The returned blessings are marked with a pattern that is
236matched by at least one of these. If no arguments are specified,
237store.forpeer returns the blessings that are marked for all peers (i.e.,
238blessings set on the store with the "..." pattern).
239`,
240 Run: func(cmd *cmdline.Command, args []string) error {
Asim Shankar66c52f92014-10-15 23:39:10 -0700241 p, err := principal()
242 if err != nil {
243 return err
244 }
245 return dumpBlessings(p.BlessingStore().ForPeer(args...))
Ankurcf6a89f2014-10-06 18:33:03 -0700246 },
247 }
248
Asim Shankar66c52f92014-10-15 23:39:10 -0700249 cmdStoreDefault = &cmdline.Command{
250 Name: "default",
Ankurcf6a89f2014-10-06 18:33:03 -0700251 Short: "Return blessings marked as default",
252 Long: `
253Returns blessings that are marked as default in the BlessingStore
254specified by the environment (VEYRON_CREDENTIALS) that this tool
255is running in.
256`,
257 Run: func(cmd *cmdline.Command, args []string) error {
Asim Shankar66c52f92014-10-15 23:39:10 -0700258 p, err := principal()
259 if err != nil {
260 return err
261 }
262 return dumpBlessings(p.BlessingStore().Default())
Ankurcf6a89f2014-10-06 18:33:03 -0700263 },
264 }
Ankur8d304122014-10-07 10:43:43 -0700265
Asim Shankar66c52f92014-10-15 23:39:10 -0700266 cmdStoreSet = &cmdline.Command{
267 Name: "set",
Ankur8d304122014-10-07 10:43:43 -0700268 Short: "Set provided blessings for peer",
269 Long: `
270Marks the provided blessings to be shared with the provided
271peers on the BlessingStore specified by the environment
272(VEYRON_CREDENTIALS) that this tool is running in.
273
274'set b pattern' marks the intention to reveal b to peers who
275present blessings of their own matching 'pattern'.
276
277'set nil pattern' can be used to remove the blessings previously
278associated with the pattern (by a prior 'set' command).
279
280It is an error to call 'store.set' with blessings whose public
281key does not match the public key of this principal specified
282by the environment.
283`,
284 ArgsName: "<file> <pattern>",
285 ArgsLong: `
286<file> is the path to a file containing a blessing typically obtained
287from this tool. - is used for STDIN.
288
289<pattern> is the BlessingPattern used to identify peers with whom this
290blessing can be shared with.
291`,
292 Run: func(cmd *cmdline.Command, args []string) error {
293 if len(args) != 2 {
Asim Shankar66c52f92014-10-15 23:39:10 -0700294 return fmt.Errorf("requires exactly two arguments <file>, <pattern>, provided %d", len(args))
Ankur8d304122014-10-07 10:43:43 -0700295 }
296 blessings, err := decodeBlessings(args[0])
297 if err != nil {
298 return fmt.Errorf("failed to decode provided blessings: %v", err)
299 }
300 pattern := security.BlessingPattern(args[1])
Asim Shankar66c52f92014-10-15 23:39:10 -0700301 p, err := principal()
302 if err != nil {
303 return err
304 }
305 if _, err := p.BlessingStore().Set(blessings, pattern); err != nil {
Ankur8d304122014-10-07 10:43:43 -0700306 return fmt.Errorf("failed to set blessings %v for peers %v: %v", blessings, pattern, err)
307 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700308 if flagAddToRoots {
309 if err := p.AddToRoots(blessings); err != nil {
310 return fmt.Errorf("AddToRoots failed: %v", err)
311 }
312 }
Ankur8d304122014-10-07 10:43:43 -0700313 return nil
314 },
315 }
316
Asim Shankar66c52f92014-10-15 23:39:10 -0700317 cmdStoreSetDefault = &cmdline.Command{
318 Name: "setdefault",
Ankur8d304122014-10-07 10:43:43 -0700319 Short: "Set provided blessings as default",
320 Long: `
321Sets the provided blessings as default in the BlessingStore specified
322by the environment (VEYRON_CREDENTIALS) that this tool is running in.
323
324It is an error to call 'store.setdefault' with blessings whose public key
325does not match the public key of the principal specified by the environment.
326`,
327 ArgsName: "<file>",
328 ArgsLong: `
329<file> is the path to a file containing a blessing typically obtained from
330this tool. - is used for STDIN.
331`,
332 Run: func(cmd *cmdline.Command, args []string) error {
333 if len(args) != 1 {
Asim Shankar66c52f92014-10-15 23:39:10 -0700334 return fmt.Errorf("requires exactly one argument, <file>, provided %d", len(args))
Ankur8d304122014-10-07 10:43:43 -0700335 }
336 blessings, err := decodeBlessings(args[0])
337 if err != nil {
338 return fmt.Errorf("failed to decode provided blessings: %v", err)
339 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700340 p, err := principal()
341 if err != nil {
342 return err
343 }
344 if err = p.BlessingStore().SetDefault(blessings); err != nil {
Ankur8d304122014-10-07 10:43:43 -0700345 return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
346 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700347 if flagAddToRoots {
348 if err := p.AddToRoots(blessings); err != nil {
349 return fmt.Errorf("AddToRoots failed: %v", err)
350 }
351 }
352 return nil
353 },
354 }
355
356 cmdCreate = &cmdline.Command{
357 Name: "create",
358 Short: "Create a new principal and persist it into a directory",
359 Long: `
360 Creates a new principal with a single self-blessed blessing and writes it out
361 to the provided directory. The same directory can be used to set the VEYRON_CREDENTIALS
362 environment variables for other veyron applications.
363 `,
364 ArgsName: "<directory> <blessing>",
365 ArgsLong: `
366 <directory> is the directory to which the principal will be persisted.
367 <blessing> is the self-blessed blessing that the principal will be setup to use by default.
368 `,
369 Run: func(cmd *cmdline.Command, args []string) error {
370 if len(args) != 2 {
371 return fmt.Errorf("requires exactly two arguments: <directory> and <blessing>, provided %d", len(args))
372 }
373 dir, name := args[0], args[1]
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700374 // TODO(suharshs,ashankar,ataly): How should we make an ecrypted pk... or is that up to the agent?
375 p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
376 if err != nil {
377 return err
Asim Shankar66c52f92014-10-15 23:39:10 -0700378 }
379 blessings, err := p.BlessSelf(name)
380 if err != nil {
381 return fmt.Errorf("BlessSelf(%q) failed: %v", name, err)
382 }
383 if err := p.BlessingStore().SetDefault(blessings); err != nil {
384 return fmt.Errorf("BlessingStore.SetDefault(%v) failed: %v", blessings, err)
385 }
386 if _, err := p.BlessingStore().Set(blessings, security.AllPrincipals); err != nil {
387 return fmt.Errorf("BlessingStore.Set(%v, %q) failed: %v", blessings, security.AllPrincipals, err)
388 }
389 if err := p.AddToRoots(blessings); err != nil {
390 return fmt.Errorf("AddToRoots(%v) failed: %v", blessings, err)
391 }
392 fmt.Printf("%s=%q\n", VEYRON_CREDENTIALS, dir)
Ankur8d304122014-10-07 10:43:43 -0700393 return nil
394 },
395 }
Ankur1d46f552014-10-09 12:13:31 -0700396
397 cmdSeekBlessings = &cmdline.Command{
398 Name: "seekblessings",
399 Short: "Seek blessings from a web-based Veyron blesser",
400 Long: `
401Seeks blessings from a web-based Veyron blesser which
402requires the caller to first authenticate with Google using OAuth. Simply
403run the command to see what happens.
404
405The blessings are sought for the principal specified by the environment
406(VEYRON_CREDENTIALS) that this tool is running in.
407
408The blessings obtained are set as default, unless a --skip_set_default flag
409is provided, and are also set for sharing with all peers, unless a more
410specific peer pattern is provided using the --for_peer flag.
411`,
412 Run: func(cmd *cmdline.Command, args []string) error {
Asim Shankar08ab3892014-10-16 12:04:07 -0700413 // Initialize the runtime first so that any local errors are reported
414 // before the HTTP roundtrips for obtaining the macaroon begin.
415 r, err := runtime()
416 if err != nil {
417 return err
418 }
Ankur1d46f552014-10-09 12:13:31 -0700419 blessedChan := make(chan string)
420 defer close(blessedChan)
Asim Shankar66c52f92014-10-15 23:39:10 -0700421 macaroonChan, err := getMacaroonForBlessRPC(flagSeekBlessingsFrom, blessedChan)
Ankur1d46f552014-10-09 12:13:31 -0700422 if err != nil {
423 return fmt.Errorf("failed to get macaroon from Veyron blesser: %v", err)
424 }
425 macaroon := <-macaroonChan
426 service := <-macaroonChan
Asim Shankar66c52f92014-10-15 23:39:10 -0700427 ctx, cancel := r.NewContext().WithTimeout(time.Minute)
Ankur1d46f552014-10-09 12:13:31 -0700428 defer cancel()
429
430 var reply vdlutil.Any
431 blesser, err := identity.BindMacaroonBlesser(service)
432 if err == nil {
433 reply, err = blesser.Bless(ctx, macaroon)
434 }
435 if err != nil {
436 return fmt.Errorf("failed to get blessing from %q: %v", service, err)
437 }
438 wire, ok := reply.(security.WireBlessings)
439 if !ok {
440 return fmt.Errorf("received %T, want security.WireBlessings", reply)
441 }
442 blessings, err := security.NewBlessings(wire)
443 if err != nil {
444 return fmt.Errorf("failed to construct Blessings object from wire data: %v", err)
445 }
446 blessedChan <- fmt.Sprint(blessings)
447 // Wait for getTokenForBlessRPC to clean up:
448 <-macaroonChan
449
Asim Shankar66c52f92014-10-15 23:39:10 -0700450 if flagSeekBlessingsSetDefault {
451 if err := r.Principal().BlessingStore().SetDefault(blessings); err != nil {
Ankur1d46f552014-10-09 12:13:31 -0700452 return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
453 }
454 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700455 if pattern := security.BlessingPattern(flagSeekBlessingsForPeer); len(pattern) > 0 {
456 if _, err := r.Principal().BlessingStore().Set(blessings, pattern); err != nil {
457 return fmt.Errorf("failed to set blessings %v for peers %v: %v", blessings, pattern, err)
458 }
459 }
460 if flagAddToRoots {
461 if err := r.Principal().AddToRoots(blessings); err != nil {
462 return fmt.Errorf("AddToRoots failed: %v", err)
463 }
Ankur1d46f552014-10-09 12:13:31 -0700464 }
465 return dumpBlessings(blessings)
466 },
467 }
Ankurcf6a89f2014-10-06 18:33:03 -0700468)
469
470func main() {
Asim Shankar66c52f92014-10-15 23:39:10 -0700471 cmdBlessSelf.Flags.DurationVar(&flagBlessSelfFor, "for", 0, "Duration of blessing validity (zero means no that the blessing is always valid)")
472 cmdBless.Flags.DurationVar(&flagBlessFor, "for", time.Minute, "Duration of blessing validity")
473 cmdBless.Flags.StringVar(&flagBlessWith, "with", "", "Path to file containing blessing to extend. ")
474 cmdSeekBlessings.Flags.StringVar(&flagSeekBlessingsFrom, "from", "https://proxy.envyor.com:8125/google", "URL to use to begin the seek blessings process")
475 cmdSeekBlessings.Flags.BoolVar(&flagSeekBlessingsSetDefault, "set_default", true, "If true, the blessings obtained will be set as the default blessing in the store")
476 cmdSeekBlessings.Flags.StringVar(&flagSeekBlessingsForPeer, "for_peer", string(security.AllPrincipals), "If non-empty, the blessings obtained will be marked for peers matching this pattern in the store")
477 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")
478 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")
479 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")
480
481 cmdStore := &cmdline.Command{
482 Name: "store",
483 Short: "Manipulate and inspect the principal's blessing store",
484 Long: `
485Commands to manipulate and inspect the blessing store of the principal.
486
487All blessings are printed to stdout using base64-VOM-encoding
488`,
489 Children: []*cmdline.Command{cmdStoreDefault, cmdStoreSetDefault, cmdStoreForPeer, cmdStoreSet},
Ankurcf6a89f2014-10-06 18:33:03 -0700490 }
Ankurcf6a89f2014-10-06 18:33:03 -0700491
492 (&cmdline.Command{
493 Name: "principal",
494 Short: "Create and manage veyron principals",
495 Long: `
496The principal tool helps create and manage blessings and the set of trusted
497roots bound to a principal.
498
499All objects are printed using base64-VOM-encoding.
500`,
Asim Shankar66c52f92014-10-15 23:39:10 -0700501 Children: []*cmdline.Command{cmdCreate, cmdSeekBlessings, cmdDump, cmdDumpBlessings, cmdBlessSelf, cmdBless, cmdStore},
Ankurcf6a89f2014-10-06 18:33:03 -0700502 }).Main()
503}
504
Asim Shankar66c52f92014-10-15 23:39:10 -0700505func runtime() (veyron2.Runtime, error) {
506 if len(os.Getenv(VEYRON_CREDENTIALS)) == 0 {
507 return nil, fmt.Errorf("VEYRON_CREDENTIALS environment variable must be set")
508 }
509 return rt.Init(), nil
510}
511
512func principal() (security.Principal, error) {
513 r, err := runtime()
514 if err != nil {
515 return nil, err
516 }
517 return r.Principal(), nil
518}
519
Ankurcf6a89f2014-10-06 18:33:03 -0700520func decodeBlessings(fname string) (security.Blessings, error) {
521 var wire security.WireBlessings
522 if err := decode(fname, &wire); err != nil {
523 return nil, err
524 }
525 return security.NewBlessings(wire)
526}
527
528func dumpBlessings(blessings security.Blessings) error {
529 if blessings == nil {
530 return errors.New("no blessings found")
531 }
532 str, err := util.Base64VomEncode(blessings)
533 if err != nil {
534 return fmt.Errorf("base64-VOM encoding failed: %v", err)
535 }
536 fmt.Println(str)
537 return nil
538}
539
540func read(fname string) (string, error) {
541 if len(fname) == 0 {
542 return "", nil
543 }
544 f := os.Stdin
545 if fname != "-" {
546 var err error
547 if f, err = os.Open(fname); err != nil {
548 return "", fmt.Errorf("failed to open %q: %v", fname, err)
549 }
550 }
551 defer f.Close()
552 var buf bytes.Buffer
553 if _, err := io.Copy(&buf, f); err != nil {
554 return "", fmt.Errorf("failed to read %q: %v", fname, err)
555 }
556 return buf.String(), nil
557}
558
559func decode(fname string, val interface{}) error {
560 str, err := read(fname)
561 if err != nil {
562 return err
563 }
564 if err := util.Base64VomDecode(str, val); err != nil || val == nil {
565 return fmt.Errorf("failed to decode %q: %v", fname, err)
566 }
567 return nil
568}
569
570func defaultBlessingName() string {
571 var name string
572 if user, _ := user.Current(); user != nil && len(user.Username) > 0 {
573 name = user.Username
574 } else {
575 name = "anonymous"
576 }
577 if host, _ := os.Hostname(); len(host) > 0 {
578 name = name + "@" + host
579 }
580 return name
581}
Asim Shankardf88a2e2014-10-21 17:20:28 -0700582
583func rootkey(chain []security.Certificate) string {
584 if len(chain) == 0 {
585 return "<empty certificate chain>"
586 }
587 key, err := security.UnmarshalPublicKey(chain[0].PublicKey)
588 if err != nil {
589 return fmt.Sprintf("<invalid PublicKey: %v>", err)
590 }
591 return fmt.Sprintf("%v", key)
592}