blob: 8fb855579208ad91c9f87353b747b4069e635b9a [file] [log] [blame]
package main
import (
"flag"
"os"
"path/filepath"
"syscall"
"time"
"veyron.io/lib/cmdline"
"veyron.io/veyron/veyron/lib/flags/consts"
"veyron.io/veyron/veyron/security/agent"
"veyron.io/veyron/veyron/security/agent/keymgr"
"veyron.io/veyron/veyron2"
"veyron.io/veyron/veyron2/options"
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron2/vlog"
_ "veyron.io/veyron/veyron/profiles"
)
var runtime veyron2.Runtime
var durationFlag time.Duration
var nameOverride string
var cmdVrun = &cmdline.Command{
Run: vrun,
Name: "vrun",
Short: "Executes a command with a derived principal.",
Long: "The vrun tool executes a command with a derived principal.",
ArgsName: "<command> [command args...]",
}
func main() {
syscall.CloseOnExec(3)
syscall.CloseOnExec(4)
flag.DurationVar(&durationFlag, "duration", 1*time.Hour, "Duration for the blessing.")
flag.StringVar(&nameOverride, "name", "", "Name to use for the blessing. Uses the command name if unset.")
cmdVrun.Flags.DurationVar(&durationFlag, "duration", 1*time.Hour, "Duration for the blessing.")
cmdVrun.Flags.StringVar(&nameOverride, "name", "", "Name to use for the blessing. Uses the command name if unset.")
cmdVrun.Main()
}
func vrun(cmd *cmdline.Command, args []string) error {
var err error
runtime, err = rt.New()
if err != nil {
vlog.Errorf("Could not initialize runtime")
return err
}
defer runtime.Cleanup()
if len(args) == 0 {
return cmd.UsageErrorf("vrun: no command specified")
}
principal, conn, err := createPrincipal()
if err != nil {
return err
}
err = bless(principal, filepath.Base(args[0]))
if err != nil {
return err
}
return doExec(args, conn)
}
func bless(p security.Principal, name string) error {
caveat, err := security.ExpiryCaveat(time.Now().Add(durationFlag))
if err != nil {
vlog.Errorf("Couldn't create caveat")
return err
}
if 0 != len(nameOverride) {
name = nameOverride
}
blessing, err := runtime.Principal().Bless(p.PublicKey(), runtime.Principal().BlessingStore().Default(), name, caveat)
if err != nil {
vlog.Errorf("Couldn't bless")
return err
}
if err = p.BlessingStore().SetDefault(blessing); err != nil {
vlog.Errorf("Couldn't set default blessing")
return err
}
if _, err = p.BlessingStore().Set(blessing, security.AllPrincipals); err != nil {
vlog.Errorf("Couldn't set default client blessing")
return err
}
if err = p.AddToRoots(blessing); err != nil {
vlog.Errorf("Couldn't set trusted roots")
return err
}
return nil
}
func doExec(cmd []string, conn *os.File) error {
os.Setenv(consts.VeyronCredentials, "")
os.Setenv(agent.FdVarName, "3")
if conn.Fd() != 3 {
if err := syscall.Dup2(int(conn.Fd()), 3); err != nil {
vlog.Errorf("Couldn't dup fd")
return err
}
conn.Close()
}
err := syscall.Exec(cmd[0], cmd, os.Environ())
vlog.Errorf("Couldn't exec %s.", cmd[0])
return err
}
func createPrincipal() (security.Principal, *os.File, error) {
kagent, err := keymgr.NewAgent()
if err != nil {
vlog.Errorf("Could not initialize agent")
return nil, nil, err
}
_, conn, err := kagent.NewPrincipal(runtime.NewContext(), true)
if err != nil {
vlog.Errorf("Couldn't create principal")
return nil, nil, err
}
// Connect to the Principal
client, err := runtime.NewClient(options.VCSecurityNone)
if err != nil {
vlog.Errorf("Couldn't create client")
return nil, nil, err
}
fd, err := syscall.Dup(int(conn.Fd()))
if err != nil {
vlog.Errorf("Couldn't copy fd")
return nil, nil, err
}
syscall.CloseOnExec(fd)
principal, err := agent.NewAgentPrincipal(client, fd, runtime.NewContext())
if err != nil {
vlog.Errorf("Couldn't connect to principal")
return nil, nil, err
}
return principal, conn, nil
}