blob: 6b6ee339824bd6d0110507b317f981e16615136d [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
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -080034 flagBlessCaveats caveatsFlag
Asim Shankarf11b1bc2014-11-12 17:18:45 -080035 flagBlessFor time.Duration
36 flagBlessWith string
37 flagBlessRemoteKey string
38 flagBlessRemoteToken string
Asim Shankar66c52f92014-10-15 23:39:10 -070039
Ankur77c32ac2014-12-18 14:18:19 -080040 // Flags for the "fork" command
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -080041 flagForkCaveats caveatsFlag
42 flagForkFor time.Duration
43 flagForkWith string
Ankur77c32ac2014-12-18 14:18:19 -080044
Asim Shankar66c52f92014-10-15 23:39:10 -070045 // Flags for the "seekblessings" command
46 flagSeekBlessingsFrom string
47 flagSeekBlessingsSetDefault bool
48 flagSeekBlessingsForPeer string
Suharsh Sivakumara76dba62014-12-22 16:00:34 -080049 flagSeekBlessingsBrowser bool
Asim Shankar66c52f92014-10-15 23:39:10 -070050
51 // Flags common to many commands
Ankurc24ff422014-12-16 17:59:26 -080052 flagAddToRoots bool
53 flagCreateOverwrite bool
Ankur1d46f552014-10-09 12:13:31 -070054
Ankure548f392014-12-08 18:42:41 -080055 // Flags for the "recvblessings" command
56 flagRecvBlessingsSetDefault bool
57 flagRecvBlessingsForPeer string
58
Ankur1615a7d2014-10-09 11:58:02 -070059 cmdDump = &cmdline.Command{
60 Name: "dump",
61 Short: "Dump out information about the principal",
62 Long: `
Asim Shankar66c52f92014-10-15 23:39:10 -070063Prints out information about the principal specified by the environment
Asim Shankar1789b8a2014-10-31 17:31:41 -070064that this tool is running in.
Ankur1615a7d2014-10-09 11:58:02 -070065`,
66 Run: func(cmd *cmdline.Command, args []string) error {
Matt Rosencrantza5ad2722015-01-22 11:17:47 -080067 ctx, shutdown := veyron2.Init()
68 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -080069
Matt Rosencrantza5ad2722015-01-22 11:17:47 -080070 p := veyron2.GetPrincipal(ctx)
Ankur1615a7d2014-10-09 11:58:02 -070071 fmt.Printf("Public key : %v\n", p.PublicKey())
Ankur1615a7d2014-10-09 11:58:02 -070072 fmt.Println("---------------- BlessingStore ----------------")
73 fmt.Printf("%v", p.BlessingStore().DebugString())
Ankur1615a7d2014-10-09 11:58:02 -070074 fmt.Println("---------------- BlessingRoots ----------------")
75 fmt.Printf("%v", p.Roots().DebugString())
76 return nil
77 },
78 }
79
Asim Shankar66c52f92014-10-15 23:39:10 -070080 cmdDumpBlessings = &cmdline.Command{
81 Name: "dumpblessings",
82 Short: "Dump out information about the provided blessings",
Ankurcf6a89f2014-10-06 18:33:03 -070083 Long: `
Asim Shankar66c52f92014-10-15 23:39:10 -070084Prints out information about the blessings (typically obtained from this tool)
Ankurcf6a89f2014-10-06 18:33:03 -070085encoded in the provided file.
86`,
87 ArgsName: "<file>",
88 ArgsLong: `
Asim Shankar66c52f92014-10-15 23:39:10 -070089<file> is the path to a file containing blessings typically obtained from
Ankurcf6a89f2014-10-06 18:33:03 -070090this tool. - is used for STDIN.
91`,
92 Run: func(cmd *cmdline.Command, args []string) error {
93 if len(args) != 1 {
94 return fmt.Errorf("requires exactly one argument, <file>, provided %d", len(args))
95 }
96 blessings, err := decodeBlessings(args[0])
97 if err != nil {
98 return fmt.Errorf("failed to decode provided blessings: %v", err)
99 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700100 wire := security.MarshalBlessings(blessings)
101 fmt.Printf("Blessings : %v\n", blessings)
102 fmt.Printf("PublicKey : %v\n", blessings.PublicKey())
Asim Shankardf88a2e2014-10-21 17:20:28 -0700103 fmt.Printf("Certificate chains : %d\n", len(wire.CertificateChains))
Asim Shankar66c52f92014-10-15 23:39:10 -0700104 for idx, chain := range wire.CertificateChains {
Asim Shankardf88a2e2014-10-21 17:20:28 -0700105 fmt.Printf("Chain #%d (%d certificates). Root certificate public key: %v\n", idx, len(chain), rootkey(chain))
106 for certidx, cert := range chain {
107 fmt.Printf(" Certificate #%d: %v with ", certidx, cert.Extension)
108 switch n := len(cert.Caveats); n {
109 case 1:
110 fmt.Printf("1 caveat")
111 default:
112 fmt.Printf("%d caveats", n)
113 }
114 fmt.Println("")
115 for cavidx, cav := range cert.Caveats {
116 fmt.Printf(" (%d) %v\n", cavidx, &cav)
117 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700118 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700119 }
Ankurcf6a89f2014-10-06 18:33:03 -0700120 return nil
121 },
122 }
123
124 cmdBlessSelf = &cmdline.Command{
125 Name: "blessself",
126 Short: "Generate a self-signed blessing",
127 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700128Returns a blessing with name <name> and self-signed by the principal specified
129by the environment that this tool is running in. Optionally, the blessing can
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800130be restricted with an expiry caveat specified using the --for flag. Additional
131caveats can be added with the --caveat flag.
Ankurcf6a89f2014-10-06 18:33:03 -0700132`,
133 ArgsName: "[<name>]",
134 ArgsLong: `
135<name> is the name used to create the self-signed blessing. If not
136specified, a name will be generated based on the hostname of the
137machine and the name of the user running this command.
138`,
139 Run: func(cmd *cmdline.Command, args []string) error {
Ankurcf6a89f2014-10-06 18:33:03 -0700140 var name string
141 switch len(args) {
142 case 0:
143 name = defaultBlessingName()
144 case 1:
145 name = args[0]
146 default:
147 return fmt.Errorf("requires at most one argument, provided %d", len(args))
148 }
149
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800150 caveats, err := flagBlessSelfCaveats.Compile()
151 if err != nil {
152 return fmt.Errorf("failed to parse caveats: %v", err)
153 }
154
Asim Shankar66c52f92014-10-15 23:39:10 -0700155 if flagBlessSelfFor != 0 {
156 cav, err := security.ExpiryCaveat(time.Now().Add(flagBlessSelfFor))
Ankurcf6a89f2014-10-06 18:33:03 -0700157 if err != nil {
Ankur8d304122014-10-07 10:43:43 -0700158 return fmt.Errorf("failed to create expiration Caveat: %v", err)
Ankurcf6a89f2014-10-06 18:33:03 -0700159 }
160 caveats = append(caveats, cav)
161 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800162
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800163 ctx, shutdown := veyron2.Init()
164 defer shutdown()
165 principal := veyron2.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800166 blessing, err := principal.BlessSelf(name, caveats...)
Ankurcf6a89f2014-10-06 18:33:03 -0700167 if err != nil {
168 return fmt.Errorf("failed to create self-signed blessing for name %q: %v", name, err)
169 }
170
171 return dumpBlessings(blessing)
172 },
173 }
174
Asim Shankar66c52f92014-10-15 23:39:10 -0700175 cmdBless = &cmdline.Command{
176 Name: "bless",
177 Short: "Bless another principal",
178 Long: `
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800179Bless another principal.
Asim Shankar66c52f92014-10-15 23:39:10 -0700180
Ankurc24ff422014-12-16 17:59:26 -0800181The blesser is obtained from the runtime this tool is using. The blessing that
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800182will be extended is the default one from the blesser's store, or specified by
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800183the --with flag. Expiration on the blessing are controlled via the --for flag.
184Additional caveats are controlled with the --caveat flag.
Asim Shankar66c52f92014-10-15 23:39:10 -0700185
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800186For example, let's say a principal "alice" wants to bless another principal "bob"
187as "alice/friend", the invocation would be:
188 VEYRON_CREDENTIALS=<path to alice> principal bless <path to bob> friend
189and this will dump the blessing to STDOUT.
190
191With the --remote_key and --remote_token flags, this command can be used to
192bless a principal on a remote machine as well. In this case, the blessing is
193not dumped to STDOUT but sent to the remote end. Use 'principal help
194recvblessings' for more details on that.
195`,
Asim Shankar66c52f92014-10-15 23:39:10 -0700196 ArgsName: "<principal to bless> <extension>",
197 ArgsLong: `
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800198<principal to bless> represents the principal to be blessed (i.e., whose public
199key will be provided with a name). This can be either:
200(a) The directory containing credentials for that principal,
201OR
202(b) The filename (- for STDIN) containing any other blessings of that
203 principal,
204OR
205(c) The object name produced by the 'recvblessings' command of this tool
206 running on behalf of another principal (if the --remote_key and
207 --remote_token flags are specified).
Asim Shankar66c52f92014-10-15 23:39:10 -0700208
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800209<extension> is the string extension that will be applied to create the
210blessing.
Asim Shankar66c52f92014-10-15 23:39:10 -0700211 `,
212 Run: func(cmd *cmdline.Command, args []string) error {
213 if len(args) != 2 {
214 return fmt.Errorf("require exactly two arguments, provided %d", len(args))
215 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800216
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800217 ctx, shutdown := veyron2.Init()
218 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800219
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800220 p := veyron2.GetPrincipal(ctx)
Asim Shankar66c52f92014-10-15 23:39:10 -0700221
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800222 var (
223 err error
224 with security.Blessings
225 )
Asim Shankar66c52f92014-10-15 23:39:10 -0700226 if len(flagBlessWith) > 0 {
227 if with, err = decodeBlessings(flagBlessWith); err != nil {
228 return fmt.Errorf("failed to read blessings from --with=%q: %v", flagBlessWith, err)
229 }
230 } else {
231 with = p.BlessingStore().Default()
232 }
233
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800234 caveats, err := flagBlessCaveats.Compile()
235 if err != nil {
236 return fmt.Errorf("failed to parse caveats: %v", err)
237 }
238
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800239 if c, err := security.ExpiryCaveat(time.Now().Add(flagBlessFor)); err != nil {
240 return fmt.Errorf("failed to create ExpiryCaveat: %v", err)
241 } else {
242 caveats = append(caveats, c)
243 }
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800244
Asim Shankar66c52f92014-10-15 23:39:10 -0700245 tobless, extension := args[0], args[1]
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800246 if (len(flagBlessRemoteKey) == 0) != (len(flagBlessRemoteToken) == 0) {
247 return fmt.Errorf("either both --remote_key and --remote_token should be set, or neither should")
248 }
249 if len(flagBlessRemoteKey) > 0 {
250 // Send blessings to a "server" started by a "recvblessings" command
251 granter := &granter{p, with, extension, caveats, flagBlessRemoteKey}
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800252 return sendBlessings(ctx, tobless, granter, flagBlessRemoteToken)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800253 }
254 // Blessing a principal whose key is available locally.
255 var key security.PublicKey
Asim Shankar66c52f92014-10-15 23:39:10 -0700256 if finfo, err := os.Stat(tobless); err == nil && finfo.IsDir() {
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700257 other, err := vsecurity.LoadPersistentPrincipal(tobless, nil)
Asim Shankar66c52f92014-10-15 23:39:10 -0700258 if err != nil {
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700259 if other, err = vsecurity.CreatePersistentPrincipal(tobless, nil); err != nil {
260 return fmt.Errorf("failed to read principal in directory %q: %v", tobless, err)
261 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700262 }
263 key = other.PublicKey()
264 } else if other, err := decodeBlessings(tobless); err != nil {
265 return fmt.Errorf("failed to decode blessings in %q: %v", tobless, err)
266 } else {
267 key = other.PublicKey()
268 }
269
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800270 blessings, err := p.Bless(key, with, extension, caveats[0], caveats[1:]...)
Asim Shankar66c52f92014-10-15 23:39:10 -0700271 if err != nil {
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800272 return fmt.Errorf("Bless(%v, %v, %q, ...) failed: %v", key, with, extension, err)
Asim Shankar66c52f92014-10-15 23:39:10 -0700273 }
274 return dumpBlessings(blessings)
275 },
276 }
277
278 cmdStoreForPeer = &cmdline.Command{
279 Name: "forpeer",
Ankurcf6a89f2014-10-06 18:33:03 -0700280 Short: "Return blessings marked for the provided peer",
281 Long: `
282Returns blessings that are marked for the provided peer in the
Asim Shankar1789b8a2014-10-31 17:31:41 -0700283BlessingStore specified by the environment that this tool is
284running in.
Ankurcf6a89f2014-10-06 18:33:03 -0700285`,
286 ArgsName: "[<peer_1> ... <peer_k>]",
287 ArgsLong: `
288<peer_1> ... <peer_k> are the (human-readable string) blessings bound
289to the peer. The returned blessings are marked with a pattern that is
290matched by at least one of these. If no arguments are specified,
291store.forpeer returns the blessings that are marked for all peers (i.e.,
292blessings set on the store with the "..." pattern).
293`,
294 Run: func(cmd *cmdline.Command, args []string) error {
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800295 ctx, shutdown := veyron2.Init()
296 defer shutdown()
297 principal := veyron2.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800298 return dumpBlessings(principal.BlessingStore().ForPeer(args...))
Ankurcf6a89f2014-10-06 18:33:03 -0700299 },
300 }
301
Asim Shankar66c52f92014-10-15 23:39:10 -0700302 cmdStoreDefault = &cmdline.Command{
303 Name: "default",
Ankurcf6a89f2014-10-06 18:33:03 -0700304 Short: "Return blessings marked as default",
305 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700306Returns blessings that are marked as default in the BlessingStore specified by
307the environment that this tool is running in.
Ankurcf6a89f2014-10-06 18:33:03 -0700308`,
309 Run: func(cmd *cmdline.Command, args []string) error {
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800310 ctx, shutdown := veyron2.Init()
311 defer shutdown()
312 principal := veyron2.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800313 return dumpBlessings(principal.BlessingStore().Default())
Ankurcf6a89f2014-10-06 18:33:03 -0700314 },
315 }
Ankur8d304122014-10-07 10:43:43 -0700316
Asim Shankar66c52f92014-10-15 23:39:10 -0700317 cmdStoreSet = &cmdline.Command{
318 Name: "set",
Ankur8d304122014-10-07 10:43:43 -0700319 Short: "Set provided blessings for peer",
320 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700321Marks the provided blessings to be shared with the provided peers on the
322BlessingStore specified by the environment that this tool is running in.
Ankur8d304122014-10-07 10:43:43 -0700323
324'set b pattern' marks the intention to reveal b to peers who
325present blessings of their own matching 'pattern'.
326
327'set nil pattern' can be used to remove the blessings previously
328associated with the pattern (by a prior 'set' command).
329
330It is an error to call 'store.set' with blessings whose public
331key does not match the public key of this principal specified
332by the environment.
333`,
334 ArgsName: "<file> <pattern>",
335 ArgsLong: `
336<file> is the path to a file containing a blessing typically obtained
337from this tool. - is used for STDIN.
338
339<pattern> is the BlessingPattern used to identify peers with whom this
340blessing can be shared with.
341`,
342 Run: func(cmd *cmdline.Command, args []string) error {
343 if len(args) != 2 {
Asim Shankar66c52f92014-10-15 23:39:10 -0700344 return fmt.Errorf("requires exactly two arguments <file>, <pattern>, provided %d", len(args))
Ankur8d304122014-10-07 10:43:43 -0700345 }
346 blessings, err := decodeBlessings(args[0])
347 if err != nil {
348 return fmt.Errorf("failed to decode provided blessings: %v", err)
349 }
350 pattern := security.BlessingPattern(args[1])
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800351
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800352 ctx, shutdown := veyron2.Init()
353 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800354
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800355 p := veyron2.GetPrincipal(ctx)
Asim Shankar66c52f92014-10-15 23:39:10 -0700356 if _, err := p.BlessingStore().Set(blessings, pattern); err != nil {
Ankur8d304122014-10-07 10:43:43 -0700357 return fmt.Errorf("failed to set blessings %v for peers %v: %v", blessings, pattern, err)
358 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700359 if flagAddToRoots {
360 if err := p.AddToRoots(blessings); err != nil {
361 return fmt.Errorf("AddToRoots failed: %v", err)
362 }
363 }
Ankur8d304122014-10-07 10:43:43 -0700364 return nil
365 },
366 }
367
Mike Burrows367515e2014-12-02 11:30:18 -0800368 cmdStoreAddToRoots = &cmdline.Command{
369 Name: "addtoroots",
370 Short: "Add provided blessings to root set",
371 Long: `
372Adds the provided blessings to the set of trusted roots for this principal.
373
374'addtoroots b' adds blessings b to the trusted root set.
375
376For example, to make the principal in credentials directory A trust the
377root of the default blessing in credentials directory B:
378 principal -veyron.credentials=B bless A some_extension |
379 principal -veyron.credentials=A store addtoroots -
380
381The extension 'some_extension' has no effect in the command above.
382`,
383 ArgsName: "<file>",
384 ArgsLong: `
385<file> is the path to a file containing a blessing typically obtained
386from this tool. - is used for STDIN.
387`,
388 Run: func(cmd *cmdline.Command, args []string) error {
389 if len(args) != 1 {
390 return fmt.Errorf("requires exactly one argument <file>, provided %d", len(args))
391 }
392 blessings, err := decodeBlessings(args[0])
393 if err != nil {
394 return fmt.Errorf("failed to decode provided blessings: %v", err)
395 }
396
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800397 ctx, shutdown := veyron2.Init()
398 defer shutdown()
Mike Burrows367515e2014-12-02 11:30:18 -0800399
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800400 p := veyron2.GetPrincipal(ctx)
Mike Burrows367515e2014-12-02 11:30:18 -0800401 if err := p.AddToRoots(blessings); err != nil {
402 return fmt.Errorf("AddToRoots failed: %v", err)
403 }
404 return nil
405 },
406 }
407
Asim Shankar66c52f92014-10-15 23:39:10 -0700408 cmdStoreSetDefault = &cmdline.Command{
409 Name: "setdefault",
Ankur8d304122014-10-07 10:43:43 -0700410 Short: "Set provided blessings as default",
411 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700412Sets the provided blessings as default in the BlessingStore specified by the
413environment that this tool is running in.
Ankur8d304122014-10-07 10:43:43 -0700414
Asim Shankar1789b8a2014-10-31 17:31:41 -0700415It is an error to call 'store.setdefault' with blessings whose public key does
416not match the public key of the principal specified by the environment.
Ankur8d304122014-10-07 10:43:43 -0700417`,
418 ArgsName: "<file>",
419 ArgsLong: `
420<file> is the path to a file containing a blessing typically obtained from
421this tool. - is used for STDIN.
422`,
423 Run: func(cmd *cmdline.Command, args []string) error {
424 if len(args) != 1 {
Asim Shankar66c52f92014-10-15 23:39:10 -0700425 return fmt.Errorf("requires exactly one argument, <file>, provided %d", len(args))
Ankur8d304122014-10-07 10:43:43 -0700426 }
427 blessings, err := decodeBlessings(args[0])
428 if err != nil {
429 return fmt.Errorf("failed to decode provided blessings: %v", err)
430 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800431
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800432 ctx, shutdown := veyron2.Init()
433 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800434
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800435 p := veyron2.GetPrincipal(ctx)
Asim Shankar1789b8a2014-10-31 17:31:41 -0700436 if err := p.BlessingStore().SetDefault(blessings); err != nil {
Ankur8d304122014-10-07 10:43:43 -0700437 return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
438 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700439 if flagAddToRoots {
440 if err := p.AddToRoots(blessings); err != nil {
441 return fmt.Errorf("AddToRoots failed: %v", err)
442 }
443 }
444 return nil
445 },
446 }
447
448 cmdCreate = &cmdline.Command{
449 Name: "create",
450 Short: "Create a new principal and persist it into a directory",
451 Long: `
Ankur4704f5f2014-10-23 12:40:54 -0700452Creates a new principal with a single self-blessed blessing and writes it out
Ankurc24ff422014-12-16 17:59:26 -0800453to the provided directory. The same directory can then be used to set the
454VEYRON_CREDENTIALS environment variable for other veyron applications.
Ankur4704f5f2014-10-23 12:40:54 -0700455
456The operation fails if the directory already contains a principal. In this case
Ankurc24ff422014-12-16 17:59:26 -0800457the --overwrite flag can be provided to clear the directory and write out the
gauthamtb7bb39b2014-11-10 11:40:41 -0800458new principal.
Ankur4704f5f2014-10-23 12:40:54 -0700459`,
Asim Shankar66c52f92014-10-15 23:39:10 -0700460 ArgsName: "<directory> <blessing>",
461 ArgsLong: `
Ankurc24ff422014-12-16 17:59:26 -0800462 <directory> is the directory to which the new principal will be persisted.
Asim Shankar66c52f92014-10-15 23:39:10 -0700463 <blessing> is the self-blessed blessing that the principal will be setup to use by default.
464 `,
465 Run: func(cmd *cmdline.Command, args []string) error {
466 if len(args) != 2 {
467 return fmt.Errorf("requires exactly two arguments: <directory> and <blessing>, provided %d", len(args))
468 }
469 dir, name := args[0], args[1]
Ankur4704f5f2014-10-23 12:40:54 -0700470 if flagCreateOverwrite {
Ankurc24ff422014-12-16 17:59:26 -0800471 if err := os.RemoveAll(dir); err != nil {
gauthamtb7bb39b2014-11-10 11:40:41 -0800472 return err
473 }
Ankur4704f5f2014-10-23 12:40:54 -0700474 }
Ankurc24ff422014-12-16 17:59:26 -0800475 p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700476 if err != nil {
477 return err
Asim Shankar66c52f92014-10-15 23:39:10 -0700478 }
479 blessings, err := p.BlessSelf(name)
480 if err != nil {
481 return fmt.Errorf("BlessSelf(%q) failed: %v", name, err)
482 }
Ankurc24ff422014-12-16 17:59:26 -0800483 if err := vsecurity.SetDefaultBlessings(p, blessings); err != nil {
484 return fmt.Errorf("could not set blessings %v as default: %v", blessings, err)
Asim Shankar66c52f92014-10-15 23:39:10 -0700485 }
Ankurc24ff422014-12-16 17:59:26 -0800486 return nil
487 },
488 }
489
490 cmdFork = &cmdline.Command{
491 Name: "fork",
492 Short: "Fork a new principal from the principal that this tool is running as and persist it into a directory",
493 Long: `
494Creates a new principal with a blessing from the principal specified by the
495environment that this tool is running in, and writes it out to the provided
496directory. The blessing that will be extended is the default one from the
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800497blesser's store, or specified by the --with flag. Expiration on the blessing
498are controlled via the --for flag. Additional caveats on the blessing are
499controlled with the --caveat flag. The blessing is marked as default and
Ankurc24ff422014-12-16 17:59:26 -0800500shareable with all peers on the new principal's blessing store.
501
502The operation fails if the directory already contains a principal. In this case
503the --overwrite flag can be provided to clear the directory and write out the
504forked principal.
505`,
506 ArgsName: "<directory> <extension>",
507 ArgsLong: `
508 <directory> is the directory to which the forked principal will be persisted.
509 <extension> is the extension under which the forked principal is blessed.
510 `,
511 Run: func(cmd *cmdline.Command, args []string) error {
512 if len(args) != 2 {
513 return fmt.Errorf("requires exactly two arguments: <directory> and <extension>, provided %d", len(args))
Asim Shankar66c52f92014-10-15 23:39:10 -0700514 }
Ankurc24ff422014-12-16 17:59:26 -0800515 dir, extension := args[0], args[1]
516
517 if flagCreateOverwrite {
518 if err := os.RemoveAll(dir); err != nil {
519 return err
520 }
521 }
522 p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
523 if err != nil {
524 return err
525 }
526
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800527 ctx, shutdown := veyron2.Init()
528 defer shutdown()
Ankurc24ff422014-12-16 17:59:26 -0800529
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800530 caveats, err := flagForkCaveats.Compile()
531 if err != nil {
532 return fmt.Errorf("failed to parse caveats: %v", err)
533 }
534
535 var with security.Blessings
Ankur77c32ac2014-12-18 14:18:19 -0800536 if len(flagForkWith) > 0 {
537 if with, err = decodeBlessings(flagForkWith); err != nil {
538 return fmt.Errorf("failed to read blessings from --with=%q: %v", flagForkWith, err)
Ankurc24ff422014-12-16 17:59:26 -0800539 }
540 } else {
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800541 with = veyron2.GetPrincipal(ctx).BlessingStore().Default()
Ankurc24ff422014-12-16 17:59:26 -0800542 }
Ankur77c32ac2014-12-18 14:18:19 -0800543 if c, err := security.ExpiryCaveat(time.Now().Add(flagForkFor)); err != nil {
Ankurc24ff422014-12-16 17:59:26 -0800544 return fmt.Errorf("failed to create ExpiryCaveat: %v", err)
545 } else {
546 caveats = append(caveats, c)
547 }
Ankurc24ff422014-12-16 17:59:26 -0800548
549 key := p.PublicKey()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800550 rp := veyron2.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800551 blessings, err := rp.Bless(key, with, extension, caveats[0], caveats[1:]...)
Ankurc24ff422014-12-16 17:59:26 -0800552 if err != nil {
553 return fmt.Errorf("Bless(%v, %v, %q, ...) failed: %v", key, with, extension, err)
554 }
555 if err := vsecurity.SetDefaultBlessings(p, blessings); err != nil {
556 return fmt.Errorf("could not set blessings %v as default: %v", blessings, err)
Asim Shankar66c52f92014-10-15 23:39:10 -0700557 }
Ankur8d304122014-10-07 10:43:43 -0700558 return nil
559 },
560 }
Ankur1d46f552014-10-09 12:13:31 -0700561
562 cmdSeekBlessings = &cmdline.Command{
563 Name: "seekblessings",
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800564 Short: "Seek blessings from a web-based Veyron blessing service",
Ankur1d46f552014-10-09 12:13:31 -0700565 Long: `
566Seeks blessings from a web-based Veyron blesser which
567requires the caller to first authenticate with Google using OAuth. Simply
568run the command to see what happens.
569
Asim Shankar1789b8a2014-10-31 17:31:41 -0700570The blessings are sought for the principal specified by the environment that
571this tool is running in.
Ankur1d46f552014-10-09 12:13:31 -0700572
Ankure548f392014-12-08 18:42:41 -0800573The blessings obtained are set as default, unless the --set_default flag is
574set to true, and are also set for sharing with all peers, unless a more
Ankur1d46f552014-10-09 12:13:31 -0700575specific peer pattern is provided using the --for_peer flag.
576`,
577 Run: func(cmd *cmdline.Command, args []string) error {
Asim Shankar08ab3892014-10-16 12:04:07 -0700578 // Initialize the runtime first so that any local errors are reported
579 // before the HTTP roundtrips for obtaining the macaroon begin.
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800580 ctx, shutdown := veyron2.Init()
581 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800582
Ankur1d46f552014-10-09 12:13:31 -0700583 blessedChan := make(chan string)
584 defer close(blessedChan)
Suharsh Sivakumara76dba62014-12-22 16:00:34 -0800585 macaroonChan, err := getMacaroonForBlessRPC(flagSeekBlessingsFrom, blessedChan, flagSeekBlessingsBrowser)
Ankur1d46f552014-10-09 12:13:31 -0700586 if err != nil {
587 return fmt.Errorf("failed to get macaroon from Veyron blesser: %v", err)
588 }
Ankur1d46f552014-10-09 12:13:31 -0700589
Suharsh Sivakumar67ef84a2015-02-13 13:04:44 -0800590 blessings, err := exchangeMacaroonForBlessing(ctx, macaroonChan)
Ankur1d46f552014-10-09 12:13:31 -0700591 if err != nil {
Suharsh Sivakumar67ef84a2015-02-13 13:04:44 -0800592 return err
Ankur1d46f552014-10-09 12:13:31 -0700593 }
594 blessedChan <- fmt.Sprint(blessings)
595 // Wait for getTokenForBlessRPC to clean up:
596 <-macaroonChan
597
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800598 p := veyron2.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800599
Asim Shankar66c52f92014-10-15 23:39:10 -0700600 if flagSeekBlessingsSetDefault {
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800601 if err := p.BlessingStore().SetDefault(blessings); err != nil {
Ankur1d46f552014-10-09 12:13:31 -0700602 return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
603 }
604 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700605 if pattern := security.BlessingPattern(flagSeekBlessingsForPeer); len(pattern) > 0 {
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800606 if _, err := p.BlessingStore().Set(blessings, pattern); err != nil {
Asim Shankar66c52f92014-10-15 23:39:10 -0700607 return fmt.Errorf("failed to set blessings %v for peers %v: %v", blessings, pattern, err)
608 }
609 }
610 if flagAddToRoots {
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800611 if err := p.AddToRoots(blessings); err != nil {
Asim Shankar66c52f92014-10-15 23:39:10 -0700612 return fmt.Errorf("AddToRoots failed: %v", err)
613 }
Ankur1d46f552014-10-09 12:13:31 -0700614 }
Asim Shankar3f9bbab2015-02-15 13:51:37 -0800615 fmt.Fprintf(cmd.Stdout(), "Received blessings: %v\n", blessings)
Jiri Simsa37b0a092015-02-13 09:32:39 -0800616 return nil
Ankur1d46f552014-10-09 12:13:31 -0700617 },
618 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800619
620 cmdRecvBlessings = &cmdline.Command{
621 Name: "recvblessings",
622 Short: "Receive blessings sent by another principal and use them as the default",
623 Long: `
624Allow another principal (likely a remote process) to bless this one.
625
626This command sets up the invoker (this process) to wait for a blessing
627from another invocation of this tool (remote process) and prints out the
628command to be run as the remote principal.
629
Ankure548f392014-12-08 18:42:41 -0800630The received blessings are set as default, unless the --set_default flag is
631set to true, and are also set for sharing with all peers, unless a more
632specific peer pattern is provided using the --for_peer flag.
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800633
634TODO(ashankar,cnicolaou): Make this next paragraph possible! Requires
635the ability to obtain the proxied endpoint.
636
637Typically, this command should require no arguments.
638However, if the sender and receiver are on different network domains, it may
639make sense to use the --veyron.proxy flag:
Robin Thellend8fea01c2014-12-11 13:48:10 -0800640 principal --veyron.proxy=proxy recvblessings
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800641
642The command to be run at the sender is of the form:
643 principal bless --remote_key=KEY --remote_token=TOKEN ADDRESS
644
645The --remote_key flag is used to by the sender to "authenticate" the receiver,
646ensuring it blesses the intended recipient and not any attacker that may have
647taken over the address.
648
649The --remote_token flag is used by the sender to authenticate itself to the
650receiver. This helps ensure that the receiver rejects blessings from senders
651who just happened to guess the network address of the 'recvblessings'
652invocation.
653`,
654 Run: func(cmd *cmdline.Command, args []string) error {
655 if len(args) != 0 {
656 return fmt.Errorf("command accepts no arguments")
657 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800658
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800659 ctx, shutdown := veyron2.Init()
660 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800661
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800662 server, err := veyron2.NewServer(ctx)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800663 if err != nil {
664 return fmt.Errorf("failed to create server to listen for blessings: %v", err)
665 }
666 defer server.Stop()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800667 eps, err := server.Listen(veyron2.GetListenSpec(ctx))
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800668 if err != nil {
669 return fmt.Errorf("failed to setup listening: %v", err)
670 }
671 var token [24]byte
672 if _, err := rand.Read(token[:]); err != nil {
673 return fmt.Errorf("unable to generate token: %v", err)
674 }
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800675
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800676 p := veyron2.GetPrincipal(ctx)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800677 service := &recvBlessingsService{
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800678 principal: p,
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800679 token: base64.URLEncoding.EncodeToString(token[:]),
680 notify: make(chan error),
681 }
682 if err := server.Serve("", service, allowAnyone{}); err != nil {
683 return fmt.Errorf("failed to setup service: %v", err)
684 }
685 // Proposed name:
686 extension := fmt.Sprintf("extension%d", int(token[0])<<16|int(token[1])<<8|int(token[2]))
687 fmt.Println("Run the following command on behalf of the principal that will send blessings:")
688 fmt.Println("You may want to adjust flags affecting the caveats on this blessing, for example using")
689 fmt.Println("the --for flag, or change the extension to something more meaningful")
690 fmt.Println()
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800691 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 -0800692 fmt.Println()
693 fmt.Println("...waiting for sender..")
694 return <-service.notify
695 },
696 }
Ankurcf6a89f2014-10-06 18:33:03 -0700697)
698
699func main() {
Asim Shankar66c52f92014-10-15 23:39:10 -0700700 cmdBlessSelf.Flags.DurationVar(&flagBlessSelfFor, "for", 0, "Duration of blessing validity (zero means no that the blessing is always valid)")
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800701 cmdBlessSelf.Flags.Var(&flagBlessSelfCaveats, "caveat", flagBlessSelfCaveats.usage())
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800702
Ankur77c32ac2014-12-18 14:18:19 -0800703 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 -0800704 cmdFork.Flags.Var(&flagForkCaveats, "caveat", flagForkCaveats.usage())
Ankur77c32ac2014-12-18 14:18:19 -0800705 cmdFork.Flags.DurationVar(&flagForkFor, "for", 0, "Duration for which the forked blessing is valid (zero means no that the blessing is always valid)")
706 cmdFork.Flags.StringVar(&flagForkWith, "with", "", "Path to file containing blessing to extend")
707
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800708 cmdBless.Flags.Var(&flagBlessCaveats, "caveat", flagBlessCaveats.usage())
Asim Shankar66c52f92014-10-15 23:39:10 -0700709 cmdBless.Flags.DurationVar(&flagBlessFor, "for", time.Minute, "Duration of blessing validity")
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800710 cmdBless.Flags.StringVar(&flagBlessWith, "with", "", "Path to file containing blessing to extend")
711 cmdBless.Flags.StringVar(&flagBlessRemoteKey, "remote_key", "", "Public key of the remote principal to bless (obtained from the 'recvblessings' command run by the remote principal")
712 cmdBless.Flags.StringVar(&flagBlessRemoteToken, "remote_token", "", "Token provided by principal running the 'recvblessings' command")
713
Robin Thellend8fea01c2014-12-11 13:48:10 -0800714 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 -0700715 cmdSeekBlessings.Flags.BoolVar(&flagSeekBlessingsSetDefault, "set_default", true, "If true, the blessings obtained will be set as the default blessing in the store")
716 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 -0800717 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 -0700718 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 -0800719
Asim Shankar66c52f92014-10-15 23:39:10 -0700720 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 -0800721
Asim Shankar66c52f92014-10-15 23:39:10 -0700722 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 -0800723
Ankur4704f5f2014-10-23 12:40:54 -0700724 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 -0700725
Ankure548f392014-12-08 18:42:41 -0800726 cmdRecvBlessings.Flags.BoolVar(&flagRecvBlessingsSetDefault, "set_default", true, "If true, the blessings received will be set as the default blessing in the store")
727 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")
728
Asim Shankar66c52f92014-10-15 23:39:10 -0700729 cmdStore := &cmdline.Command{
730 Name: "store",
731 Short: "Manipulate and inspect the principal's blessing store",
732 Long: `
733Commands to manipulate and inspect the blessing store of the principal.
734
735All blessings are printed to stdout using base64-VOM-encoding
736`,
Mike Burrows367515e2014-12-02 11:30:18 -0800737 Children: []*cmdline.Command{cmdStoreDefault, cmdStoreSetDefault, cmdStoreForPeer, cmdStoreSet, cmdStoreAddToRoots},
Ankurcf6a89f2014-10-06 18:33:03 -0700738 }
Ankurcf6a89f2014-10-06 18:33:03 -0700739
Matt Rosencrantz92303e12015-01-21 09:02:42 -0800740 root := &cmdline.Command{
Ankurcf6a89f2014-10-06 18:33:03 -0700741 Name: "principal",
742 Short: "Create and manage veyron principals",
743 Long: `
744The principal tool helps create and manage blessings and the set of trusted
745roots bound to a principal.
746
747All objects are printed using base64-VOM-encoding.
748`,
Ankurc24ff422014-12-16 17:59:26 -0800749 Children: []*cmdline.Command{cmdCreate, cmdFork, cmdSeekBlessings, cmdRecvBlessings, cmdDump, cmdDumpBlessings, cmdBlessSelf, cmdBless, cmdStore},
Matt Rosencrantz92303e12015-01-21 09:02:42 -0800750 }
751 os.Exit(root.Main())
Ankurcf6a89f2014-10-06 18:33:03 -0700752}
753
Ankurcf6a89f2014-10-06 18:33:03 -0700754func decodeBlessings(fname string) (security.Blessings, error) {
755 var wire security.WireBlessings
756 if err := decode(fname, &wire); err != nil {
757 return nil, err
758 }
759 return security.NewBlessings(wire)
760}
761
762func dumpBlessings(blessings security.Blessings) error {
763 if blessings == nil {
764 return errors.New("no blessings found")
765 }
Ankuree0aa812014-11-14 10:56:52 -0800766 str, err := base64VomEncode(security.MarshalBlessings(blessings))
Ankurcf6a89f2014-10-06 18:33:03 -0700767 if err != nil {
768 return fmt.Errorf("base64-VOM encoding failed: %v", err)
769 }
770 fmt.Println(str)
771 return nil
772}
773
774func read(fname string) (string, error) {
775 if len(fname) == 0 {
776 return "", nil
777 }
778 f := os.Stdin
779 if fname != "-" {
780 var err error
781 if f, err = os.Open(fname); err != nil {
782 return "", fmt.Errorf("failed to open %q: %v", fname, err)
783 }
784 }
785 defer f.Close()
786 var buf bytes.Buffer
787 if _, err := io.Copy(&buf, f); err != nil {
788 return "", fmt.Errorf("failed to read %q: %v", fname, err)
789 }
790 return buf.String(), nil
791}
792
793func decode(fname string, val interface{}) error {
794 str, err := read(fname)
795 if err != nil {
796 return err
797 }
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700798 if err := base64VomDecode(str, val); err != nil || val == nil {
Ankurcf6a89f2014-10-06 18:33:03 -0700799 return fmt.Errorf("failed to decode %q: %v", fname, err)
800 }
801 return nil
802}
803
804func defaultBlessingName() string {
805 var name string
806 if user, _ := user.Current(); user != nil && len(user.Username) > 0 {
807 name = user.Username
808 } else {
809 name = "anonymous"
810 }
811 if host, _ := os.Hostname(); len(host) > 0 {
812 name = name + "@" + host
813 }
814 return name
815}
Asim Shankardf88a2e2014-10-21 17:20:28 -0700816
817func rootkey(chain []security.Certificate) string {
818 if len(chain) == 0 {
819 return "<empty certificate chain>"
820 }
821 key, err := security.UnmarshalPublicKey(chain[0].PublicKey)
822 if err != nil {
823 return fmt.Sprintf("<invalid PublicKey: %v>", err)
824 }
825 return fmt.Sprintf("%v", key)
826}
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700827
828func base64VomEncode(i interface{}) (string, error) {
829 buf := &bytes.Buffer{}
830 closer := base64.NewEncoder(base64.URLEncoding, buf)
Todd Wang3425a902015-01-21 18:43:59 -0800831 enc, err := vom.NewBinaryEncoder(closer)
Suharsh Sivakumar12b089d2015-01-02 14:17:12 -0800832 if err != nil {
833 return "", err
834 }
835 if err := enc.Encode(i); err != nil {
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700836 return "", err
837 }
838 // Must close the base64 encoder to flush out any partially written
839 // blocks.
840 if err := closer.Close(); err != nil {
841 return "", err
842 }
843 return buf.String(), nil
844}
845
846func base64VomDecode(s string, i interface{}) error {
847 b, err := base64.URLEncoding.DecodeString(s)
848 if err != nil {
849 return err
850 }
Todd Wang3425a902015-01-21 18:43:59 -0800851 dec, err := vom.NewDecoder(bytes.NewBuffer(b))
Suharsh Sivakumar12b089d2015-01-02 14:17:12 -0800852 if err != nil {
853 return err
854 }
855 return dec.Decode(i)
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700856}
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800857
858type recvBlessingsService struct {
859 principal security.Principal
860 notify chan error
861 token string
862}
863
864func (r *recvBlessingsService) Grant(call ipc.ServerCall, token string) error {
865 b := call.Blessings()
866 if b == nil {
867 return fmt.Errorf("no blessings granted by sender")
868 }
869 if len(token) != len(r.token) {
870 // A timing attack can be used to figure out the length
871 // of the token, but then again, so can looking at the
872 // source code. So, it's okay.
873 return fmt.Errorf("blessings received from unexpected sender")
874 }
875 if subtle.ConstantTimeCompare([]byte(token), []byte(r.token)) != 1 {
876 return fmt.Errorf("blessings received from unexpected sender")
877 }
Ankure548f392014-12-08 18:42:41 -0800878 if flagRecvBlessingsSetDefault {
879 if err := r.principal.BlessingStore().SetDefault(b); err != nil {
880 return fmt.Errorf("failed to set blessings %v as default: %v", b, err)
881 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800882 }
Ankure548f392014-12-08 18:42:41 -0800883 if pattern := security.BlessingPattern(flagRecvBlessingsForPeer); len(pattern) > 0 {
884 if _, err := r.principal.BlessingStore().Set(b, pattern); err != nil {
885 return fmt.Errorf("failed to set blessings %v for peers %v: %v", b, pattern, err)
886 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800887 }
888 if flagAddToRoots {
889 if err := r.principal.AddToRoots(b); err != nil {
890 return fmt.Errorf("failed to add blessings to recognized roots: %v", err)
891 }
892 }
893 fmt.Println("Received blessings:", b)
894 r.notify <- nil
895 return nil
896}
897
898type allowAnyone struct{}
899
900func (allowAnyone) Authorize(security.Context) error { return nil }
901
902type granter struct {
903 p security.Principal
904 with security.Blessings
905 extension string
906 caveats []security.Caveat
907 serverKey string
908}
909
910func (g *granter) Grant(server security.Blessings) (security.Blessings, error) {
911 if got := fmt.Sprintf("%v", server.PublicKey()); got != g.serverKey {
912 // If the granter returns an error, the IPC framework should
913 // abort the RPC before sending the request to the server.
914 // Thus, there is no concern about leaking the token to an
915 // imposter server.
916 return nil, fmt.Errorf("key mismatch: Remote end has public key %v, want %v", got, g.serverKey)
917 }
918 return g.p.Bless(server.PublicKey(), g.with, g.extension, g.caveats[0], g.caveats[1:]...)
919}
920func (*granter) IPCCallOpt() {}
921
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800922func sendBlessings(ctx *context.T, object string, granter *granter, remoteToken string) error {
923 client := veyron2.GetClient(ctx)
924 call, err := client.StartCall(ctx, object, "Grant", []interface{}{remoteToken}, granter)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800925 if err != nil {
926 return fmt.Errorf("failed to start RPC to %q: %v", object, err)
927 }
928 if ierr := call.Finish(&err); ierr != nil {
929 return fmt.Errorf("failed to finish RPC to %q: %v", object, ierr)
930 }
931 return err
932}