blob: ce01ec6d1de0b3dfb1bd9c1df1fecdb79b2669b8 [file] [log] [blame]
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -08001// The following enables go generate to generate the doc.go file.
Jiri Simsa24a71552015-02-27 11:31:36 -08002//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/x/lib/cmdline/testdata/gendoc.go .
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -08003
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 "fmt"
12 "io"
13 "os"
14 "os/user"
15 "time"
16
Jiri Simsa6ac95222015-02-23 16:11:49 -080017 "v.io/v23"
18 "v.io/v23/context"
19 "v.io/v23/ipc"
20 "v.io/v23/security"
21 "v.io/v23/vom"
Jiri Simsa24a71552015-02-27 11:31:36 -080022 "v.io/x/lib/cmdline"
Jiri Simsaffceefa2015-02-28 11:03:34 -080023 _ "v.io/x/ref/profiles/static"
24 vsecurity "v.io/x/ref/security"
Ankurcf6a89f2014-10-06 18:33:03 -070025)
26
27var (
28 // Flags for the "blessself" command
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -080029 flagBlessSelfCaveats caveatsFlag
30 flagBlessSelfFor time.Duration
Ankurcf6a89f2014-10-06 18:33:03 -070031
Asim Shankar66c52f92014-10-15 23:39:10 -070032 // Flags for the "bless" command
Asim Shankara0bba462015-02-20 22:50:51 -080033 flagBlessCaveats caveatsFlag
34 flagBlessFor time.Duration
35 flagBlessRequireCaveats bool
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
Asim Shankara0bba462015-02-20 22:50:51 -080041 flagForkCaveats caveatsFlag
42 flagForkFor time.Duration
43 flagForkRequireCaveats bool
44 flagForkWith string
Ankur77c32ac2014-12-18 14:18:19 -080045
Asim Shankar66c52f92014-10-15 23:39:10 -070046 // Flags for the "seekblessings" command
47 flagSeekBlessingsFrom string
48 flagSeekBlessingsSetDefault bool
49 flagSeekBlessingsForPeer string
Suharsh Sivakumara76dba62014-12-22 16:00:34 -080050 flagSeekBlessingsBrowser bool
Asim Shankar66c52f92014-10-15 23:39:10 -070051
52 // Flags common to many commands
Ankurc24ff422014-12-16 17:59:26 -080053 flagAddToRoots bool
54 flagCreateOverwrite bool
Ankur1d46f552014-10-09 12:13:31 -070055
Ankure548f392014-12-08 18:42:41 -080056 // Flags for the "recvblessings" command
57 flagRecvBlessingsSetDefault bool
58 flagRecvBlessingsForPeer string
59
Bogdan Capritaed02d302015-02-21 12:41:05 -080060 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 --require_caveats=false")
Asim Shankara0bba462015-02-20 22:50:51 -080061 cmdDump = &cmdline.Command{
Ankur1615a7d2014-10-09 11:58:02 -070062 Name: "dump",
63 Short: "Dump out information about the principal",
64 Long: `
Asim Shankar66c52f92014-10-15 23:39:10 -070065Prints out information about the principal specified by the environment
Asim Shankar1789b8a2014-10-31 17:31:41 -070066that this tool is running in.
Ankur1615a7d2014-10-09 11:58:02 -070067`,
68 Run: func(cmd *cmdline.Command, args []string) error {
Jiri Simsa6ac95222015-02-23 16:11:49 -080069 ctx, shutdown := v23.Init()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -080070 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -080071
Jiri Simsa6ac95222015-02-23 16:11:49 -080072 p := v23.GetPrincipal(ctx)
Ankur1615a7d2014-10-09 11:58:02 -070073 fmt.Printf("Public key : %v\n", p.PublicKey())
Ankur1615a7d2014-10-09 11:58:02 -070074 fmt.Println("---------------- BlessingStore ----------------")
75 fmt.Printf("%v", p.BlessingStore().DebugString())
Ankur1615a7d2014-10-09 11:58:02 -070076 fmt.Println("---------------- BlessingRoots ----------------")
77 fmt.Printf("%v", p.Roots().DebugString())
78 return nil
79 },
80 }
81
Asim Shankar66c52f92014-10-15 23:39:10 -070082 cmdDumpBlessings = &cmdline.Command{
83 Name: "dumpblessings",
84 Short: "Dump out information about the provided blessings",
Ankurcf6a89f2014-10-06 18:33:03 -070085 Long: `
Asim Shankar66c52f92014-10-15 23:39:10 -070086Prints out information about the blessings (typically obtained from this tool)
Ankurcf6a89f2014-10-06 18:33:03 -070087encoded in the provided file.
88`,
89 ArgsName: "<file>",
90 ArgsLong: `
Asim Shankar66c52f92014-10-15 23:39:10 -070091<file> is the path to a file containing blessings typically obtained from
Ankurcf6a89f2014-10-06 18:33:03 -070092this tool. - is used for STDIN.
93`,
94 Run: func(cmd *cmdline.Command, args []string) error {
95 if len(args) != 1 {
96 return fmt.Errorf("requires exactly one argument, <file>, provided %d", len(args))
97 }
98 blessings, err := decodeBlessings(args[0])
99 if err != nil {
100 return fmt.Errorf("failed to decode provided blessings: %v", err)
101 }
Asim Shankarb07ec692015-02-27 23:40:44 -0800102 wire, err := blessings2wire(blessings)
103 if err != nil {
104 return fmt.Errorf("failed to decode certificate chains: %v", err)
105 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700106 fmt.Printf("Blessings : %v\n", blessings)
107 fmt.Printf("PublicKey : %v\n", blessings.PublicKey())
Asim Shankardf88a2e2014-10-21 17:20:28 -0700108 fmt.Printf("Certificate chains : %d\n", len(wire.CertificateChains))
Asim Shankar66c52f92014-10-15 23:39:10 -0700109 for idx, chain := range wire.CertificateChains {
Asim Shankardf88a2e2014-10-21 17:20:28 -0700110 fmt.Printf("Chain #%d (%d certificates). Root certificate public key: %v\n", idx, len(chain), rootkey(chain))
111 for certidx, cert := range chain {
112 fmt.Printf(" Certificate #%d: %v with ", certidx, cert.Extension)
113 switch n := len(cert.Caveats); n {
114 case 1:
115 fmt.Printf("1 caveat")
116 default:
117 fmt.Printf("%d caveats", n)
118 }
119 fmt.Println("")
120 for cavidx, cav := range cert.Caveats {
121 fmt.Printf(" (%d) %v\n", cavidx, &cav)
122 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700123 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700124 }
Ankurcf6a89f2014-10-06 18:33:03 -0700125 return nil
126 },
127 }
128
129 cmdBlessSelf = &cmdline.Command{
130 Name: "blessself",
131 Short: "Generate a self-signed blessing",
132 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700133Returns a blessing with name <name> and self-signed by the principal specified
134by the environment that this tool is running in. Optionally, the blessing can
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800135be restricted with an expiry caveat specified using the --for flag. Additional
136caveats can be added with the --caveat flag.
Ankurcf6a89f2014-10-06 18:33:03 -0700137`,
138 ArgsName: "[<name>]",
139 ArgsLong: `
140<name> is the name used to create the self-signed blessing. If not
141specified, a name will be generated based on the hostname of the
142machine and the name of the user running this command.
143`,
144 Run: func(cmd *cmdline.Command, args []string) error {
Ankurcf6a89f2014-10-06 18:33:03 -0700145 var name string
146 switch len(args) {
147 case 0:
148 name = defaultBlessingName()
149 case 1:
150 name = args[0]
151 default:
152 return fmt.Errorf("requires at most one argument, provided %d", len(args))
153 }
154
Asim Shankara0bba462015-02-20 22:50:51 -0800155 caveats, err := caveatsFromFlags(flagBlessSelfFor, &flagBlessSelfCaveats)
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800156 if err != nil {
Asim Shankara0bba462015-02-20 22:50:51 -0800157 return err
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800158 }
Jiri Simsa6ac95222015-02-23 16:11:49 -0800159 ctx, shutdown := v23.Init()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800160 defer shutdown()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800161 principal := v23.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800162 blessing, err := principal.BlessSelf(name, caveats...)
Ankurcf6a89f2014-10-06 18:33:03 -0700163 if err != nil {
164 return fmt.Errorf("failed to create self-signed blessing for name %q: %v", name, err)
165 }
166
167 return dumpBlessings(blessing)
168 },
169 }
170
Asim Shankar66c52f92014-10-15 23:39:10 -0700171 cmdBless = &cmdline.Command{
172 Name: "bless",
173 Short: "Bless another principal",
174 Long: `
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800175Bless another principal.
Asim Shankar66c52f92014-10-15 23:39:10 -0700176
Ankurc24ff422014-12-16 17:59:26 -0800177The blesser is obtained from the runtime this tool is using. The blessing that
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800178will be extended is the default one from the blesser's store, or specified by
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800179the --with flag. Expiration on the blessing are controlled via the --for flag.
180Additional caveats are controlled with the --caveat flag.
Asim Shankar66c52f92014-10-15 23:39:10 -0700181
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800182For example, let's say a principal "alice" wants to bless another principal "bob"
183as "alice/friend", the invocation would be:
184 VEYRON_CREDENTIALS=<path to alice> principal bless <path to bob> friend
185and this will dump the blessing to STDOUT.
186
187With the --remote_key and --remote_token flags, this command can be used to
188bless a principal on a remote machine as well. In this case, the blessing is
189not dumped to STDOUT but sent to the remote end. Use 'principal help
190recvblessings' for more details on that.
191`,
Asim Shankar66c52f92014-10-15 23:39:10 -0700192 ArgsName: "<principal to bless> <extension>",
193 ArgsLong: `
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800194<principal to bless> represents the principal to be blessed (i.e., whose public
195key will be provided with a name). This can be either:
196(a) The directory containing credentials for that principal,
197OR
198(b) The filename (- for STDIN) containing any other blessings of that
199 principal,
200OR
201(c) The object name produced by the 'recvblessings' command of this tool
202 running on behalf of another principal (if the --remote_key and
203 --remote_token flags are specified).
Asim Shankar66c52f92014-10-15 23:39:10 -0700204
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800205<extension> is the string extension that will be applied to create the
206blessing.
Asim Shankar66c52f92014-10-15 23:39:10 -0700207 `,
208 Run: func(cmd *cmdline.Command, args []string) error {
209 if len(args) != 2 {
210 return fmt.Errorf("require exactly two arguments, provided %d", len(args))
211 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800212
Jiri Simsa6ac95222015-02-23 16:11:49 -0800213 ctx, shutdown := v23.Init()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800214 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800215
Jiri Simsa6ac95222015-02-23 16:11:49 -0800216 p := v23.GetPrincipal(ctx)
Asim Shankar66c52f92014-10-15 23:39:10 -0700217
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800218 var (
219 err error
220 with security.Blessings
221 )
Asim Shankar66c52f92014-10-15 23:39:10 -0700222 if len(flagBlessWith) > 0 {
223 if with, err = decodeBlessings(flagBlessWith); err != nil {
224 return fmt.Errorf("failed to read blessings from --with=%q: %v", flagBlessWith, err)
225 }
226 } else {
227 with = p.BlessingStore().Default()
228 }
Asim Shankara0bba462015-02-20 22:50:51 -0800229 caveats, err := caveatsFromFlags(flagBlessFor, &flagBlessCaveats)
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800230 if err != nil {
Asim Shankara0bba462015-02-20 22:50:51 -0800231 return err
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800232 }
Asim Shankara0bba462015-02-20 22:50:51 -0800233 if !flagBlessRequireCaveats && len(caveats) == 0 {
234 caveats = []security.Caveat{security.UnconstrainedUse()}
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800235 }
Bogdan Caprita553e5822015-02-20 14:50:41 -0800236 if len(caveats) == 0 {
Asim Shankara0bba462015-02-20 22:50:51 -0800237 return errNoCaveats
Bogdan Caprita553e5822015-02-20 14:50:41 -0800238 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700239 tobless, extension := args[0], args[1]
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800240 if (len(flagBlessRemoteKey) == 0) != (len(flagBlessRemoteToken) == 0) {
241 return fmt.Errorf("either both --remote_key and --remote_token should be set, or neither should")
242 }
243 if len(flagBlessRemoteKey) > 0 {
244 // Send blessings to a "server" started by a "recvblessings" command
245 granter := &granter{p, with, extension, caveats, flagBlessRemoteKey}
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800246 return sendBlessings(ctx, tobless, granter, flagBlessRemoteToken)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800247 }
248 // Blessing a principal whose key is available locally.
249 var key security.PublicKey
Asim Shankar66c52f92014-10-15 23:39:10 -0700250 if finfo, err := os.Stat(tobless); err == nil && finfo.IsDir() {
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700251 other, err := vsecurity.LoadPersistentPrincipal(tobless, nil)
Asim Shankar66c52f92014-10-15 23:39:10 -0700252 if err != nil {
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700253 if other, err = vsecurity.CreatePersistentPrincipal(tobless, nil); err != nil {
254 return fmt.Errorf("failed to read principal in directory %q: %v", tobless, err)
255 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700256 }
257 key = other.PublicKey()
258 } else if other, err := decodeBlessings(tobless); err != nil {
259 return fmt.Errorf("failed to decode blessings in %q: %v", tobless, err)
260 } else {
261 key = other.PublicKey()
262 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800263 blessings, err := p.Bless(key, with, extension, caveats[0], caveats[1:]...)
Asim Shankar66c52f92014-10-15 23:39:10 -0700264 if err != nil {
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800265 return fmt.Errorf("Bless(%v, %v, %q, ...) failed: %v", key, with, extension, err)
Asim Shankar66c52f92014-10-15 23:39:10 -0700266 }
267 return dumpBlessings(blessings)
268 },
269 }
270
271 cmdStoreForPeer = &cmdline.Command{
272 Name: "forpeer",
Ankurcf6a89f2014-10-06 18:33:03 -0700273 Short: "Return blessings marked for the provided peer",
274 Long: `
275Returns blessings that are marked for the provided peer in the
Asim Shankar1789b8a2014-10-31 17:31:41 -0700276BlessingStore specified by the environment that this tool is
277running in.
Ankurcf6a89f2014-10-06 18:33:03 -0700278`,
279 ArgsName: "[<peer_1> ... <peer_k>]",
280 ArgsLong: `
281<peer_1> ... <peer_k> are the (human-readable string) blessings bound
282to the peer. The returned blessings are marked with a pattern that is
283matched by at least one of these. If no arguments are specified,
284store.forpeer returns the blessings that are marked for all peers (i.e.,
285blessings set on the store with the "..." pattern).
286`,
287 Run: func(cmd *cmdline.Command, args []string) error {
Jiri Simsa6ac95222015-02-23 16:11:49 -0800288 ctx, shutdown := v23.Init()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800289 defer shutdown()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800290 principal := v23.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800291 return dumpBlessings(principal.BlessingStore().ForPeer(args...))
Ankurcf6a89f2014-10-06 18:33:03 -0700292 },
293 }
294
Asim Shankar66c52f92014-10-15 23:39:10 -0700295 cmdStoreDefault = &cmdline.Command{
296 Name: "default",
Ankurcf6a89f2014-10-06 18:33:03 -0700297 Short: "Return blessings marked as default",
298 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700299Returns blessings that are marked as default in the BlessingStore specified by
300the environment that this tool is running in.
Ankurcf6a89f2014-10-06 18:33:03 -0700301`,
302 Run: func(cmd *cmdline.Command, args []string) error {
Jiri Simsa6ac95222015-02-23 16:11:49 -0800303 ctx, shutdown := v23.Init()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800304 defer shutdown()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800305 principal := v23.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800306 return dumpBlessings(principal.BlessingStore().Default())
Ankurcf6a89f2014-10-06 18:33:03 -0700307 },
308 }
Ankur8d304122014-10-07 10:43:43 -0700309
Asim Shankar66c52f92014-10-15 23:39:10 -0700310 cmdStoreSet = &cmdline.Command{
311 Name: "set",
Ankur8d304122014-10-07 10:43:43 -0700312 Short: "Set provided blessings for peer",
313 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700314Marks the provided blessings to be shared with the provided peers on the
315BlessingStore specified by the environment that this tool is running in.
Ankur8d304122014-10-07 10:43:43 -0700316
317'set b pattern' marks the intention to reveal b to peers who
318present blessings of their own matching 'pattern'.
319
320'set nil pattern' can be used to remove the blessings previously
321associated with the pattern (by a prior 'set' command).
322
323It is an error to call 'store.set' with blessings whose public
324key does not match the public key of this principal specified
325by the environment.
326`,
327 ArgsName: "<file> <pattern>",
328 ArgsLong: `
329<file> is the path to a file containing a blessing typically obtained
330from this tool. - is used for STDIN.
331
332<pattern> is the BlessingPattern used to identify peers with whom this
333blessing can be shared with.
334`,
335 Run: func(cmd *cmdline.Command, args []string) error {
336 if len(args) != 2 {
Asim Shankar66c52f92014-10-15 23:39:10 -0700337 return fmt.Errorf("requires exactly two arguments <file>, <pattern>, provided %d", len(args))
Ankur8d304122014-10-07 10:43:43 -0700338 }
339 blessings, err := decodeBlessings(args[0])
340 if err != nil {
341 return fmt.Errorf("failed to decode provided blessings: %v", err)
342 }
343 pattern := security.BlessingPattern(args[1])
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800344
Jiri Simsa6ac95222015-02-23 16:11:49 -0800345 ctx, shutdown := v23.Init()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800346 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800347
Jiri Simsa6ac95222015-02-23 16:11:49 -0800348 p := v23.GetPrincipal(ctx)
Asim Shankar66c52f92014-10-15 23:39:10 -0700349 if _, err := p.BlessingStore().Set(blessings, pattern); err != nil {
Ankur8d304122014-10-07 10:43:43 -0700350 return fmt.Errorf("failed to set blessings %v for peers %v: %v", blessings, pattern, err)
351 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700352 if flagAddToRoots {
353 if err := p.AddToRoots(blessings); err != nil {
354 return fmt.Errorf("AddToRoots failed: %v", err)
355 }
356 }
Ankur8d304122014-10-07 10:43:43 -0700357 return nil
358 },
359 }
360
Asim Shankar5fbe3262015-03-11 23:03:51 -0700361 cmdAddToRoots = &cmdline.Command{
Mike Burrows367515e2014-12-02 11:30:18 -0800362 Name: "addtoroots",
363 Short: "Add provided blessings to root set",
364 Long: `
365Adds the provided blessings to the set of trusted roots for this principal.
366
367'addtoroots b' adds blessings b to the trusted root set.
368
369For example, to make the principal in credentials directory A trust the
370root of the default blessing in credentials directory B:
371 principal -veyron.credentials=B bless A some_extension |
Asim Shankar5fbe3262015-03-11 23:03:51 -0700372 principal -veyron.credentials=A addtoroots -
Mike Burrows367515e2014-12-02 11:30:18 -0800373
374The extension 'some_extension' has no effect in the command above.
375`,
376 ArgsName: "<file>",
377 ArgsLong: `
378<file> is the path to a file containing a blessing typically obtained
379from this tool. - is used for STDIN.
380`,
381 Run: func(cmd *cmdline.Command, args []string) error {
382 if len(args) != 1 {
383 return fmt.Errorf("requires exactly one argument <file>, provided %d", len(args))
384 }
385 blessings, err := decodeBlessings(args[0])
386 if err != nil {
387 return fmt.Errorf("failed to decode provided blessings: %v", err)
388 }
389
Jiri Simsa6ac95222015-02-23 16:11:49 -0800390 ctx, shutdown := v23.Init()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800391 defer shutdown()
Mike Burrows367515e2014-12-02 11:30:18 -0800392
Jiri Simsa6ac95222015-02-23 16:11:49 -0800393 p := v23.GetPrincipal(ctx)
Mike Burrows367515e2014-12-02 11:30:18 -0800394 if err := p.AddToRoots(blessings); err != nil {
395 return fmt.Errorf("AddToRoots failed: %v", err)
396 }
397 return nil
398 },
399 }
400
Asim Shankar66c52f92014-10-15 23:39:10 -0700401 cmdStoreSetDefault = &cmdline.Command{
402 Name: "setdefault",
Ankur8d304122014-10-07 10:43:43 -0700403 Short: "Set provided blessings as default",
404 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700405Sets the provided blessings as default in the BlessingStore specified by the
406environment that this tool is running in.
Ankur8d304122014-10-07 10:43:43 -0700407
Asim Shankar1789b8a2014-10-31 17:31:41 -0700408It is an error to call 'store.setdefault' with blessings whose public key does
409not match the public key of the principal specified by the environment.
Ankur8d304122014-10-07 10:43:43 -0700410`,
411 ArgsName: "<file>",
412 ArgsLong: `
413<file> is the path to a file containing a blessing typically obtained from
414this tool. - is used for STDIN.
415`,
416 Run: func(cmd *cmdline.Command, args []string) error {
417 if len(args) != 1 {
Asim Shankar66c52f92014-10-15 23:39:10 -0700418 return fmt.Errorf("requires exactly one argument, <file>, provided %d", len(args))
Ankur8d304122014-10-07 10:43:43 -0700419 }
420 blessings, err := decodeBlessings(args[0])
421 if err != nil {
422 return fmt.Errorf("failed to decode provided blessings: %v", err)
423 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800424
Jiri Simsa6ac95222015-02-23 16:11:49 -0800425 ctx, shutdown := v23.Init()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800426 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800427
Jiri Simsa6ac95222015-02-23 16:11:49 -0800428 p := v23.GetPrincipal(ctx)
Asim Shankar1789b8a2014-10-31 17:31:41 -0700429 if err := p.BlessingStore().SetDefault(blessings); err != nil {
Ankur8d304122014-10-07 10:43:43 -0700430 return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
431 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700432 if flagAddToRoots {
433 if err := p.AddToRoots(blessings); err != nil {
434 return fmt.Errorf("AddToRoots failed: %v", err)
435 }
436 }
437 return nil
438 },
439 }
440
441 cmdCreate = &cmdline.Command{
442 Name: "create",
443 Short: "Create a new principal and persist it into a directory",
444 Long: `
Ankur4704f5f2014-10-23 12:40:54 -0700445Creates a new principal with a single self-blessed blessing and writes it out
Ankurc24ff422014-12-16 17:59:26 -0800446to the provided directory. The same directory can then be used to set the
447VEYRON_CREDENTIALS environment variable for other veyron applications.
Ankur4704f5f2014-10-23 12:40:54 -0700448
449The operation fails if the directory already contains a principal. In this case
Ankurc24ff422014-12-16 17:59:26 -0800450the --overwrite flag can be provided to clear the directory and write out the
gauthamtb7bb39b2014-11-10 11:40:41 -0800451new principal.
Ankur4704f5f2014-10-23 12:40:54 -0700452`,
Asim Shankar66c52f92014-10-15 23:39:10 -0700453 ArgsName: "<directory> <blessing>",
454 ArgsLong: `
Ankurc24ff422014-12-16 17:59:26 -0800455 <directory> is the directory to which the new principal will be persisted.
Asim Shankar66c52f92014-10-15 23:39:10 -0700456 <blessing> is the self-blessed blessing that the principal will be setup to use by default.
457 `,
458 Run: func(cmd *cmdline.Command, args []string) error {
459 if len(args) != 2 {
460 return fmt.Errorf("requires exactly two arguments: <directory> and <blessing>, provided %d", len(args))
461 }
462 dir, name := args[0], args[1]
Ankur4704f5f2014-10-23 12:40:54 -0700463 if flagCreateOverwrite {
Ankurc24ff422014-12-16 17:59:26 -0800464 if err := os.RemoveAll(dir); err != nil {
gauthamtb7bb39b2014-11-10 11:40:41 -0800465 return err
466 }
Ankur4704f5f2014-10-23 12:40:54 -0700467 }
Ankurc24ff422014-12-16 17:59:26 -0800468 p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700469 if err != nil {
470 return err
Asim Shankar66c52f92014-10-15 23:39:10 -0700471 }
472 blessings, err := p.BlessSelf(name)
473 if err != nil {
474 return fmt.Errorf("BlessSelf(%q) failed: %v", name, err)
475 }
Ankurc24ff422014-12-16 17:59:26 -0800476 if err := vsecurity.SetDefaultBlessings(p, blessings); err != nil {
477 return fmt.Errorf("could not set blessings %v as default: %v", blessings, err)
Asim Shankar66c52f92014-10-15 23:39:10 -0700478 }
Ankurc24ff422014-12-16 17:59:26 -0800479 return nil
480 },
481 }
482
483 cmdFork = &cmdline.Command{
484 Name: "fork",
485 Short: "Fork a new principal from the principal that this tool is running as and persist it into a directory",
486 Long: `
487Creates a new principal with a blessing from the principal specified by the
488environment that this tool is running in, and writes it out to the provided
489directory. The blessing that will be extended is the default one from the
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800490blesser's store, or specified by the --with flag. Expiration on the blessing
491are controlled via the --for flag. Additional caveats on the blessing are
492controlled with the --caveat flag. The blessing is marked as default and
Ankurc24ff422014-12-16 17:59:26 -0800493shareable with all peers on the new principal's blessing store.
494
495The operation fails if the directory already contains a principal. In this case
496the --overwrite flag can be provided to clear the directory and write out the
497forked principal.
498`,
499 ArgsName: "<directory> <extension>",
500 ArgsLong: `
501 <directory> is the directory to which the forked principal will be persisted.
502 <extension> is the extension under which the forked principal is blessed.
503 `,
504 Run: func(cmd *cmdline.Command, args []string) error {
505 if len(args) != 2 {
506 return fmt.Errorf("requires exactly two arguments: <directory> and <extension>, provided %d", len(args))
Asim Shankar66c52f92014-10-15 23:39:10 -0700507 }
Ankurc24ff422014-12-16 17:59:26 -0800508 dir, extension := args[0], args[1]
509
Jiri Simsa6ac95222015-02-23 16:11:49 -0800510 ctx, shutdown := v23.Init()
Asim Shankara0bba462015-02-20 22:50:51 -0800511 defer shutdown()
512
513 caveats, err := caveatsFromFlags(flagForkFor, &flagForkCaveats)
514 if err != nil {
515 return err
516 }
517 if !flagForkRequireCaveats && len(caveats) == 0 {
518 caveats = []security.Caveat{security.UnconstrainedUse()}
519 }
520 if len(caveats) == 0 {
521 return errNoCaveats
522 }
523 var with security.Blessings
524 if len(flagForkWith) > 0 {
525 if with, err = decodeBlessings(flagForkWith); err != nil {
526 return fmt.Errorf("failed to read blessings from --with=%q: %v", flagForkWith, err)
527 }
528 } else {
Jiri Simsa6ac95222015-02-23 16:11:49 -0800529 with = v23.GetPrincipal(ctx).BlessingStore().Default()
Asim Shankara0bba462015-02-20 22:50:51 -0800530 }
531
Ankurc24ff422014-12-16 17:59:26 -0800532 if flagCreateOverwrite {
533 if err := os.RemoveAll(dir); err != nil {
534 return err
535 }
536 }
537 p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
538 if err != nil {
539 return err
540 }
541
Ankurc24ff422014-12-16 17:59:26 -0800542 key := p.PublicKey()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800543 rp := v23.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800544 blessings, err := rp.Bless(key, with, extension, caveats[0], caveats[1:]...)
Ankurc24ff422014-12-16 17:59:26 -0800545 if err != nil {
546 return fmt.Errorf("Bless(%v, %v, %q, ...) failed: %v", key, with, extension, err)
547 }
548 if err := vsecurity.SetDefaultBlessings(p, blessings); err != nil {
549 return fmt.Errorf("could not set blessings %v as default: %v", blessings, err)
Asim Shankar66c52f92014-10-15 23:39:10 -0700550 }
Ankur8d304122014-10-07 10:43:43 -0700551 return nil
552 },
553 }
Ankur1d46f552014-10-09 12:13:31 -0700554
555 cmdSeekBlessings = &cmdline.Command{
556 Name: "seekblessings",
Suharsh Sivakumard1cc6e02015-03-16 13:58:49 -0700557 Short: "Seek blessings from a web-based Vanadium blessing service",
Ankur1d46f552014-10-09 12:13:31 -0700558 Long: `
Suharsh Sivakumard1cc6e02015-03-16 13:58:49 -0700559Seeks blessings from a web-based Vanadium blesser which
Ankur1d46f552014-10-09 12:13:31 -0700560requires the caller to first authenticate with Google using OAuth. Simply
561run the command to see what happens.
562
Asim Shankar1789b8a2014-10-31 17:31:41 -0700563The blessings are sought for the principal specified by the environment that
564this tool is running in.
Ankur1d46f552014-10-09 12:13:31 -0700565
Ankure548f392014-12-08 18:42:41 -0800566The blessings obtained are set as default, unless the --set_default flag is
567set to true, and are also set for sharing with all peers, unless a more
Ankur1d46f552014-10-09 12:13:31 -0700568specific peer pattern is provided using the --for_peer flag.
569`,
570 Run: func(cmd *cmdline.Command, args []string) error {
Asim Shankar08ab3892014-10-16 12:04:07 -0700571 // Initialize the runtime first so that any local errors are reported
572 // before the HTTP roundtrips for obtaining the macaroon begin.
Jiri Simsa6ac95222015-02-23 16:11:49 -0800573 ctx, shutdown := v23.Init()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800574 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800575
Ankur1d46f552014-10-09 12:13:31 -0700576 blessedChan := make(chan string)
577 defer close(blessedChan)
Suharsh Sivakumara76dba62014-12-22 16:00:34 -0800578 macaroonChan, err := getMacaroonForBlessRPC(flagSeekBlessingsFrom, blessedChan, flagSeekBlessingsBrowser)
Ankur1d46f552014-10-09 12:13:31 -0700579 if err != nil {
Suharsh Sivakumard1cc6e02015-03-16 13:58:49 -0700580 return fmt.Errorf("failed to get macaroon from Vanadium blesser: %v", err)
Ankur1d46f552014-10-09 12:13:31 -0700581 }
Ankur1d46f552014-10-09 12:13:31 -0700582
Suharsh Sivakumar67ef84a2015-02-13 13:04:44 -0800583 blessings, err := exchangeMacaroonForBlessing(ctx, macaroonChan)
Ankur1d46f552014-10-09 12:13:31 -0700584 if err != nil {
Suharsh Sivakumar67ef84a2015-02-13 13:04:44 -0800585 return err
Ankur1d46f552014-10-09 12:13:31 -0700586 }
587 blessedChan <- fmt.Sprint(blessings)
588 // Wait for getTokenForBlessRPC to clean up:
589 <-macaroonChan
590
Jiri Simsa6ac95222015-02-23 16:11:49 -0800591 p := v23.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800592
Asim Shankar66c52f92014-10-15 23:39:10 -0700593 if flagSeekBlessingsSetDefault {
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800594 if err := p.BlessingStore().SetDefault(blessings); err != nil {
Ankur1d46f552014-10-09 12:13:31 -0700595 return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
596 }
597 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700598 if pattern := security.BlessingPattern(flagSeekBlessingsForPeer); len(pattern) > 0 {
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800599 if _, err := p.BlessingStore().Set(blessings, pattern); err != nil {
Asim Shankar66c52f92014-10-15 23:39:10 -0700600 return fmt.Errorf("failed to set blessings %v for peers %v: %v", blessings, pattern, err)
601 }
602 }
603 if flagAddToRoots {
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800604 if err := p.AddToRoots(blessings); err != nil {
Asim Shankar66c52f92014-10-15 23:39:10 -0700605 return fmt.Errorf("AddToRoots failed: %v", err)
606 }
Ankur1d46f552014-10-09 12:13:31 -0700607 }
Asim Shankar3f9bbab2015-02-15 13:51:37 -0800608 fmt.Fprintf(cmd.Stdout(), "Received blessings: %v\n", blessings)
Jiri Simsa37b0a092015-02-13 09:32:39 -0800609 return nil
Ankur1d46f552014-10-09 12:13:31 -0700610 },
611 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800612
613 cmdRecvBlessings = &cmdline.Command{
614 Name: "recvblessings",
615 Short: "Receive blessings sent by another principal and use them as the default",
616 Long: `
617Allow another principal (likely a remote process) to bless this one.
618
619This command sets up the invoker (this process) to wait for a blessing
620from another invocation of this tool (remote process) and prints out the
621command to be run as the remote principal.
622
Ankure548f392014-12-08 18:42:41 -0800623The received blessings are set as default, unless the --set_default flag is
624set to true, and are also set for sharing with all peers, unless a more
625specific peer pattern is provided using the --for_peer flag.
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800626
627TODO(ashankar,cnicolaou): Make this next paragraph possible! Requires
628the ability to obtain the proxied endpoint.
629
630Typically, this command should require no arguments.
631However, if the sender and receiver are on different network domains, it may
632make sense to use the --veyron.proxy flag:
Robin Thellend8fea01c2014-12-11 13:48:10 -0800633 principal --veyron.proxy=proxy recvblessings
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800634
635The command to be run at the sender is of the form:
636 principal bless --remote_key=KEY --remote_token=TOKEN ADDRESS
637
638The --remote_key flag is used to by the sender to "authenticate" the receiver,
639ensuring it blesses the intended recipient and not any attacker that may have
640taken over the address.
641
642The --remote_token flag is used by the sender to authenticate itself to the
643receiver. This helps ensure that the receiver rejects blessings from senders
644who just happened to guess the network address of the 'recvblessings'
645invocation.
646`,
647 Run: func(cmd *cmdline.Command, args []string) error {
648 if len(args) != 0 {
649 return fmt.Errorf("command accepts no arguments")
650 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800651
Jiri Simsa6ac95222015-02-23 16:11:49 -0800652 ctx, shutdown := v23.Init()
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800653 defer shutdown()
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800654
Jiri Simsa6ac95222015-02-23 16:11:49 -0800655 server, err := v23.NewServer(ctx)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800656 if err != nil {
657 return fmt.Errorf("failed to create server to listen for blessings: %v", err)
658 }
659 defer server.Stop()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800660 eps, err := server.Listen(v23.GetListenSpec(ctx))
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800661 if err != nil {
662 return fmt.Errorf("failed to setup listening: %v", err)
663 }
664 var token [24]byte
665 if _, err := rand.Read(token[:]); err != nil {
666 return fmt.Errorf("unable to generate token: %v", err)
667 }
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800668
Jiri Simsa6ac95222015-02-23 16:11:49 -0800669 p := v23.GetPrincipal(ctx)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800670 service := &recvBlessingsService{
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800671 principal: p,
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800672 token: base64.URLEncoding.EncodeToString(token[:]),
673 notify: make(chan error),
674 }
675 if err := server.Serve("", service, allowAnyone{}); err != nil {
676 return fmt.Errorf("failed to setup service: %v", err)
677 }
678 // Proposed name:
679 extension := fmt.Sprintf("extension%d", int(token[0])<<16|int(token[1])<<8|int(token[2]))
680 fmt.Println("Run the following command on behalf of the principal that will send blessings:")
681 fmt.Println("You may want to adjust flags affecting the caveats on this blessing, for example using")
682 fmt.Println("the --for flag, or change the extension to something more meaningful")
683 fmt.Println()
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800684 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 -0800685 fmt.Println()
686 fmt.Println("...waiting for sender..")
687 return <-service.notify
688 },
689 }
Ankurcf6a89f2014-10-06 18:33:03 -0700690)
691
692func main() {
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800693 cmdBlessSelf.Flags.Var(&flagBlessSelfCaveats, "caveat", flagBlessSelfCaveats.usage())
Asim Shankara0bba462015-02-20 22:50:51 -0800694 cmdBlessSelf.Flags.DurationVar(&flagBlessSelfFor, "for", 0, "Duration of blessing validity (zero implies no expiration)")
695
Ankur77c32ac2014-12-18 14:18:19 -0800696 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 -0800697 cmdFork.Flags.Var(&flagForkCaveats, "caveat", flagForkCaveats.usage())
Asim Shankara0bba462015-02-20 22:50:51 -0800698 cmdFork.Flags.DurationVar(&flagForkFor, "for", 0, "Duration of blessing validity (zero implies no expiration caveat)")
699 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 -0800700 cmdFork.Flags.StringVar(&flagForkWith, "with", "", "Path to file containing blessing to extend")
701
Suharsh Sivakumar1d61f642015-02-17 20:56:14 -0800702 cmdBless.Flags.Var(&flagBlessCaveats, "caveat", flagBlessCaveats.usage())
Asim Shankara0bba462015-02-20 22:50:51 -0800703 cmdBless.Flags.DurationVar(&flagBlessFor, "for", 0, "Duration of blessing validity (zero implies no expiration caveat)")
704 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 -0800705 cmdBless.Flags.StringVar(&flagBlessWith, "with", "", "Path to file containing blessing to extend")
706 cmdBless.Flags.StringVar(&flagBlessRemoteKey, "remote_key", "", "Public key of the remote principal to bless (obtained from the 'recvblessings' command run by the remote principal")
707 cmdBless.Flags.StringVar(&flagBlessRemoteToken, "remote_token", "", "Token provided by principal running the 'recvblessings' command")
708
Robin Thellend8fea01c2014-12-11 13:48:10 -0800709 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 -0700710 cmdSeekBlessings.Flags.BoolVar(&flagSeekBlessingsSetDefault, "set_default", true, "If true, the blessings obtained will be set as the default blessing in the store")
711 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 -0800712 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 -0700713 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 -0800714
Asim Shankar66c52f92014-10-15 23:39:10 -0700715 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 -0800716
Asim Shankar66c52f92014-10-15 23:39:10 -0700717 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 -0800718
Ankur4704f5f2014-10-23 12:40:54 -0700719 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 -0700720
Ankure548f392014-12-08 18:42:41 -0800721 cmdRecvBlessings.Flags.BoolVar(&flagRecvBlessingsSetDefault, "set_default", true, "If true, the blessings received will be set as the default blessing in the store")
722 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")
723
Asim Shankar66c52f92014-10-15 23:39:10 -0700724 cmdStore := &cmdline.Command{
725 Name: "store",
726 Short: "Manipulate and inspect the principal's blessing store",
727 Long: `
728Commands to manipulate and inspect the blessing store of the principal.
729
730All blessings are printed to stdout using base64-VOM-encoding
731`,
Asim Shankar5fbe3262015-03-11 23:03:51 -0700732 Children: []*cmdline.Command{cmdStoreDefault, cmdStoreSetDefault, cmdStoreForPeer, cmdStoreSet},
Ankurcf6a89f2014-10-06 18:33:03 -0700733 }
Ankurcf6a89f2014-10-06 18:33:03 -0700734
Matt Rosencrantz92303e12015-01-21 09:02:42 -0800735 root := &cmdline.Command{
Ankurcf6a89f2014-10-06 18:33:03 -0700736 Name: "principal",
Suharsh Sivakumard1cc6e02015-03-16 13:58:49 -0700737 Short: "Create and manage vanadium principals",
Ankurcf6a89f2014-10-06 18:33:03 -0700738 Long: `
739The principal tool helps create and manage blessings and the set of trusted
740roots bound to a principal.
741
742All objects are printed using base64-VOM-encoding.
743`,
Asim Shankar5fbe3262015-03-11 23:03:51 -0700744 Children: []*cmdline.Command{cmdCreate, cmdFork, cmdSeekBlessings, cmdRecvBlessings, cmdDump, cmdDumpBlessings, cmdBlessSelf, cmdBless, cmdStore, cmdAddToRoots},
Matt Rosencrantz92303e12015-01-21 09:02:42 -0800745 }
746 os.Exit(root.Main())
Ankurcf6a89f2014-10-06 18:33:03 -0700747}
748
Ankurcf6a89f2014-10-06 18:33:03 -0700749func decodeBlessings(fname string) (security.Blessings, error) {
Asim Shankarb07ec692015-02-27 23:40:44 -0800750 var b security.Blessings
751 err := decode(fname, &b)
752 return b, err
Ankurcf6a89f2014-10-06 18:33:03 -0700753}
754
755func dumpBlessings(blessings security.Blessings) error {
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800756 if blessings.IsZero() {
757 return fmt.Errorf("no blessings found")
Ankurcf6a89f2014-10-06 18:33:03 -0700758 }
Asim Shankarb07ec692015-02-27 23:40:44 -0800759 str, err := base64VomEncode(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
Matt Rosencrantz1dcd0a92015-02-27 11:05:59 -0800857func (r *recvBlessingsService) Grant(call ipc.StreamServerCall, token string) error {
Suharsh Sivakumar380bf342015-02-27 15:38:27 -0800858 b := call.GrantedBlessings()
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800859 if b.IsZero() {
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800860 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
Matt Rosencrantz5c7ed212015-02-27 22:42:35 -0800893func (allowAnyone) Authorize(security.Call) error { return nil }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800894
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.
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800909 return security.Blessings{}, fmt.Errorf("key mismatch: Remote end has public key %v, want %v", got, g.serverKey)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800910 }
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 {
Jiri Simsa6ac95222015-02-23 16:11:49 -0800916 client := v23.GetClient(ctx)
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800917 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}
Asim Shankarb07ec692015-02-27 23:40:44 -0800941
942// Circuitous route to get to the certificate chains.
943// See comments on why security.MarshalBlessings is discouraged.
944// Though, a better alternative is worth looking into.
945func blessings2wire(b security.Blessings) (security.WireBlessings, error) {
946 var wire security.WireBlessings
947 data, err := vom.Encode(b)
948 if err != nil {
949 return wire, err
950 }
951 err = vom.Decode(data, &wire)
952 return wire, err
953}