| // Package agent provides a client for communicating with an "Agent" |
| // process holding the private key for an identity. |
| package agent |
| |
| import ( |
| "fmt" |
| "net" |
| "os" |
| |
| "veyron.io/veyron/veyron/lib/unixfd" |
| "veyron.io/veyron/veyron2/context" |
| "veyron.io/veyron/veyron2/ipc" |
| "veyron.io/veyron/veyron2/naming" |
| "veyron.io/veyron/veyron2/security" |
| "veyron.io/veyron/veyron2/vdl/vdlutil" |
| "veyron.io/veyron/veyron2/vlog" |
| ) |
| |
| // FdVarName is the name of the environment variable containing |
| // the file descriptor for talking to the agent. |
| const FdVarName = "VEYRON_AGENT_FD" |
| |
| type client struct { |
| caller caller |
| key security.PublicKey |
| } |
| |
| type caller struct { |
| client ipc.Client |
| name string |
| ctx context.T |
| } |
| |
| func (c *caller) call(name string, results []interface{}, args ...interface{}) (err error) { |
| var call ipc.Call |
| results = append(results, &err) |
| if call, err = c.client.StartCall(c.ctx, c.name, name, args); err == nil { |
| if ierr := call.Finish(results...); ierr != nil { |
| err = ierr |
| } |
| } |
| return |
| } |
| |
| func results(inputs ...interface{}) []interface{} { |
| if len(inputs) > 0 { |
| return inputs |
| } |
| return make([]interface{}, 0) |
| } |
| |
| // NewAgentPrincipal returns a security.Pricipal using the PrivateKey held in a remote agent process. |
| // 'fd' is the socket for connecting to the agent, typically obtained from |
| // os.GetEnv(agent.FdVarName). |
| // 'ctx' should not have a deadline, and should never be cancelled. |
| func NewAgentPrincipal(c ipc.Client, fd int, ctx context.T) (security.Principal, error) { |
| conn, err := net.FileConn(os.NewFile(uintptr(fd), "agent_client")) |
| if err != nil { |
| return nil, err |
| } |
| // This is just an arbitrary 1 byte string. The value is ignored. |
| data := make([]byte, 1) |
| addr, err := unixfd.SendConnection(conn.(*net.UnixConn), data) |
| if err != nil { |
| return nil, err |
| } |
| caller := caller{ |
| client: c, |
| name: naming.JoinAddressName(naming.FormatEndpoint(addr.Network(), addr.String()), ""), |
| ctx: ctx, |
| } |
| |
| agent := &client{caller: caller} |
| if err := agent.fetchPublicKey(); err != nil { |
| return nil, err |
| } |
| return agent, nil |
| } |
| |
| func (c *client) fetchPublicKey() (err error) { |
| var b []byte |
| if err = c.caller.call("PublicKey", results(&b)); err != nil { |
| return |
| } |
| c.key, err = security.UnmarshalPublicKey(b) |
| return |
| } |
| |
| func (c *client) Bless(key security.PublicKey, with security.Blessings, extension string, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Blessings, error) { |
| var blessings security.WireBlessings |
| marshalledKey, err := key.MarshalBinary() |
| if err != nil { |
| return nil, err |
| } |
| err = c.caller.call("Bless", results(&blessings), marshalledKey, security.MarshalBlessings(with), extension, caveat, additionalCaveats) |
| if err != nil { |
| return nil, err |
| } |
| return security.NewBlessings(blessings) |
| } |
| |
| func (c *client) BlessSelf(name string, caveats ...security.Caveat) (security.Blessings, error) { |
| var blessings security.WireBlessings |
| err := c.caller.call("BlessSelf", results(&blessings), name, caveats) |
| if err != nil { |
| return nil, err |
| } |
| return security.NewBlessings(blessings) |
| } |
| |
| func (c *client) Sign(message []byte) (sig security.Signature, err error) { |
| err = c.caller.call("Sign", results(&sig), message) |
| return |
| } |
| |
| func (c *client) MintDischarge(tp security.ThirdPartyCaveat, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Discharge, error) { |
| var discharge security.Discharge |
| err := c.caller.call("MintDischarge", results(&discharge), vdlutil.Any(tp), caveat, additionalCaveats) |
| if err != nil { |
| return nil, err |
| } |
| return discharge, nil |
| } |
| |
| func (c *client) PublicKey() security.PublicKey { |
| return c.key |
| } |
| |
| func (c *client) BlessingStore() security.BlessingStore { |
| return &blessingStore{c.caller, c.key} |
| } |
| |
| func (c *client) Roots() security.BlessingRoots { |
| return &blessingRoots{c.caller} |
| } |
| |
| func (c *client) AddToRoots(blessings security.Blessings) error { |
| return c.caller.call("AddToRoots", results(), security.MarshalBlessings(blessings)) |
| } |
| |
| type blessingStore struct { |
| caller caller |
| key security.PublicKey |
| } |
| |
| func (b *blessingStore) Set(blessings security.Blessings, forPeers security.BlessingPattern) (security.Blessings, error) { |
| var resultBlessings security.WireBlessings |
| err := b.caller.call("BlessingStoreSet", results(&resultBlessings), security.MarshalBlessings(blessings), forPeers) |
| if err != nil { |
| return nil, err |
| } |
| return security.NewBlessings(resultBlessings) |
| } |
| |
| func (b *blessingStore) ForPeer(peerBlessings ...string) security.Blessings { |
| var resultBlessings security.WireBlessings |
| err := b.caller.call("BlessingStoreForPeer", results(&resultBlessings), peerBlessings) |
| if err != nil { |
| vlog.Errorf("error calling BlessingStoreForPeer: %v", err) |
| return nil |
| } |
| blessings, err := security.NewBlessings(resultBlessings) |
| if err != nil { |
| vlog.Errorf("error creating Blessings from WireBlessings: %v", err) |
| return nil |
| } |
| return blessings |
| } |
| |
| func (b *blessingStore) SetDefault(blessings security.Blessings) error { |
| return b.caller.call("BlessingStoreSetDefault", results(), security.MarshalBlessings(blessings)) |
| } |
| |
| func (b *blessingStore) Default() security.Blessings { |
| var resultBlessings security.WireBlessings |
| err := b.caller.call("BlessingStoreDefault", results(&resultBlessings)) |
| if err != nil { |
| vlog.Errorf("error calling BlessingStoreDefault: %v", err) |
| return nil |
| } |
| blessings, err := security.NewBlessings(resultBlessings) |
| if err != nil { |
| vlog.Errorf("error creating Blessing from WireBlessings: %v", err) |
| return nil |
| } |
| return blessings |
| } |
| |
| func (b *blessingStore) PublicKey() security.PublicKey { |
| return b.key |
| } |
| |
| func (b *blessingStore) DebugString() (s string) { |
| err := b.caller.call("BlessingStoreDebugString", results(&s)) |
| if err != nil { |
| s = fmt.Sprintf("error calling BlessingStoreDebugString: %v", err) |
| vlog.Errorf(s) |
| } |
| return |
| } |
| |
| type blessingRoots struct { |
| caller caller |
| } |
| |
| func (b *blessingRoots) Add(root security.PublicKey, pattern security.BlessingPattern) error { |
| marshalledKey, err := root.MarshalBinary() |
| if err != nil { |
| return err |
| } |
| return b.caller.call("BlessingRootsAdd", results(), marshalledKey, pattern) |
| } |
| |
| func (b *blessingRoots) Recognized(root security.PublicKey, blessing string) error { |
| marshalledKey, err := root.MarshalBinary() |
| if err != nil { |
| return err |
| } |
| return b.caller.call("BlessingRootsAdd", results(), marshalledKey, blessing) |
| } |
| |
| func (b *blessingRoots) DebugString() (s string) { |
| err := b.caller.call("BlessingRootsDebugString", results(&s)) |
| if err != nil { |
| s = fmt.Sprintf("error calling BlessingRootsDebugString: %v", err) |
| vlog.Errorf(s) |
| } |
| return |
| } |