blob: f162452d68ad60a4cd3cb52cf5e78bcf70bb2950 [file] [log] [blame]
// 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
}