blob: a13d73de51456b2e7688c7e1d7c58796a1243771 [file] [log] [blame]
Ryan Brown9d8aa9b2014-12-11 12:06:48 -08001package main
2
3import (
4 "flag"
5 "os"
6 "path/filepath"
7 "syscall"
8 "time"
9
Jiri Simsac0a28652014-12-25 15:42:39 -080010 "v.io/lib/cmdline"
Jiri Simsa764efb72014-12-25 20:57:03 -080011 "v.io/core/veyron/lib/flags/consts"
12 "v.io/core/veyron/security/agent"
13 "v.io/core/veyron/security/agent/keymgr"
Ryan Brown9d8aa9b2014-12-11 12:06:48 -080014
Jiri Simsa764efb72014-12-25 20:57:03 -080015 "v.io/core/veyron2"
16 "v.io/core/veyron2/options"
17 "v.io/core/veyron2/rt"
18 "v.io/core/veyron2/security"
19 "v.io/core/veyron2/vlog"
Ryan Brown9d8aa9b2014-12-11 12:06:48 -080020
Jiri Simsa764efb72014-12-25 20:57:03 -080021 _ "v.io/core/veyron/profiles"
Ryan Brown9d8aa9b2014-12-11 12:06:48 -080022)
23
24var runtime veyron2.Runtime
25var durationFlag time.Duration
26var nameOverride string
27
28var cmdVrun = &cmdline.Command{
29 Run: vrun,
30 Name: "vrun",
31 Short: "Executes a command with a derived principal.",
32 Long: "The vrun tool executes a command with a derived principal.",
33 ArgsName: "<command> [command args...]",
34}
35
36func main() {
37 syscall.CloseOnExec(3)
38 syscall.CloseOnExec(4)
39
40 flag.DurationVar(&durationFlag, "duration", 1*time.Hour, "Duration for the blessing.")
41 flag.StringVar(&nameOverride, "name", "", "Name to use for the blessing. Uses the command name if unset.")
42 cmdVrun.Flags.DurationVar(&durationFlag, "duration", 1*time.Hour, "Duration for the blessing.")
43 cmdVrun.Flags.StringVar(&nameOverride, "name", "", "Name to use for the blessing. Uses the command name if unset.")
44
45 cmdVrun.Main()
46}
47
48func vrun(cmd *cmdline.Command, args []string) error {
49 var err error
50 runtime, err = rt.New()
51 if err != nil {
52 vlog.Errorf("Could not initialize runtime")
53 return err
54 }
55 defer runtime.Cleanup()
56
57 if len(args) == 0 {
58 return cmd.UsageErrorf("vrun: no command specified")
59 }
60 principal, conn, err := createPrincipal()
61 if err != nil {
62 return err
63 }
64 err = bless(principal, filepath.Base(args[0]))
65 if err != nil {
66 return err
67 }
68 return doExec(args, conn)
69}
70
71func bless(p security.Principal, name string) error {
72 caveat, err := security.ExpiryCaveat(time.Now().Add(durationFlag))
73 if err != nil {
74 vlog.Errorf("Couldn't create caveat")
75 return err
76 }
77 if 0 != len(nameOverride) {
78 name = nameOverride
79 }
80
81 blessing, err := runtime.Principal().Bless(p.PublicKey(), runtime.Principal().BlessingStore().Default(), name, caveat)
82 if err != nil {
83 vlog.Errorf("Couldn't bless")
84 return err
85 }
86
87 if err = p.BlessingStore().SetDefault(blessing); err != nil {
88 vlog.Errorf("Couldn't set default blessing")
89 return err
90 }
91 if _, err = p.BlessingStore().Set(blessing, security.AllPrincipals); err != nil {
92 vlog.Errorf("Couldn't set default client blessing")
93 return err
94 }
95 if err = p.AddToRoots(blessing); err != nil {
96 vlog.Errorf("Couldn't set trusted roots")
97 return err
98 }
99 return nil
100}
101
102func doExec(cmd []string, conn *os.File) error {
103 os.Setenv(consts.VeyronCredentials, "")
104 os.Setenv(agent.FdVarName, "3")
105 if conn.Fd() != 3 {
106 if err := syscall.Dup2(int(conn.Fd()), 3); err != nil {
107 vlog.Errorf("Couldn't dup fd")
108 return err
109 }
110 conn.Close()
111 }
112 err := syscall.Exec(cmd[0], cmd, os.Environ())
113 vlog.Errorf("Couldn't exec %s.", cmd[0])
114 return err
115}
116
117func createPrincipal() (security.Principal, *os.File, error) {
118 kagent, err := keymgr.NewAgent()
119 if err != nil {
120 vlog.Errorf("Could not initialize agent")
121 return nil, nil, err
122 }
123
124 _, conn, err := kagent.NewPrincipal(runtime.NewContext(), true)
125 if err != nil {
126 vlog.Errorf("Couldn't create principal")
127 return nil, nil, err
128 }
129
130 // Connect to the Principal
131 client, err := runtime.NewClient(options.VCSecurityNone)
132 if err != nil {
133 vlog.Errorf("Couldn't create client")
134 return nil, nil, err
135 }
136 fd, err := syscall.Dup(int(conn.Fd()))
137 if err != nil {
138 vlog.Errorf("Couldn't copy fd")
139 return nil, nil, err
140 }
141 syscall.CloseOnExec(fd)
142 principal, err := agent.NewAgentPrincipal(client, fd, runtime.NewContext())
143 if err != nil {
144 vlog.Errorf("Couldn't connect to principal")
145 return nil, nil, err
146 }
147 return principal, conn, nil
148}