blob: d2574dc30211e265aa44bdaed2aba3afbeb18cf1 [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 Simsa764efb72014-12-25 20:57:03 -080010 "v.io/core/veyron/lib/unixfd"
Suharsh Sivakumarae774a52015-01-09 14:26:32 -080011 "v.io/core/veyron2"
Jiri Simsa764efb72014-12-25 20:57:03 -080012 "v.io/core/veyron2/context"
13 "v.io/core/veyron2/ipc"
14 "v.io/core/veyron2/naming"
Suharsh Sivakumarae774a52015-01-09 14:26:32 -080015 "v.io/core/veyron2/options"
Jiri Simsa764efb72014-12-25 20:57:03 -080016 "v.io/core/veyron2/security"
17 "v.io/core/veyron2/vdl/vdlutil"
18 "v.io/core/veyron2/vlog"
Matt Rosencrantz6edab562015-01-12 11:07:55 -080019 "v.io/core/veyron2/vtrace"
Ryan Brownfed691e2014-09-15 13:09:40 -070020)
21
Ryan Brown50b473a2014-09-23 14:23:00 -070022// FdVarName is the name of the environment variable containing
23// the file descriptor for talking to the agent.
24const FdVarName = "VEYRON_AGENT_FD"
Ryan Brownfed691e2014-09-15 13:09:40 -070025
26type client struct {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070027 caller caller
Ryan Brownfed691e2014-09-15 13:09:40 -070028 key security.PublicKey
29}
30
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070031type caller struct {
Matt Rosencrantz6edab562015-01-12 11:07:55 -080032 ctx *context.T
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070033 client ipc.Client
34 name string
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070035}
36
37func (c *caller) call(name string, results []interface{}, args ...interface{}) (err error) {
Ryan Brownfed691e2014-09-15 13:09:40 -070038 var call ipc.Call
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070039 results = append(results, &err)
Matt Rosencrantz6edab562015-01-12 11:07:55 -080040
41 ctx, _ := vtrace.SetNewTrace(c.ctx)
Suharsh Sivakumarae774a52015-01-09 14:26:32 -080042 // VCSecurityNone is safe here since we're using anonymous unix sockets.
Matt Rosencrantz6edab562015-01-12 11:07:55 -080043 if call, err = c.client.StartCall(ctx, c.name, name, args, options.VCSecurityNone); err == nil {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070044 if ierr := call.Finish(results...); ierr != nil {
Ryan Brownfed691e2014-09-15 13:09:40 -070045 err = ierr
46 }
47 }
48 return
49}
50
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070051func results(inputs ...interface{}) []interface{} {
52 if len(inputs) > 0 {
53 return inputs
54 }
55 return make([]interface{}, 0)
56}
57
58// NewAgentPrincipal returns a security.Pricipal using the PrivateKey held in a remote agent process.
Ryan Brown50b473a2014-09-23 14:23:00 -070059// 'fd' is the socket for connecting to the agent, typically obtained from
60// os.GetEnv(agent.FdVarName).
Ryan Brownfed691e2014-09-15 13:09:40 -070061// 'ctx' should not have a deadline, and should never be cancelled.
Matt Rosencrantz6edab562015-01-12 11:07:55 -080062func NewAgentPrincipal(ctx *context.T, fd int) (security.Principal, error) {
Ryan Brown81789442014-10-30 13:23:53 -070063 f := os.NewFile(uintptr(fd), "agent_client")
64 defer f.Close()
65 conn, err := net.FileConn(f)
Ryan Brown50b473a2014-09-23 14:23:00 -070066 if err != nil {
67 return nil, err
68 }
69 // This is just an arbitrary 1 byte string. The value is ignored.
70 data := make([]byte, 1)
Ryan Brown81789442014-10-30 13:23:53 -070071 addr, err := unixfd.SendConnection(conn.(*net.UnixConn), data, true)
Ryan Brown50b473a2014-09-23 14:23:00 -070072 if err != nil {
73 return nil, err
74 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070075 caller := caller{
Suharsh Sivakumarae774a52015-01-09 14:26:32 -080076 client: veyron2.GetClient(ctx),
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070077 name: naming.JoinAddressName(naming.FormatEndpoint(addr.Network(), addr.String()), ""),
78 ctx: ctx,
79 }
80
81 agent := &client{caller: caller}
Ryan Brownfed691e2014-09-15 13:09:40 -070082 if err := agent.fetchPublicKey(); err != nil {
83 return nil, err
84 }
85 return agent, nil
86}
87
88func (c *client) fetchPublicKey() (err error) {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070089 var b []byte
90 if err = c.caller.call("PublicKey", results(&b)); err != nil {
Ryan Brownfed691e2014-09-15 13:09:40 -070091 return
92 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070093 c.key, err = security.UnmarshalPublicKey(b)
Ryan Brownfed691e2014-09-15 13:09:40 -070094 return
95}
96
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070097func (c *client) Bless(key security.PublicKey, with security.Blessings, extension string, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Blessings, error) {
98 var blessings security.WireBlessings
99 marshalledKey, err := key.MarshalBinary()
100 if err != nil {
101 return nil, err
102 }
103 err = c.caller.call("Bless", results(&blessings), marshalledKey, security.MarshalBlessings(with), extension, caveat, additionalCaveats)
104 if err != nil {
105 return nil, err
106 }
107 return security.NewBlessings(blessings)
108}
109
110func (c *client) BlessSelf(name string, caveats ...security.Caveat) (security.Blessings, error) {
111 var blessings security.WireBlessings
112 err := c.caller.call("BlessSelf", results(&blessings), name, caveats)
113 if err != nil {
114 return nil, err
115 }
116 return security.NewBlessings(blessings)
117}
118
119func (c *client) Sign(message []byte) (sig security.Signature, err error) {
120 err = c.caller.call("Sign", results(&sig), message)
121 return
122}
123
124func (c *client) MintDischarge(tp security.ThirdPartyCaveat, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Discharge, error) {
125 var discharge security.Discharge
126 err := c.caller.call("MintDischarge", results(&discharge), vdlutil.Any(tp), caveat, additionalCaveats)
127 if err != nil {
128 return nil, err
129 }
130 return discharge, nil
131}
132
Ryan Brownfed691e2014-09-15 13:09:40 -0700133func (c *client) PublicKey() security.PublicKey {
134 return c.key
135}
136
gauthamtf8263932014-12-16 10:59:09 -0800137func (c *client) BlessingsByName(pattern security.BlessingPattern) []security.Blessings {
138 var wbResults []security.WireBlessings
139 err := c.caller.call("BlessingsByName", results(&wbResults), pattern)
140 if err != nil {
141 vlog.Errorf("error calling BlessingsByName: %v", err)
142 return nil
143 }
144 blessings := make([]security.Blessings, len(wbResults))
145 for i, wb := range wbResults {
146 var err error
147 blessings[i], err = security.NewBlessings(wb)
148 if err != nil {
149 vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
150 }
151 }
152 return blessings
153}
154
gauthamt8dc9a182015-01-08 18:03:18 -0800155func (c *client) BlessingsInfo(blessings security.Blessings) map[string][]security.Caveat {
156 var bInfo map[string][]security.Caveat
157 err := c.caller.call("BlessingsInfo", results(&bInfo), security.MarshalBlessings(blessings))
gauthamtf8263932014-12-16 10:59:09 -0800158 if err != nil {
159 vlog.Errorf("error calling BlessingsInfo: %v", err)
160 return nil
161 }
gauthamt8dc9a182015-01-08 18:03:18 -0800162 return bInfo
gauthamtf8263932014-12-16 10:59:09 -0800163}
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700164func (c *client) BlessingStore() security.BlessingStore {
165 return &blessingStore{c.caller, c.key}
166}
167
168func (c *client) Roots() security.BlessingRoots {
169 return &blessingRoots{c.caller}
170}
171
172func (c *client) AddToRoots(blessings security.Blessings) error {
173 return c.caller.call("AddToRoots", results(), security.MarshalBlessings(blessings))
174}
175
176type blessingStore struct {
177 caller caller
178 key security.PublicKey
179}
180
181func (b *blessingStore) Set(blessings security.Blessings, forPeers security.BlessingPattern) (security.Blessings, error) {
182 var resultBlessings security.WireBlessings
183 err := b.caller.call("BlessingStoreSet", results(&resultBlessings), security.MarshalBlessings(blessings), forPeers)
184 if err != nil {
185 return nil, err
Ryan Brownfed691e2014-09-15 13:09:40 -0700186 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700187 return security.NewBlessings(resultBlessings)
188}
189
190func (b *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
191 var resultBlessings security.WireBlessings
192 err := b.caller.call("BlessingStoreForPeer", results(&resultBlessings), peerBlessings)
193 if err != nil {
194 vlog.Errorf("error calling BlessingStoreForPeer: %v", err)
195 return nil
196 }
197 blessings, err := security.NewBlessings(resultBlessings)
198 if err != nil {
199 vlog.Errorf("error creating Blessings from WireBlessings: %v", err)
200 return nil
201 }
202 return blessings
203}
204
205func (b *blessingStore) SetDefault(blessings security.Blessings) error {
206 return b.caller.call("BlessingStoreSetDefault", results(), security.MarshalBlessings(blessings))
207}
208
209func (b *blessingStore) Default() security.Blessings {
210 var resultBlessings security.WireBlessings
211 err := b.caller.call("BlessingStoreDefault", results(&resultBlessings))
212 if err != nil {
213 vlog.Errorf("error calling BlessingStoreDefault: %v", err)
214 return nil
215 }
216 blessings, err := security.NewBlessings(resultBlessings)
217 if err != nil {
218 vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
219 return nil
220 }
221 return blessings
222}
223
224func (b *blessingStore) PublicKey() security.PublicKey {
225 return b.key
226}
227
gauthamtf8263932014-12-16 10:59:09 -0800228func (b *blessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
229 var wbMap map[security.BlessingPattern]security.WireBlessings
230 err := b.caller.call("BlessingStorePeerBlessings", results(&wbMap))
231 if err != nil {
232 vlog.Errorf("error calling BlessingStorePeerBlessings: %v", err)
233 return nil
234 }
235 bMap := make(map[security.BlessingPattern]security.Blessings)
236 for pattern, wb := range wbMap {
237 blessings, err := security.NewBlessings(wb)
238 if err != nil {
239 vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
240 return nil
241 }
242 bMap[pattern] = blessings
243 }
244 return bMap
245}
246
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700247func (b *blessingStore) DebugString() (s string) {
248 err := b.caller.call("BlessingStoreDebugString", results(&s))
249 if err != nil {
250 s = fmt.Sprintf("error calling BlessingStoreDebugString: %v", err)
251 vlog.Errorf(s)
252 }
253 return
254}
255
256type blessingRoots struct {
257 caller caller
258}
259
260func (b *blessingRoots) Add(root security.PublicKey, pattern security.BlessingPattern) error {
261 marshalledKey, err := root.MarshalBinary()
262 if err != nil {
263 return err
264 }
265 return b.caller.call("BlessingRootsAdd", results(), marshalledKey, pattern)
266}
267
268func (b *blessingRoots) Recognized(root security.PublicKey, blessing string) error {
269 marshalledKey, err := root.MarshalBinary()
270 if err != nil {
271 return err
272 }
273 return b.caller.call("BlessingRootsAdd", results(), marshalledKey, blessing)
274}
275
276func (b *blessingRoots) DebugString() (s string) {
277 err := b.caller.call("BlessingRootsDebugString", results(&s))
278 if err != nil {
279 s = fmt.Sprintf("error calling BlessingRootsDebugString: %v", err)
280 vlog.Errorf(s)
281 }
Ryan Brownfed691e2014-09-15 13:09:40 -0700282 return
283}