blob: baa3d68aecad6a632f36cd5bff347b8aa434a35c [file] [log] [blame]
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -08001// The following enables go generate to generate the doc.go file.
2//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/lib/cmdline/testdata/gendoc.go .
3
Ankurcf6a89f2014-10-06 18:33:03 -07004package main
5
6import (
7 "bytes"
Asim Shankarf11b1bc2014-11-12 17:18:45 -08008 "crypto/rand"
9 "crypto/subtle"
Asim Shankarb3a82ba2014-10-29 11:41:27 -070010 "encoding/base64"
Ankurcf6a89f2014-10-06 18:33:03 -070011 "errors"
12 "fmt"
13 "io"
14 "os"
15 "os/user"
16 "time"
17
Matt Rosencrantza5ad2722015-01-22 11:17:47 -080018 _ "v.io/core/veyron/profiles/static"
Jiri Simsa764efb72014-12-25 20:57:03 -080019 vsecurity "v.io/core/veyron/security"
Jiri Simsa764efb72014-12-25 20:57:03 -080020 "v.io/core/veyron2"
Matt Rosencrantz89445a42015-01-05 13:32:37 -080021 "v.io/core/veyron2/context"
Jiri Simsa764efb72014-12-25 20:57:03 -080022 "v.io/core/veyron2/ipc"
Jiri Simsa764efb72014-12-25 20:57:03 -080023 "v.io/core/veyron2/security"
Todd Wang3425a902015-01-21 18:43:59 -080024 "v.io/core/veyron2/vom"
Todd Wang478fcf92014-12-26 12:37:37 -080025 "v.io/lib/cmdline"
Ankurcf6a89f2014-10-06 18:33:03 -070026)
27
28var (
29 // Flags for the "blessself" command
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -080030 flagBlessSelfCaveats caveatsFlag
31 flagBlessSelfFor time.Duration
Ankurcf6a89f2014-10-06 18:33:03 -070032
Asim Shankar66c52f92014-10-15 23:39:10 -070033 // Flags for the "bless" command
Asim Shankara0bba462015-02-20 22:50:51 -080034 flagBlessCaveats caveatsFlag
35 flagBlessFor time.Duration
36 flagBlessRequireCaveats bool
37 flagBlessWith string
38 flagBlessRemoteKey string
39 flagBlessRemoteToken string
Asim Shankar66c52f92014-10-15 23:39:10 -070040
Ankur77c32ac2014-12-18 14:18:19 -080041 // Flags for the "fork" command
Asim Shankara0bba462015-02-20 22:50:51 -080042 flagForkCaveats caveatsFlag
43 flagForkFor time.Duration
44 flagForkRequireCaveats bool
45 flagForkWith string
Ankur77c32ac2014-12-18 14:18:19 -080046
Asim Shankar66c52f92014-10-15 23:39:10 -070047 // Flags for the "seekblessings" command
48 flagSeekBlessingsFrom string
49 flagSeekBlessingsSetDefault bool
50 flagSeekBlessingsForPeer string
Suharsh Sivakumara76dba62014-12-22 16:00:34 -080051 flagSeekBlessingsBrowser bool
Asim Shankar66c52f92014-10-15 23:39:10 -070052
53 // Flags common to many commands
Ankurc24ff422014-12-16 17:59:26 -080054 flagAddToRoots bool
55 flagCreateOverwrite bool
Ankur1d46f552014-10-09 12:13:31 -070056
Ankure548f392014-12-08 18:42:41 -080057 // Flags for the "recvblessings" command
58 flagRecvBlessingsSetDefault bool
59 flagRecvBlessingsForPeer string
60
Asim Shankara0bba462015-02-20 22:50:51 -080061 errNoCaveats = fmt.Errorf("no caveats provided: it is generally dangerous to bless another principal without any caveats as that gives them almost unrestricted access to the blesser's credentials. If you really want to do this, set --nocaveats")
62 cmdDump = &cmdline.Command{
Ankur1615a7d2014-10-09 11:58:02 -070063 Name: "dump",
64 Short: "Dump out information about the principal",
65 Long: `
Asim Shankar66c52f92014-10-15 23:39:10 -070066Prints out information about the principal specified by the environment
Asim Shankar1789b8a2014-10-31 17:31:41 -070067that this tool is running in.
Ankur1615a7d2014-10-09 11:58:02 -070068`,
69 Run: func(cmd *cmdline.Command, args []string) error {
Matt Rosencrantza5ad2722015-01-22 11:17:47 -080070 ctx, shutdown := veyron2.Init()
71 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -080072
Matt Rosencrantza5ad2722015-01-22 11:17:47 -080073 p := veyron2.GetPrincipal(ctx)
Ankur1615a7d2014-10-09 11:58:02 -070074 fmt.Printf("Public key : %v\n", p.PublicKey())
Ankur1615a7d2014-10-09 11:58:02 -070075 fmt.Println("---------------- BlessingStore ----------------")
76 fmt.Printf("%v", p.BlessingStore().DebugString())
Ankur1615a7d2014-10-09 11:58:02 -070077 fmt.Println("---------------- BlessingRoots ----------------")
78 fmt.Printf("%v", p.Roots().DebugString())
79 return nil
80 },
81 }
82
Asim Shankar66c52f92014-10-15 23:39:10 -070083 cmdDumpBlessings = &cmdline.Command{
84 Name: "dumpblessings",
85 Short: "Dump out information about the provided blessings",
Ankurcf6a89f2014-10-06 18:33:03 -070086 Long: `
Asim Shankar66c52f92014-10-15 23:39:10 -070087Prints out information about the blessings (typically obtained from this tool)
Ankurcf6a89f2014-10-06 18:33:03 -070088encoded in the provided file.
89`,
90 ArgsName: "<file>",
91 ArgsLong: `
Asim Shankar66c52f92014-10-15 23:39:10 -070092<file> is the path to a file containing blessings typically obtained from
Ankurcf6a89f2014-10-06 18:33:03 -070093this tool. - is used for STDIN.
94`,
95 Run: func(cmd *cmdline.Command, args []string) error {
96 if len(args) != 1 {
97 return fmt.Errorf("requires exactly one argument, <file>, provided %d", len(args))
98 }
99 blessings, err := decodeBlessings(args[0])
100 if err != nil {
101 return fmt.Errorf("failed to decode provided blessings: %v", err)
102 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700103 wire := security.MarshalBlessings(blessings)
104 fmt.Printf("Blessings : %v\n", blessings)
105 fmt.Printf("PublicKey : %v\n", blessings.PublicKey())
Asim Shankardf88a2e2014-10-21 17:20:28 -0700106 fmt.Printf("Certificate chains : %d\n", len(wire.CertificateChains))
Asim Shankar66c52f92014-10-15 23:39:10 -0700107 for idx, chain := range wire.CertificateChains {
Asim Shankardf88a2e2014-10-21 17:20:28 -0700108 fmt.Printf("Chain #%d (%d certificates). Root certificate public key: %v\n", idx, len(chain), rootkey(chain))
109 for certidx, cert := range chain {
110 fmt.Printf(" Certificate #%d: %v with ", certidx, cert.Extension)
111 switch n := len(cert.Caveats); n {
112 case 1:
113 fmt.Printf("1 caveat")
114 default:
115 fmt.Printf("%d caveats", n)
116 }
117 fmt.Println("")
118 for cavidx, cav := range cert.Caveats {
119 fmt.Printf(" (%d) %v\n", cavidx, &cav)
120 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700121 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700122 }
Ankurcf6a89f2014-10-06 18:33:03 -0700123 return nil
124 },
125 }
126
127 cmdBlessSelf = &cmdline.Command{
128 Name: "blessself",
129 Short: "Generate a self-signed blessing",
130 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700131Returns a blessing with name <name> and self-signed by the principal specified
132by the environment that this tool is running in. Optionally, the blessing can
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800133be restricted with an expiry caveat specified using the --for flag. Additional
134caveats can be added with the --caveat flag.
Ankurcf6a89f2014-10-06 18:33:03 -0700135`,
136 ArgsName: "[<name>]",
137 ArgsLong: `
138<name> is the name used to create the self-signed blessing. If not
139specified, a name will be generated based on the hostname of the
140machine and the name of the user running this command.
141`,
142 Run: func(cmd *cmdline.Command, args []string) error {
Ankurcf6a89f2014-10-06 18:33:03 -0700143 var name string
144 switch len(args) {
145 case 0:
146 name = defaultBlessingName()
147 case 1:
148 name = args[0]
149 default:
150 return fmt.Errorf("requires at most one argument, provided %d", len(args))
151 }
152
Asim Shankara0bba462015-02-20 22:50:51 -0800153 caveats, err := caveatsFromFlags(flagBlessSelfFor, &flagBlessSelfCaveats)
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800154 if err != nil {
Asim Shankara0bba462015-02-20 22:50:51 -0800155 return err
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800156 }
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800157 ctx, shutdown := veyron2.Init()
158 defer shutdown()
159 principal := veyron2.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800160 blessing, err := principal.BlessSelf(name, caveats...)
Ankurcf6a89f2014-10-06 18:33:03 -0700161 if err != nil {
162 return fmt.Errorf("failed to create self-signed blessing for name %q: %v", name, err)
163 }
164
165 return dumpBlessings(blessing)
166 },
167 }
168
Asim Shankar66c52f92014-10-15 23:39:10 -0700169 cmdBless = &cmdline.Command{
170 Name: "bless",
171 Short: "Bless another principal",
172 Long: `
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800173Bless another principal.
Asim Shankar66c52f92014-10-15 23:39:10 -0700174
Ankurc24ff422014-12-16 17:59:26 -0800175The blesser is obtained from the runtime this tool is using. The blessing that
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800176will be extended is the default one from the blesser's store, or specified by
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800177the --with flag. Expiration on the blessing are controlled via the --for flag.
178Additional caveats are controlled with the --caveat flag.
Asim Shankar66c52f92014-10-15 23:39:10 -0700179
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800180For example, let's say a principal "alice" wants to bless another principal "bob"
181as "alice/friend", the invocation would be:
182 VEYRON_CREDENTIALS=<path to alice> principal bless <path to bob> friend
183and this will dump the blessing to STDOUT.
184
185With the --remote_key and --remote_token flags, this command can be used to
186bless a principal on a remote machine as well. In this case, the blessing is
187not dumped to STDOUT but sent to the remote end. Use 'principal help
188recvblessings' for more details on that.
189`,
Asim Shankar66c52f92014-10-15 23:39:10 -0700190 ArgsName: "<principal to bless> <extension>",
191 ArgsLong: `
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800192<principal to bless> represents the principal to be blessed (i.e., whose public
193key will be provided with a name). This can be either:
194(a) The directory containing credentials for that principal,
195OR
196(b) The filename (- for STDIN) containing any other blessings of that
197 principal,
198OR
199(c) The object name produced by the 'recvblessings' command of this tool
200 running on behalf of another principal (if the --remote_key and
201 --remote_token flags are specified).
Asim Shankar66c52f92014-10-15 23:39:10 -0700202
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800203<extension> is the string extension that will be applied to create the
204blessing.
Asim Shankar66c52f92014-10-15 23:39:10 -0700205 `,
206 Run: func(cmd *cmdline.Command, args []string) error {
207 if len(args) != 2 {
208 return fmt.Errorf("require exactly two arguments, provided %d", len(args))
209 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800210
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800211 ctx, shutdown := veyron2.Init()
212 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800213
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800214 p := veyron2.GetPrincipal(ctx)
Asim Shankar66c52f92014-10-15 23:39:10 -0700215
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800216 var (
217 err error
218 with security.Blessings
219 )
Asim Shankar66c52f92014-10-15 23:39:10 -0700220 if len(flagBlessWith) > 0 {
221 if with, err = decodeBlessings(flagBlessWith); err != nil {
222 return fmt.Errorf("failed to read blessings from --with=%q: %v", flagBlessWith, err)
223 }
224 } else {
225 with = p.BlessingStore().Default()
226 }
Asim Shankara0bba462015-02-20 22:50:51 -0800227 caveats, err := caveatsFromFlags(flagBlessFor, &flagBlessCaveats)
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800228 if err != nil {
Asim Shankara0bba462015-02-20 22:50:51 -0800229 return err
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800230 }
Asim Shankara0bba462015-02-20 22:50:51 -0800231 if !flagBlessRequireCaveats && len(caveats) == 0 {
232 caveats = []security.Caveat{security.UnconstrainedUse()}
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800233 }
Bogdan Caprita553e5822015-02-20 14:50:41 -0800234 if len(caveats) == 0 {
Asim Shankara0bba462015-02-20 22:50:51 -0800235 return errNoCaveats
Bogdan Caprita553e5822015-02-20 14:50:41 -0800236 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700237 tobless, extension := args[0], args[1]
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800238 if (len(flagBlessRemoteKey) == 0) != (len(flagBlessRemoteToken) == 0) {
239 return fmt.Errorf("either both --remote_key and --remote_token should be set, or neither should")
240 }
241 if len(flagBlessRemoteKey) > 0 {
242 // Send blessings to a "server" started by a "recvblessings" command
243 granter := &granter{p, with, extension, caveats, flagBlessRemoteKey}
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800244 return sendBlessings(ctx, tobless, granter, flagBlessRemoteToken)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800245 }
246 // Blessing a principal whose key is available locally.
247 var key security.PublicKey
Asim Shankar66c52f92014-10-15 23:39:10 -0700248 if finfo, err := os.Stat(tobless); err == nil && finfo.IsDir() {
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700249 other, err := vsecurity.LoadPersistentPrincipal(tobless, nil)
Asim Shankar66c52f92014-10-15 23:39:10 -0700250 if err != nil {
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700251 if other, err = vsecurity.CreatePersistentPrincipal(tobless, nil); err != nil {
252 return fmt.Errorf("failed to read principal in directory %q: %v", tobless, err)
253 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700254 }
255 key = other.PublicKey()
256 } else if other, err := decodeBlessings(tobless); err != nil {
257 return fmt.Errorf("failed to decode blessings in %q: %v", tobless, err)
258 } else {
259 key = other.PublicKey()
260 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800261 blessings, err := p.Bless(key, with, extension, caveats[0], caveats[1:]...)
Asim Shankar66c52f92014-10-15 23:39:10 -0700262 if err != nil {
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800263 return fmt.Errorf("Bless(%v, %v, %q, ...) failed: %v", key, with, extension, err)
Asim Shankar66c52f92014-10-15 23:39:10 -0700264 }
265 return dumpBlessings(blessings)
266 },
267 }
268
269 cmdStoreForPeer = &cmdline.Command{
270 Name: "forpeer",
Ankurcf6a89f2014-10-06 18:33:03 -0700271 Short: "Return blessings marked for the provided peer",
272 Long: `
273Returns blessings that are marked for the provided peer in the
Asim Shankar1789b8a2014-10-31 17:31:41 -0700274BlessingStore specified by the environment that this tool is
275running in.
Ankurcf6a89f2014-10-06 18:33:03 -0700276`,
277 ArgsName: "[<peer_1> ... <peer_k>]",
278 ArgsLong: `
279<peer_1> ... <peer_k> are the (human-readable string) blessings bound
280to the peer. The returned blessings are marked with a pattern that is
281matched by at least one of these. If no arguments are specified,
282store.forpeer returns the blessings that are marked for all peers (i.e.,
283blessings set on the store with the "..." pattern).
284`,
285 Run: func(cmd *cmdline.Command, args []string) error {
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800286 ctx, shutdown := veyron2.Init()
287 defer shutdown()
288 principal := veyron2.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800289 return dumpBlessings(principal.BlessingStore().ForPeer(args...))
Ankurcf6a89f2014-10-06 18:33:03 -0700290 },
291 }
292
Asim Shankar66c52f92014-10-15 23:39:10 -0700293 cmdStoreDefault = &cmdline.Command{
294 Name: "default",
Ankurcf6a89f2014-10-06 18:33:03 -0700295 Short: "Return blessings marked as default",
296 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700297Returns blessings that are marked as default in the BlessingStore specified by
298the environment that this tool is running in.
Ankurcf6a89f2014-10-06 18:33:03 -0700299`,
300 Run: func(cmd *cmdline.Command, args []string) error {
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800301 ctx, shutdown := veyron2.Init()
302 defer shutdown()
303 principal := veyron2.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800304 return dumpBlessings(principal.BlessingStore().Default())
Ankurcf6a89f2014-10-06 18:33:03 -0700305 },
306 }
Ankur8d304122014-10-07 10:43:43 -0700307
Asim Shankar66c52f92014-10-15 23:39:10 -0700308 cmdStoreSet = &cmdline.Command{
309 Name: "set",
Ankur8d304122014-10-07 10:43:43 -0700310 Short: "Set provided blessings for peer",
311 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700312Marks the provided blessings to be shared with the provided peers on the
313BlessingStore specified by the environment that this tool is running in.
Ankur8d304122014-10-07 10:43:43 -0700314
315'set b pattern' marks the intention to reveal b to peers who
316present blessings of their own matching 'pattern'.
317
318'set nil pattern' can be used to remove the blessings previously
319associated with the pattern (by a prior 'set' command).
320
321It is an error to call 'store.set' with blessings whose public
322key does not match the public key of this principal specified
323by the environment.
324`,
325 ArgsName: "<file> <pattern>",
326 ArgsLong: `
327<file> is the path to a file containing a blessing typically obtained
328from this tool. - is used for STDIN.
329
330<pattern> is the BlessingPattern used to identify peers with whom this
331blessing can be shared with.
332`,
333 Run: func(cmd *cmdline.Command, args []string) error {
334 if len(args) != 2 {
Asim Shankar66c52f92014-10-15 23:39:10 -0700335 return fmt.Errorf("requires exactly two arguments <file>, <pattern>, provided %d", len(args))
Ankur8d304122014-10-07 10:43:43 -0700336 }
337 blessings, err := decodeBlessings(args[0])
338 if err != nil {
339 return fmt.Errorf("failed to decode provided blessings: %v", err)
340 }
341 pattern := security.BlessingPattern(args[1])
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800342
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800343 ctx, shutdown := veyron2.Init()
344 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800345
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800346 p := veyron2.GetPrincipal(ctx)
Asim Shankar66c52f92014-10-15 23:39:10 -0700347 if _, err := p.BlessingStore().Set(blessings, pattern); err != nil {
Ankur8d304122014-10-07 10:43:43 -0700348 return fmt.Errorf("failed to set blessings %v for peers %v: %v", blessings, pattern, err)
349 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700350 if flagAddToRoots {
351 if err := p.AddToRoots(blessings); err != nil {
352 return fmt.Errorf("AddToRoots failed: %v", err)
353 }
354 }
Ankur8d304122014-10-07 10:43:43 -0700355 return nil
356 },
357 }
358
Mike Burrows367515e2014-12-02 11:30:18 -0800359 cmdStoreAddToRoots = &cmdline.Command{
360 Name: "addtoroots",
361 Short: "Add provided blessings to root set",
362 Long: `
363Adds the provided blessings to the set of trusted roots for this principal.
364
365'addtoroots b' adds blessings b to the trusted root set.
366
367For example, to make the principal in credentials directory A trust the
368root of the default blessing in credentials directory B:
369 principal -veyron.credentials=B bless A some_extension |
370 principal -veyron.credentials=A store addtoroots -
371
372The extension 'some_extension' has no effect in the command above.
373`,
374 ArgsName: "<file>",
375 ArgsLong: `
376<file> is the path to a file containing a blessing typically obtained
377from this tool. - is used for STDIN.
378`,
379 Run: func(cmd *cmdline.Command, args []string) error {
380 if len(args) != 1 {
381 return fmt.Errorf("requires exactly one argument <file>, provided %d", len(args))
382 }
383 blessings, err := decodeBlessings(args[0])
384 if err != nil {
385 return fmt.Errorf("failed to decode provided blessings: %v", err)
386 }
387
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800388 ctx, shutdown := veyron2.Init()
389 defer shutdown()
Mike Burrows367515e2014-12-02 11:30:18 -0800390
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800391 p := veyron2.GetPrincipal(ctx)
Mike Burrows367515e2014-12-02 11:30:18 -0800392 if err := p.AddToRoots(blessings); err != nil {
393 return fmt.Errorf("AddToRoots failed: %v", err)
394 }
395 return nil
396 },
397 }
398
Asim Shankar66c52f92014-10-15 23:39:10 -0700399 cmdStoreSetDefault = &cmdline.Command{
400 Name: "setdefault",
Ankur8d304122014-10-07 10:43:43 -0700401 Short: "Set provided blessings as default",
402 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700403Sets the provided blessings as default in the BlessingStore specified by the
404environment that this tool is running in.
Ankur8d304122014-10-07 10:43:43 -0700405
Asim Shankar1789b8a2014-10-31 17:31:41 -0700406It is an error to call 'store.setdefault' with blessings whose public key does
407not match the public key of the principal specified by the environment.
Ankur8d304122014-10-07 10:43:43 -0700408`,
409 ArgsName: "<file>",
410 ArgsLong: `
411<file> is the path to a file containing a blessing typically obtained from
412this tool. - is used for STDIN.
413`,
414 Run: func(cmd *cmdline.Command, args []string) error {
415 if len(args) != 1 {
Asim Shankar66c52f92014-10-15 23:39:10 -0700416 return fmt.Errorf("requires exactly one argument, <file>, provided %d", len(args))
Ankur8d304122014-10-07 10:43:43 -0700417 }
418 blessings, err := decodeBlessings(args[0])
419 if err != nil {
420 return fmt.Errorf("failed to decode provided blessings: %v", err)
421 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800422
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800423 ctx, shutdown := veyron2.Init()
424 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800425
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800426 p := veyron2.GetPrincipal(ctx)
Asim Shankar1789b8a2014-10-31 17:31:41 -0700427 if err := p.BlessingStore().SetDefault(blessings); err != nil {
Ankur8d304122014-10-07 10:43:43 -0700428 return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
429 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700430 if flagAddToRoots {
431 if err := p.AddToRoots(blessings); err != nil {
432 return fmt.Errorf("AddToRoots failed: %v", err)
433 }
434 }
435 return nil
436 },
437 }
438
439 cmdCreate = &cmdline.Command{
440 Name: "create",
441 Short: "Create a new principal and persist it into a directory",
442 Long: `
Ankur4704f5f2014-10-23 12:40:54 -0700443Creates a new principal with a single self-blessed blessing and writes it out
Ankurc24ff422014-12-16 17:59:26 -0800444to the provided directory. The same directory can then be used to set the
445VEYRON_CREDENTIALS environment variable for other veyron applications.
Ankur4704f5f2014-10-23 12:40:54 -0700446
447The operation fails if the directory already contains a principal. In this case
Ankurc24ff422014-12-16 17:59:26 -0800448the --overwrite flag can be provided to clear the directory and write out the
gauthamtb7bb39b2014-11-10 11:40:41 -0800449new principal.
Ankur4704f5f2014-10-23 12:40:54 -0700450`,
Asim Shankar66c52f92014-10-15 23:39:10 -0700451 ArgsName: "<directory> <blessing>",
452 ArgsLong: `
Ankurc24ff422014-12-16 17:59:26 -0800453 <directory> is the directory to which the new principal will be persisted.
Asim Shankar66c52f92014-10-15 23:39:10 -0700454 <blessing> is the self-blessed blessing that the principal will be setup to use by default.
455 `,
456 Run: func(cmd *cmdline.Command, args []string) error {
457 if len(args) != 2 {
458 return fmt.Errorf("requires exactly two arguments: <directory> and <blessing>, provided %d", len(args))
459 }
460 dir, name := args[0], args[1]
Ankur4704f5f2014-10-23 12:40:54 -0700461 if flagCreateOverwrite {
Ankurc24ff422014-12-16 17:59:26 -0800462 if err := os.RemoveAll(dir); err != nil {
gauthamtb7bb39b2014-11-10 11:40:41 -0800463 return err
464 }
Ankur4704f5f2014-10-23 12:40:54 -0700465 }
Ankurc24ff422014-12-16 17:59:26 -0800466 p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700467 if err != nil {
468 return err
Asim Shankar66c52f92014-10-15 23:39:10 -0700469 }
470 blessings, err := p.BlessSelf(name)
471 if err != nil {
472 return fmt.Errorf("BlessSelf(%q) failed: %v", name, err)
473 }
Ankurc24ff422014-12-16 17:59:26 -0800474 if err := vsecurity.SetDefaultBlessings(p, blessings); err != nil {
475 return fmt.Errorf("could not set blessings %v as default: %v", blessings, err)
Asim Shankar66c52f92014-10-15 23:39:10 -0700476 }
Ankurc24ff422014-12-16 17:59:26 -0800477 return nil
478 },
479 }
480
481 cmdFork = &cmdline.Command{
482 Name: "fork",
483 Short: "Fork a new principal from the principal that this tool is running as and persist it into a directory",
484 Long: `
485Creates a new principal with a blessing from the principal specified by the
486environment that this tool is running in, and writes it out to the provided
487directory. The blessing that will be extended is the default one from the
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800488blesser's store, or specified by the --with flag. Expiration on the blessing
489are controlled via the --for flag. Additional caveats on the blessing are
490controlled with the --caveat flag. The blessing is marked as default and
Ankurc24ff422014-12-16 17:59:26 -0800491shareable with all peers on the new principal's blessing store.
492
493The operation fails if the directory already contains a principal. In this case
494the --overwrite flag can be provided to clear the directory and write out the
495forked principal.
496`,
497 ArgsName: "<directory> <extension>",
498 ArgsLong: `
499 <directory> is the directory to which the forked principal will be persisted.
500 <extension> is the extension under which the forked principal is blessed.
501 `,
502 Run: func(cmd *cmdline.Command, args []string) error {
503 if len(args) != 2 {
504 return fmt.Errorf("requires exactly two arguments: <directory> and <extension>, provided %d", len(args))
Asim Shankar66c52f92014-10-15 23:39:10 -0700505 }
Ankurc24ff422014-12-16 17:59:26 -0800506 dir, extension := args[0], args[1]
507
Asim Shankara0bba462015-02-20 22:50:51 -0800508 ctx, shutdown := veyron2.Init()
509 defer shutdown()
510
511 caveats, err := caveatsFromFlags(flagForkFor, &flagForkCaveats)
512 if err != nil {
513 return err
514 }
515 if !flagForkRequireCaveats && len(caveats) == 0 {
516 caveats = []security.Caveat{security.UnconstrainedUse()}
517 }
518 if len(caveats) == 0 {
519 return errNoCaveats
520 }
521 var with security.Blessings
522 if len(flagForkWith) > 0 {
523 if with, err = decodeBlessings(flagForkWith); err != nil {
524 return fmt.Errorf("failed to read blessings from --with=%q: %v", flagForkWith, err)
525 }
526 } else {
527 with = veyron2.GetPrincipal(ctx).BlessingStore().Default()
528 }
529
Ankurc24ff422014-12-16 17:59:26 -0800530 if flagCreateOverwrite {
531 if err := os.RemoveAll(dir); err != nil {
532 return err
533 }
534 }
535 p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
536 if err != nil {
537 return err
538 }
539
Ankurc24ff422014-12-16 17:59:26 -0800540 key := p.PublicKey()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800541 rp := veyron2.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800542 blessings, err := rp.Bless(key, with, extension, caveats[0], caveats[1:]...)
Ankurc24ff422014-12-16 17:59:26 -0800543 if err != nil {
544 return fmt.Errorf("Bless(%v, %v, %q, ...) failed: %v", key, with, extension, err)
545 }
546 if err := vsecurity.SetDefaultBlessings(p, blessings); err != nil {
547 return fmt.Errorf("could not set blessings %v as default: %v", blessings, err)
Asim Shankar66c52f92014-10-15 23:39:10 -0700548 }
Ankur8d304122014-10-07 10:43:43 -0700549 return nil
550 },
551 }
Ankur1d46f552014-10-09 12:13:31 -0700552
553 cmdSeekBlessings = &cmdline.Command{
554 Name: "seekblessings",
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800555 Short: "Seek blessings from a web-based Veyron blessing service",
Ankur1d46f552014-10-09 12:13:31 -0700556 Long: `
557Seeks blessings from a web-based Veyron blesser which
558requires the caller to first authenticate with Google using OAuth. Simply
559run the command to see what happens.
560
Asim Shankar1789b8a2014-10-31 17:31:41 -0700561The blessings are sought for the principal specified by the environment that
562this tool is running in.
Ankur1d46f552014-10-09 12:13:31 -0700563
Ankure548f392014-12-08 18:42:41 -0800564The blessings obtained are set as default, unless the --set_default flag is
565set to true, and are also set for sharing with all peers, unless a more
Ankur1d46f552014-10-09 12:13:31 -0700566specific peer pattern is provided using the --for_peer flag.
567`,
568 Run: func(cmd *cmdline.Command, args []string) error {
Asim Shankar08ab3892014-10-16 12:04:07 -0700569 // Initialize the runtime first so that any local errors are reported
570 // before the HTTP roundtrips for obtaining the macaroon begin.
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800571 ctx, shutdown := veyron2.Init()
572 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800573
Ankur1d46f552014-10-09 12:13:31 -0700574 blessedChan := make(chan string)
575 defer close(blessedChan)
Suharsh Sivakumara76dba62014-12-22 16:00:34 -0800576 macaroonChan, err := getMacaroonForBlessRPC(flagSeekBlessingsFrom, blessedChan, flagSeekBlessingsBrowser)
Ankur1d46f552014-10-09 12:13:31 -0700577 if err != nil {
578 return fmt.Errorf("failed to get macaroon from Veyron blesser: %v", err)
579 }
Ankur1d46f552014-10-09 12:13:31 -0700580
Suharsh Sivakumar67ef84a2015-02-13 13:04:44 -0800581 blessings, err := exchangeMacaroonForBlessing(ctx, macaroonChan)
Ankur1d46f552014-10-09 12:13:31 -0700582 if err != nil {
Suharsh Sivakumar67ef84a2015-02-13 13:04:44 -0800583 return err
Ankur1d46f552014-10-09 12:13:31 -0700584 }
585 blessedChan <- fmt.Sprint(blessings)
586 // Wait for getTokenForBlessRPC to clean up:
587 <-macaroonChan
588
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800589 p := veyron2.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800590
Asim Shankar66c52f92014-10-15 23:39:10 -0700591 if flagSeekBlessingsSetDefault {
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800592 if err := p.BlessingStore().SetDefault(blessings); err != nil {
Ankur1d46f552014-10-09 12:13:31 -0700593 return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
594 }
595 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700596 if pattern := security.BlessingPattern(flagSeekBlessingsForPeer); len(pattern) > 0 {
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800597 if _, err := p.BlessingStore().Set(blessings, pattern); err != nil {
Asim Shankar66c52f92014-10-15 23:39:10 -0700598 return fmt.Errorf("failed to set blessings %v for peers %v: %v", blessings, pattern, err)
599 }
600 }
601 if flagAddToRoots {
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800602 if err := p.AddToRoots(blessings); err != nil {
Asim Shankar66c52f92014-10-15 23:39:10 -0700603 return fmt.Errorf("AddToRoots failed: %v", err)
604 }
Ankur1d46f552014-10-09 12:13:31 -0700605 }
Asim Shankar3f9bbab2015-02-15 13:51:37 -0800606 fmt.Fprintf(cmd.Stdout(), "Received blessings: %v\n", blessings)
Jiri Simsa37b0a092015-02-13 09:32:39 -0800607 return nil
Ankur1d46f552014-10-09 12:13:31 -0700608 },
609 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800610
611 cmdRecvBlessings = &cmdline.Command{
612 Name: "recvblessings",
613 Short: "Receive blessings sent by another principal and use them as the default",
614 Long: `
615Allow another principal (likely a remote process) to bless this one.
616
617This command sets up the invoker (this process) to wait for a blessing
618from another invocation of this tool (remote process) and prints out the
619command to be run as the remote principal.
620
Ankure548f392014-12-08 18:42:41 -0800621The received blessings are set as default, unless the --set_default flag is
622set to true, and are also set for sharing with all peers, unless a more
623specific peer pattern is provided using the --for_peer flag.
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800624
625TODO(ashankar,cnicolaou): Make this next paragraph possible! Requires
626the ability to obtain the proxied endpoint.
627
628Typically, this command should require no arguments.
629However, if the sender and receiver are on different network domains, it may
630make sense to use the --veyron.proxy flag:
Robin Thellend8fea01c2014-12-11 13:48:10 -0800631 principal --veyron.proxy=proxy recvblessings
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800632
633The command to be run at the sender is of the form:
634 principal bless --remote_key=KEY --remote_token=TOKEN ADDRESS
635
636The --remote_key flag is used to by the sender to "authenticate" the receiver,
637ensuring it blesses the intended recipient and not any attacker that may have
638taken over the address.
639
640The --remote_token flag is used by the sender to authenticate itself to the
641receiver. This helps ensure that the receiver rejects blessings from senders
642who just happened to guess the network address of the 'recvblessings'
643invocation.
644`,
645 Run: func(cmd *cmdline.Command, args []string) error {
646 if len(args) != 0 {
647 return fmt.Errorf("command accepts no arguments")
648 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800649
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800650 ctx, shutdown := veyron2.Init()
651 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800652
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800653 server, err := veyron2.NewServer(ctx)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800654 if err != nil {
655 return fmt.Errorf("failed to create server to listen for blessings: %v", err)
656 }
657 defer server.Stop()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800658 eps, err := server.Listen(veyron2.GetListenSpec(ctx))
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800659 if err != nil {
660 return fmt.Errorf("failed to setup listening: %v", err)
661 }
662 var token [24]byte
663 if _, err := rand.Read(token[:]); err != nil {
664 return fmt.Errorf("unable to generate token: %v", err)
665 }
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800666
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800667 p := veyron2.GetPrincipal(ctx)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800668 service := &recvBlessingsService{
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800669 principal: p,
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800670 token: base64.URLEncoding.EncodeToString(token[:]),
671 notify: make(chan error),
672 }
673 if err := server.Serve("", service, allowAnyone{}); err != nil {
674 return fmt.Errorf("failed to setup service: %v", err)
675 }
676 // Proposed name:
677 extension := fmt.Sprintf("extension%d", int(token[0])<<16|int(token[1])<<8|int(token[2]))
678 fmt.Println("Run the following command on behalf of the principal that will send blessings:")
679 fmt.Println("You may want to adjust flags affecting the caveats on this blessing, for example using")
680 fmt.Println("the --for flag, or change the extension to something more meaningful")
681 fmt.Println()
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800682 fmt.Printf("principal bless --remote_key=%v --remote_token=%v %v %v\n", p.PublicKey(), service.token, eps[0].Name(), extension)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800683 fmt.Println()
684 fmt.Println("...waiting for sender..")
685 return <-service.notify
686 },
687 }
Ankurcf6a89f2014-10-06 18:33:03 -0700688)
689
690func main() {
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800691 cmdBlessSelf.Flags.Var(&flagBlessSelfCaveats, "caveat", flagBlessSelfCaveats.usage())
Asim Shankara0bba462015-02-20 22:50:51 -0800692 cmdBlessSelf.Flags.DurationVar(&flagBlessSelfFor, "for", 0, "Duration of blessing validity (zero implies no expiration)")
693
Ankur77c32ac2014-12-18 14:18:19 -0800694 cmdFork.Flags.BoolVar(&flagCreateOverwrite, "overwrite", false, "If true, any existing principal data in the directory will be overwritten")
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800695 cmdFork.Flags.Var(&flagForkCaveats, "caveat", flagForkCaveats.usage())
Asim Shankara0bba462015-02-20 22:50:51 -0800696 cmdFork.Flags.DurationVar(&flagForkFor, "for", 0, "Duration of blessing validity (zero implies no expiration caveat)")
697 cmdFork.Flags.BoolVar(&flagForkRequireCaveats, "require_caveats", true, "If false, allow blessing without any caveats. This is typically not advised as the principal wielding the blessing will be almost as powerful as its blesser")
Ankur77c32ac2014-12-18 14:18:19 -0800698 cmdFork.Flags.StringVar(&flagForkWith, "with", "", "Path to file containing blessing to extend")
699
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800700 cmdBless.Flags.Var(&flagBlessCaveats, "caveat", flagBlessCaveats.usage())
Asim Shankara0bba462015-02-20 22:50:51 -0800701 cmdBless.Flags.DurationVar(&flagBlessFor, "for", 0, "Duration of blessing validity (zero implies no expiration caveat)")
702 cmdBless.Flags.BoolVar(&flagBlessRequireCaveats, "require_caveats", true, "If false, allow blessing without any caveats. This is typically not advised as the principal wielding the blessing will be almost as powerful as its blesser")
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800703 cmdBless.Flags.StringVar(&flagBlessWith, "with", "", "Path to file containing blessing to extend")
704 cmdBless.Flags.StringVar(&flagBlessRemoteKey, "remote_key", "", "Public key of the remote principal to bless (obtained from the 'recvblessings' command run by the remote principal")
705 cmdBless.Flags.StringVar(&flagBlessRemoteToken, "remote_token", "", "Token provided by principal running the 'recvblessings' command")
706
Robin Thellend8fea01c2014-12-11 13:48:10 -0800707 cmdSeekBlessings.Flags.StringVar(&flagSeekBlessingsFrom, "from", "https://auth.dev.v.io:8125/google", "URL to use to begin the seek blessings process")
Asim Shankar66c52f92014-10-15 23:39:10 -0700708 cmdSeekBlessings.Flags.BoolVar(&flagSeekBlessingsSetDefault, "set_default", true, "If true, the blessings obtained will be set as the default blessing in the store")
709 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")
Suharsh Sivakumara76dba62014-12-22 16:00:34 -0800710 cmdSeekBlessings.Flags.BoolVar(&flagSeekBlessingsBrowser, "browser", true, "If false, the seekblessings command will not open the browser and only print the url to visit.")
Asim Shankar66c52f92014-10-15 23:39:10 -0700711 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")
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800712
Asim Shankar66c52f92014-10-15 23:39:10 -0700713 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")
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800714
Asim Shankar66c52f92014-10-15 23:39:10 -0700715 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")
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800716
Ankur4704f5f2014-10-23 12:40:54 -0700717 cmdCreate.Flags.BoolVar(&flagCreateOverwrite, "overwrite", false, "If true, any existing principal data in the directory will be overwritten")
Asim Shankar66c52f92014-10-15 23:39:10 -0700718
Ankure548f392014-12-08 18:42:41 -0800719 cmdRecvBlessings.Flags.BoolVar(&flagRecvBlessingsSetDefault, "set_default", true, "If true, the blessings received will be set as the default blessing in the store")
720 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")
721
Asim Shankar66c52f92014-10-15 23:39:10 -0700722 cmdStore := &cmdline.Command{
723 Name: "store",
724 Short: "Manipulate and inspect the principal's blessing store",
725 Long: `
726Commands to manipulate and inspect the blessing store of the principal.
727
728All blessings are printed to stdout using base64-VOM-encoding
729`,
Mike Burrows367515e2014-12-02 11:30:18 -0800730 Children: []*cmdline.Command{cmdStoreDefault, cmdStoreSetDefault, cmdStoreForPeer, cmdStoreSet, cmdStoreAddToRoots},
Ankurcf6a89f2014-10-06 18:33:03 -0700731 }
Ankurcf6a89f2014-10-06 18:33:03 -0700732
Matt Rosencrantz92303e12015-01-21 09:02:42 -0800733 root := &cmdline.Command{
Ankurcf6a89f2014-10-06 18:33:03 -0700734 Name: "principal",
735 Short: "Create and manage veyron principals",
736 Long: `
737The principal tool helps create and manage blessings and the set of trusted
738roots bound to a principal.
739
740All objects are printed using base64-VOM-encoding.
741`,
Ankurc24ff422014-12-16 17:59:26 -0800742 Children: []*cmdline.Command{cmdCreate, cmdFork, cmdSeekBlessings, cmdRecvBlessings, cmdDump, cmdDumpBlessings, cmdBlessSelf, cmdBless, cmdStore},
Matt Rosencrantz92303e12015-01-21 09:02:42 -0800743 }
744 os.Exit(root.Main())
Ankurcf6a89f2014-10-06 18:33:03 -0700745}
746
Ankurcf6a89f2014-10-06 18:33:03 -0700747func decodeBlessings(fname string) (security.Blessings, error) {
748 var wire security.WireBlessings
749 if err := decode(fname, &wire); err != nil {
750 return nil, err
751 }
752 return security.NewBlessings(wire)
753}
754
755func dumpBlessings(blessings security.Blessings) error {
756 if blessings == nil {
757 return errors.New("no blessings found")
758 }
Ankuree0aa812014-11-14 10:56:52 -0800759 str, err := base64VomEncode(security.MarshalBlessings(blessings))
Ankurcf6a89f2014-10-06 18:33:03 -0700760 if err != nil {
761 return fmt.Errorf("base64-VOM encoding failed: %v", err)
762 }
763 fmt.Println(str)
764 return nil
765}
766
767func read(fname string) (string, error) {
768 if len(fname) == 0 {
769 return "", nil
770 }
771 f := os.Stdin
772 if fname != "-" {
773 var err error
774 if f, err = os.Open(fname); err != nil {
775 return "", fmt.Errorf("failed to open %q: %v", fname, err)
776 }
777 }
778 defer f.Close()
779 var buf bytes.Buffer
780 if _, err := io.Copy(&buf, f); err != nil {
781 return "", fmt.Errorf("failed to read %q: %v", fname, err)
782 }
783 return buf.String(), nil
784}
785
786func decode(fname string, val interface{}) error {
787 str, err := read(fname)
788 if err != nil {
789 return err
790 }
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700791 if err := base64VomDecode(str, val); err != nil || val == nil {
Ankurcf6a89f2014-10-06 18:33:03 -0700792 return fmt.Errorf("failed to decode %q: %v", fname, err)
793 }
794 return nil
795}
796
797func defaultBlessingName() string {
798 var name string
799 if user, _ := user.Current(); user != nil && len(user.Username) > 0 {
800 name = user.Username
801 } else {
802 name = "anonymous"
803 }
804 if host, _ := os.Hostname(); len(host) > 0 {
805 name = name + "@" + host
806 }
807 return name
808}
Asim Shankardf88a2e2014-10-21 17:20:28 -0700809
810func rootkey(chain []security.Certificate) string {
811 if len(chain) == 0 {
812 return "<empty certificate chain>"
813 }
814 key, err := security.UnmarshalPublicKey(chain[0].PublicKey)
815 if err != nil {
816 return fmt.Sprintf("<invalid PublicKey: %v>", err)
817 }
818 return fmt.Sprintf("%v", key)
819}
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700820
821func base64VomEncode(i interface{}) (string, error) {
822 buf := &bytes.Buffer{}
823 closer := base64.NewEncoder(base64.URLEncoding, buf)
Todd Wang8e17bff2015-02-18 11:18:56 -0800824 enc, err := vom.NewEncoder(closer)
Suharsh Sivakumar12b089d2015-01-02 14:17:12 -0800825 if err != nil {
826 return "", err
827 }
828 if err := enc.Encode(i); err != nil {
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700829 return "", err
830 }
831 // Must close the base64 encoder to flush out any partially written
832 // blocks.
833 if err := closer.Close(); err != nil {
834 return "", err
835 }
836 return buf.String(), nil
837}
838
839func base64VomDecode(s string, i interface{}) error {
840 b, err := base64.URLEncoding.DecodeString(s)
841 if err != nil {
842 return err
843 }
Todd Wang3425a902015-01-21 18:43:59 -0800844 dec, err := vom.NewDecoder(bytes.NewBuffer(b))
Suharsh Sivakumar12b089d2015-01-02 14:17:12 -0800845 if err != nil {
846 return err
847 }
848 return dec.Decode(i)
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700849}
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800850
851type recvBlessingsService struct {
852 principal security.Principal
853 notify chan error
854 token string
855}
856
857func (r *recvBlessingsService) Grant(call ipc.ServerCall, token string) error {
858 b := call.Blessings()
859 if b == nil {
860 return fmt.Errorf("no blessings granted by sender")
861 }
862 if len(token) != len(r.token) {
863 // A timing attack can be used to figure out the length
864 // of the token, but then again, so can looking at the
865 // source code. So, it's okay.
866 return fmt.Errorf("blessings received from unexpected sender")
867 }
868 if subtle.ConstantTimeCompare([]byte(token), []byte(r.token)) != 1 {
869 return fmt.Errorf("blessings received from unexpected sender")
870 }
Ankure548f392014-12-08 18:42:41 -0800871 if flagRecvBlessingsSetDefault {
872 if err := r.principal.BlessingStore().SetDefault(b); err != nil {
873 return fmt.Errorf("failed to set blessings %v as default: %v", b, err)
874 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800875 }
Ankure548f392014-12-08 18:42:41 -0800876 if pattern := security.BlessingPattern(flagRecvBlessingsForPeer); len(pattern) > 0 {
877 if _, err := r.principal.BlessingStore().Set(b, pattern); err != nil {
878 return fmt.Errorf("failed to set blessings %v for peers %v: %v", b, pattern, err)
879 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800880 }
881 if flagAddToRoots {
882 if err := r.principal.AddToRoots(b); err != nil {
883 return fmt.Errorf("failed to add blessings to recognized roots: %v", err)
884 }
885 }
886 fmt.Println("Received blessings:", b)
887 r.notify <- nil
888 return nil
889}
890
891type allowAnyone struct{}
892
893func (allowAnyone) Authorize(security.Context) error { return nil }
894
895type granter struct {
896 p security.Principal
897 with security.Blessings
898 extension string
899 caveats []security.Caveat
900 serverKey string
901}
902
903func (g *granter) Grant(server security.Blessings) (security.Blessings, error) {
904 if got := fmt.Sprintf("%v", server.PublicKey()); got != g.serverKey {
905 // If the granter returns an error, the IPC framework should
906 // abort the RPC before sending the request to the server.
907 // Thus, there is no concern about leaking the token to an
908 // imposter server.
909 return nil, fmt.Errorf("key mismatch: Remote end has public key %v, want %v", got, g.serverKey)
910 }
911 return g.p.Bless(server.PublicKey(), g.with, g.extension, g.caveats[0], g.caveats[1:]...)
912}
913func (*granter) IPCCallOpt() {}
914
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800915func sendBlessings(ctx *context.T, object string, granter *granter, remoteToken string) error {
916 client := veyron2.GetClient(ctx)
917 call, err := client.StartCall(ctx, object, "Grant", []interface{}{remoteToken}, granter)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800918 if err != nil {
919 return fmt.Errorf("failed to start RPC to %q: %v", object, err)
920 }
Todd Wange77f9952015-02-18 13:20:50 -0800921 if err := call.Finish(); err != nil {
922 return fmt.Errorf("failed to finish RPC to %q: %v", object, err)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800923 }
Todd Wange77f9952015-02-18 13:20:50 -0800924 return nil
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800925}
Asim Shankara0bba462015-02-20 22:50:51 -0800926
927func caveatsFromFlags(expiry time.Duration, caveatsFlag *caveatsFlag) ([]security.Caveat, error) {
928 caveats, err := caveatsFlag.Compile()
929 if err != nil {
930 return nil, fmt.Errorf("failed to parse caveats: %v", err)
931 }
932 if expiry > 0 {
933 ecav, err := security.ExpiryCaveat(time.Now().Add(expiry))
934 if err != nil {
935 return nil, fmt.Errorf("failed to create expiration caveat: %v", err)
936 }
937 caveats = append(caveats, ecav)
938 }
939 return caveats, nil
940}