blob: f162452d68ad60a4cd3cb52cf5e78bcf70bb2950 [file] [log] [blame]
Ryan Brownfed691e2014-09-15 13:09:40 -07001// Package agent provides a client for communicating with an "Agent"
2// process holding the private key for an identity.
3package agent
4
5import (
6 "fmt"
Ryan Brown50b473a2014-09-23 14:23:00 -07007 "net"
8 "os"
Ryan Brownfed691e2014-09-15 13:09:40 -07009
Jiri Simsa519c5072014-09-17 21:37:57 -070010 "veyron.io/veyron/veyron/lib/unixfd"
11 "veyron.io/veyron/veyron2/context"
12 "veyron.io/veyron/veyron2/ipc"
13 "veyron.io/veyron/veyron2/naming"
14 "veyron.io/veyron/veyron2/security"
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070015 "veyron.io/veyron/veyron2/vdl/vdlutil"
16 "veyron.io/veyron/veyron2/vlog"
Ryan Brownfed691e2014-09-15 13:09:40 -070017)
18
Ryan Brown50b473a2014-09-23 14:23:00 -070019// FdVarName is the name of the environment variable containing
20// the file descriptor for talking to the agent.
21const FdVarName = "VEYRON_AGENT_FD"
Ryan Brownfed691e2014-09-15 13:09:40 -070022
23type client struct {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070024 caller caller
Ryan Brownfed691e2014-09-15 13:09:40 -070025 key security.PublicKey
26}
27
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070028type caller struct {
29 client ipc.Client
30 name string
31 ctx context.T
32}
33
34func (c *caller) call(name string, results []interface{}, args ...interface{}) (err error) {
Ryan Brownfed691e2014-09-15 13:09:40 -070035 var call ipc.Call
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070036 results = append(results, &err)
Ryan Brownfed691e2014-09-15 13:09:40 -070037 if call, err = c.client.StartCall(c.ctx, c.name, name, args); err == nil {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070038 if ierr := call.Finish(results...); ierr != nil {
Ryan Brownfed691e2014-09-15 13:09:40 -070039 err = ierr
40 }
41 }
42 return
43}
44
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070045func results(inputs ...interface{}) []interface{} {
46 if len(inputs) > 0 {
47 return inputs
48 }
49 return make([]interface{}, 0)
50}
51
52// NewAgentPrincipal returns a security.Pricipal using the PrivateKey held in a remote agent process.
Ryan Brown50b473a2014-09-23 14:23:00 -070053// 'fd' is the socket for connecting to the agent, typically obtained from
54// os.GetEnv(agent.FdVarName).
Ryan Brownfed691e2014-09-15 13:09:40 -070055// 'ctx' should not have a deadline, and should never be cancelled.
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070056func NewAgentPrincipal(c ipc.Client, fd int, ctx context.T) (security.Principal, error) {
Ryan Brown50b473a2014-09-23 14:23:00 -070057 conn, err := net.FileConn(os.NewFile(uintptr(fd), "agent_client"))
58 if err != nil {
59 return nil, err
60 }
61 // This is just an arbitrary 1 byte string. The value is ignored.
62 data := make([]byte, 1)
63 addr, err := unixfd.SendConnection(conn.(*net.UnixConn), data)
64 if err != nil {
65 return nil, err
66 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070067 caller := caller{
68 client: c,
69 name: naming.JoinAddressName(naming.FormatEndpoint(addr.Network(), addr.String()), ""),
70 ctx: ctx,
71 }
72
73 agent := &client{caller: caller}
Ryan Brownfed691e2014-09-15 13:09:40 -070074 if err := agent.fetchPublicKey(); err != nil {
75 return nil, err
76 }
77 return agent, nil
78}
79
80func (c *client) fetchPublicKey() (err error) {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070081 var b []byte
82 if err = c.caller.call("PublicKey", results(&b)); err != nil {
Ryan Brownfed691e2014-09-15 13:09:40 -070083 return
84 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070085 c.key, err = security.UnmarshalPublicKey(b)
Ryan Brownfed691e2014-09-15 13:09:40 -070086 return
87}
88
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070089func (c *client) Bless(key security.PublicKey, with security.Blessings, extension string, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Blessings, error) {
90 var blessings security.WireBlessings
91 marshalledKey, err := key.MarshalBinary()
92 if err != nil {
93 return nil, err
94 }
95 err = c.caller.call("Bless", results(&blessings), marshalledKey, security.MarshalBlessings(with), extension, caveat, additionalCaveats)
96 if err != nil {
97 return nil, err
98 }
99 return security.NewBlessings(blessings)
100}
101
102func (c *client) BlessSelf(name string, caveats ...security.Caveat) (security.Blessings, error) {
103 var blessings security.WireBlessings
104 err := c.caller.call("BlessSelf", results(&blessings), name, caveats)
105 if err != nil {
106 return nil, err
107 }
108 return security.NewBlessings(blessings)
109}
110
111func (c *client) Sign(message []byte) (sig security.Signature, err error) {
112 err = c.caller.call("Sign", results(&sig), message)
113 return
114}
115
116func (c *client) MintDischarge(tp security.ThirdPartyCaveat, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Discharge, error) {
117 var discharge security.Discharge
118 err := c.caller.call("MintDischarge", results(&discharge), vdlutil.Any(tp), caveat, additionalCaveats)
119 if err != nil {
120 return nil, err
121 }
122 return discharge, nil
123}
124
Ryan Brownfed691e2014-09-15 13:09:40 -0700125func (c *client) PublicKey() security.PublicKey {
126 return c.key
127}
128
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700129func (c *client) BlessingStore() security.BlessingStore {
130 return &blessingStore{c.caller, c.key}
131}
132
133func (c *client) Roots() security.BlessingRoots {
134 return &blessingRoots{c.caller}
135}
136
137func (c *client) AddToRoots(blessings security.Blessings) error {
138 return c.caller.call("AddToRoots", results(), security.MarshalBlessings(blessings))
139}
140
141type blessingStore struct {
142 caller caller
143 key security.PublicKey
144}
145
146func (b *blessingStore) Set(blessings security.Blessings, forPeers security.BlessingPattern) (security.Blessings, error) {
147 var resultBlessings security.WireBlessings
148 err := b.caller.call("BlessingStoreSet", results(&resultBlessings), security.MarshalBlessings(blessings), forPeers)
149 if err != nil {
150 return nil, err
Ryan Brownfed691e2014-09-15 13:09:40 -0700151 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700152 return security.NewBlessings(resultBlessings)
153}
154
155func (b *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
156 var resultBlessings security.WireBlessings
157 err := b.caller.call("BlessingStoreForPeer", results(&resultBlessings), peerBlessings)
158 if err != nil {
159 vlog.Errorf("error calling BlessingStoreForPeer: %v", err)
160 return nil
161 }
162 blessings, err := security.NewBlessings(resultBlessings)
163 if err != nil {
164 vlog.Errorf("error creating Blessings from WireBlessings: %v", err)
165 return nil
166 }
167 return blessings
168}
169
170func (b *blessingStore) SetDefault(blessings security.Blessings) error {
171 return b.caller.call("BlessingStoreSetDefault", results(), security.MarshalBlessings(blessings))
172}
173
174func (b *blessingStore) Default() security.Blessings {
175 var resultBlessings security.WireBlessings
176 err := b.caller.call("BlessingStoreDefault", results(&resultBlessings))
177 if err != nil {
178 vlog.Errorf("error calling BlessingStoreDefault: %v", err)
179 return nil
180 }
181 blessings, err := security.NewBlessings(resultBlessings)
182 if err != nil {
183 vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
184 return nil
185 }
186 return blessings
187}
188
189func (b *blessingStore) PublicKey() security.PublicKey {
190 return b.key
191}
192
193func (b *blessingStore) DebugString() (s string) {
194 err := b.caller.call("BlessingStoreDebugString", results(&s))
195 if err != nil {
196 s = fmt.Sprintf("error calling BlessingStoreDebugString: %v", err)
197 vlog.Errorf(s)
198 }
199 return
200}
201
202type blessingRoots struct {
203 caller caller
204}
205
206func (b *blessingRoots) Add(root security.PublicKey, pattern security.BlessingPattern) error {
207 marshalledKey, err := root.MarshalBinary()
208 if err != nil {
209 return err
210 }
211 return b.caller.call("BlessingRootsAdd", results(), marshalledKey, pattern)
212}
213
214func (b *blessingRoots) Recognized(root security.PublicKey, blessing string) error {
215 marshalledKey, err := root.MarshalBinary()
216 if err != nil {
217 return err
218 }
219 return b.caller.call("BlessingRootsAdd", results(), marshalledKey, blessing)
220}
221
222func (b *blessingRoots) DebugString() (s string) {
223 err := b.caller.call("BlessingRootsDebugString", results(&s))
224 if err != nil {
225 s = fmt.Sprintf("error calling BlessingRootsDebugString: %v", err)
226 vlog.Errorf(s)
227 }
Ryan Brownfed691e2014-09-15 13:09:40 -0700228 return
229}