Ryan Brown | 9d8aa9b | 2014-12-11 12:06:48 -0800 | [diff] [blame] | 1 | package main |
| 2 | |
| 3 | import ( |
| 4 | "flag" |
| 5 | "os" |
| 6 | "path/filepath" |
| 7 | "syscall" |
| 8 | "time" |
| 9 | |
Jiri Simsa | c0a2865 | 2014-12-25 15:42:39 -0800 | [diff] [blame] | 10 | "v.io/lib/cmdline" |
Jiri Simsa | 764efb7 | 2014-12-25 20:57:03 -0800 | [diff] [blame] | 11 | "v.io/core/veyron/lib/flags/consts" |
| 12 | "v.io/core/veyron/security/agent" |
| 13 | "v.io/core/veyron/security/agent/keymgr" |
Ryan Brown | 9d8aa9b | 2014-12-11 12:06:48 -0800 | [diff] [blame] | 14 | |
Jiri Simsa | 764efb7 | 2014-12-25 20:57:03 -0800 | [diff] [blame] | 15 | "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 Brown | 9d8aa9b | 2014-12-11 12:06:48 -0800 | [diff] [blame] | 20 | |
Jiri Simsa | 764efb7 | 2014-12-25 20:57:03 -0800 | [diff] [blame] | 21 | _ "v.io/core/veyron/profiles" |
Ryan Brown | 9d8aa9b | 2014-12-11 12:06:48 -0800 | [diff] [blame] | 22 | ) |
| 23 | |
| 24 | var runtime veyron2.Runtime |
| 25 | var durationFlag time.Duration |
| 26 | var nameOverride string |
| 27 | |
| 28 | var 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 | |
| 36 | func 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 | |
| 48 | func 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 | |
| 71 | func 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 | |
| 102 | func 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 | |
| 117 | func 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 | } |